← Назад Далее →

3.2. Генерация разностной схемы

Для построения разностной схемы, соответствующей какому-либо шаблону, будем использовать интерполяционно-характеристический метод, описанный в п. 2.4. Каждому из узлов пространственно-временной сетки сопоставим значение сеточной функции ϕin. Набор узлов в шаблоне определяет, какие значения сеточной функции будут присутствовать в разностной схеме.

Рассмотрим сначала какую-либо явную схему. Например, схему «Крест», шаблон которой приведен на рисунке 30. На горизонтальной прямой t=tn в пространстве (x,t) определим параметризацию ξ=xxixi+1xi и квадратичную функцию f(ξ)=a0+a1ξ+a2ξ2, коэффициенты которой пока не определены. Поскольку мы строим разностную схему для уравнения

ut+cux=0,c=const,(3.1)

то решение этого уравнения будет постоянным вдоль характеристик - прямых x+ct=const.При выбранным шаблоне в разностной схеме участвуют четыре узла: (xi,tn1), (xi1,tn), (xi+1,tn) и (xi,tn+1), которым соответствуют значения сеточной функции uin1, uj1n, ui+1n и uin+1. По значениям сеточной функции в трех точках можно определить коэффициенты функции f(ξ). Два узла (xi1,tn) и (xi+1,tn) уже лежат на прямой t=tn и определяют значения функции f(ξ) в точках ξ=1 и ξ=1. Еще один узел (xi,tn1) лежит ниже прямой t=tn. Выпустим из этого узла характеристику, которая пересечет прямую t=tn в точке ξ=r, где r=cτh. Так как значение сеточной функции постоянно вдоль характеристики, то, тем самым, определено еще одно, третье, значение на прямой t=tn(см. рис. 30).

Это приводит нас к системе из трех уравнений:

{f(1)=a0+a1(1)+a2(1)2=ϕi1nf(1)=a0+a1(1)+a2(1)2=ϕi+1nf(r)=a0+a1(r)+a2(r)2=ϕin1,(3.2)

разрешая которую, получаем коэффициенты a0, a1< и a2:

{a0=ϕi1nr(r1)+ϕi+1nr(r+1)2ϕin12(r21)a0=ϕi+1nϕi1n2a0=ϕi1n(r1)+ϕi+1n(r+1)2ϕin12(r21).(3.3)
Рис. 30. Схема «Крест»

Таким образом, на прямой t=tn однозначно задана квадратичная функция f(ξ). Учитывая, что характеристика, проходящая через четвертый узел шаблона (xi,tn+1) пересекает прямую t=tn в точке ξ=r, разностная схема для уравнения (3.1) может быть записана в виде

f(r)=ϕin+1.(3.4)

Подставляя значения коэффициентов (3.3) в соотношение (3.4), находим:

ϕin1+r(ϕi1nϕi+1n)=ϕin+1(3.5)

или, в виде однородного уравнения:

ϕin1ϕin+1+r(ϕi1nϕi+1n)=0(3.6)

Соотношение (3.5) или эквивалентное ему (3.6) уже может рассматриваться как разностная схема, позволяющая получать значения сеточной функции на новом слое по времени tn+1 по известным значениям сеточной функции на предыдущих слоях по времени tn и tn1.Такое представление схемы будем называть интерполяционным. Однако форма записи (3.6) не является окончательной и ниже будет показано, как эту форму записи можно улучшить.

Из сказанного выше следует, что разностную схему (3.6) определяют четыре уравнения (3.2) и (3.4) с тремя неизвестными a0, a1 и a2, позволяющие, при исключении неизвестных, связать вместе одним соотношением значения сеточной функции в четырех узлах сетки. Это утверждение справедливо для любого шаблона, как для явных, так и для неявных схем. Тем самым, определен следующий алгоритм построения разностной схемы по заданному шаблону.

Для каждого узла pj,j=1...4 ищется точка ξj пересечения характеристики, проходящей через этот узел, с прямой t=tn.

Решается система

{f(ξ1)=a0+a1ξ1+a2ξ12=ϕ1f(ξ2)=a0+a1ξ2+a2ξ22=ϕ2f(ξ3)=a0+a1ξ3+a2ξ32=ϕ3f(ξ4)=a0+a1ξ4+a2ξ42=ϕ4.

С помощью первых трех уравнений исключаются неизвестные a0, a1 и a2, четвертое уравнение рассматривается как искомая разностная схема.

Фрагмент кода:

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];
  

 

Out: -r u(i-1,n)+r u(i+1,n)-u(i,n-1)+u(i,n+1)

Определим порядок аппроксимации уравнения переноса (3.1) разностной схемой (3.6). В качестве точки разложения выберем точку, совпадающую с узлом (xi,tn). Разложим входящие в схему (3.6) значения сеточной функции:

ϕin1=ϕ0ϕt|0τ+122ϕt2|0τ2+o(τ3);(3.7)
ϕi1n=ϕ0ϕx|0h+122ϕx2|0h2+o(h3);(3.8)
ϕi+1n=ϕ0+ϕx|0h+122ϕx2|0h2+o(h3);(3.9)
ϕin+1=ϕ0+ϕt|0τ+122ϕt2|0τ2+o(τ3),(3.10)

где индекс 0 означает значение в выбранной точке разложения. Подставим в (3.6) разложения (3.7)-(3.10). Слагаемые с четными степенями при h и τсократятся. Для оставшихся нечетных степеней получим:

2ϕt|0τ+r[2ϕx|0h+o(h3)]+o(τ3)=0.(3.11)

После вычитания (3.1) из (3.11) получим остаточный член

2ϕt|0τ+r[2ϕx|0h]+o(h3,τ3)(ϕt+cϕx)0==ϕt|0(2τ1)+ϕx|0(2rhc)+o(h3,τ3)

Отсюда видно, что разностная схема (3.6) аппроксимирует дифференциальное уравнение переноса (3.1) с нулевым порядком. С другой стороны, схема «крест» обладает вторым порядком аппроксимации.

Для устранения возникшего парадокса надо обратить внимание на то, что формально построенное соотношение (3.6) является однородным и может быть умножено на любое выражение. Заметим, что после подстановки в него разложений (3.7)-(3.10) мы получили выражение (3.11), в котором при производной по времени стоит коэффициент 2τ, а в уравнении переноса - единица. Умножим (3.6) на 12τ, учтем, что r=cτhи получим традиционный вид разностной схемы:

ϕin+1ϕin12τ+cϕi+1nϕi1n2h=0(3.12)

Таким образом, процедура умножения уравнения (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];
];

← Назад Далее →