<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=%D0%91%D0%BE%D1%80%D0%B8%D1%81</id>
	<title>Алговики - Вклад [ru]</title>
	<link rel="self" type="application/atom+xml" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=%D0%91%D0%BE%D1%80%D0%B8%D1%81"/>
	<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/ru/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/%D0%91%D0%BE%D1%80%D0%B8%D1%81"/>
	<updated>2026-10-22T21:29:08Z</updated>
	<subtitle>Вклад</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=21433</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=21433"/>
		<updated>2016-12-19T20:51:01Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]](разделы [[#Общее описание алгоритма|1.1]], [[#Математическое описание алгоритма|1.2]], [[#Вычислительное ядро алгоритма|1.3]], [[#Макроструктура алгоритма|1.4]], [[#Входные и выходные данные алгоритма|1.9]]), [[Участник:Борис|Б.Савков]] (разделы [[#Схема реализации последовательного алгоритма|1.5]], [[#Последовательная сложность алгоритма|1.6]], [[#Информационный граф|1.7]], [[#Ресурс параллелизма алгоритма|1.8]], [[#Свойства алгоритма|1.10]], [[#Существующие реализации алгоритма|2.7]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности &amp;lt;ref&amp;gt;Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&amp;lt;/ref&amp;gt;. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности &amp;lt;ref&amp;gt;Амосов А.А., Дубинский Ю.А., Копченова Н.В. Вычислительные методы для инженеров: Учеб. пособие. — М.: Высш. шк., 1994. — 544 с. &amp;lt;/ref&amp;gt;. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
:&amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
:&amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
:n - количество точек в разбиении&lt;br /&gt;
:&amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
:&amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
&lt;br /&gt;
1. Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
2. Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
&lt;br /&gt;
3. Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned j=0; j&amp;lt;sz; j++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[j],n,f[j]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для случая решения системы ОДУ, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
Информационная структура параллельного алгоритма Рунге-Кутты 4-го порядка представляет собой матрицу изображённую на рисунке ниже. Вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; располагаются &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые параметры вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;, соответственно, вдоль &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; изображены этапы вычисления &amp;lt;math&amp;gt;y_i&amp;lt;/math&amp;gt; значения j-параметра вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;. Таким образом, можно сказать, что вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;, изображены параллельные процессы. А ось &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; представляет собой шкалу времени. Чтобы соотнести её с реальным временем, надо просто посчитать сумму &amp;lt;math&amp;gt;\sum_{i=1}^{n} t_i&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;t_i&amp;lt;/math&amp;gt; - время с момента начала вычисления &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го всеми процессами до момента его завершения всеми процессами.&lt;br /&gt;
&lt;br /&gt;
[[Файл:System_graph.png]]&lt;br /&gt;
&lt;br /&gt;
Можно заметить, что на каждом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге происходит обмен информацией между процессами. Это выражено в виде линии пересекающей все &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые процессы на любом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt;  f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр вектора &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt;  f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров вектора &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим ту же алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
:&amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
:n - количество точек в разбиении,&lt;br /&gt;
:&amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
:функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
:m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
:n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм обладает следующими свойствами:&lt;br /&gt;
&lt;br /&gt;
* Точность. Как написано в [[#Общее описание алгоритма| разделе 1.1]], алгоритм имеет порядок точности &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость. Алгоритм устойчив на любом конечном отрезке.&lt;br /&gt;
* Гибкость. На любом этапе вычисления можно легко изменить шаг интегрирования.&lt;br /&gt;
* Вычислительная мощность алгоритма стремится к константе. Сумма входных и выходных данных равна mn+m+3, а общее количество операций - 4nCm. Таким образом, при возрастании значений входных параметров, их отношение стремится к 4C.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Для исследования масштабируемости алгоритма Рунге-Кутты 4-го порядка была написана своя [https://github.com/D86/superpc/blob/master/rk4.c|параллельная реализация]. этого алгоритма на языке C.&lt;br /&gt;
&lt;br /&gt;
Свойства реализации:&lt;br /&gt;
&lt;br /&gt;
* Реализация написана под компилятор mpicxx.  &lt;br /&gt;
* Тестирование проводилось на [http://hpc.cmc.msu.ru/bgp|IBM Blue Gene/P], расположенном на территории ВМК МГУ. &lt;br /&gt;
&lt;br /&gt;
Исследование проводилось по [https://algowiki-project.org/ru/Scalability_methodology|рекомендованной методологии].&lt;br /&gt;
&lt;br /&gt;
Тестирование&lt;br /&gt;
&lt;br /&gt;
* На вход реализации подавалась система из суперпозиций элементарных функций.&lt;br /&gt;
* Начальные значения выбирались случайным образом. &lt;br /&gt;
&lt;br /&gt;
Список изменяющихся параметров:&lt;br /&gt;
&lt;br /&gt;
В качестве изменяемых параметров выбраны количество максимальное количество процессоров, выделяемое при запуске исследуемой реализации, и параметр m, так как из [[#Входные и выходные данные алгоритма| раздела 1.9]] следует, что объём входных данных зависит от него.&lt;br /&gt;
&lt;br /&gt;
Границы изменяющихся параметров:&lt;br /&gt;
&lt;br /&gt;
* Число процессоров выделяется с 256 до 2048 с шагом 128;&lt;br /&gt;
* Значение m находится в границах от 1000 до 10000 с шагом 1000.&lt;br /&gt;
&lt;br /&gt;
График производительности:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Perf_b.png]]&lt;br /&gt;
&lt;br /&gt;
График эффективности:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Effic.png]]&lt;br /&gt;
&lt;br /&gt;
Оценки:&lt;br /&gt;
&lt;br /&gt;
На основании полученных результатов были составлены графики [https://algowiki-project.org/ru/Глоссарий#.D0.9F.D1.80.D0.BE.D0.B8.D0.B7.D0.B2.D0.BE.D0.B4.D0.B8.D1.82.D0.B5.D0.BB.D1.8C.D0.BD.D0.BE.D1.81.D1.82.D1.8C| производительности] и [https://algowiki-project.org/ru/Глоссарий#.D0.AD.D1.84.D1.84.D0.B5.D0.BA.D1.82.D0.B8.D0.B2.D0.BD.D0.BE.D1.81.D1.82.D1.8C_.D1.80.D0.B0.D1.81.D0.BF.D0.B0.D1.80.D0.B0.D0.BB.D0.BB.D0.B5.D0.BB.D0.B8.D0.B2.D0.B0.D0.BD.D0.B8.D1.8F| эффективности] параллельной реализации, вычислены максимальная и минимальная [https://algowiki-project.org/ru/Глоссарий#.D0.AD.D1.84.D1.84.D0.B5.D0.BA.D1.82.D0.B8.D0.B2.D0.BD.D0.BE.D1.81.D1.82.D1.8C_.D1.80.D0.B5.D0.B0.D0.BB.D0.B8.D0.B7.D0.B0.D1.86.D0.B8.D0.B8| эффективность реализации], 0.000256661928486 и 1.30949963513e-05 соответственно.&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=21422</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=21422"/>
		<updated>2016-12-19T19:38:57Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]](разделы [[#Общее описание алгоритма|1.1]], [[#Математическое описание алгоритма|1.2]], [[#Вычислительное ядро алгоритма|1.3]], [[#Макроструктура алгоритма|1.4]], [[#Входные и выходные данные алгоритма|1.9]]), [[Участник:Борис|Б.Савков]] (разделы [[#Схема реализации последовательного алгоритма|1.5]], [[#Последовательная сложность алгоритма|1.6]], [[#Информационный граф|1.7]], [[#Ресурс параллелизма алгоритма|1.8]], [[#Свойства алгоритма|1.10]], [[#Существующие реализации алгоритма|2.7]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности &amp;lt;ref&amp;gt;Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&amp;lt;/ref&amp;gt;. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности &amp;lt;ref&amp;gt;Амосов А.А., Дубинский Ю.А., Копченова Н.В. Вычислительные методы для инженеров: Учеб. пособие. — М.: Высш. шк., 1994. — 544 с. &amp;lt;/ref&amp;gt;. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
:&amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
:&amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
:n - количество точек в разбиении&lt;br /&gt;
:&amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
:&amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
&lt;br /&gt;
1. Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
2. Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
&lt;br /&gt;
3. Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned j=0; j&amp;lt;sz; j++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[j],n,f[j]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для случая решения системы ОДУ, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
Информационная структура параллельного алгоритма Рунге-Кутты 4-го порядка представляет собой матрицу изображённую на рисунке ниже. Вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; располагаются &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые параметры вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;, соответственно, вдоль &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; изображены этапы вычисления &amp;lt;math&amp;gt;y_i&amp;lt;/math&amp;gt; значения j-параметра вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;. Таким образом, можно сказать, что вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;, изображены параллельные процессы. А ось &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; представляет собой шкалу времени. Чтобы соотнести её с реальным временем, надо просто посчитать сумму &amp;lt;math&amp;gt;\sum_{i=1}^{n} t_i&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;t_i&amp;lt;/math&amp;gt; - время с момента начала вычисления &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го всеми процессами до момента его завершения всеми процессами.&lt;br /&gt;
&lt;br /&gt;
[[Файл:System_graph.png]]&lt;br /&gt;
&lt;br /&gt;
Можно заметить, что на каждом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге происходит обмен информацией между процессами. Это выражено в виде линии пересекающей все &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые процессы на любом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt;  f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр вектора &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt;  f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров вектора &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим ту же алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
:&amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
:n - количество точек в разбиении,&lt;br /&gt;
:&amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
:функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
:m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
:n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм обладает следующими свойствами:&lt;br /&gt;
&lt;br /&gt;
* Точность. Как написано в [[#Общее описание алгоритма| разделе 1.1]], алгоритм имеет порядок точности &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость. Алгоритм устойчив на любом конечном отрезке.&lt;br /&gt;
* Гибкость. На любом этапе вычисления можно легко изменить шаг интегрирования.&lt;br /&gt;
* Вычислительная мощность алгоритма стремится к константе. Сумма входных и выходных данных равна mn+m+3, а общее количество операций - 4nCm. Таким образом, при возрастании значений входных параметров, их отношение стремится к 4C.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Для исследования масштабируемости алгоритма Рунге-Кутты 4-го порядка была написана своя [https://github.com/D86/superpc/blob/master/rk4.c|параллельная реализация]. этого алгоритма на языке C.&lt;br /&gt;
&lt;br /&gt;
Свойства реализации:&lt;br /&gt;
&lt;br /&gt;
* Реализация написана под компилятор mpicxx.  &lt;br /&gt;
* Тестирование проводилось на [http://hpc.cmc.msu.ru/bgp|IBM Blue Gene/P], расположенном на территории ВМК МГУ. &lt;br /&gt;
&lt;br /&gt;
Исследование проводилось по [https://algowiki-project.org/ru/Scalability_methodology|рекомендованной методологии].&lt;br /&gt;
&lt;br /&gt;
Тестирование&lt;br /&gt;
&lt;br /&gt;
* На вход реализации подавалась система из суперпозиций элементарных функций.&lt;br /&gt;
* Начальные значения выбирались случайным образом. &lt;br /&gt;
&lt;br /&gt;
Список изменяющихся параметров:&lt;br /&gt;
&lt;br /&gt;
В качестве изменяемых параметров выбраны количество максимальное количество процессоров, выделяемое при запуске исследуемой реализации, и параметр m, так как из [[#Входные и выходные данные алгоритма| раздела 1.9]] следует, что объём входных данных зависит от него.&lt;br /&gt;
&lt;br /&gt;
Границы изменяющихся параметров:&lt;br /&gt;
&lt;br /&gt;
* Число процессоров выделяется с 256 до 2048 с шагом 128;&lt;br /&gt;
* Значение m находится в границах от 1000 до 10000 с шагом 1000.&lt;br /&gt;
&lt;br /&gt;
График производительности:&lt;br /&gt;
&lt;br /&gt;
[[Файл:System_graph.png]]&lt;br /&gt;
&lt;br /&gt;
График эффективности:&lt;br /&gt;
&lt;br /&gt;
[[Файл:System_graph.png]]&lt;br /&gt;
&lt;br /&gt;
Оценки:&lt;br /&gt;
&lt;br /&gt;
На основании полученных результатов были составлены графики [https://algowiki-project.org/ru/Глоссарий#.D0.9F.D1.80.D0.BE.D0.B8.D0.B7.D0.B2.D0.BE.D0.B4.D0.B8.D1.82.D0.B5.D0.BB.D1.8C.D0.BD.D0.BE.D1.81.D1.82.D1.8C| производительности] и [https://algowiki-project.org/ru/Глоссарий#.D0.AD.D1.84.D1.84.D0.B5.D0.BA.D1.82.D0.B8.D0.B2.D0.BD.D0.BE.D1.81.D1.82.D1.8C_.D1.80.D0.B0.D1.81.D0.BF.D0.B0.D1.80.D0.B0.D0.BB.D0.BB.D0.B5.D0.BB.D0.B8.D0.B2.D0.B0.D0.BD.D0.B8.D1.8F| эффективности] параллельной реализации, вычислены максимальная и минимальная [https://algowiki-project.org/ru/Глоссарий#.D0.AD.D1.84.D1.84.D0.B5.D0.BA.D1.82.D0.B8.D0.B2.D0.BD.D0.BE.D1.81.D1.82.D1.8C_.D1.80.D0.B5.D0.B0.D0.BB.D0.B8.D0.B7.D0.B0.D1.86.D0.B8.D0.B8|эффективность реализации], 0.000256661928486 и 1.30949963513e-05 соответственно.&lt;br /&gt;
&lt;br /&gt;
Результаты исследования:&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Jest&amp;diff=15186</id>
		<title>Обсуждение участника:Jest</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Jest&amp;diff=15186"/>
		<updated>2016-10-31T17:11:55Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Статья Нахождение собственных чисел квадратной матрицы методом QR разложения */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Статья [https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B Алгоритм Рунге-Кутты] ==&lt;br /&gt;
&lt;br /&gt;
=== Замечания ===&lt;br /&gt;
* нужно убрать слово «Часть» из названий пунктов.&lt;br /&gt;
* П. 1.4 - макроструктуру лучше оформить списком.&lt;br /&gt;
* П. 1.8 - «туже» заменить на «ту же».&lt;br /&gt;
* П. 1.2, 1.9 - формулы не нужно оформлять в отдельных блоках.&lt;br /&gt;
* П. 1.10 - не указана вычислительная мощность алгоритма.&lt;br /&gt;
* При указании вклада авторов не нужно каждый раз писать слово «раздел», стоит писать «разделы XXX,YYY».&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=15182</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=15182"/>
		<updated>2016-10-31T16:52:12Z</updated>

		<summary type="html">&lt;p&gt;Борис: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]](разделы [[#Общее описание алгоритма|1.1]], [[#Математическое описание алгоритма|1.2]], [[#Вычислительное ядро алгоритма|1.3]], [[#Макроструктура алгоритма|1.4]], [[#Входные и выходные данные алгоритма|1.9]]), [[Участник:Борис|Б.Савков]] (разделы [[#Схема реализации последовательного алгоритма|1.5]], [[#Последовательная сложность алгоритма|1.6]], [[#Информационный граф|1.7]], [[#Ресурс параллелизма алгоритма|1.8]], [[#Свойства алгоритма|1.10]], [[#Существующие реализации алгоритма|2.7]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности &amp;lt;ref&amp;gt;Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&amp;lt;/ref&amp;gt;. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности &amp;lt;ref&amp;gt;Амосов А.А., Дубинский Ю.А., Копченова Н.В. Вычислительные методы для инженеров: Учеб. пособие. — М.: Высш. шк., 1994. — 544 с. &amp;lt;/ref&amp;gt;. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
:&amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
:&amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
:n - количество точек в разбиении&lt;br /&gt;
:&amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
:&amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
&lt;br /&gt;
1. Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
2. Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
&lt;br /&gt;
3. Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned j=0; j&amp;lt;sz; j++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[j],n,f[j]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для случая решения системы ОДУ, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
Информационная структура параллельного алгоритма Рунге-Кутты 4-го порядка представляет собой матрицу изображённую на рисунке ниже. Вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; располагаются &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые параметры вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;, соответственно, вдоль &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; изображены этапы вычисления &amp;lt;math&amp;gt;y_i&amp;lt;/math&amp;gt; значения j-параметра вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;. Таким образом, можно сказать, что вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;, изображены параллельные процессы. А ось &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; представляет собой шкалу времени. Чтобы соотнести её с реальным временем, надо просто посчитать сумму &amp;lt;math&amp;gt;\sum_{i=1}^{n} t_i&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;t_i&amp;lt;/math&amp;gt; - время с момента начала вычисления &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го всеми процессами до момента его завершения всеми процессами.&lt;br /&gt;
&lt;br /&gt;
[[Файл:System_graph.png]]&lt;br /&gt;
&lt;br /&gt;
Можно заметить, что на каждом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге происходит обмен информацией между процессами. Это выражено в виде линии пересекающей все &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые процессы на любом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt;  f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр вектора &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt;  f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров вектора &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим ту же алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
:&amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
:n - количество точек в разбиении,&lt;br /&gt;
:&amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
:функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
:m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
:n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм обладает следующими свойствами:&lt;br /&gt;
&lt;br /&gt;
* Точность. Как написано в [[#Общее описание алгоритма| разделе 1.1]], алгоритм имеет порядок точности &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость. Алгоритм устойчив на любом конечном отрезке.&lt;br /&gt;
* Гибкость. На любом этапе вычисления можно легко изменить шаг интегрирования.&lt;br /&gt;
* Мощность алгоритма стремится к константе. Сумма входных и выходных данных равна mn+m+3, а общее количество операций - 4nCm. Таким образом, при возрастании значений входных параметров, их отношение стремится к 4C.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=15181</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=15181"/>
		<updated>2016-10-31T16:51:27Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]](разделы [[#Общее описание алгоритма|1.1]], [[#Математическое описание алгоритма|1.2]], [[#Вычислительное ядро алгоритма|1.3]], [[#Макроструктура алгоритма|1.4]], [[#Входные и выходные данные алгоритма|1.9]]), [[Участник:Борис|Б.Савков]] (разделы [[#Схема реализации последовательного алгоритма|1.5]], [[#Последовательная сложность алгоритма|1.6]], [[#Информационный граф|1.7]], [[#Ресурс параллелизма алгоритма|1.8]], [[#Свойства алгоритма|1.10]], [[#Существующие реализации алгоритма|2.7]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности &amp;lt;ref&amp;gt;Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&amp;lt;/ref&amp;gt;. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности &amp;lt;ref&amp;gt;Амосов А.А., Дубинский Ю.А., Копченова Н.В. Вычислительные методы для инженеров: Учеб. пособие. — М.: Высш. шк., 1994. — 544 с. &amp;lt;/ref&amp;gt;. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
:&amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
:&amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
:n - количество точек в разбиении&lt;br /&gt;
:&amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
:&amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
&lt;br /&gt;
1. Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
2. Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
&lt;br /&gt;
3. Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned j=0; j&amp;lt;sz; j++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[j],n,f[j]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для случая решения системы ОДУ, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
Информационная структура параллельного алгоритма Рунге-Кутты 4-го порядка представляет собой матрицу изображённую на рисунке ниже. Вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; располагаются &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые параметры вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;, соответственно, вдоль &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; изображены этапы вычисления &amp;lt;math&amp;gt;y_i&amp;lt;/math&amp;gt; значения j-параметра вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;. Таким образом, можно сказать, что вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;, изображены параллельные процессы. А ось &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; представляет собой шкалу времени. Чтобы соотнести её с реальным временем, надо просто посчитать сумму &amp;lt;math&amp;gt;\sum_{i=1}^{n} t_i&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;t_i&amp;lt;/math&amp;gt; - время с момента начала вычисления &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го всеми процессами до момента его завершения всеми процессами.&lt;br /&gt;
&lt;br /&gt;
[[Файл:System_graph.png]]&lt;br /&gt;
&lt;br /&gt;
Можно заметить, что на каждом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге происходит обмен информацией между процессами. Это выражено в виде линии пересекающей все &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые процессы на любом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt;  f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр вектора &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt;  f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров вектора &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим ту же алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
:&amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
:n - количество точек в разбиении,&lt;br /&gt;
:&amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
:функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
:m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
:n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм обладает следующими свойствами:&lt;br /&gt;
&lt;br /&gt;
* Точность. Как написано в [[#Общее описание алгоритма| разделе 1.1]], алгоритм имеет порядок точности &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость. Алгоритм устойчив на любом конечном отрезке.&lt;br /&gt;
* Гибкость. На любом этапе вычисления можно легко изменить шаг интегрирования.&lt;br /&gt;
* Мощность алгоритма стремится к константе. Сумма входных и выходных данных равна mn+m+3, а общее количество операций - 4nCm. Таким образом, при возрастании значений входных параметров, их отношение стремится к 4C.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=14058</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=14058"/>
		<updated>2016-10-26T17:19:17Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Свойства алгоритма|раздел 1.10]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности &amp;lt;ref&amp;gt;Бахвалов Н. С.,  Жидков Н. П., Кобельков. Г. М. — 6-е изд. — М. : БИНОМ. Лаборатория знаний, 2008. — 636 с.&amp;lt;/ref&amp;gt;. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности &amp;lt;ref&amp;gt;Амосов А.А., Дубинский Ю.А., Копченова Н.В. Вычислительные методы для инженеров: Учеб. пособие. — М.: Высш. шк., 1994. — 544 с. &amp;lt;/ref&amp;gt;. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned j=0; j&amp;lt;sz; j++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[j],n,f[j]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для случая решения системы ОДУ, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
Информационная структура параллельного алгоритма Рунге-Кутты 4-го порядка представляет собой матрицу изображённую на рисунке ниже. Вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; располагаются &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые параметры вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;, соответственно, вдоль &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; изображены этапы вычисления &amp;lt;math&amp;gt;y_i&amp;lt;/math&amp;gt; значения j-параметра вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;. Таким образом, можно сказать, что вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;, изображены параллельные процессы. А ось &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; представляет собой шкалу времени. Чтобы соотнести её с реальным временем, надо просто посчитать сумму &amp;lt;math&amp;gt;\sum_{i=1}^{n} t_i&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;t_i&amp;lt;/math&amp;gt; - время с момента начала вычисления &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го всеми процессами до момента его завершения всеми процессами.&lt;br /&gt;
&lt;br /&gt;
[[Файл:System_graph.png]]&lt;br /&gt;
&lt;br /&gt;
Можно заметить, что на каждом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге происходит обмен информацией между процессами. Это выражено в виде линии пересекающей все &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые процессы на любом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt;  f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр вектора &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt;  f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров вектора &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим ту же алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм обладает следующими свойствами:&lt;br /&gt;
&lt;br /&gt;
* Точность. Как написано в [[#Общее описание алгоритма| разделе 1.1]], алгоритм имеет порядок точности &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость. Алгоритм устойчив на любом конечном отрезке.&lt;br /&gt;
* Гибкость. На любом этапе вычисления можно легко изменить шаг интегрирования.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=12953</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=12953"/>
		<updated>2016-10-17T12:13:33Z</updated>

		<summary type="html">&lt;p&gt;Борис: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Свойства алгоритма|раздел 1.10]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned j=0; j&amp;lt;sz; j++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[j],n,f[j]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для случая решения системы ОДУ, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
Информационная структура параллельного алгоритма Рунге-Кутты 4-го порядка представляет собой матрицу изображённую на рисунке ниже. Вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; располагаются &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые параметры вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;, соответственно, вдоль &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; изображены этапы вычисления &amp;lt;math&amp;gt;y_i&amp;lt;/math&amp;gt; значения j-параметра вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;. Таким образом, можно сказать, что вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;, изображены параллельные процессы. А ось &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; представляет собой шкалу времени. Чтобы соотнести её с реальным временем, надо просто посчитать сумму &amp;lt;math&amp;gt;\sum_{i=1}^{n} t_i&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;t_i&amp;lt;/math&amp;gt; - время с момента начала вычисления &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го всеми процессами до момента его завершения всеми процессами.&lt;br /&gt;
&lt;br /&gt;
[[Файл:System_graph.png]]&lt;br /&gt;
&lt;br /&gt;
Можно заметить, что на каждом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге происходит обмен информацией между процессами. Это выражено в виде линии пересекающей все &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые процессы на любом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt;  f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр вектора &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt;  f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров вектора &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм обладает следующими свойствами:&lt;br /&gt;
&lt;br /&gt;
* Точность. Как написано в [[#Общее описание алгоритма| разделе 1.1]], алгоритм имеет порядок точности &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость. Алгоритм устойчив на любом конечном отрезке.&lt;br /&gt;
* Гибкость. На любом этапе вычисления можно легко изменить шаг интегрирования.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Lineprinter&amp;diff=12952</id>
		<title>Обсуждение участника:Lineprinter</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Lineprinter&amp;diff=12952"/>
		<updated>2016-10-17T12:09:33Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Перенос */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Перенос ==&lt;br /&gt;
Статья: [[Участник:Бобцов Борис/Вычисление определенного интеграла с использованием адаптивно сгущающейся сетки]]&lt;br /&gt;
Выполняет: [[Участник:Бобцов Борис| Бобцов Борис]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Кластеризация сетями Кохонена]]&lt;br /&gt;
Выполняют: [[Участник:Kravtsovkirill| Кравцов Кирилл]] и [[Участник:Emaksimov| Максимов Егор]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нахождение собственных чисел квадратной матрицы методом QR разложения (2)]]&lt;br /&gt;
Выполняют: Баев Олег и Шевелев Александр&lt;br /&gt;
&lt;br /&gt;
Статья: [[Стабилизированный метод биспоряженных градиентов (BiCGSTAB)]]&lt;br /&gt;
Выполняют: Гаврилов Алексей и Новиков Александр&lt;br /&gt;
&lt;br /&gt;
Статья: [[Участники: Бобошко А., Юмакаева А./Решение начальной задачи Коши для системы ОДУ методом Рунге-Кутта 4-го порядка]];&lt;br /&gt;
Выполняют: Бобошко Алексей и Юмакаева Алина&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на сетях Кохоннена]];&lt;br /&gt;
Выполняют:  Логвиненко Александра и Адиев Тохтар&lt;br /&gt;
&lt;br /&gt;
Статья: [[Ортогонализация Грама-Шмидта]];&lt;br /&gt;
Выполняют: [[Участник:KibAndrey| Кибанов Андрей]] и Аджиева Татьяна&lt;br /&gt;
&lt;br /&gt;
Статья: [[Самоорганизующиеся карты Кохонена]];&lt;br /&gt;
Выполняет: [[Участник:Anton goy| Гой Антон]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[ЕМ-алгоритм_(Тематическое_моделирование)]];&lt;br /&gt;
Выполняют: Мурат Апишев и Андрей Заночкин&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_Ланцоша_с_полной_переортогонализацией]];&lt;br /&gt;
Выполняет:[[Участник:Sfedotov| Федотов С.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм_k-средних]]&lt;br /&gt;
Выполняют: [[Участник:Error2407|Богомазов Евгений]], [[Участник:Илья_Егоров|Егоров Илья]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм k-means]]&lt;br /&gt;
Выполняют: [[Участник:Бротиковская Данута|Данута Бротиковская]] и [[Участник:DennZo1993|Денис Зобнин]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Partitioning Around Medoids (Алгоритм)]]&lt;br /&gt;
Выполняют: [[Участник:Denemmy| Галеев Данил]] и [[Участник:Ivan.Z| Запутляев Иван]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нечеткий_алгоритм_С_средних]]&lt;br /&gt;
Выполняют: [[Участник:Demon smd|Д.А.Гуськов]], [[Участник:marina abramenkova|М.А.Абраменкова]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Решение_задачи_Коши_для_системы_ОДУ_методом_Рунге-Кутты_4_порядка]];&lt;br /&gt;
Выполняют: [[Участник:Алимов_Дамир_Алиевич|Алимов Дамир]] и [[Участник:Anlesnichiy|Антон Лесничий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Строгий_алгоритм_С_средних_(Hard_C-Means,_HCM)]];&lt;br /&gt;
Выполняют: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]] и [[Участник:Юрий_Комаров|Комаров Юрий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на минимальном остовном дереве]];&lt;br /&gt;
Выполняет: [[Участник:Astandrik | Стандрик Антон Сергеевич]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Умножение разреженной матрицы на вектор]];&lt;br /&gt;
Выполняет: [[Участник:Lexaloris | Новоселов Алексей]], Выполняет: [[Участник:kochet|П.А. Кочетков]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нахождение_собственных_чисел_квадратной_матрицы_методом_QR_разложения_(3)|Нахождение собственных чисел квадратной матрицы методом QR разложения (3)]];&lt;br /&gt;
Выполняют: [[Участник:Смирнова_Александра|Смирнова А.С.]], [[Участник:Александра_Киямова|Киямова А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод_Якоби_вычисления_сингулярных_чисел_и_векторов]];&lt;br /&gt;
Выполняют: [[Участница:Почернина_Елена| Почернина Елена]] и [[Участница:Светлана|Костюкова Светлана]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод_Ньютона_для_решения_систем_нелинейных_уравнений(2)]];&lt;br /&gt;
Выполняют: [[Участник:Oleggium|Гирняк О.Р.]], [[Участник:Dimx19|Васильков Д.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм_кластеризации_с_использованием_представлений]];&lt;br /&gt;
Выполняют: [[Участник:Cookie|Шатков С.А.]], [[Участница:JuliaA|Антохина Ю.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Быстрое_преобразование_Фурье_(FFT)|Быстрое преобразование Фурье (FFT)]];&lt;br /&gt;
Выполняют: [[Участник:Victoria_Stepanischeva|Степанищева Виктория]] и [[Участник:Igor_Munkin|Мунькин Игорь]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Быстрое_дискретное_преобразование_Фурье|Быстрое_дискретное_преобразование_Фурье]];&lt;br /&gt;
Выполняют: [[Участник:ivanov.kir.m | К.М.Иванов]], [[Участник:Pumpkin | А.C.Сапин]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_k_средних]]&lt;br /&gt;
Выполняют: [[Участник:Parkhomenko|Пархоменко Павел]], [[Участник:ivan.mashonskiy|Машонский Иван]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[EM-алгоритм_кластеризации]]&lt;br /&gt;
Выполняет: [[Участник:Noite|Зинченко Дмитрий]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_k_means]]&lt;br /&gt;
Выполняют: [[Участник:IanaV| Валуйская Яна]], [[Участник:GlotovES| Глотов Евгений]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод Якоби вычисления собственных значений симметричной матрицы ЗП |Метод Якоби вычисления собственных значений симметричной матрицы ЗП]];&lt;br /&gt;
Выполняют: [[Участник:Зиновьев Владимир|Зиновьев В.С.]], [[Участник:Пронин Андрей|Пронин А.М.]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_кластеризации,_основанный_на_минимальном_покрывающем_дереве]]&lt;br /&gt;
Выполняет: [[Участник:Kanast74|Дмитриева Анастасия]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Нахождение_собственных_чисел_квадратной_матрицы_методом_QR_разложения_(4)]]&lt;br /&gt;
Выполняют: [[Участник:F-morozov|Морозов Ф. В.]], [[Участник:Nataliya|Пащенко Н. Ф.]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Хранение_ненулевых_элементов_разреженных_матриц._Умножение_разреженной_матрицы_на_вектор]];&lt;br /&gt;
Выполняют: [[Участник:Trrufina|Третьякова Р.М.]] и [[Участник:Екатерина_Буторина|Буторина Е.В.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм_кластеризации_с_использованием_представлений2]];&lt;br /&gt;
Выполняет: [[Участник:Лукьянова Анна|Лукьянова А.Я.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод Якоби вычисления собственных значений симметричной матрицы]];&lt;br /&gt;
Выполняют: [[Участник: Galkina|Галкина А.С.]], [[Участник: Игорь|Плахов И.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод рекурсивной координатной бисекции]];&lt;br /&gt;
Выполняют: [[Участник: Obirvalger|Гордеев Михаил]], [[Участник: KolmakovEA|Колмаков Евгений]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Итерационный метод решения системы линейных алгебраических уравнений GMRES (обобщенный метод минимальных невязок)]];&lt;br /&gt;
Выполняют: [[Участник: Эльвира Ахиярова|Ахиярова Эльвира]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Хранение ненулевых элементов разреженной матрицы. Умножение разреженной матрицы на вектор]];&lt;br /&gt;
Выполняют: [[Участник: Janyell|Сычева Евгения]], [[Участник: Ahahalin|Хахалин Анатолий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Построение матрицы Адамара произвольного размера]];&lt;br /&gt;
Выполняют: [[Участник: Бугаков Юрий|Бугаков Юрий]], Кужамалиев Ернур&lt;br /&gt;
&lt;br /&gt;
Статья: [[Вычисление определенного интеграла с использованием адаптивно сгущающейся сетки (1)]]&lt;br /&gt;
Выполняют: [[Участница:Sannikovats| Санникова Татьяна Сергеевна]], [[Участник:Plukshin| Лукшин Петр Андреевич]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на построении каркаса]];&lt;br /&gt;
Выполняют: [[Участник:SenderovichNikita| Сендерович Никита]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на максимизации ожидания]];&lt;br /&gt;
Выполняют: Готман Мария, Лукашкина Юлия&lt;br /&gt;
&lt;br /&gt;
Статья: [[Partitioning_Around_Medoids_(PAM)]]&lt;br /&gt;
Выполняют: [[Участник:Avasilenko|А.Э.Василенко]], [[Участник:Anastasia|А.В.Тузикова]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нечеткий алгоритм С-средних (Fuzzy C-means)]]&lt;br /&gt;
Выполняют: [[Участник:Nikmedoed|Н.А. Муромцев]], [[Участник:illusive_mike|М.С. Дворецкий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нечеткий алгоритм C средних]]&lt;br /&gt;
Выполняют: [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Плотностный алгоритм кластеризации DBSCAN]]&lt;br /&gt;
Выполняют: [[Участник:Elena777mc|Малахова Е.С.]], [[Участник:Жаннат_Сагиолданова|Сагиолданова Ж.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Кластеризация Partitioning Around Medoids (PAM)]]&lt;br /&gt;
Выполняют:[[ Участник:Тодуа Антон| Тодуа Антон]], [[Участник:Гусева Юлия| Гусева Юлия]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Участник:Бугаков Юрий (613 группа), Кужамалиев Ернур (601 группа)/Построение матрицы Адамара произвольной размерности]]&lt;br /&gt;
Выполняют:[[ Участник:Бугаков Юрий| Бугаков Юрий]], [[Участник:Кужамалиев Ернур| Кужамалиев Ернур]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Участник:Nikita/Построение_матрицы_Адамара|Построение матрицы Адамара]]&lt;br /&gt;
Выполняют: [[Участник:Nikita|Иванов Никита]], [[Участник:Tsyganov Nikita|Цыганов Никита]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод Ньютона для решения систем нелинейных уравнений]]&lt;br /&gt;
Выполняют: [[Участник:Александр Чернышев|Александр Чернышев]], [[Участник:Захаров Никита|Захаров Никита]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[BIRCH|Сбалансированный итеративный алгоритм редукции и кластеризации с использованием иерархий&lt;br /&gt;
(BIRCH)]]&lt;br /&gt;
Выполняют: [[Участник:Светлана Морозова|Морозова Светлана]], [[Участник:Smirnov.maxim|Смирнов Максим]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Плотностный_алгоритм_кластеризации|Плотностный_алгоритм_кластеризации]], Выполняют: [[Участник:Ramon93i7|Шемякин Роман]], [[Участник:Dadrik|Вашуров Илья]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм CLOPE кластеризации категориальных данных]].&lt;br /&gt;
Выполняют: [[Участник:Артем_Карпухин|Карпухин Артем]], [[Участник:Артем_Желтков|Желтков Артем]].&lt;br /&gt;
&lt;br /&gt;
Статья: [[Участник:Борис/Алгоритм_Рунге-Кутты]]&lt;br /&gt;
Выполняет: [[Участник:Борис| Савков Борис]] и Степанов Евгений.&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=12194</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=12194"/>
		<updated>2016-10-15T21:43:15Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Свойства алгоритма|раздел 1.10]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned j=0; j&amp;lt;sz; j++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[j],n,f[j]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для случая решения системы ОДУ, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
Информационная структура параллельного алгоритма Рунге-Кутты 4-го порядка представляет собой матрицу изображённую на рисунке ниже. Вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; располагаются &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые параметры вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;, соответственно, вдоль &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; изображены этапы вычисления &amp;lt;math&amp;gt;y_i&amp;lt;/math&amp;gt; значения j-параметра вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;. Таким образом, можно сказать, что вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;, изображены параллельные процессы. А ось &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; представляет собой шкалу времени. Чтобы соотнести её с реальным временем, надо просто посчитать сумму &amp;lt;math&amp;gt;\sum_{i=1}^{n} t_i&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;t_i&amp;lt;/math&amp;gt; - время с момента начала вычисления &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го всеми процессами до момента его завершения всеми процессами.&lt;br /&gt;
&lt;br /&gt;
[[Файл:System_graph.png]]&lt;br /&gt;
&lt;br /&gt;
Можно заметить, что на каждом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге происходит обмен информацией между процессами. Это выражено в виде линии пересекающей все &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые процессы на любом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt;  f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр вектора &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt;  f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров вектора &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм обладает следующими свойствами:&lt;br /&gt;
&lt;br /&gt;
* Точность. Как написано в [[#Общее описание алгоритма| разделе 1.1]], алгоритм имеет порядок точности &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость. Алгоритм устойчив на любом конечном отрезке.&lt;br /&gt;
* Гибкость. На любом этапе вычисления можно легко изменить шаг интегрирования.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=12192</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=12192"/>
		<updated>2016-10-15T21:42:44Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Свойства алгоритма|раздел 1.10]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned j=0; j&amp;lt;sz; j++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[j],n,f[j]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для случая решения системы ОДУ, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
Информационная структура параллельного алгоритма Рунге-Кутты 4-го порядка представляет собой матрицу изображённую на рисунке ниже. Вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; располагаются &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые параметры вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;, соответственно, вдоль &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; изображены этапы вычисления &amp;lt;math&amp;gt;y_i&amp;lt;/math&amp;gt; значения j-параметра вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;. Таким образом, можно сказать, что вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;, изображены параллельные процессы. А ось &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; представляет собой шкалу времени. Чтобы соотнести её с реальным временем, надо просто посчитать сумму &amp;lt;math&amp;gt;\sum_{i=1}^{n} t_i&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;t_i&amp;lt;/math&amp;gt; - время с момента начала вычисления &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го всеми процессами до момента его завершения всеми процессами.&lt;br /&gt;
&lt;br /&gt;
[[Файл:System_graph.png]]&lt;br /&gt;
&lt;br /&gt;
Можно заметить, что на каждом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге происходит обмен информацией между процессами. Это выражено в виде линии пересекающей все &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые процессы на любом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр вектора &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров вектора &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм обладает следующими свойствами:&lt;br /&gt;
&lt;br /&gt;
* Точность. Как написано в [[#Общее описание алгоритма| разделе 1.1]], алгоритм имеет порядок точности &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость. Алгоритм устойчив на любом конечном отрезке.&lt;br /&gt;
* Гибкость. На любом этапе вычисления можно легко изменить шаг интегрирования.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=12190</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=12190"/>
		<updated>2016-10-15T21:41:57Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Свойства алгоритма|раздел 1.10]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned j=0; j&amp;lt;sz; j++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[j],n,f[j]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для случая решения системы ОДУ, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
Информационная структура параллельного алгоритма Рунге-Кутты 4-го порядка представляет собой матрицу изображённую на рисунке ниже. Вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; располагаются &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые параметры вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;, соответственно, вдоль &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; изображены этапы вычисления &amp;lt;math&amp;gt;y_i&amp;lt;/math&amp;gt; значения j-параметра вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;. Таким образом, можно сказать, что вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;, изображены параллельные процессы. А ось &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; представляет собой шкалу времени. Чтобы соотнести её с реальным временем, надо просто посчитать сумму &amp;lt;math&amp;gt;\sum_{i=1}^{n} t_i&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;t_i&amp;lt;/math&amp;gt; - время с момента начала вычисления &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го всеми процессами до момента его завершения всеми процессами.&lt;br /&gt;
&lt;br /&gt;
[[Файл:System_graph.png]]&lt;br /&gt;
&lt;br /&gt;
Можно заметить, что на каждом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге происходит обмен информацией между процессами. Это выражено в виде линии пересекающей все &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые процессы на любом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр вектора &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров вектора &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм обладает следующими свойствами:&lt;br /&gt;
&lt;br /&gt;
* Точность. Как написано в [[#Общее описание алгоритма| разделе 1.1]], алгоритм имеет порядок точности &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость. Алгоритм устойчив на любом конечном отрезке.&lt;br /&gt;
* Гибкость. На любом этапе вычисления можно легко изменить шаг интегрирования.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=12187</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=12187"/>
		<updated>2016-10-15T21:40:40Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Свойства алгоритма|раздел 1.10]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned j=0; j&amp;lt;sz; j++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[j],n,f[j]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для случая решения системы ОДУ, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
Информационная структура параллельного алгоритма Рунге-Кутты 4-го порядка представляет собой матрицу изображённую на рисунке ниже. Вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; располагаются &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые параметры вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;, соответственно, вдоль &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; изображены этапы вычисления &amp;lt;math&amp;gt;y_i&amp;lt;/math&amp;gt; значения j-параметра вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;. Таким образом, можно сказать, что вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;, изображены параллельные процессы. А ось &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; представляет собой шкалу времени. Чтобы соотнести её с реальным временем, надо просто посчитать сумму &amp;lt;math&amp;gt;\sum_{i=1}^{n} t_i&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;t_i&amp;lt;/math&amp;gt; - время с момента начала вычисления &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го всеми процессами до момента его завершения всеми процессами.&lt;br /&gt;
&lt;br /&gt;
[[Файл:System_graph.png]]&lt;br /&gt;
&lt;br /&gt;
Можно заметить, что на каждом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге происходит обмен информацией между процессами. Это выражено в виде линии пересекающей все &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые процессы на любом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм обладает следующими свойствами:&lt;br /&gt;
&lt;br /&gt;
* Точность. Как написано в [[#Общее описание алгоритма| разделе 1.1]], алгоритм имеет порядок точности &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость. Алгоритм устойчив на любом конечном отрезке.&lt;br /&gt;
* Гибкость. На любом этапе вычисления можно легко изменить шаг интегрирования.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=12110</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=12110"/>
		<updated>2016-10-15T21:09:04Z</updated>

		<summary type="html">&lt;p&gt;Борис: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Свойства алгоритма|раздел 1.10]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned j=0; j&amp;lt;sz; j++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[j],n,f[j]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для случая решения системы ОДУ, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
Информационная структура параллельного алгоритма Рунге-Кутты 4-го порядка представляет собой матрицу изображённую на рисунке ниже. Вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; располагаются &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые параметры вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;, соответственно, вдоль &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; изображены этапы вычисления &amp;lt;math&amp;gt;y_i&amp;lt;/math&amp;gt; значения j-параметра вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;. Таким образом, можно сказать, что вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;, изображены параллельные процессы. А ось &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; представляет собой шкалу времени. Чтобы соотнести её с реальным временем, надо просто посчитать сумму &amp;lt;math&amp;gt;\sum_{i=1}^{n} t_i&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;t_i&amp;lt;/math&amp;gt; - время с момента начала вычисления &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го всеми процессами до момента его завершения всеми процессами.&lt;br /&gt;
&lt;br /&gt;
[[Файл:system_graph.jpg]]&lt;br /&gt;
&lt;br /&gt;
Можно заметить, что на каждом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге происходит обмен информацией между процессами. Это выражено в виде линии пересекающей все &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые процессы на любом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм обладает следующими свойствами:&lt;br /&gt;
&lt;br /&gt;
* Точность. Как написано в [[#Общее описание алгоритма| разделе 1.1]], алгоритм имеет порядок точности &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость. Алгоритм устойчив на любом конечном отрезке.&lt;br /&gt;
* Гибкость. На любом этапе вычисления можно легко изменить шаг интегрирования.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=12065</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=12065"/>
		<updated>2016-10-15T20:59:40Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Свойства алгоритма|раздел 1.10]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned j=0; j&amp;lt;sz; j++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[j],n,f[j]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для случая решения системы ОДУ, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
Информационная структура параллельного алгоритма Рунге-Кутты 4-го порядка представляет собой матрицу изображённую на рисунке ниже. Вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; располагаются &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые параметры вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;, соответственно, вдоль &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; изображены этапы вычисления &amp;lt;math&amp;gt;y_i&amp;lt;/math&amp;gt; значения j-параметра вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;. Таким образом, можно сказать, что вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;, изображены параллельные процессы. А ось &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; представляет собой шкалу времени. Чтобы соотнести её с реальным временем, надо просто посчитать сумму &amp;lt;math&amp;gt;\sum_{i=1}^{n} t_i&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;t_i&amp;lt;/math&amp;gt; - время с момента начала вычисления &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го всеми процессами до момента его завершения всеми процессами.&lt;br /&gt;
&lt;br /&gt;
[[Файл:system_graph.jpg]]&lt;br /&gt;
&lt;br /&gt;
Можно заметить, что на каждом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге происходит обмен информацией между процессами. Это выражено в виде линии пересекающей все &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые процессы на любом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм обладает следующими свойствами:&lt;br /&gt;
&lt;br /&gt;
* Точность. Как написано в [[#Общее описание алгоритма| разделе 1.1]], алгоритм имеет порядок точности &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость. Алгоритм устойчив на любом конечном отрезке.&lt;br /&gt;
* Гибкость. На любом этапе вычисления можно легко изменить шаг интегрирования.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=12027</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=12027"/>
		<updated>2016-10-15T20:55:45Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Свойства алгоритма|раздел 1.10]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned j=0; j&amp;lt;sz; j++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[j],n,f[j]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для случая решения системы ОДУ, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
Информационная структура параллельного алгоритма Рунге-Кутты 4-го порядка представляет собой матрицу изображённую на рисунке ниже. Вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; располагаются &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые параметры вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;, соответственно, вдоль &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; изображены этапы вычисления &amp;lt;math&amp;gt;y_i&amp;lt;/math&amp;gt; значения j-параметра вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;. Таким образом, можно сказать, что вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;, изображены параллельные процессы. А ось &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; представляет собой шкалу времени. Чтобы соотнести её с реальным временем, надо просто посчитать сумму, где &amp;lt;math&amp;gt;t_i&amp;lt;/math&amp;gt; - время с момента начала вычисления &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го всеми процессами до момента его завершения всеми процессами.&lt;br /&gt;
&lt;br /&gt;
[[Файл:system_graph.jpg]]&lt;br /&gt;
&lt;br /&gt;
Можно заметить, что на каждом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге происходит обмен информацией между процессами. Это выражено в виде линии пересекающей все &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые процессы на любом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм обладает следующими свойствами:&lt;br /&gt;
&lt;br /&gt;
* Точность. Как написано в [[#Общее описание алгоритма| разделе 1.1]], алгоритм имеет порядок точности &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость. Алгоритм устойчив на любом конечном отрезке.&lt;br /&gt;
* Гибкость. На любом этапе вычисления можно легко изменить шаг интегрирования.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=12014</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=12014"/>
		<updated>2016-10-15T20:54:45Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Свойства алгоритма|раздел 1.10]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned j=0; j&amp;lt;sz; j++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[j],n,f[j]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для случая решения системы ОДУ, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
Информационная структура параллельного алгоритма Рунге-Кутты 4-го порядка представляет собой матрицу изображённую на рисунке ниже. Вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; располагаются &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые параметры вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;, соответственно, вдоль &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; изображены этапы вычисления &amp;lt;math&amp;gt;y_i&amp;lt;/math&amp;gt; значения j-параметра вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;. Таким образом, можно сказать, что вдоль оси &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;, изображены параллельные процессы. А ось &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; представляет собой шкалу времени. Чтобы соотнести её с реальным временем, надо просто посчитать сумму, где &amp;lt;math&amp;gt;t_i&amp;lt;/math&amp;gt; - время с момента начала вычисления &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го всеми процессами до момента его завершения всеми процессами.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Example.jpg]]&lt;br /&gt;
&lt;br /&gt;
Можно заметить, что на каждом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге происходит обмен информацией между процессами. Это выражено в виде линии пересекающей все &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ые процессы на любом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм обладает следующими свойствами:&lt;br /&gt;
&lt;br /&gt;
* Точность. Как написано в [[#Общее описание алгоритма| разделе 1.1]], алгоритм имеет порядок точности &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость. Алгоритм устойчив на любом конечном отрезке.&lt;br /&gt;
* Гибкость. На любом этапе вычисления можно легко изменить шаг интегрирования.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11814</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11814"/>
		<updated>2016-10-15T20:32:23Z</updated>

		<summary type="html">&lt;p&gt;Борис: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Свойства алгоритма|раздел 1.10]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned j=0; j&amp;lt;sz; j++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[j],n,f[j]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для случая решения системы ОДУ, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм обладает следующими свойствами:&lt;br /&gt;
&lt;br /&gt;
* Точность. Как написано в [[#Общее описание алгоритма| разделе 1.1]], алгоритм имеет порядок точности &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость. Алгоритм устойчив на любом конечном отрезке.&lt;br /&gt;
* Гибкость. На любом этапе вычисления можно легко изменить шаг интегрирования.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11797</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11797"/>
		<updated>2016-10-15T20:29:38Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned j=0; j&amp;lt;sz; j++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[j],n,f[j]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для случая решения системы ОДУ, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм обладает следующими свойствами:&lt;br /&gt;
&lt;br /&gt;
* Точность. Как написано в [[#Общее описание алгоритма| разделе 1.1]], алгоритм имеет порядок точности &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость. Алгоритм устойчив на любом конечном отрезке.&lt;br /&gt;
* Гибкость. На любом этапе вычисления можно легко изменить шаг интегрирования.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11794</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11794"/>
		<updated>2016-10-15T20:29:18Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned j=0; j&amp;lt;sz; j++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[j],n,f[j]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для случая решения системы ОДУ, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм обладает следующими свойствами:&lt;br /&gt;
&lt;br /&gt;
* Точность. Как написано в [[#Общее описание алгоритма| разделе 1.1]], алгоритм имеет порядок точности &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость. Алгоритм устойчив на всяком конечном отрезке.&lt;br /&gt;
* Гибкость. На любом этапе вычисления можно легко изменить шаг интегрирования.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11698</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11698"/>
		<updated>2016-10-15T20:12:53Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Схема реализации последовательного алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned j=0; j&amp;lt;sz; j++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[j],n,f[j]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для случая решения системы ОДУ, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11628</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11628"/>
		<updated>2016-10-15T20:04:06Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned i=0; i&amp;lt;sz; i++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[i],n,f[i]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для случая решения системы ОДУ, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11618</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11618"/>
		<updated>2016-10-15T20:03:14Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned i=0; i&amp;lt;sz; i++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[i],n,f[i]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для многомерного случая, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt; i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;  y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11613</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11613"/>
		<updated>2016-10-15T20:02:13Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned i=0; i&amp;lt;sz; i++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[i],n,f[i]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для многомерного случая, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt;\bold i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; f &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11610</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11610"/>
		<updated>2016-10-15T20:01:34Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned i=0; i&amp;lt;sz; i++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[i],n,f[i]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для многомерного случая, когда &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt;\bold i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11605</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11605"/>
		<updated>2016-10-15T20:01:00Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Схема реализации последовательного алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(double a, double b, std::vector&amp;lt;double&amp;gt; y0, int n, std::vector&amp;lt;double (*)(double,double)&amp;gt; f)&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = y0.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned i=0; i&amp;lt;sz; i++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a,b,y[i],n,f[i]));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для многомерного случая, когда &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt;\bold i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11518</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11518"/>
		<updated>2016-10-15T19:41:26Z</updated>

		<summary type="html">&lt;p&gt;Борис: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[#Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(std::vector&amp;lt;double&amp;gt; a, std::vector&amp;lt;double&amp;gt; b, std::vector&amp;lt;double&amp;gt; y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = myvector.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned i=0; i&amp;lt;sz; i++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a[i],b[i],y0,n,f));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для многомерного случая, когда &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt;\bold i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11513</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11513"/>
		<updated>2016-10-15T19:40:53Z</updated>

		<summary type="html">&lt;p&gt;Борис: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Информационный граф|раздел 1.7]], [[#Ресурс параллелизма алгоритма|раздел 1.8]], [[Существующие реализации алгоритма|раздел 2.7]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(std::vector&amp;lt;double&amp;gt; a, std::vector&amp;lt;double&amp;gt; b, std::vector&amp;lt;double&amp;gt; y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = myvector.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned i=0; i&amp;lt;sz; i++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a[i],b[i],y0,n,f));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для многомерного случая, когда &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt;\bold i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11500</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11500"/>
		<updated>2016-10-15T19:38:57Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Ресурс параллелизма алгоритма|раздел 1.8]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(std::vector&amp;lt;double&amp;gt; a, std::vector&amp;lt;double&amp;gt; b, std::vector&amp;lt;double&amp;gt; y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = myvector.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned i=0; i&amp;lt;sz; i++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a[i],b[i],y0,n,f));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для многомерного случая, когда &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt;\bold i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций для разных языков программирования. Наиболее популярными являются следующие из них:&lt;br /&gt;
* библиотека RK4, которая существует в вариантах для C++, FORTRAN90, FORTRAN77, python и MATLAB;&lt;br /&gt;
* библиотека ode45 для MATLAB;&lt;br /&gt;
* модуль scipy для PYTHON.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11284</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11284"/>
		<updated>2016-10-15T19:07:08Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Ресурс параллелизма алгоритма|раздел 1.8]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(std::vector&amp;lt;double&amp;gt; a, std::vector&amp;lt;double&amp;gt; b, std::vector&amp;lt;double&amp;gt; y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = myvector.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned i=0; i&amp;lt;sz; i++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a[i],b[i],y0,n,f));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для многомерного случая, когда &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt;\bold i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является одним из наиболее используемых для решения ОДУ и их систем, поэтому существует большое число его реализаций. Наиболее популярными являются следующие из них:&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11052</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11052"/>
		<updated>2016-10-15T18:12:46Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Ресурс параллелизма алгоритма|раздел 1.8]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(std::vector&amp;lt;double&amp;gt; a, std::vector&amp;lt;double&amp;gt; b, std::vector&amp;lt;double&amp;gt; y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = myvector.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned i=0; i&amp;lt;sz; i++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a[i],b[i],y0,n,f));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для многомерного случая, когда &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt;\bold i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11039</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11039"/>
		<updated>2016-10-15T18:09:16Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Ресурс параллелизма алгоритма|раздел 1.8]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(std::vector&amp;lt;double&amp;gt; a, std::vector&amp;lt;double&amp;gt; b, std::vector&amp;lt;double&amp;gt; y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = myvector.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned i=0; i&amp;lt;sz; i++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a[i],b[i],y0,n,f));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. Для многомерного случая, когда &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt;\bold i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11037</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11037"/>
		<updated>2016-10-15T18:08:56Z</updated>

		<summary type="html">&lt;p&gt;Борис: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ( [[#Схема реализации последовательного алгоритма|раздел 1.5]], [[#Последовательная сложность алгоритма|раздел 1.6]], [[#Ресурс параллелизма алгоритма|раздел 1.8]])&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(std::vector&amp;lt;double&amp;gt; a, std::vector&amp;lt;double&amp;gt; b, std::vector&amp;lt;double&amp;gt; y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = myvector.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned i=0; i&amp;lt;sz; i++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a[i],b[i],y0,n,f));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. Для многомерного случая, когда &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt;\bold i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в [[#Последовательная сложность алгоритма|разделе 1.6]] для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11019</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11019"/>
		<updated>2016-10-15T18:04:42Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ()&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(std::vector&amp;lt;double&amp;gt; a, std::vector&amp;lt;double&amp;gt; b, std::vector&amp;lt;double&amp;gt; y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = myvector.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned i=0; i&amp;lt;sz; i++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a[i],b[i],y0,n,f));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. Для многомерного случая, когда &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция core будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt;\bold i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в пункте 1.6 для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11014</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11014"/>
		<updated>2016-10-15T18:04:04Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Схема реализации последовательного алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ()&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(std::vector&amp;lt;double&amp;gt; a, std::vector&amp;lt;double&amp;gt; b, std::vector&amp;lt;double&amp;gt; y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = myvector.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned i=0; i&amp;lt;sz; i++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a[i],b[i],y0,n,f));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// other code ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. Для многомерного случая, когда &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция rungekutta4 будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt;\bold i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в пункте 1.6 для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11004</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=11004"/>
		<updated>2016-10-15T18:02:45Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Схема реализации последовательного алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ()&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
std::vector&amp;lt;double&amp;gt; rungekutta4(std::vector&amp;lt;double&amp;gt; a, std::vector&amp;lt;double&amp;gt; b, std::vector&amp;lt;double&amp;gt; y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt;::size_type sz = myvector.size();&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; result;&lt;br /&gt;
    for (unsigned i=0; i&amp;lt;sz; i++) &lt;br /&gt;
    {&lt;br /&gt;
        rezult.push_back(core(a[i],b[i],y0,n,f));&lt;br /&gt;
    }&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
double core(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (unsigned i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. Для многомерного случая, когда &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция rungekutta4 будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt;\bold i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в пункте 1.6 для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=10930</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=10930"/>
		<updated>2016-10-15T17:49:49Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ()&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
double rungekutta4(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сначала одномерный случай. Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма для одномерного случая равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;. Для многомерного случая, когда &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; являются векторами размерности &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, функция rungekutta4 будет вызвана &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, и итоговая сложность алгоритма составит &amp;lt;math&amp;gt;4nCm&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt;\bold i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в пункте 1.6 для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=10892</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=10892"/>
		<updated>2016-10-15T17:43:57Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ()&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
double rungekutta4(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt;\bold i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;, что и в пункте 1.6 для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=10888</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=10888"/>
		<updated>2016-10-15T17:43:27Z</updated>

		<summary type="html">&lt;p&gt;Борис: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ()&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
double rungekutta4(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм Рунге-Кутты 4-го порядка является итерационным алгоритмом. В нём каждый шаг цикла зависит от предыдущего. В самом шаге, каждая последующая операция также зависит от результата предыдущей. Таким образом, упразднить цикл до независимых и соответственно параллельных операций не является возможным. Однако, так как на результат функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; влияет только &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый параметр векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, то для каждого &amp;lt;math&amp;gt; i &amp;lt;/math&amp;gt; можно производить независимое вычисление. В итоге, если вычислять результаты выполнения функции &amp;lt;math&amp;gt; \bold f &amp;lt;/math&amp;gt; одновременно для вля всех &amp;lt;math&amp;gt;\bold i&amp;lt;/math&amp;gt;-ых параметров векторов &amp;lt;math&amp;gt; \bold x &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \bold y &amp;lt;/math&amp;gt;, получим туже алгоритмическую сложность &amp;lt;math&amp;gt; 4nС &amp;lt;/math&amp;gt;, что и в пункте 1.6 для одномерного случая.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=10303</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=10303"/>
		<updated>2016-10-15T15:47:01Z</updated>

		<summary type="html">&lt;p&gt;Борис: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод Рунге-Кутты 4 порядка&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O()&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;m + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;m * n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Jest|Е.П.Степанов]]([[#Общее описание алгоритма|раздел 1.1]], [[#Математическое описание алгоритма|раздел 1.2]], [[#Вычислительное ядро алгоритма|раздел 1.3]], [[#Макроструктура алгоритма|раздел 1.4]], [[#Входные и выходные данные алгоритма|раздел 1.9]]), [[Участник:Борис|Б.Савков]] ()&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^m, x \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть известно значение y(x) и требуется вычислить значение y(x+h). Это можно сделать при помощи формулы:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; y(x + h) = y(x) + \int_0^hy&#039;(x + t)dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аппроксимируя интеграл в правой части, можно получить методы Рунге-Кутты разного порядка точности. В общем виде формулы методов Рунге-Кутты можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Увеличивая число s вспомогательных точек, можно построить методы Рунге-Кутты любого порядка точности p. Однако уже при p &amp;gt; 5 эти методы используются довольно редко. Это объясняется как чрезмерной громоздкостью получающихся вычислительных формул, так и тем, что преимущества методов высокого порядка точности  над методами, в которых p = 4 или p = 5, проявляются либо в тех задачах, где нужна очень высокая точность и используются ЭВМ высокой разрядности, либо в тех задачах, где решение очень гладкое. Кроме того, методы Рунге-Кутты высокого порядка точности  часто оказываются менее эффективными по сравнению с методами Адамса того же порядка точности. На этой странице представлен наиболее распространенный метод Рунге-Кутты 4 порядка с ошибкой на конечном интервале интегрирования &amp;lt;math&amp;gt;O(h^4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существуют как явные, так и неявные методы Рунге-Кутты. Последние имеют ряд преимуществ над явными методами, однако это достигается за счет существенного усложнения вычислительного алгоритма, так как на каждом шаге приходится считать систему нелинейных уравнений. На этой странице представлен явный метод Рунге-Кутты.&lt;br /&gt;
&lt;br /&gt;
Можно отметить, что в современных программах, реализующих метод Рунге-Кутты, обязательно используется некоторый алгоритм автоматического изменения шага интегрирования. Интуитивно ясно, что на участках плавного изменения решения счет можно вести с достаточно крупным шагом. В то же время на тех участках, где происходят резкие изменения поведения решения, необходимо выбирать мелкий шаг интегрирования. Обычно начальное значение шага h1 задает пользователь. Далее шаг интегрирования меняется в соответствии с величиной получаемой в ходе вычислений оценки локальной погрешности. Для упрощения описания на этой странице используется постоянный шаг интегрирования h, зависящий от размера сетки разбиения n.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Далее подразумевается, что &amp;lt;math&amp;gt; \bold y, \bold y_i,\bold f,  \bold k_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;x, h, n, a, b \in \mathbb{R}^1 &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходные данные: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;, &lt;br /&gt;
    n - количество точек в разбиении&lt;br /&gt;
    &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; - функция вычисления производной&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора значений в узлах сетки, т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Формулы метода:  &lt;br /&gt;
:Вначале вычисляется шаг сетки:&lt;br /&gt;
::&amp;lt;math&amp;gt; h = \frac{b-a}{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:Приближенное значение в следующих точках вычисляется по итерационной формуле:&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + {h \over 6}(\textbf{k}_1 + 2\textbf{k}_2 + 2\textbf{k}_3 + \textbf{k}_4)&amp;lt;/math&amp;gt;,&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_1 = \textbf{f} \left( x_n, \textbf{y}_n \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_2 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_1 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_3 = \textbf{f} \left( x_n + {h \over 2}, \textbf{y}_n + {h \over 2} \textbf{k}_2 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;\textbf{k}_4 = \textbf{f} \left( x_n + h, \textbf{y}_n + h\ \textbf{k}_3 \right),&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;x_{n+1} = x_n + h.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром метода Рунге-Кутты можно считать вычисление значений функции производной&lt;br /&gt;
:&amp;lt;math&amp;gt;\textbf{f}(x, \textbf{y})&amp;lt;/math&amp;gt;,&lt;br /&gt;
так как при вычислении каждого нового &amp;lt;math&amp;gt;\textbf{y}_n&amp;lt;/math&amp;gt; требуется 4 вычисления значения функции производной. Таким образом, сложность работы алгоритма существенно зависит от сложности вычисления функции &amp;lt;math&amp;gt;\textbf{f}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Макроструктура алгоритма может быть представлена в следующем виде:&lt;br /&gt;
:Вычисление вспомогательных коэффициентов &amp;lt;math&amp;gt;\textbf{k}_j, j \in [1,4]&amp;lt;/math&amp;gt;;&lt;br /&gt;
:Вычисление приближенного значения &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; в следующей точке;&lt;br /&gt;
:Переход на следующую итерацию или остановка.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации последовательного алгоритма на языке C++ (указатель на функцию f передаётся через аргументы представленной ниже функции):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
double rungekutta4(double a, double b, double y0, int n, double (*f)(double,double))&lt;br /&gt;
{&lt;br /&gt;
    double h, k1, k2, k3, k4, x, y;&lt;br /&gt;
    h = (b - a)/n;&lt;br /&gt;
    y = y0;&lt;br /&gt;
    x = a;&lt;br /&gt;
    for (int i = 0; i &amp;lt; n; i++)&lt;br /&gt;
    {&lt;br /&gt;
        k1 = f(x, y);&lt;br /&gt;
        k2 = f(x + h/2, y + h*k1/2);&lt;br /&gt;
        k3 = f(x + h/2, y + h*k2/2);&lt;br /&gt;
        k4 = f(x + h/2, y + h*k3);&lt;br /&gt;
        x += h;&lt;br /&gt;
        y += h*(k1 + 2*k2 + 2*k3 + k4)/6;&lt;br /&gt;
    }&lt;br /&gt;
    return y;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Наравне с обычными операциями, такими как сложение, умножение и тому подобными, в представленном выше алгоритме присутствует вызов функции &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt;. Так как эта функция может содержать в себе любое количество простых математических операций, будем считать, что её сложность &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; много больше любой из них, и равна константе &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. За весь алгоритм, она вызывается &amp;lt;math&amp;gt;4n&amp;lt;/math&amp;gt; раза. Таким образом, сложность последовательного алгоритма равна &amp;lt;math&amp;gt;4nC&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &lt;br /&gt;
    &amp;lt;math&amp;gt; a, b &amp;lt;/math&amp;gt; - интервал интегрирования,    &lt;br /&gt;
    n - количество точек в разбиении,&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_0 &amp;lt;/math&amp;gt; - вектор значений размерности m при &amp;lt;math&amp;gt; x = a &amp;lt;/math&amp;gt;,&lt;br /&gt;
    функцию вычисления производной &amp;lt;math&amp;gt;\bold f &amp;lt;/math&amp;gt; будем считать встроенной в алгоритм.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;:&lt;br /&gt;
    m + 3&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
    &amp;lt;math&amp;gt; \bold y_i &amp;lt;/math&amp;gt; - вектора размера m значений в n узлах сетки (т.е. при &amp;lt;math&amp;gt; x = a + i * \frac{b-a}{n}, i \in [1, n] &amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;&lt;br /&gt;
    n * m&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== [[Особенности реализации последовательного алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Возможные способы и особенности параллельной реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Динамические характеристики и эффективность реализации алгоритма]] ==&lt;br /&gt;
&lt;br /&gt;
== [[Выводы для классов архитектур]] ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=6512</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=6512"/>
		<updated>2016-10-13T14:37:56Z</updated>

		<summary type="html">&lt;p&gt;Борис: Добавлены разделы&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^n, x \in \mathbb{R} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Локальность данных и вычислений]] ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=6490</id>
		<title>Участник:Борис/Алгоритм Рунге-Кутты</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%91%D0%BE%D1%80%D0%B8%D1%81/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5-%D0%9A%D1%83%D1%82%D1%82%D1%8B&amp;diff=6490"/>
		<updated>2016-10-13T14:20:52Z</updated>

		<summary type="html">&lt;p&gt;Борис: Начало первого раздела&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ме́тоды Ру́нге — Ку́тты (распространено неправильное название Ме́тоды Ру́нге — Ку́тта или же Ме́тоды Ру́нге — Кутта́) — важное семейство численных алгоритмов решения обыкновенных дифференциальных уравнений и их систем. Данные итеративные методы явного и неявного приближённого вычисления были разработаны около 1900 года немецкими математиками К. Рунге и М. В. Куттой.&lt;br /&gt;
&lt;br /&gt;
Метод Рунге - Кутты применяется при решения задачи Коши для системы обыкновенных дифференциальных уравнений первого порядка:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}&lt;br /&gt;
\textbf{y}&#039; = \textbf{f}(x, \textbf{y}),\\&lt;br /&gt;
\textbf{y}(x_0) = \textbf{y}_0.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом &amp;lt;math&amp;gt;\textbf{y}, \textbf{f}, x&amp;lt;/math&amp;gt; отвечают следующим свойствам: &amp;lt;math&amp;gt; \textbf{y}, \textbf{f} \in \mathbb{R}^n, x \in \mathbb{R} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\textbf{y}_{n+1} = \textbf{y}_n + h\sum_{i=1}^s b_i \textbf{k}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{array}{ll}&lt;br /&gt;
\textbf{k}_1 =&amp;amp; \textbf{f}(x_n, \textbf{y}_n),\\&lt;br /&gt;
\textbf{k}_2 =&amp;amp; \textbf{f}(x_n+c_2h, \textbf{y}_n+a_{21}h\textbf{k}_1),\\&lt;br /&gt;
\cdots&amp;amp;\\&lt;br /&gt;
\textbf{k}_s =&amp;amp; \textbf{f}(x_n+c_sh, \textbf{y}_n+a_{s1}h\textbf{k}_1+a_{s2}h\textbf{k}_2+\cdots+a_{s,s-1}h\textbf{k}_{s-1})&lt;br /&gt;
\end{array}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;/div&gt;</summary>
		<author><name>Борис</name></author>
	</entry>
</feed>