Алгоритм трехдиагональной матрицы
В числовой линейной алгебре алгоритм трехдиагональной матрицы , также известный как алгоритм Томаса (названный в честь Ллевеллина Томаса ), представляет собой упрощенную форму исключения Гаусса , которую можно использовать для решения трехдиагональных систем уравнений . Трехдиагональную систему для n неизвестных можно записать как
где и .
Для таких систем решение можно получить в операции вместо требуется методом исключения Гаусса . Первая проверка устраняет 's, а затем (сокращенная) обратная замена дает решение. Примеры таких матриц обычно возникают в результате дискретизации одномерного уравнения Пуассона и интерполяции естественным кубическим сплайном .
Алгоритм Томаса нестабилен в целом, но является таковым в некоторых особых случаях, например, когда матрица является диагонально доминирующей (либо по строкам, либо по столбцам) или симметричной положительно определенной ; [1] [2] более точную характеристику устойчивости алгоритма Томаса см. в теореме Хайэма 9.12. [3] Если в общем случае требуется стабильность, метод исключения Гаусса с частичным поворотом (GEPP). вместо этого рекомендуется использовать [2]
Метод
[ редактировать ]Прямой анализ состоит из вычисления новых коэффициентов следующим образом, обозначая новые коэффициенты штрихами:
и
Тогда решение получается обратной заменой:
Приведенный выше метод не изменяет исходные векторы коэффициентов, но также должен отслеживать новые коэффициенты. Если векторы коэффициентов можно изменить, то алгоритм с меньшими затратами на бухгалтерский учет будет выглядеть следующим образом:
Для делать
с последующей обратной заменой
Реализация в виде функции C , которая использует рабочее пространство, чтобы избежать изменения входных данных для переменного тока, что позволяет их повторно использовать:
void thomas(const int X, double x[restrict X],
const double a[restrict X], const double b[restrict X],
const double c[restrict X], double scratch[restrict X]) {
/*
solves Ax = d, where A is a tridiagonal matrix consisting of vectors a, b, c
X = number of equations
x[] = initially contains the input v, and returns x. indexed from [0, ..., X - 1]
a[] = subdiagonal, indexed from [1, ..., X - 1]
b[] = main diagonal, indexed from [0, ..., X - 1]
c[] = superdiagonal, indexed from [0, ..., X - 2]
scratch[] = scratch space of length X, provided by caller, allowing a, b, c to be const
not performed in this example: manual expensive common subexpression elimination
*/
scratch[0] = c[0] / b[0];
x[0] = x[0] / b[0];
/* loop from 1 to X - 1 inclusive */
for (int ix = 1; ix < X; ix++) {
if (ix < X-1){
scratch[ix] = c[ix] / (b[ix] - a[ix] * scratch[ix - 1]);
}
x[ix] = (x[ix] - a[ix] * x[ix - 1]) / (b[ix] - a[ix] * scratch[ix - 1]);
}
/* loop from X - 2 to 0 inclusive */
for (int ix = X - 2; ix >= 0; ix--)
x[ix] -= scratch[ix] * x[ix + 1];
}
Вывод
[ редактировать ]Вывод алгоритма трехдиагональной матрицы является частным случаем исключения Гаусса .
Предположим, что неизвестные , и что уравнения, которые необходимо решить, следующие:
Рассмотрите возможность изменения второго ( ) уравнение с первым уравнением следующим образом:
что даст:
Обратите внимание, что было исключено из второго уравнения. Использование аналогичной тактики с модифицированным вторым уравнением третьего уравнения дает:
На этот раз был устранен. Если эту процедуру повторять до тех пор, пока ряд; (измененный) уравнение будет включать только одно неизвестное, . Это можно решить, а затем использовать для решения уравнение и так далее, пока все неизвестные не будут решены.
Очевидно, что коэффициенты модифицированных уравнений становятся все более и более сложными, если это указано явно. Изучив процедуру, измененные коэффициенты (обозначенные тильдами) вместо этого могут быть определены рекурсивно:
Чтобы еще больше ускорить процесс решения, можно разделить (если нет деления на нулевой риск), новые модифицированные коэффициенты, каждый из которых отмечен штрихом, будут:
Это дает следующую систему с теми же неизвестными и коэффициентами, определенными в терминах исходных выше:
Последнее уравнение содержит только одно неизвестное. Решение его, в свою очередь, сводит следующее последнее уравнение к одному неизвестному, так что эту обратную замену можно использовать для нахождения всех неизвестных:
Варианты
[ редактировать ]В некоторых ситуациях, особенно в тех, которые связаны с периодическими граничными условиями , может потребоваться решение слегка возмущенной формы трехдиагональной системы:
В этом случае мы можем использовать формулу Шермана-Моррисона , чтобы избежать дополнительных операций исключения Гаусса и при этом использовать алгоритм Томаса. Метод требует решения модифицированной нециклической версии системы как для входных данных, так и для разреженного корректирующего вектора, а затем объединения решений. Это можно сделать эффективно, если оба решения вычисляются одновременно, поскольку прямая часть алгоритма чистой трехдиагональной матрицы может использоваться совместно.
Если мы укажем:
Тогда решаемая система:
В этом случае коэффициенты и вообще говоря, ненулевые, поэтому их наличие не позволяет напрямую применить алгоритм Томаса. Поэтому мы можем рассмотреть и следующим образом: Где — параметр, который необходимо выбрать. Матрица можно реконструировать как . Тогда решение получается следующим образом: [4] сначала решаем две трехдиагональные системы уравнений, применяя алгоритм Томаса:
Затем восстанавливаем решение используя формулу Шермана-Моррисона :
Реализация в виде функции C , которая использует рабочее пространство, чтобы избежать изменения входных данных для переменного тока, что позволяет их повторно использовать:
void cyclic_thomas(const int X, double x[restrict X], const double a[restrict X], const double b[restrict X], const double c[restrict X], double cmod[restrict X], double u[restrict X]) {
/*
solves Ax = v, where A is a cyclic tridiagonal matrix consisting of vectors a, b, c
X = number of equations
x[] = initially contains the input v, and returns x. indexed from [0, ..., X - 1]
a[] = subdiagonal, regularly indexed from [1, ..., X - 1], a[0] is lower left corner
b[] = main diagonal, indexed from [0, ..., X - 1]
c[] = superdiagonal, regularly indexed from [0, ..., X - 2], c[X - 1] is upper right
cmod[], u[] = scratch vectors each of length X
*/
/* lower left and upper right corners of the cyclic tridiagonal system respectively */
const double alpha = a[0];
const double beta = c[X - 1];
/* arbitrary, but chosen such that division by zero is avoided */
const double gamma = -b[0];
cmod[0] = alpha / (b[0] - gamma);
u[0] = gamma / (b[0] - gamma);
x[0] /= (b[0] - gamma);
/* loop from 1 to X - 2 inclusive */
for (int ix = 1; ix + 1 < X; ix++) {
const double m = 1.0 / (b[ix] - a[ix] * cmod[ix - 1]);
cmod[ix] = c[ix] * m;
u[ix] = (0.0f - a[ix] * u[ix - 1]) * m;
x[ix] = (x[ix] - a[ix] * x[ix - 1]) * m;
}
/* handle X - 1 */
const double m = 1.0 / (b[X - 1] - alpha * beta / gamma - beta * cmod[X - 2]);
u[X - 1] = (alpha - a[X - 1] * u[X - 2]) * m;
x[X - 1] = (x[X - 1] - a[X - 1] * x[X - 2]) * m;
/* loop from X - 2 to 0 inclusive */
for (int ix = X - 2; ix >= 0; ix--) {
u[ix] -= cmod[ix] * u[ix + 1];
x[ix] -= cmod[ix] * x[ix + 1];
}
const double fact = (x[0] + x[X - 1] * beta / gamma) / (1.0 + u[0] + u[X - 1] * beta / gamma);
/* loop from 0 to X - 1 inclusive */
for (int ix = 0; ix < X; ix++)
x[ix] -= fact * u[ix];
}
Существует и другой способ решения рассмотренной выше слегка возмущенной формы трехдиагональной системы. [5] Рассмотрим две вспомогательные линейные системы размерности :
Для удобства дополнительно определим и . Теперь мы можем найти решения и применение алгоритма Томаса к двум вспомогательным трехдиагональным системам.
Решение тогда можно представить в виде:
Действительно, умножив каждое уравнение второй вспомогательной системы на , сложив с соответствующим уравнением первой вспомогательной системы и воспользовавшись представлением , мы сразу видим, что число уравнений через исходной системы удовлетворены; осталось только удовлетворить номер уравнения . Для этого рассмотрим формулу для и и заменить и в первое уравнение исходной системы. Это дает одно скалярное уравнение для :
Таким образом, мы находим:
Реализация в виде функции C , которая использует рабочее пространство, чтобы избежать изменения входных данных для переменного тока, что позволяет их повторно использовать:
void cyclic_thomas(const int X, double x[restrict X], const double a[restrict X], const double b[restrict X], const double c[restrict X], double cmod[restrict X], double v[restrict X]) {
/* first solve a system of length X - 1 for two right hand sides, ignoring ix == 0 */
cmod[1] = c[1] / b[1];
v[1] = -a[1] / b[1];
x[1] = x[1] / b[1];
/* loop from 2 to X - 1 inclusive */
for (int ix = 2; ix < X - 1; ix++) {
const double m = 1.0 / (b[ix] - a[ix] * cmod[ix - 1]);
cmod[ix] = c[ix] * m;
v[ix] = (0.0f - a[ix] * v[ix - 1]) * m;
x[ix] = (x[ix] - a[ix] * x[ix - 1]) * m;
}
/* handle X - 1 */
const double m = 1.0 / (b[X - 1] - a[X - 1] * cmod[X - 2]);
cmod[X - 1] = c[X - 1] * m;
v[X - 1] = (-c[0] - a[X - 1] * v[X - 2]) * m;
x[X - 1] = (x[X - 1] - a[X - 1] * x[X - 2]) * m;
/* loop from X - 2 to 1 inclusive */
for (int ix = X - 2; ix >= 1; ix--) {
v[ix] -= cmod[ix] * v[ix + 1];
x[ix] -= cmod[ix] * x[ix + 1];
}
x[0] = (x[0] - a[0] * x[X - 1] - c[0] * x[1]) / (b[0] + a[0] * v[X - 1] + c[0] * v[1]);
/* loop from 1 to X - 1 inclusive */
for (int ix = 1; ix < X; ix++)
x[ix] += x[0] * v[ix];
}
В обоих случаях решаемые вспомогательные системы действительно трехдиагональны, поэтому общая вычислительная сложность решения системы остается линейным относительно размерности системы , то есть арифметические операции.
В других ситуациях система уравнений может быть блочной трехдиагональной (см. блочную матрицу ) с меньшими подматрицами, расположенными как отдельные элементы в вышеуказанной матричной системе (например, двумерная задача Пуассона ). Для этих ситуаций были разработаны упрощенные формы исключения Гаусса. [6]
учебнике «Числовая математика» В Альфио Квартерони , Сакко и Салери приведена модифицированная версия алгоритма, которая позволяет избежать некоторых делений (вместо этого используется умножение), что полезно для некоторых компьютерных архитектур.
Параллельные трехдиагональные решатели были опубликованы для многих векторных и параллельных архитектур, включая графические процессоры. [7] [8]
Подробное описание параллельных трехдиагональных и блочных трехдиагональных решателей см. [9]
Ссылки
[ редактировать ]- ^ Прадип Нийоги (2006). Введение в вычислительную гидродинамику . Пирсон Образовательная Индия. п. 76. ИСБН 978-81-7758-764-7 .
- ^ Jump up to: а б Бисва Натх Датта (2010). Численная линейная алгебра и приложения, второе издание . СИАМ. п. 162. ИСБН 978-0-89871-765-5 .
- ^ Николас Дж. Хайэм (2002). Точность и устойчивость численных алгоритмов: второе издание . СИАМ. п. 175. ИСБН 978-0-89871-802-7 .
- ^ Батиста, Милан; Ибрагим Каравиа, Абдель Рахман А. (2009). «Использование формулы Шермана – Моррисона – Вудбери для решения циклических блочных трехдиагональных и циклических блочных пятидиагональных линейных систем уравнений» . Прикладная математика и вычислительная техника . 210 (2): 558–563. дои : 10.1016/j.amc.2009.01.003 . ISSN 0096-3003 .
- ^ Рябенький, Виктор С.; Цынков, Семен В. (2006-11-02), «Введение» , Теоретическое введение в численный анализ , Чепмен и Холл/CRC, стр. 1–19, номер домена : 10.1201/9781420011166-1 , ISBN. 978-0-429-14339-7 , получено 25 мая 2022 г.
- ^ Квартерони, Альфио ; Сакко, Риккардо; Салери, Фаусто (2007). «Раздел 3.8». Численная математика . Спрингер, Нью-Йорк. ISBN 978-3-540-34658-6 .
- ^ Чанг, Л.-В.; Хву, В,-М. (2014). «Руководство по реализации трехдиагональных решателей на графических процессорах». В В. Кидратенко (ред.). Численные вычисления с помощью графических процессоров . Спрингер. ISBN 978-3-319-06548-9 .
{{cite conference}}
: CS1 maint: несколько имен: список авторов ( ссылка ) - ^ Венетис, IE; Курис, А.; Собчик А.; Галлопулос, Э.; Самех, А. (2015). «Прямой трехдиагональный решатель, основанный на вращении Гивенса для архитектур графических процессоров». Параллельные вычисления . 49 : 101–116. дои : 10.1016/j.parco.2015.03.008 .
- ^ Галлопулос, Э.; Филипп, Б.; Самех, АХ (2016). «Глава 5». Параллелизм в матричных вычислениях . Спрингер. ISBN 978-94-017-7188-7 .
- Конте, SD; де Бур, К. (1972). Элементарный численный анализ . МакГроу-Хилл, Нью-Йорк. ISBN 0070124469 .
- Эта статья включает текст из статьи Tridiagonal_matrix_algorithm_-_TDMA_(Thomas_algorithm) на CFD-Wiki , которая находится под лицензией GFDL .
- Пресс, WH; Теукольский, С.А.; Феттерлинг, WT; Фланнери, BP (2007). «Раздел 2.4» . Численные рецепты: искусство научных вычислений (3-е изд.). Нью-Йорк: Издательство Кембриджского университета. ISBN 978-0-521-88068-8 .