<?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=Abogovski</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=Abogovski"/>
	<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/Abogovski"/>
	<updated>2026-10-23T17:19:02Z</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20458</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20458"/>
		<updated>2016-12-09T02:12:20Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
Вычисление диапазона перебора из настроек перебора (заданных при компиляции) и &amp;quot;порядкового номера&amp;quot; процесса (ранга в MPI_COMM_WORLD)&lt;br /&gt;
можно отнести к вычислительному ядру&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Способ обхода выбран таким образом, чтобы переход к следующему набору параметров требовал наименьшее число операций, для этого же используется стек T из n = AREAS_CNT матриц 2x2.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подробнее см. раздел вычислительное ядро&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
mpi_rank, mpi_size = p -- ранг процесса в MPI_COMM_WORLD, размер MPI_COMM_WORLD (число процессов)&lt;br /&gt;
&lt;br /&gt;
n -- число областей непрерывности&lt;br /&gt;
&lt;br /&gt;
[[Image:my_info_graph.png]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов (логарифмическая шкала), ось ординат -- время (линейная шкала). Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пример: JobId = 1382989, p = 128, Time = 00:14&lt;br /&gt;
&lt;br /&gt;
[[Image:Graph_fixed1.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других существующих реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20457</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20457"/>
		<updated>2016-12-09T02:12:06Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
Вычисление диапазона перебора из настроек перебора (заданных при компиляции) и &amp;quot;порядкового номера&amp;quot; процесса (ранга в MPI_COMM_WORLD)&lt;br /&gt;
можно отнести к вычислительному ядру&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Способ обхода выбран таким образом, чтобы переход к следующему набору параметров требовал наименьшее число операций, для этого же используется стек T из n = AREAS_CNT матриц 2x2.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подробнее см. раздел вычислительное ядро&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
mpi_rank, mpi_size = p -- ранг процесса в MPI_COMM_WORLD, размер MPI_COMM_WORLD (число процессов)&lt;br /&gt;
&lt;br /&gt;
n -- число областей непрерывности&lt;br /&gt;
&lt;br /&gt;
[[Image:my_info_graph.png]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов (логарифмическая шкала), ось ординат -- время (линейная шкала). Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
lomonosov.parallel.ru username: abogovski_607&lt;br /&gt;
&lt;br /&gt;
Пример работы: JobId = 1382989, p = 128, Time = 00:14&lt;br /&gt;
&lt;br /&gt;
[[Image:Graph_fixed1.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других существующих реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20456</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20456"/>
		<updated>2016-12-09T02:09:25Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
Вычисление диапазона перебора из настроек перебора (заданных при компиляции) и &amp;quot;порядкового номера&amp;quot; процесса (ранга в MPI_COMM_WORLD)&lt;br /&gt;
можно отнести к вычислительному ядру&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Способ обхода выбран таким образом, чтобы переход к следующему набору параметров требовал наименьшее число операций, для этого же используется стек T из n = AREAS_CNT матриц 2x2.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подробнее см. раздел вычислительное ядро&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
mpi_rank, mpi_size = p -- ранг процесса в MPI_COMM_WORLD, размер MPI_COMM_WORLD (число процессов)&lt;br /&gt;
&lt;br /&gt;
n -- число областей непрерывности&lt;br /&gt;
&lt;br /&gt;
[[Image:my_info_graph.png]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов (логарифмическая шкала), ось ординат -- время (линейная шкала). Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
lomonosov.parallel.ru username: abogovski_607&lt;br /&gt;
Пример: JobId = 1382989, p = 128, Time = 00:14&lt;br /&gt;
&lt;br /&gt;
[[Image:Graph_fixed1.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других существующих реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20455</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20455"/>
		<updated>2016-12-09T00:59:49Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
Вычисление диапазона перебора из настроек перебора (заданных при компиляции) и &amp;quot;порядкового номера&amp;quot; процесса (ранга в MPI_COMM_WORLD)&lt;br /&gt;
можно отнести к вычислительному ядру&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Способ обхода выбран таким образом, чтобы переход к следующему набору параметров требовал наименьшее число операций, для этого же используется стек T из n = AREAS_CNT матриц 2x2.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подробнее см. раздел вычислительное ядро&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
mpi_rank, mpi_size = p -- ранг процесса в MPI_COMM_WORLD, размер MPI_COMM_WORLD (число процессов)&lt;br /&gt;
&lt;br /&gt;
n -- число областей непрерывности&lt;br /&gt;
&lt;br /&gt;
[[Image:my_info_graph.png]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов (логарифмическая шкала), ось ординат -- время (линейная шкала). Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
lomonosov.parallel.ru username: abogovski_607&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| JobIds || p || Average Time(mm:ss)&lt;br /&gt;
|-&lt;br /&gt;
| 1382989, 1383000 || 128 || 00:14&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Image:Graph_fixed1.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других существующих реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20454</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20454"/>
		<updated>2016-12-09T00:57:46Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
Вычисление диапазона перебора из настроек перебора (заданных при компиляции) и &amp;quot;порядкового номера&amp;quot; процесса (ранга в MPI_COMM_WORLD)&lt;br /&gt;
можно отнести к вычислительному ядру&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Способ обхода выбран таким образом, чтобы переход к следующему набору параметров требовал наименьшее число операций, для этого же используется стек T из n = AREAS_CNT матриц 2x2.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подробнее см. раздел вычислительное ядро&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
mpi_rank, mpi_size -- ранг процесса в MPI_COMM_WORLD, размер MPI_COMM_WORLD&lt;br /&gt;
&lt;br /&gt;
n -- число областей непрерывности&lt;br /&gt;
&lt;br /&gt;
м&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов (логарифмическая шкала), ось ординат -- время (линейная шкала). Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
lomonosov.parallel.ru username: abogovski_607&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| JobIds || p || Average Time(mm:ss)&lt;br /&gt;
|-&lt;br /&gt;
| 1382989, 1383000 || 128 || 00:14&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Image:Graph_fixed1.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других существующих реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20453</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20453"/>
		<updated>2016-12-08T22:58:55Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
Вычисление диапазона перебора из настроек перебора (заданных при компиляции) и &amp;quot;порядкового номера&amp;quot; процесса (ранга в MPI_COMM_WORLD)&lt;br /&gt;
можно отнести к вычислительному ядру&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Способ обхода выбран таким образом, чтобы переход к следующему набору параметров требовал наименьшее число операций, для этого же используется стек T из n = AREAS_CNT матриц 2x2.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подробнее см. раздел вычислительное ядро&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
mpi_rank, mpi_size -- ранг процесса в MPI_COMM_WORLD, размер MPI_COMM_WORLD&lt;br /&gt;
&lt;br /&gt;
n -- число областей непрерывности&lt;br /&gt;
&lt;br /&gt;
м&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов (логарифмическая шкала), ось ординат -- время (линейная шкала). Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Graph_fixed1.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других существующих реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20450</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20450"/>
		<updated>2016-12-08T22:05:59Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Перебор на заданных диапазонах */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
Вычисление диапазона перебора из настроек перебора (заданных при компиляции) и &amp;quot;порядкового номера&amp;quot; процесса (ранга в MPI_COMM_WORLD)&lt;br /&gt;
можно отнести к вычислительному ядру&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Способ обхода выбран таким образом, чтобы переход к следующему набору параметров требовал наименьшее число операций, для этого же используется стек T из n = AREAS_CNT матриц 2x2.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подробнее см. раздел вычислительное ядро&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов (логарифмическая шкала), ось ординат -- время (линейная шкала). Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Graph_fixed1.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других существующих реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20439</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20439"/>
		<updated>2016-12-08T21:17:29Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Выбор диапазонов перебора для параметров каждой области */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
Вычисление диапазона перебора из настроек перебора (заданных при компиляции) и &amp;quot;порядкового номера&amp;quot; процесса (ранга в MPI_COMM_WORLD)&lt;br /&gt;
можно отнести к вычислительному ядру&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подробнее см. раздел вычислительное ядро&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов (логарифмическая шкала), ось ординат -- время (линейная шкала). Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Graph_fixed1.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других существующих реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20438</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20438"/>
		<updated>2016-12-08T21:17:04Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Выбор диапазонов перебора для параметров каждой области */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
Вычисление диапазона перебора из заданных при компиляции настроек перебора и &amp;quot;порядкового номера&amp;quot; процесса (ранга в MPI_COMM_WORLD)&lt;br /&gt;
можно отнести к вычислительному ядру&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подробнее см. раздел вычислительное ядро&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов (логарифмическая шкала), ось ординат -- время (линейная шкала). Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Graph_fixed1.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других существующих реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20437</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20437"/>
		<updated>2016-12-08T21:16:25Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Выбор диапазонов перебора для параметров каждой области */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
Вычисление диапазона перебора из заданных при компиляции параметров и &amp;quot;порядкового номера&amp;quot; процесса (ранга в MPI_COMM_WORLD)&lt;br /&gt;
можно отнести к вычислительному ядру&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подробнее см. раздел вычислительное ядро&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов (логарифмическая шкала), ось ординат -- время (линейная шкала). Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Graph_fixed1.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других существующих реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20435</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20435"/>
		<updated>2016-12-08T21:15:59Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Выбор диапазонов перебора для параметров каждой области */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
Выбор вычисление диапазона перебора из заданных при компиляции параметров и &amp;quot;порядкового номера&amp;quot; процесса (ранга в MPI_COMM_WORLD)&lt;br /&gt;
можно отнести к вычислительному ядру&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подробнее см. раздел вычислительное ядро&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов (логарифмическая шкала), ось ординат -- время (линейная шкала). Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Graph_fixed1.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других существующих реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20433</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20433"/>
		<updated>2016-12-08T21:13:40Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Схема реализации последовательного алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подробнее см. раздел вычислительное ядро&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов (логарифмическая шкала), ось ординат -- время (линейная шкала). Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Graph_fixed1.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других существующих реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20432</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20432"/>
		<updated>2016-12-08T21:11:20Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Схема реализации последовательного алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядром всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подробнее см. раздел вычислительное ядро&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов (логарифмическая шкала), ось ординат -- время (линейная шкала). Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Graph_fixed1.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других существующих реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20431</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20431"/>
		<updated>2016-12-08T21:10:04Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Схема реализации последовательного алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подробнее см. вычислительное ядро&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов (логарифмическая шкала), ось ординат -- время (линейная шкала). Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Graph_fixed1.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других существующих реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20429</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20429"/>
		<updated>2016-12-08T21:09:03Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов (логарифмическая шкала), ось ординат -- время (линейная шкала). Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Graph_fixed1.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других существующих реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20428</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20428"/>
		<updated>2016-12-08T21:08:37Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов (логарифмическая шкала), ось ординат -- время (линейная шкала). Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Graph_fixed1.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других существующих реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20427</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20427"/>
		<updated>2016-12-08T21:07:06Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов (логарифмическая шкала), ось ординат -- время (линейная шкала). Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Graph_fixed1.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других существующих реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20421</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20421"/>
		<updated>2016-12-08T20:55:55Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов (логарифмическая шкала), ось ординат -- время (линейная шкала). Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Graph_fixed1.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20419</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20419"/>
		<updated>2016-12-08T20:55:17Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов, ось ординат -- время. Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Graph_fixed1.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20416</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20416"/>
		<updated>2016-12-08T20:51:52Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов, ось ординат -- время. Получилось что-то похожее на &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Scaling_graph.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20414</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20414"/>
		<updated>2016-12-08T20:51:22Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов, ось ординат -- время. Получилось примерно &amp;lt;math&amp;gt;t = 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Scaling_graph.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20413</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20413"/>
		<updated>2016-12-08T20:51:05Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов, ось ординат -- время. Получилось примерно &amp;lt;math&amp;gt;t \textasciitilde 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Scaling_graph.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20411</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20411"/>
		<updated>2016-12-08T20:49:40Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов, ось ординат -- время. Получилось примерно &amp;lt;math&amp;gt;t \~ 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Scaling_graph.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20410</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20410"/>
		<updated>2016-12-08T20:49:32Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
Ось абсцисс -- число процессов, ось ординат -- время. Получилось примерно &amp;lt;math&amp;gt;t ~ 1/p&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Scaling_graph.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20406</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20406"/>
		<updated>2016-12-08T20:40:56Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
[[Image:Scaling_graph.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20405</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20405"/>
		<updated>2016-12-08T20:40:47Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
[[Image:Scaling_graph.png]]&lt;br /&gt;
[[Файл:scaling_graph.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20404</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20404"/>
		<updated>2016-12-08T20:38:22Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Масштабируемость алгоритма и его реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
[[File:Scaling_graph.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
* Алгоритм имеет линейную масштабируемость на любой системе, где сохранение данных не займет существенную часть времени. (вычислительные ядра не взаимодействуют)&lt;br /&gt;
* Алгоритм не учитывает возможность оптимизации с помощью векторизации.&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача очень специфическая, поэтому других реализаций не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20398</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20398"/>
		<updated>2016-12-08T20:09:32Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20397</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20397"/>
		<updated>2016-12-08T20:09:19Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20396</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20396"/>
		<updated>2016-12-08T20:09:04Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20395</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20395"/>
		<updated>2016-12-08T20:08:09Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной масштабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20394</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20394"/>
		<updated>2016-12-08T20:07:06Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(k^{2n - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной мастшабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20393</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20393"/>
		<updated>2016-12-08T20:06:01Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(2^{kn - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(2^{kn})&amp;lt;/math&amp;gt;), так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной мастшабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20392</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20392"/>
		<updated>2016-12-08T20:05:36Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(2^{kn - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(2^{kn})&amp;lt;/math&amp;gt;, так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной мастшабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20391</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20391"/>
		<updated>2016-12-08T20:05:24Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; - число параллельных процессов, тогда паралелльная сложность - амортизированное &amp;lt;math&amp;gt;O(2^{kn - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(2^{kn})&amp;lt;/math&amp;gt;, так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной мастшабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20390</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20390"/>
		<updated>2016-12-08T20:05:12Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; -- число параллельных процессов, тогда паралелльная сложность -- амортизированное &amp;lt;math&amp;gt;O(2^{kn - p})&amp;lt;/math&amp;gt;&lt;br /&gt;
(в сравнении с последовательной &amp;lt;math&amp;gt;O(2^{kn})&amp;lt;/math&amp;gt;, так как пересылка и сохранение результатов в конце занимают намного меньше времени чем сам перебор, который распараллеливается с линейной мастшабируемостью.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20389</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20389"/>
		<updated>2016-12-08T19:57:09Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Литература */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Так как структура алгоритма представляет собой дерево (с большим количеством потомков в каждом узле) -- алгоритм хорошо распараллеливается. Наблюдается линейная масштабируемость. Сбор и сохранение данных в конце почти не влиют на производительность.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диссертация: Дудкина А.А. &amp;quot;К &amp;lt;math&amp;gt;L_p&amp;lt;/math&amp;gt;-теории эллиптических краевых задач с разрывными коэффицентами&amp;quot;, Москва, 2009&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20388</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20388"/>
		<updated>2016-12-08T19:46:31Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Схема реализации последовательного алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1)) // 0 - номер процесса, 1 - количество процессов&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Так как структура алгоритма представляет собой дерево (с большим количеством потомков в каждом узле) -- алгоритм хорошо распараллеливается. Наблюдается линейная масштабируемость. Сбор и сохранение данных в конце почти не влиют на производительность.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20387</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20387"/>
		<updated>2016-12-08T19:45:03Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Входные и выходные данные алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Так как структура алгоритма представляет собой дерево (с большим количеством потомков в каждом узле) -- алгоритм хорошо распараллеливается. Наблюдается линейная масштабируемость. Сбор и сохранение данных в конце почти не влиют на производительность.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; времени исполнения является лишь идентификатор процесса и количество процессов.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20385</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20385"/>
		<updated>2016-12-08T19:43:47Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Входные и выходные данные алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Так как структура алгоритма представляет собой дерево (с большим количеством потомков в каждом узле) -- алгоритм хорошо распараллеливается. Наблюдается линейная масштабируемость. Сбор и сохранение данных в конце почти не влиют на производительность.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия. Они определены в коде как константы (задаются во время компиляции)&lt;br /&gt;
&lt;br /&gt;
В данной реализации &amp;quot;входными данными&amp;quot; является лишь идентификатор процесса и количество процессов (требуется для&lt;br /&gt;
В качестве выходных данных было взято число всех найденных наборов &amp;lt;math&amp;gt;\{ \varkappa\}, \{ \alpha\}&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20383</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20383"/>
		<updated>2016-12-08T19:36:23Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Схема реализации последовательного алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Приведенная выше паралелльная реализация является эффективной последовательной при выборе единственным вычислительным ядро всего диапазона перебора, то есть &lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
CheckRBoundaryCond(ParallelParams(0, 1))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Так как структура алгоритма представляет собой дерево (с большим количеством потомков в каждом узле) -- алгоритм хорошо распараллеливается. Наблюдается линейная масштабируемость. Сбор и сохранение данных в конце почти не влиют на производительность.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия.&lt;br /&gt;
Выходные данные: наборы &amp;lt;math&amp;gt;\varkappa, \alpha&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20382</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20382"/>
		<updated>2016-12-08T19:31:48Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
В первой подобласти: зафиксируем &amp;lt;math&amp;gt;\varkappa=1&amp;lt;/math&amp;gt;&lt;br /&gt;
Далее перебор значений остальных параметров.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноcть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Так как структура алгоритма представляет собой дерево (с большим количеством потомков в каждом узле) -- алгоритм хорошо распараллеливается. Наблюдается линейная масштабируемость. Сбор и сохранение данных в конце почти не влиют на производительность.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия.&lt;br /&gt;
Выходные данные: наборы &amp;lt;math&amp;gt;\varkappa, \alpha&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20380</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20380"/>
		<updated>2016-12-08T19:27:38Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Вычислительное ядро алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Area&lt;br /&gt;
{&lt;br /&gt;
	double angle;&lt;br /&gt;
	double kappa;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template&amp;lt;typename T&amp;gt;&lt;br /&gt;
struct Range&lt;br /&gt;
{&lt;br /&gt;
	T min;&lt;br /&gt;
	T max;&lt;br /&gt;
	T step;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
struct Matrix&lt;br /&gt;
{&lt;br /&gt;
	double elems[2][2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const Matrix IdentityMatrix = { { { 1, 0 }, { 0, 1 } } };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inline void RotateScale(Matrix&amp;amp; out, const Matrix&amp;amp; in, double phi, double scale = 1.0)&lt;br /&gt;
{&lt;br /&gt;
	double c = cos(phi);&lt;br /&gt;
	double s = sin(phi);&lt;br /&gt;
	out.elems[0][0] = in.elems[0][0] * c + in.elems[1][0] * s;&lt;br /&gt;
	out.elems[0][1] = in.elems[0][1] * c + in.elems[1][1] * s;&lt;br /&gt;
	out.elems[1][0] = scale * (- in.elems[0][0] * s + in.elems[1][0] * c);&lt;br /&gt;
	out.elems[1][1] = scale * (- in.elems[0][1] * s + in.elems[1][1] * c);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
В первой подобласти: зафиксируем &amp;lt;math&amp;gt;\varkappa=1&amp;lt;/math&amp;gt;&lt;br /&gt;
Далее перебор значений остальных параметров.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Так как структура алгоритма представляет собой дерево (с большим количеством потомков в каждом узле) -- алгоритм хорошо распараллеливается. Наблюдается линейная масштабируемость. Сбор и сохранение данных в конце почти не влиют на производительность.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия.&lt;br /&gt;
Выходные данные: наборы &amp;lt;math&amp;gt;\varkappa, \alpha&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20379</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20379"/>
		<updated>2016-12-08T19:24:46Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Вычислительное ядро алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; (или весь диапазон, в случае последовательной реализации)&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
=== Выбор диапазонов перебора для параметров каждой области ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&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;\varkappa, \alpha&amp;lt;/math&amp;gt;) и заданном левом граничном условии.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
В первой подобласти: зафиксируем &amp;lt;math&amp;gt;\varkappa=1&amp;lt;/math&amp;gt;&lt;br /&gt;
Далее перебор значений остальных параметров.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Так как структура алгоритма представляет собой дерево (с большим количеством потомков в каждом узле) -- алгоритм хорошо распараллеливается. Наблюдается линейная масштабируемость. Сбор и сохранение данных в конце почти не влиют на производительность.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия.&lt;br /&gt;
Выходные данные: наборы &amp;lt;math&amp;gt;\varkappa, \alpha&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20378</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=20378"/>
		<updated>2016-12-08T19:19:24Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Вычислительное ядро алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt;&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
Выбора диапазона перебора для параметров каждой области&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ParallelParams(int mpi_rank, int mpi_size)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges(AREAS_CNT);&lt;br /&gt;
	constexpr double angle_step = (ANGLE_TO - ANGLE_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	constexpr double kappa_step = (KAPPA_TO - KAPPA_FROM) / (double) RANGE_STEPS_CNT;&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r0 = { { ANGLE_FROM + mpi_rank * angle_step, 1 }, { ANGLE_FROM + (mpi_rank + 1) * angle_step, 1 },{ angle_step, kappa_step } };&lt;br /&gt;
	Range&amp;lt;Area&amp;gt; r1 = { { ANGLE_FROM, KAPPA_FROM },{ ANGLE_TO, KAPPA_TO },{ angle_step, kappa_step } };&lt;br /&gt;
	ranges[0] = r0;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		ranges[i] = r1;&lt;br /&gt;
	return ranges;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
int vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; CheckRBoundaryCond(vector&amp;lt;Range&amp;lt;Area&amp;gt;&amp;gt; ranges)&lt;br /&gt;
{&lt;br /&gt;
	vector&amp;lt;vector&amp;lt;Area&amp;gt;&amp;gt; results;&lt;br /&gt;
	vector&amp;lt;Area&amp;gt; areas(AREAS_CNT);&lt;br /&gt;
	vector&amp;lt;Matrix&amp;gt; T(AREAS_CNT);&lt;br /&gt;
	&lt;br /&gt;
	for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		areas[i] = ranges[i].min;&lt;br /&gt;
&lt;br /&gt;
	T[0] = IdentityMatrix;&lt;br /&gt;
	for (size_t i = 1; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
		RotateScale(T[i], T[i - 1], areas[i - 1].angle, areas[i - 1].kappa / areas[i].kappa);&lt;br /&gt;
&lt;br /&gt;
	for (int lvl = AREAS_CNT; lvl &amp;gt; 0; ) {&lt;br /&gt;
		// check boundary condition if at top lvl area&lt;br /&gt;
		if (lvl == AREAS_CNT) {&lt;br /&gt;
			&lt;br /&gt;
			double angle = 0.0;&lt;br /&gt;
			for (size_t i = 0; i &amp;lt; AREAS_CNT; ++i)&lt;br /&gt;
				angle += areas[i].angle;&lt;br /&gt;
			double rbcond = T.back().elems[0][1] * cos(angle) + T.back().elems[1][1] * sin(angle);&lt;br /&gt;
			if (abs(rbcond) &amp;lt; EPS) {&lt;br /&gt;
				results.push_back(areas);&lt;br /&gt;
			}&lt;br /&gt;
			lvl--;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// try increase kappa at lvl-th area and go up&lt;br /&gt;
		double next_kappa = areas[lvl].kappa + ranges[lvl].step.kappa;&lt;br /&gt;
		if (next_kappa &amp;lt;= ranges[lvl].max.kappa + 0.5 * ranges[lvl].step.kappa) {&lt;br /&gt;
			areas[lvl].kappa = next_kappa;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		} &lt;br /&gt;
		&lt;br /&gt;
		// try increase angle at lvl-th area and go up&lt;br /&gt;
		double next_angle = areas[lvl].angle + ranges[lvl].step.angle;&lt;br /&gt;
		if (next_angle &amp;lt;= ranges[lvl].max.angle + 0.5 * ranges[lvl].step.angle) {&lt;br /&gt;
			areas[lvl].angle = next_angle;&lt;br /&gt;
			RotateScale(T[lvl], T[lvl - 1], areas[lvl - 1].angle, areas[lvl - 1].kappa / areas[lvl].kappa);&lt;br /&gt;
			lvl++;&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// jump to previous area&lt;br /&gt;
		areas[lvl] = ranges[lvl].min;&lt;br /&gt;
		lvl--;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return results;		&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
В первой подобласти: зафиксируем &amp;lt;math&amp;gt;\varkappa=1&amp;lt;/math&amp;gt;&lt;br /&gt;
Далее перебор значений остальных параметров.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Так как структура алгоритма представляет собой дерево (с большим количеством потомков в каждом узле) -- алгоритм хорошо распараллеливается. Наблюдается линейная масштабируемость. Сбор и сохранение данных в конце почти не влиют на производительность.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия.&lt;br /&gt;
Выходные данные: наборы &amp;lt;math&amp;gt;\varkappa, \alpha&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=19823</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=19823"/>
		<updated>2016-12-01T11:44:02Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt;&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
В первой подобласти: зафиксируем &amp;lt;math&amp;gt;\varkappa=1&amp;lt;/math&amp;gt;&lt;br /&gt;
Далее перебор значений остальных параметров.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&amp;quot;Паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Так как структура алгоритма представляет собой дерево (с большим количеством потомков в каждом узле) -- алгоритм хорошо распараллеливается. Наблюдается линейная масштабируемость. Сбор и сохранение данных в конце почти не влиют на производительность.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия.&lt;br /&gt;
Выходные данные: наборы &amp;lt;math&amp;gt;\varkappa, \alpha&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=19822</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=19822"/>
		<updated>2016-12-01T11:39:29Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt;&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
В первой подобласти: зафиксируем &amp;lt;math&amp;gt;\varkappa=1&amp;lt;/math&amp;gt;&lt;br /&gt;
Далее перебор значений остальных параметров.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Вычислительное ядро -- &amp;quot;паралелельные&amp;quot; независимые ветви.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Так как структура алгоритма представляет собой дерево (с большим количеством потомков в каждом узле) -- алгоритм хорошо распараллеливается. Наблюдается линейная масштабируемость. Сбор и сохранение данных в конце почти не влиют на производительность.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия.&lt;br /&gt;
Выходные данные: наборы &amp;lt;math&amp;gt;\varkappa, \alpha&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=19807</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=19807"/>
		<updated>2016-12-01T04:18:57Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt;&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
В первой подобласти: зафиксируем &amp;lt;math&amp;gt;\varkappa=1&amp;lt;/math&amp;gt;&lt;br /&gt;
Далее перебор значений остальных параметров.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&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;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия.&lt;br /&gt;
Выходные данные: наборы &amp;lt;math&amp;gt;\varkappa, \alpha&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=19806</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=19806"/>
		<updated>2016-12-01T04:16:21Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt;&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
В первой подобласти: зафиксируем &amp;lt;math&amp;gt;\varkappa=1&amp;lt;/math&amp;gt;&lt;br /&gt;
Далее перебор значений остальных параметров.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
* n - число областей непрерывности &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt;&lt;br /&gt;
* k - число пробных значений в диапазоне перебора&lt;br /&gt;
&lt;br /&gt;
сложноть последовательной реализации -- &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Это очень важный раздел описания. Именно здесь можно показать (увидеть) как устроена параллельная структура алгоритма, для чего приводится описание и изображение его информационного графа ([[глоссарий#Граф алгоритма|&#039;&#039;графа алгоритма&#039;&#039;]] &amp;lt;ref name=&amp;quot;VVVVVV&amp;quot;&amp;gt;Воеводин В.В., Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с. &amp;lt;/ref&amp;gt;). Для рисунков с изображением графа будут составлены рекомендации по их формированию, чтобы все информационные графы, внесенные в энциклопедию, можно было бы воспринимать и интерпретировать одинаково. Дополнительно можно привести полное параметрическое  описание графа в терминах покрывающих функций &amp;lt;ref name=&amp;quot;VVVVVV&amp;quot; /&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Интересных вариантов для отражения информационной структуры алгоритмов много. Для каких-то алгоритмов нужно показать максимально подробную структуру, а иногда важнее макроструктура. Много информации несут разного рода проекции информационного графа, выделяя его регулярные составляющие и одновременно скрывая несущественные детали. Иногда оказывается полезным показать последовательность в изменении графа при изменении значений внешних переменных  (например, размеров матриц): мы часто ожидаем &amp;quot;подобное&amp;quot; изменение информационного графа, но это изменение не всегда очевидно на практике.  &lt;br /&gt;
&lt;br /&gt;
В целом, задача изображения графа алгоритма весьма нетривиальна. Начнем с того, что это потенциально бесконечный граф, число вершин и дуг которого определяется значениями внешних переменных, а они могут быть весьма и весьма велики. В такой ситуации, как правило, спасают упомянутые выше соображения подобия, делающие графы для разных значений внешних переменных &amp;quot;похожими&amp;quot;: почти всегда достаточно привести лишь один граф небольшого размера, добавив, что графы для остальных значений будут устроены &amp;quot;точно также&amp;quot;. На практике, увы, не всегда все так просто, и здесь нужно быть аккуратным.&lt;br /&gt;
&lt;br /&gt;
Далее, граф алгоритма - это потенциально многомерный объект. Наиболее естественная система координат для размещения вершин и дуг информационного графа опирается на структуру вложенности циклов в реализации алгоритма. Если глубина вложенности циклов не превышает трех, то и граф размещается в привычном трехмерном пространстве, однако для более сложных циклических конструкций с глубиной вложенности 4 и больше необходимы специальные методы представления и изображения графов. &lt;br /&gt;
&lt;br /&gt;
В данном разделе AlgoWiki могут использоваться многие интересные возможности, которые еще подлежат обсуждению: возможность повернуть граф при его отображении на экране компьютера для выбора наиболее удобного угла обзора, разметка вершин по типу соответствующим им операций, отражение [[глоссарий#Ярусно-параллельная форма графа алгоритма|&#039;&#039;ярусно-параллельной формы графа&#039;&#039;]] и другие. Но в любом случае нужно не забывать главную задачу данного раздела - показать информационную структуру алгоритма так, чтобы стали понятны все его ключевые особенности, особенности параллельной структуры, особенности множеств дуг, участки регулярности и, напротив, участки с недерминированной структурой, зависящей от входных данных. &lt;br /&gt;
&lt;br /&gt;
На рис.1 показана информационная структура алгоритма умножения матриц, на рис.2 - информационная структура одного из вариантов алгоритма решения систем линейных алгебраических уравнений с блочно-двухдиагональной матрицей.&lt;br /&gt;
&lt;br /&gt;
[[file:Fig1.svg|thumb|center|300px|Рис.1. Информационная структура алгоритма умножения матриц]]&lt;br /&gt;
[[file:Fig2.svg|thumb|center|300px|Рис.2. Информационная структура одного из вариантов алгоритма решения систем линейных алгебраических уравнений с блочно-двухдиагональной матрицей]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Так как структура алгоритма представляет собой дерево (с большим количеством потомков в каждом узле) -- алгоритм хорошо распараллеливается. Наблюдается линейная масштабируемость. Сбор и сохранение данных в конце почти не влиют на производительность.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия.&lt;br /&gt;
Выходные данные: наборы &amp;lt;math&amp;gt;\varkappa, \alpha&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>Abogovski</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=19805</id>
		<title>Участник:Abogovski/Вспомогательная задача при решении задачи Штурма-Лиувилля с условиями сопряжения</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:Abogovski/%D0%92%D1%81%D0%BF%D0%BE%D0%BC%D0%BE%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BF%D1%80%D0%B8_%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B8_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_%D0%A8%D1%82%D1%83%D1%80%D0%BC%D0%B0-%D0%9B%D0%B8%D1%83%D0%B2%D0%B8%D0%BB%D0%BB%D1%8F_%D1%81_%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%D0%BC%D0%B8_%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&amp;diff=19805"/>
		<updated>2016-12-01T04:14:53Z</updated>

		<summary type="html">&lt;p&gt;Abogovski: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Боговский Антон, 409&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
К этой вспомогательной задаче (см. Математическое описание алгоритма) сводится решение задачи Штурма-Лиувилля с условия сопряжения, возникающей при разделении переменных в краевой задаче для эллиптического оператора с кусочно-постоянными коэффицентами. Ищутся области (углы) для которых, существуют собственное число равное единице.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Искомые области находятся перебором параметров области (углы, на которых коэффицент постоянен, и значения коэффицента на этих подобластях.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим задачу Дирихле на ограниченной области для эллиптического уравнения в дивергентной форме с кусочно-постоянными коэффицентами. &lt;br /&gt;
&amp;lt;math&amp;gt;div(\varkappa grad u) = div F &amp;lt;/math&amp;gt;,&lt;br /&gt;
где коэффицент &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; -- кусочно-постоянный. При решении задачи методом разделения переменных в полярных возникает задача Штурма-Лиувилля относительного полярного угла &amp;lt;math&amp;gt;\Phi&#039;(\varphi) = \lambda \Phi(\varphi)&amp;lt;/math&amp;gt; c условиями сопряжения на разрывах коэффицента: непрерывность &amp;lt;math&amp;gt;\Phi(\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varkappa(\varphi)\Phi&#039;(\varphi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве области для модельной задачи возьмем круг (или сектор круга) с радиальными линиями разрыва &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt;. Тогда на каждом отрезке непрерывности &amp;lt;math&amp;gt;\varkappa(\varphi)&amp;lt;/math&amp;gt; решение -- линейная комбинация &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;. Если для области такого вида (набора значений &amp;lt;math&amp;gt;\varkappa&amp;lt;/math&amp;gt; и величин углов) существуют набор постоянных при &amp;lt;math&amp;gt;cos(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;sin(\sqrt{-\lambda}\varphi)&amp;lt;/math&amp;gt;, такой что граничные условия и условия сопряжения выполнены, то существует собственная функция.&lt;br /&gt;
&lt;br /&gt;
Ищем такие области. Заметим, что решения задачи штурма Лиувилля зависят от &amp;lt;math&amp;gt;\alpha = \sqrt{-\lambda}\varphi&amp;lt;/math&amp;gt; -- перейдем к такой переменной. Зададим граничное условие на одной стороне сектора, условия сопряжения на линиях разрыва и проверим (переберем) различные значения &amp;lt;math&amp;gt;\alpha, \varkappa&amp;lt;/math&amp;gt; на выполнение граничного условия&lt;br /&gt;
на правой стороне.&lt;br /&gt;
&lt;br /&gt;
(Условия сопряжения дают связь между коэффицентами при &amp;lt;math&amp;gt;cos,sin&amp;lt;/math&amp;gt; через композицию матриц растяжения и поворота, зависящих от &amp;lt;math&amp;gt;\alpha, \varkappa&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;\varkappa=1&amp;lt;/math&amp;gt; и поддиапазон перебора значений &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt;&lt;br /&gt;
* Остальные значения перебираются в заданном диапазоне -- обход дерева всех наборов значений параметра (при заданном шаге по значениям).&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
* Для каждого процесса из его номера вычисляется поддерево наборов значений для обхода.&lt;br /&gt;
* Каждым из процессов выполняется обход своего поддерева&lt;br /&gt;
* 0-ой процесс, закончив обход своего поддерева, собирает все результаты и сохраняет их в файл с уникальным именем&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
В первой подобласти: зафиксируем &amp;lt;math&amp;gt;\varkappa=1&amp;lt;/math&amp;gt;&lt;br /&gt;
Далее перебор значений остальных параметров.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
n = ЧИСЛО_ЛИНИЙ_РАЗРЫВА&lt;br /&gt;
k = ЧИСЛО_ЗНАЧЕНИЙ_В_ДИАПОЗОНЕ_ПЕРЕБОРА&lt;br /&gt;
&lt;br /&gt;
СЛОЖНОСТЬ = &amp;lt;math&amp;gt;O(k^{2n})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Это очень важный раздел описания. Именно здесь можно показать (увидеть) как устроена параллельная структура алгоритма, для чего приводится описание и изображение его информационного графа ([[глоссарий#Граф алгоритма|&#039;&#039;графа алгоритма&#039;&#039;]] &amp;lt;ref name=&amp;quot;VVVVVV&amp;quot;&amp;gt;Воеводин В.В., Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с. &amp;lt;/ref&amp;gt;). Для рисунков с изображением графа будут составлены рекомендации по их формированию, чтобы все информационные графы, внесенные в энциклопедию, можно было бы воспринимать и интерпретировать одинаково. Дополнительно можно привести полное параметрическое  описание графа в терминах покрывающих функций &amp;lt;ref name=&amp;quot;VVVVVV&amp;quot; /&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Интересных вариантов для отражения информационной структуры алгоритмов много. Для каких-то алгоритмов нужно показать максимально подробную структуру, а иногда важнее макроструктура. Много информации несут разного рода проекции информационного графа, выделяя его регулярные составляющие и одновременно скрывая несущественные детали. Иногда оказывается полезным показать последовательность в изменении графа при изменении значений внешних переменных  (например, размеров матриц): мы часто ожидаем &amp;quot;подобное&amp;quot; изменение информационного графа, но это изменение не всегда очевидно на практике.  &lt;br /&gt;
&lt;br /&gt;
В целом, задача изображения графа алгоритма весьма нетривиальна. Начнем с того, что это потенциально бесконечный граф, число вершин и дуг которого определяется значениями внешних переменных, а они могут быть весьма и весьма велики. В такой ситуации, как правило, спасают упомянутые выше соображения подобия, делающие графы для разных значений внешних переменных &amp;quot;похожими&amp;quot;: почти всегда достаточно привести лишь один граф небольшого размера, добавив, что графы для остальных значений будут устроены &amp;quot;точно также&amp;quot;. На практике, увы, не всегда все так просто, и здесь нужно быть аккуратным.&lt;br /&gt;
&lt;br /&gt;
Далее, граф алгоритма - это потенциально многомерный объект. Наиболее естественная система координат для размещения вершин и дуг информационного графа опирается на структуру вложенности циклов в реализации алгоритма. Если глубина вложенности циклов не превышает трех, то и граф размещается в привычном трехмерном пространстве, однако для более сложных циклических конструкций с глубиной вложенности 4 и больше необходимы специальные методы представления и изображения графов. &lt;br /&gt;
&lt;br /&gt;
В данном разделе AlgoWiki могут использоваться многие интересные возможности, которые еще подлежат обсуждению: возможность повернуть граф при его отображении на экране компьютера для выбора наиболее удобного угла обзора, разметка вершин по типу соответствующим им операций, отражение [[глоссарий#Ярусно-параллельная форма графа алгоритма|&#039;&#039;ярусно-параллельной формы графа&#039;&#039;]] и другие. Но в любом случае нужно не забывать главную задачу данного раздела - показать информационную структуру алгоритма так, чтобы стали понятны все его ключевые особенности, особенности параллельной структуры, особенности множеств дуг, участки регулярности и, напротив, участки с недерминированной структурой, зависящей от входных данных. &lt;br /&gt;
&lt;br /&gt;
На рис.1 показана информационная структура алгоритма умножения матриц, на рис.2 - информационная структура одного из вариантов алгоритма решения систем линейных алгебраических уравнений с блочно-двухдиагональной матрицей.&lt;br /&gt;
&lt;br /&gt;
[[file:Fig1.svg|thumb|center|300px|Рис.1. Информационная структура алгоритма умножения матриц]]&lt;br /&gt;
[[file:Fig2.svg|thumb|center|300px|Рис.2. Информационная структура одного из вариантов алгоритма решения систем линейных алгебраических уравнений с блочно-двухдиагональной матрицей]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Так как структура алгоритма представляет собой дерево (с большим количеством потомков в каждом узле) -- алгоритм хорошо распараллеливается. Наблюдается линейная масштабируемость. Сбор и сохранение данных в конце почти не влиют на производительность.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Параметрами задачи являются: число областей непрерывности, диапазон и точность перебора &amp;lt;math&amp;gt;\varkappa, \alpha&amp;lt;/math&amp;gt;, требуемая точность выполнения граничного условия.&lt;br /&gt;
Выходные данные: наборы &amp;lt;math&amp;gt;\varkappa, \alpha&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;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>Abogovski</name></author>
	</entry>
</feed>