Для построения разностной схемы, соответствующей какому-либо шаблону, будем использовать интерполяционно-характеристический метод, описанный в п. 2.4. Каждому из узлов пространственно-временной сетки сопоставим значение сеточной функции
Рассмотрим сначала какую-либо явную схему. Например, схему «Крест», шаблон которой приведен на рисунке 30. На горизонтальной прямой
то решение этого уравнения будет постоянным вдоль характеристик - прямых
Это приводит нас к системе из трех уравнений:
разрешая которую, получаем коэффициенты
Рис. 30. Схема «Крест» |
Таким образом, на прямой
Подставляя значения коэффициентов (3.3) в соотношение (3.4), находим:
или, в виде однородного уравнения:
Соотношение (3.5) или эквивалентное ему (3.6) уже может рассматриваться как разностная схема, позволяющая получать значения сеточной функции на новом слое по времени
Из сказанного выше следует, что разностную схему (3.6) определяют четыре уравнения (3.2) и (3.4) с тремя неизвестными
Для каждого узла
Решается система
С помощью первых трех уравнений исключаются неизвестные
Фрагмент кода:
F[x_] := a0 + a1*x + a2*x^2; BuildScheme[m_] := Module[{eqs = {}, ic, jc, mi, x, ui, sch, cf}, For[ic = 3, ic >= 1, ic--, For[jc = 1, jc <= 3, jc++, |
|
mi = m[ [(ic - 1)*3 + jc] ]; | (* узел сетки *) |
If[mi != 0, | (* нашли точку нашего шаблона *) |
x = (jc - 2) + (ic - 2) * r; | (* пересечение характеристики с опорной линией *) |
ui = u[i + jc - 2, n - ic + 2]; | (* значение сеточной функции в узле *) |
eqs = Join[eqs, {ui == F[x]}], | (* добавляем к списку уравнение ui=F[x] *) |
] | (* If[ip!=0 *) |
] | (* For[jc=1 *) |
]; | (* For[ic=1 *) |
sch = ui - Simplify[ui /. First @ Solve[conds, {a0, a1, a2, ui}]]; Return[sch]; ]; m = {0, 1, 0, 1, 0, 1, 0, 1, 0}; sch = BuildScheme[m]; Print[sch // TraditionalForm]; |
Определим порядок аппроксимации уравнения переноса (3.1) разностной схемой (3.6). В качестве точки разложения выберем точку, совпадающую с узлом
где индекс 0 означает значение в выбранной точке разложения. Подставим в (3.6) разложения (3.7)-(3.10). Слагаемые с четными степенями при
После вычитания (3.1) из (3.11) получим остаточный член
Отсюда видно, что разностная схема (3.6) аппроксимирует дифференциальное уравнение переноса (3.1) с нулевым порядком. С другой стороны, схема «крест» обладает вторым порядком аппроксимации.
Для устранения возникшего парадокса надо обратить внимание на то, что формально построенное соотношение (3.6) является однородным и может быть умножено на любое выражение. Заметим, что после подстановки в него разложений (3.7)-(3.10) мы получили выражение (3.11), в котором при производной по времени стоит коэффициент
Таким образом, процедура умножения уравнения (3.6) на выражение, обратное коэффициенту при производной по времени, позволяет получить разностную схему, аппроксимирующую дифференциальное уравнение (3.1).
В коде исследование порядка аппроксимации и поиск коэффициентов при производных осуществляется следующей процедурой:
Approx[sh_, center_, pow_] := Module[{sh1, sh2, ic, nc, cf}, Clear[i, n, x, t, h, tau]; |
|
ic = center[ [1] ]; nc = center[ [2] ]; | (* центр аппроксимации *) |
(* подставляем разложения в ряд Тейлора вместо сеточной функции: *) sh1 = sh /. { u[i, n] -> Series[u[x + (0 + (ic - i))*h, t + (0 + (nc - n))* tau], {h, 0, pow}, {tau, 0, pow}], u[i + di_, n] -> Series[u[x + (di + (ic - i))*h, t + (0 + (nc - n))* tau], {h, 0, pow}, { tau, 0, pow}], u[i, n + dn_] -> Series[u[x + (0 + (ic - i))*h, t + (dn + (nc - n))*tau], {h, 0, pow}, {tau, 0, pow}], u[i + di_, n + dn_] -> Series[u[x + (di + (ic - i))*h, t + (dn + (nc - n))*tau], {h, 0, pow}, {tau, 0, pow}] }; |
|
(* для вторых производных учитываем решение: *) sh2 = sh1 /. { D[(D[u[x, t], t] + c*D[u[x, t], x]), x] -> 0, D[(D[u[x, t], t] + c*D[u[x, t], x]), t] -> 0 }; |
|
cfDuDt =Coefficient[sh2, D[u[x, t], t]]; | (* коэффициент при производной по времени *) |
cfDuDx = Coefficient[sh2, D[u[x, t], x]]; | (* коэффициент при производной по пространству *) |
Return[{cfDuDt, cfDuDx}]; ]; |
Модуль построения схемы BuildScheme, приведенный выше, следует закончить так:
... sch = ui - Simplify[ui /. First @ Solve[conds, {a0, a1, a2, ui}]]; cf = Approx[sch, {i, n}, 2]; sch = Simplify[sch / cf[ [1] ] ]; Return[sch]; ]; |