Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Начала прогаммирования в среде MatLab / Начала программирования в среде MatLab.pdf
Скачиваний:
254
Добавлен:
02.05.2014
Размер:
5.66 Mб
Скачать

2.6. Создание функций от функций

118

 

 

 

2.6. Создание функций от функций

Некоторые алгоритмы являются общими для функций определенного типа. Поэтому их программная реализация едина для всех функций этого типа, но требует использования алгоритма вычисления конкретной функции. Последний алгоритм может быть зафиксирован в виде определенной файл-функции. Чтобы первый, более общий алгоритм был приспособлен для любой функции, нужно, чтобы имя этой функции было некоторой переменной, принимающей определенное значение (текстового имени файла-функции) только при обращении к основному алгоритму.

Такие функции от функций уже рассматривались в разд. 2.1. К ним принадлежат процедуры:

-вычислений интеграла от функции, которые требуют указания имени М- файла, содержащего вычисления значения подынтегральной функции;

-численного интегрирования дифференциальных уравнений, использование которых требует указания имени М-файла, в котором вычисляются правые части уравнений в форме Коши;

-алгоритмов численного вычисления корней нелинейных алгебраических уравнений (нулей функций), которые нуждаются в указания файла-функции, нуль которого отыскивается;

-алгоритмов поиска минимума функции, которую, в свою очередь, надо задавать соответствующим М-файлом и т.п.

На практике довольно часто возникает необходимость создавать собственные процедуры такого типа. MatLAB предоставляет такие возможности.

2.6.1.Процедура feval

В MatLAB любая функция (процедура), например, с именем FUN1, может быть выполнена не только с помощью обычного обращения:

[y1,y2,... ,yk] = FUN1(x1,x2,... ,xn),

а и при помощи специальной процедуры feval: [y1,y2,... ,yk] = feval(‘FUN1',x1,x2,... ,xn),

где имя функции FUN1 является уже одной из входных переменных (текстовой - и поэтому помещается в апострофы).

Преимуществом вызова функции во второй форме является то, что этот вызов не изменяет формы при изменении имени функции, например, на FUN2. Это позволяет унифицировать обращение ко всем функциям определенного вида, т. е. таким, которые имеют одинаковое число входных и выходных параметров определенного типа. При этом имя функции (а значит, и сама функция, которая используется) может быть произвольным и изменяться при повторных обращениях.

Так как при вызове функции с помощью процедуры feval имя функции рассматривается как один из входных параметров процедуры, то его (имя функции) можно использовать как переменную и оформлять в М-файле обращения к ней, не зная еще конкретного имени функции.

2.6. Создание функций от функций

119

 

 

 

2.6.2. Примеры создания процедур от функций

Процедура метода Рунге-Кутта 4-го порядка численного интегрирования ОДУ

Пусть задана система обыкновенных дифференциальных уравнений (ОДУ) в форме Коши:

ddty = Z ( y,t) ,

где y - вектор переменных состояния системы; t - аргумент (время); Z - вектор заданных (в общем случае – нелинейных) функций, которые, собственно, и определяют конкретную систему ОДУ.

Если значение вектора y в момент времени t известно, то общая формула, по которой может быть найден вектор yout значений переменных состояния системы в момент времени tout = t + h (где h - шаг интегрирования), имеет вид:

yout = y + h*F(y,t).

Функция F(y,t) связана с вектором Z и может приобретать разный вид в зависимости от выбранного метода численного интегрирования. Для метода РунгеКутта 4-го порядка выберем такую ее форму:

F = (k1 + 3 k2 + 3 k3 + k4 ) / 8 ,

где k1 = Z(y, t);

k 2 = Z(y + h k1 / 3, t + h / 3);

k3 = Z(y + h k 2 h k1 / 3, t + 2h / 3); k 4 = Z(y + h k3 h k 2 h k1, t + h) .

Создадим М-файл процедуры, которая осуществляет эти вычисления, на-

звав его "rko43":

function [tout,yout] = rko43(Zpfun,h,t,y)

%RKO43 Интегрирование ОДУ методом Рунге-Кутта 4-го порядка,

%правые части которых заданы процедурой Zpfun.

%Входные переменные:

%Zpfun - строка символов, который содержит имя процедуры

%вычисления правых частей ОДУ

%Обращение: z = fun(t,y), где Zpfun = 'fun'

%где t - текущий момент времени

%

y - вектор текущих значений переменных состояния

%

z - вычисленные значения производных z(i) = dy(i)/dt.

%h - шаг интегрирования

%t - предыдущий момент времени

%y - предыдущее значение вектора переменных состояния.

%Выходные переменные:

%tout - новый момент времени

%yout - вычисленное значение вектора y через шаг интегрирования

%Расчет промежуточных значений производных

k1 = feval(Zpfun, t, y);

k2 = feval(Zpfun, t+h/3, y+h/3*k1);

k3 = feval(Zpfun, t+2*h/3, y+h*k2-h/3*k1);

k4 = feval(Zpfun, t+h, y+h*(k3+k1-k2));

2.6. Создание функций от функций

120

 

 

 

%Расчет новых значений вектора переменных состояния tout = t + h;

yout = y + h*(k1 + 3*k2 + 3*k3 + k4)/8;

%Конец процедуры RKO43

Обратите внимание на такие обстоятельства:

-обращение к процедуре вычисления правых частей не конкретизированно; имя этой процедуры входит в число входных переменных процедуры интегрирования и должно быть конкретизировано лишь при вызове последней;

-промежуточные переменные k являются векторами-строками (так же, как

ипеременные 'y' и 'z', вычисляемые в процедуре правых частей).

Процедура правых частей ОДУ маятника

Рассмотрим процесс создания процедуры вычисления правых частей ОДУ на примере уравнения маятника, точка подвеса которого поступательно перемещается со временем по гармоничному закону:

J ϕ&&+ R ϕ& + mgl (1+ nmy sin(ω t +ε y )) sinϕ =

= −mgl nmx sin(ω t +εx ) cosϕ,

где: J - момент инерции маятника; R - коэффициент демпфирования; mgl - опорный маятниковый момент маятника; nmy - амплитуда виброперегрузки точки под-

веса маятника в вертикальном направлении; nmx - амплитуда виброперегрузки в горизонтальном направлении; ϕ - угол отклонения маятника от вертикали; ω - частота колебаний точки подвеса; εx ,ε y - начальные фазы колебаний (по уско-

рениям) точки подвеса в горизонтальном и вертикальном направлениях.

Чтобы составить М-файл процедуры вычисления правых частей заданной системы ОДУ, прежде всего надо привести исходную систему ОДУ к форме Коши. Для этого введем обозначения:

y1 = ϕ; y2 = ϕ&.

Тогда исходное уравнение маятника можно представить в виде совокупности двух дифференциальных уравнений 1-го порядка:

dydt1 = y2;

dydt2 ={mgl nmx sin(ω t +εx ) cos( y1) R y2 − − mgl [1+ nmy sin(ω t +ε y )] sin( y1)}/ J

Сравнивая полученную систему с общей формой уравнений Коши, можно сделать вывод, что

2.6. Создание функций от функций

121

 

 

 

z1 = y2;

z2 ={mgl nmx sin(ω t +εx ) cos( y1) R y2 − − mgl [1 + nmy sin(ω t +ε y )] sin( y1)}/ J

Именно вычисление этих двух функций и должно происходить в процедуре правых частей. Назовем будущую процедуру fm0. Выходной переменной в ней будет вектор z = [z1 z2], а входными - момент времени t и вектор y = [y1 y2]. Некоторую сложность представляет то, что постоянные коэффициенты в правых частях нельзя передать в процедуру через ее заголовок. Поэтому объединим их в вектор коэффициентов К = [J, R, mgl, nmy, nmx, om, ey, ex] и отнесем этот вектор к категории глобальных

global K.

Тогда М-файл будет иметь вид:

function z = FM0(t,y);

%Процедура правых частей уравнения Физического Маятника.

%Осуществляет расчет вектора “z” производных

%от вектора "y" переменных состояния по формулам:

%z(1)=y(2);

%z(2)=(-mgl*nmx*sin(om*t+ex)*cos(y(1))-R*y(2)-...

%mgl*(1+nmy*sin(om*t+ey))*sin(y(1)))/J,

%Коэффициенты передаются в процедуру через глобальный вектор

%К=[J,R,mgl,nmy,nmx,om,ey,ex]

global K z(1) = y(2);

z(2) = (-K(3)*K(5)*sin(K(6)*t+K(8))*cos(y(1)) - K(2)*y(2) -...

K(3)*(1+K(4)*sin(K(6)*t+K(7)))*sin(y(1)))/K(1); % Конец процедуры FM0

При использовании этой процедуры следует помнить, что в тексте программы предварительно должен быть объявлен глобальный вектор К с помощью служебного слова global, а потом определены все 8 его элементов.

Эту процедуру можно несколько усложнить, группируя вместе вычисление всех внешних моментов сил, кроме момента сил тяготения, и оформляя их как отдельную процедуру. Для этого сначала превратим начальное уравнение, записы-

вая его в виде:

ϕ′′+sinϕ = S(τ,ϕ,ϕ) ,

где штрих - обозначение производной по безразмерному времени τ =ω0 t ,

ω0 = mglJ ,

а через S(τ,ϕ,ϕ) обозначена некоторая заданная функция безразмерного времени, угла поворота маятника и его безразмерной скорости

ϕ′ = ddϕτ .

Врассматриваемом случае эта функция приобретает такой вид:

2.6. Создание функций от функций

122

 

 

 

S(t,ϕ,ϕ) = −2 ζ ϕ′−

[nmx sin(ν τ +εx ) cosϕ + nmy sin(ν τ +εy ) sinϕ],

причем безразмерные величины ζ и ν определяются выражениями:

ζ =

 

R

; ν =

ω

.

 

mgl J

 

2

 

 

ω0

Такая безразмерная форма представления уравнений является предпочтительной и удобной, так как позволяет сократить количество параметров (в нашем случае вместо трех размерных параметров J, R и mgl остался один - ζ ), а также

представлять решение уравнения в более общей форме.

Вынесение вычисления моментов внешних действий в отдельную вычислительную процедуру позволяет также сделать процедуру правых частей уравнения маятника более общей, если обращение к процедуре вычисления моментов осуществлять тоже через функцию feval.

Создадим процедуру MomFm1, которая будет вычислять моменты сил, которые действуют на маятник:

function m = MomFM1(t,y);

%Вычисление Моментов сил, которые действуют на Физический Маятник.

%Осуществляет расчет момента "m" сил

%по формуле:

%m =-2*dz*y(2) - (nmx*sin(nu*t+ex)*cos(y(1)) +...

%+ nmy*sin(nu*t+ey)*sin(y(1)),

%Коэффициенты передаются в процедуру через глобальный вектор

%КM1=[dz,nmy,nmx,nu,ey,ex]

global KM1

m= -2*KM1(1)*y(2)- (KM1(3)*sin(KM1(4)*t+KM1(6))*cos(y(1)) +...

KM1(2)*sin(KM1(4)*t+KM1(5))*sin(y(1))); % Конец процедуры MomFM1

Теперь следует перестроить процедуру правых частей. Назовем этот вари-

ант FM1:

function z = FM1(mpfun,t,y);

%Процедура правых частей уравнения Физического Маятника.

%Осуществляет расчет вектора “z” производных

%векторов "y" переменных состояния по формулам:

%z(1)=y(2);

%z(2)= - sin(y(1)) +S(t,y),

%входные параметры:

%mpfun - имя процедуры S(t,y)

%

mpfun = 'S';

%t - текущий момент времени;

%y - текущее значение вектора переменных состояния;

%выходные параметры:

%z - вектор значений производных от переменных состояния.

z(1) = y(2);

z(2) = - sin(y(1)) + feval(mpfun,t,y);

%Конец процедуры FM1

2.6. Создание функций от функций

123

 

 

 

Так как вид обращения к процедуре правых частей изменился (добавлена новая входная переменная - имя процедуры вычисления моментов), необходимо также перестроить и процедуру численного метода. Назовем ее RKO43m:

function [tout,yout] = rko43m(Zpfun,Mpfun,h,t,y)

%RKO43m Интегрирование ОДУ методом Рунге-Кутта 4-го порядка,

%правые части которых заданы процедурами Zpfun и Mpfun.

%Входные параметры:

%Zpfun - строка символов, который содержит имени процедуры

%вычисление правых частей ОДУ.

%Обращение: z = fun(Mpfun,t,y),

%где Zpfun = 'fun',

%

Mpfun - строка с именем процедуры, к которой

%обращается процедура fun;

%

t - текущий момент времени

%

y - вектор текущих значений переменных состояния

%

z - вычисленные значения производных z(i) = dy(i)/dt.

%h - шаг интегрирования

%t - предшествующий момент времени

%y - предшествующее значение вектора переменных состояния.

%Выходные параметры:

%tout - новый момент времени

%yout - новое значение вектора переменных состояния

%через шаг интегрирования

%Расчет промежуточных значений производных k1 = feval(Zpfun, Mpfun,t, y);

k2 = feval(Zpfun, Mpfun, t+h/3, y+h/3*k1);

k3 = feval(Zpfun, Mpf un, t+2*h/3, y+h*k2-h/3*k1);

k4 = feval(Zpfun, Mpfun, t+h, y+h*(k3+k1-k2));

%Расчет новых значений вектора переменных состояния tout = t + h;

yout = y + h*(k1 + 3*k2 + 3*k3 + k4)/8;

%Конец процедуры RKO43m

Такая форма представления процедуры вычисления правых частей дифференциальных уравнений неудобна. Во-первых, процедуру вида FM1 нельзя использовать при интегрировании процедурами MatLAB ode23 и ode45 (последние требуют, чтобы в процедуре правых частей было только два входных параметра, а в процедуре FM1 их три). Во-вторых, такая форма вызовет необходимость создания новых М-файлов методов численного интегрирования.

Этого можно избегнуть, представив имя дополнительной функции Mpfun на глобальную переменную. Тогда процедура правых частей может быть записана так:

function z = FM2(t,y);

%Процедура правых частей уравнения Физического Маятника.

%Осуществляет расчет вектора “z”

%производных вектору "y" переменных состояния по формулам:

%

z(1)=y(2);

%

z(2)= - sin(y(1)) +S(t,y),

%Входные параметры:

%mpfun - имя процедуры S(t,y) - глобальная переменная

%

mpfun = 'S';

%t - текущий момент времени;

%y - текущее значение вектора переменных состояния;