Этот пример показов, как решить численно сложную краевую значения задачу с помощью продолжения, что эффективно разбивает задачу на последовательность более простых задач.
Для , рассмотрим дифференциальное уравнение
.
Задача ставится на интервале и удовлетворяет граничным условиям
,
.
Когда решение уравнения претерпевает быстрый переход около , поэтому трудно решить численно. Вместо этого этот пример использует продолжение для итерации нескольких значений до . Каждый из промежуточных решений используется в качестве начального предположения для следующей задачи.
Чтобы решить эту систему уравнений в MATLAB, необходимо кодировать уравнения, граничные условия и исходное предположение перед вызовом решателя для краевой задачи bvp4c
. Можно либо включить необходимые функции в качестве локальных функций в конце файла (как это сделано здесь), либо можно сохранить их как отдельные, именованные файлы в директории по пути MATLAB.
Использование замен и , можно переписать уравнение как систему уравнений первого порядка
,
.
Напишите функцию, чтобы кодировать уравнения сигнатурой dydx = shockode(x,y)
, где:
x
- независимая переменная.
y
- зависимая переменная.
dydx(1)
приводит уравнение для , и dydx(2)
приводит уравнение для .
Сделайте функцию векторизированной, так что shockode([x1 x2 ...],[y1 y2 ...])
возвращает [shockode(x1,y1) shockode(x2,y2) ...]
. Этот подход улучшает эффективность решателя.
Соответствующая функция является
function dydx = shockode(x,y) pix = pi*x; dydx = [y(2,:) -x/e.*y(2,:) - pi^2*cos(pix) - pix/e.*sin(pix)]; end
Примечание.Все функции включены в качестве локальных функций в конце примера.
Решатель BVP требует, чтобы граничные условия были в форме . В этой форме граничные условия:
,
.
Написание функции для кодирования граничных условий сигнатурой res = shockbc(ya,yb)
, где:
ya
- значение граничного условия в начале интервала .
yb
- значение граничного условия в конце интервала .
Соответствующая функция является
function res = shockbc(ya,yb) % boundary conditions res = [ya(1)+2 yb(1)]; end
Аналитические якобианы для функции ОДУ и граничных условий могут быть легко вычислены в этой задаче. Предоставление якобианов делает решатель более эффективным, поскольку решатель больше не должен аппроксимировать их с конечными различиями.
Для функции ODE, матрица Якобия является
.
Соответствующая функция является
function jac = shockjac(x,y,e) jac = [0 1 0 -x/e]; end
Точно так же для граничных условий матрицы Якобия
, .
Соответствующая функция является
function [dBCdya,dBCdyb] = shockbcjac(ya,yb) dBCdya = [1 0; 0 0]; dBCdyb = [0 0; 1 0]; end
Используйте постоянное предположение для решения на mesh из пяти точек в .
sol = bvpinit([-1 -0.5 0 0.5 1],[1 0]);
Если вы пытаетесь решить уравнение непосредственно используя , тогда решатель не в состоянии преодолеть плохое обусловление задачи около точка перехода. Вместо этого, чтобы получить решение для , этот пример использует продолжение путем решения последовательности задач для , , и . Выход от решателя в каждой итерации действует как догадка для решения в следующей итерации (вот почему переменная для начального предположения от bvpinit
является sol
, и выход от решателя также назван sol
).
Поскольку значение якобиана зависит от значения , установите опции в цикле, задавая shockjac
и shockbcjac
функции для якобийцев. Кроме того, включите векторизацию с shockode
кодируется для обработки векторов значений.
e = 0.1; for i = 2:4 e = e/10; options = bvpset('FJacobian',@(x,y) shockjac(x,y,e),'BCJacobian',@shockbcjac,'Vectorized','on'); sol = bvp4c(@(x,y) shockode(x,y,e),@shockbc, sol, options); end
Постройте график результатов из bvp4c
для mesh и решение . С продолжением решатель способен обрабатывать разрыв в .
plot(sol.x,sol.y(1,:),'-o'); axis([-1 1 -2.2 2.2]); title(['There Is a Shock at x = 0 When e =' sprintf('%.e',e) '.']); xlabel('x'); ylabel('solution y');
Здесь перечислены локальные функции, которые решатель BVP bvp4c
вызывается для вычисления решения. Также можно сохранить эти функции как собственные файлы в директории по пути MATLAB.
function dydx = shockode(x,y,e) % equation to solve pix = pi*x; dydx = [y(2,:) -x/e.*y(2,:) - pi^2*cos(pix) - pix/e.*sin(pix)]; end %------------------------------------------- function res = shockbc(ya,yb) % boundary conditions res = [ya(1)+2 yb(1)]; end %------------------------------------------- function jac = shockjac(x,y,e) % jacobian of shockode jac = [0 1 0 -x/e]; end %------------------------------------------- function [dBCdya,dBCdyb] = shockbcjac(ya,yb) % jacobian of shockbc dBCdya = [1 0; 0 0]; dBCdyb = [0 0; 1 0]; end %-------------------------------------------