Красавин Компютерныы практикум в среде МатЛаб 2015
.pdf
Рис. 19.2. Спектральный анализ крика голубого кита
В примере 19.3 приведен код для анализа частотного спектра одномерной цепочки атомов (рис. 19.3, 19.4).
Пример 19.3. В примере предусмотрена возможность наблюдения колебаний атомов в реальном времени; для этого следует раскомментировать (закомментировать) обозначенные строки.
Fs = 10; %Fs – частота дискретизации dt = 1/Fs; % dt - шаг по времени
a = 1; % a – межатомное расстояние N = 50; %N – количество атомов
L = 10000; %L – число шагов по времени
alpha = 1; %alpha – коэффициент взаимодействия атомов
lattice = [a:a:(a*N)]; %lattice – 'решетка', начальное положение атомов
M = 1; %M – атомная масса, по умолчанию все атомы одинаковые и имееют массу 1
coord = lattice + a*(2*rand(1,N)-1)/100; %coord – вектор координат атомов, задаем случайное начальное отклонение
221
% раскомментировать для визуализации колебаний
%coord=lattice;
%coord(1)=coord(1)+rand/10;
%
coordPast = coord; % coordPast – вектор координат атомов на предыдущей итерации
coordFuture = coord; % coordFuture – вектор координат атомов на будущей итерации; предназначены для реализации разностной схемы Эйлера
position = zeros(L,N); % position – матрица положений атомов во времени
h = waitbar(0,'Period calculating'); % инициализация waitbar для отображения процесса подсчета координат; % закомментировать при визуализации колебаний
%figure
for j = 1:1:L % цикл по времени
for i = 1:1:N % цикл по координатам
if i == 1 % учет краевых уcловий Борна–Кармана coordFuture(1) = dt^2*(-alpha/M)*(2*coord(1)- (coord(N)-(lattice(end)))-coord(2))+2*coord(1)- coordPast(1);
elseif i == N % реализация разностной схемы Эйлера coordFuture(N) = dt^2*(-alpha/M)*(2*coord(N)-coord(N- 1)-(coord(1)+lattice(end)))+2*coord(N)-coordPast(N);
else
coordFuture(i) = dt^2*(-alpha/M)*(2*coord(i)-coord(i- 1)-coord(i+1))+2*coord(i)-coordPast(i);
end
end
coordPast = coord; % переход на следующую итерацию coord = coordFuture;
position(j,:) = coordFuture; % текущее положение атомов
% раскомментировать для визуализации колебаний
%plot(lattice,lattice-coordFuture,’or’) %axis([min(lattice)-1 max(lattice)+1 -1/10 1/10]) %drawnow
%pause(dt)
waitbar(j/L) % закомментировать при визуализации колебаний end
222
close(h) % закомментировать при визуализации колебаний
f = [0:1:(L-1)]*Fs/L*2*pi; % f – сетка по частотам для дискретного фурье-преобразования
Y = zeros(N,L); % Y – будущий фурье-образ зависимости положений атомов от времени
h = waitbar(0,'FFT'); % инициализация waitbar для отображения процесса дискретного фурье-преобразования; закомментировать при визуализации колебаний
for i = 1:1:N |
= |
position(:,i) |
– |
sum(position(:,i)) |
position(:,i) |
/numel(position(:,i)); % нормировка
Y(i,:) = fft(position(:,i)); % дискретное фурье-преобразование Y(i,:) = abs(Y(i,:)); % амплитудное значение фурье-образа waitbar(i/N) % закомментировать при визуализации колебаний
end
close(h) % закомментировать при визуализации колебаний
sumY = sum(Y(i,:),1); % суммируем фурье-образы в один фурье-образ всей системы
k = (2*pi/a)*(0:1:(N-1))/N; % k – массив волновых векторов системы
omega = 2*sqrt(alpha/M)*sin(k*a/2); |
% omega |
– вектор |
аналитических значених |
частот |
акустических |
колебаний системы |
|
|
analit_omega = omega(1:end/2); % analit_omega – рассматриваем только одну ветвь частот
[pks,locs] = findpeaks(sumY(1:end/20), f(1:end/20), 'Npeaks', numel(analit_omega)-1); % ищем значения частот акустических колебаний в полученном суммарном фурье-образе
locs = sort(locs); % cортируем полученные значения частот (locs)
figure % рис. 19.3 |
|
|
|
|
plot(locs,pks,’sr’) |
|
|
|
|
hold on |
% |
строим |
АЧХ |
системы, |
plot(f(1:end/20),sumY(1:end/20)) |
рассматриваем только 1/20, так как остальная часть не несет полезной информации
xlabel('Частота (рад/с)') ylabel('Амплитуда')
title('{\bf Частотные компоненты колебаний одномерной цепочки атомов}')
figure % рис. 19.4
plot([-k(end/2:-1:1) k(1:end/2)],[locs(end:-1:1) 0 0 locs],’*b’) % строим законы дисперсии
223
hold on
plot([-k(end/2:-1:1) k(1:end/2)], [analit_omega(end:-1:1) analit_omega],’r’)
xlabel('Волновой вектор') ylabel('Частота (рад/с)')
title('{\bf Закон дисперсии акустической ветви одномерной цепочки атомов}')
legend({'Полученные значения', 'Аналитическое выражение'}, 'Location', 'SouthWest')
Рис. 19.3. Акустическая ветвь колебаний цепочки атомов
224
Рис. 19.4. Частотный спектр колебаний цепочки атомов
225
20
Разреженные матрицы
20.1. Схема хранения
Разреженными называются матрицы, содержащие нулевые элементы, число которых намного превосходит число ненулевых элементов. Разреженные матрицы встречаются в различных научных областях; для работы с ними созданы специальные алгоритмы. Строго говоря, матрица может считаться разреженной, если компактная схема хранения ее элементов и алгоритмы для разреженных матриц дают существенный выигрыш в быстродействии и использовании памяти по сравнению с обычными плотными матрицами.
Элементы разреженных матриц хранятся в специальных массивах, имеющих тип double array (sparse). В этих массивах хранятся только ненулевые элементы, а также информация о месте в матрице, где эти элементы находятся. Функция sparse переводит схему хранения матрицы из обычной в разреженную:
A = [ 4 0 0 -1 0 % поэлементное задание матрицы
0 0 2 0 1
1 1 0 0 0
3 0 0 0 -7
0 0 5 0 5]
A =
4 |
0 |
0 |
-1 |
0 |
0 |
0 |
2 |
0 |
1 |
1 |
1 |
0 |
0 |
0 |
3 |
0 |
0 |
0 |
-7 |
0 |
0 |
8 |
0 |
5 |
|
|
|
|
226 |
AS = sparse(A)
AS = |
4 |
(1,1) |
|
(3,1) |
1 |
(4,1) |
3 |
(3,2) |
1 |
(2,3) |
2 |
(5,3) |
8 |
(1,4) |
-1 |
(2,5) |
1 |
(4,5) |
-7 |
(5,5) |
5 |
На рис. 20.1 показана схема хранения разреженной матрицы в MatLab.
Рис. 20.1. Схема хранения разреженной матрицы вMatLab
20.2. Создание разреженных матриц
Функция sparse, помимо преобразования полной матрицы в разреженную, предоставляет возможность создания разреженной
227
матрицы используя векторы, содержащие значения ненулевых элементов и их положения в матрице:
AS = sparse(i,j,nzer,m,n)
Здесь i – вектор строчных индексов ненулевых элементов; j – вектор столбцевых индексов ненулевых элементов; nzer – вектор ненулевых элементов; m,n – размеры полной матрицы. Матрица на рис 20.1 может быть задана при помощи следующих команд:
i = [1 3 4 3 2 5 1 2 4 5]; % элементы разреженной матрицы перечисляются по столбцам
j = [1 1 1 2 3 3 4 5 5 5]; nzer = [4 1 3 1 2 8 -1 1 -7 5]; AS = sparse(i,j,nzer,5,5);
В следующих примерах разобраны различные способы задания разреженных матриц при помощи функции sparse, эффективные и неэффективные.
Пример 20.1. При помощи следующих команд можно создать трехдиагональную разреженную матрицуследующего вида:
2 |
1 |
1 |
|
|
1 |
2 |
2 |
1 . |
|
|
|
1 |
||
i = [1:10 2:10 1:9]; % индексы строк |
1 |
2 |
||
j = [1:10 1:9 2:10]; % индексы столбцов
s = [2*ones(1,10) ones(1,9) ones(1,9)]; % элементы матрицы
B = sparse(i,j,s); % при отсутствии четвертого и пятого аргументов размеры матрицы вычисляются автоматически, исходя из максимальных значений элементов векторов i и j
228
Пример 20.2. Разберем эффективные и неэффективные способы создания разреженных матриц.
%1
%самый неэффективный способ
%n – размер квадратной матрицы
%nz – число ненулевых элементов
A = sparse(n,n); % инициализация разреженной матрицы размера nхn
for k = 1:nz
i = 1 + fix(n*rand(1)); % строки и столбцы выбираются случайно j = 1 + fix(n*rand(1));
x = rand(1);
A(i,j) = A(i,j) + x; % в выбранное место матрицы записывается случайное число; такая операция чрезвычайно медленно работает с разреженными матрицами
end
%2
%более эффективной является предварительная инициализация массивов индексов строк, столбцов и значений элементов
i = zeros(nz,1); % инициализация массива индексов строк j = zeros(nz,1);
x = zeros(nz,1);
for k = 1:nz
i(k) = 1 + fix(n*rand(1)); j(k) = 1 + fix(n*rand(1)); x(k) = rand(1);
end
A = sparse(i,j,x);
%3
%наилучший способ – полностью избегать циклов for
e = rand(3,nz);
e(1,:) = 1 + fix(n*e(1,:)); e(2,:) = 1 + fix(n*e(1,:));
A = sparse(e(1,:),e(2,:),e(3,:));
229
Пример 20.3. Рассмотрим функцию spy.
p32 = pascal(32); % матрица Паскаля – матрица, элементами которой являются биномиальные коэффициенты
s32 = rem(p32,2); % функция rem вычисляет остаток от деления элементов матрицы на 2; получается матрица из нулей и единиц
sps32 = sparse(s32); % создание разреженной матрицы
figure % рис. 20.2
spy(sps32) % функция spy рисует портрет матрицы – ненулевые элементы отмечаются точками; под графиком выводится число ненулевых элементов в матрице; портрет этой матрицы совпадает с ковром Серпинского
set(gca, 'LineWidth',1)
set(gca, 'FontName', 'Trebuchet MS') set(gca, 'FontSize', 8)
set(gca, 'FontWeight', 'bold')
Рис. 20.2. Портрет разреженной матрицы
20.3. Операции с разреженными матрицами
Все такие операции линейной алгебры, как сложение, вычитание, умножение матриц и т.д., реализованы в MatLab и для
230
