23
3. Tworzenie skryptów i współpraca z plikami danych
Skrypt
jest
m-plikiem zawierającym ciąg poleceń. Zawsze na początku skryptu
powinien występować komentarz dokładnie opisujący działanie skryptu. Komentarz
rozpoczyna się od znaku %. Ze względu na zachowanie uniwersalności pisanych
programów w Matlabie wskazane jest używanie w komentarzu tylko znaków ASCII,
nawet jeżeli system operacyjny komputera pozwala pisać polskie litery. Przeniesienie
skryptu z polskimi literami na komputer nie tolerujący polskich ogonków, uczyni
komentarz zupełnie nieczytelnym.
Komentarz jest dostępny za pomocą polecenia help z nazwą skryptu jako
parametrem, np. dla skryptu o nazwie axb.m należy podać polecenie
help axb
Zmienne i wyrażenia występujące w pliku skryptowym mają charakter globalny i
są dostępne w dowolnej linii realizowanego programu obliczeń. Zwykle skrypt jest
tworzony dla wielokrotnie powtarzalnych obliczeń, łatwiejszego wprowadzania
większej ilości danych czytanych z plików zewnętrznych, czy też wyprowadzania
wyników do plików zewnętrznych.
W przypadku wprowadzania danych z klawiatury w skrypcie wykorzystuje się
funkcję input, np.
a = input(‘Podaj z klawiatury wartosc a = ‘);
Po napotkaniu instrukcji input wyświetlany jest na ekranie łańcuch stanowiący
argument wejściowy funkcji input, a następnie Matlab oczekuje na wprowadzenie
liczby z klawiatury.
Do wyprowadzania wyników obliczeń na ekran wykorzystuje się funkcję disp, np.
disp(‘Wynik obliczen wynosi’); disp(wynik);
W przypadku dużej liczby danych i wyników można przy pisaniu skryptu
korzystać z funkcji save oraz load.
Wszystkie zmienne w przestrzeni roboczej Matlaba można zapisać na dysku w
aktualnym katalogu poleceniem
save nazwa_pliku
Zmienne zapisywane są w tym przypadku na dysku w pliku o rozszerzeniu *.mat.
Zmienne występujące w przestrzeni roboczej zapamiętywane są w kodzie
wewnętrznym, nieczytelnym dla użytkownika.
Pominięcie nazwy pliku, czyli podanie samego polecenia
save
24
powoduje, że wszystkie zmienne są zapamiętane w pliku o nazwie domyślnej
matlab.mat , utworzonym w aktualnym katalogu.
Jeżeli mają być zapamiętane jedynie wybrane zmienne, to należy po nazwie pliku
dodać nazwy tych zmiennych
save nazwa_pliku zmienna1 zmienna 2 zmienna3
Przykładowy skrypt zapamiętujący zmienne na dysku w pliku *.mat
% m-plik o nazwie savemat.m
% - zawiera tresc skryptu savemat
% - ilustruje zapamietywanie zmiennych na dysku w pliku *.mat
% Uruchomienie skryptu savemat wymaga:
% - wybrania katalogu nazimi.prn : cd:\nazimi.prn
% - wprowadzenia z klawiatury polecenia: savemat
% UWAGA ! Polecenie nie moze zawierac rozszerzenia *.m
disp(' Skrypt savemat');
disp(' - tworzy macierz Z o elementach zespolnych:');
disp(' Z = [1+2i 3+4i; 5+6i 7+8i];');
disp(' - wyswietla elementy macierzy Z'); disp(Z);
disp(' - zapisuje macierz Z na dysku w pliku maczespZ.mat:');
disp(' save maczespZ Z;');
Z = [1+2i 3+4i; 5+6i 7+8i];
save maczespZ Z;
disp('...');
disp(' Plik maczespZ.mat zapisano w aktualnym katalogu');
disp(' koniec skryptu savemat');
Po wykonaniu skryptu w aktualnym katalogu zostanie utworzony plik o nazwie
maczespZ.mat. Wartości zapamiętanych zmiennych w pliku *.mat mogą być
wykorzystane przez inne skrypty za pomocą polecenia
load nazwa_pliku
Jeśli nazwa pliku zostanie pominięta to w wyniku polecenia
load
zostaną odczytane wszystkie dane z pliku matlab.mat.
Przykładowy skrypt czytający zmienne zapamiętane na dysku w pliku *.mat
% m-plik o nazwie loadmat.m
% - zawiera tresc skryptu loadmat
% - skrypt ilustruje czytanie z dysku zmiennych
% zapisanych na dysku w pliku *.mat
% Uruchomienie skryptu loadmat wymaga:
25
% - wybrania katalogu nazimi.npr za pomoca polecenia
% cd:\nazimi.npr
% - wprowadzenia z klawiatury polecenia
% loadmat
% UWAGA ! Polecenie nie moze zawierac rozszerzenia *.m
disp(' Skrypt loadmat');
disp(' - czyta z pliku maczespZ.mat macierz zespolona Z');
load maczespZ;
disp(' - zapamietuje wczytana macierz jako Z1');
Z1=Z;
disp(' - wyswietla elementy macierzy Z1');
disp(Z1);
disp(' - mnozy macierz przez liczbe 10: Z2=Z1*10;');
Z2=Z1*10;
disp(' - wyswietla elementy wynikowej macierzy Z2');
disp(Z2);
disp(' koniec skryptu loadmat');
Jeżeli użytkownik chce mieć możliwość podglądu lub edytowania wartości
zapamiętywanych na dysku, to powinien skorzystać z opcji zapamiętywania
zmiennych w kodzie ASCII. Podanie opcji
-ascii
powoduje zapamiętanie zmiennych w postaci znakowej, z użyciem 8 cyfrowego
zapisu liczb
save nazwa_pliku zmienna1 zmienna 2 zmienna3 -ascii
Zapisane zmienne tworzą tablice liczb umieszczonych jedna pod drugą, a nazwy
zmiennych są pomijane. Zapamiętane dane mogą być wykorzystane w innych
skryptach za pomocą polecenia
load
nazwa.rozszerzenie
Wczytywane są wartości zapamiętane w pliku tekstowym o podanej nazwie z
rozszerzeniem. Dane muszą tworzyć tablicę prostokątną. Wczytane dane zostaną
zapamiętane w macierzy o nazwie takiej jak nazwa pliku, np.
load
A.dat
powoduje zapamiętanie wczytanych danych w macierzy o nazwie A.
Polecenie
load nazwa_pliku –acsii
umożliwia wczytanie macierzy z pliku tekstowego, którego nazwa nie zawiera
rozszerzenia. Podanie samej nazwy pliku bez opcji –ascii powoduje poszukiwanie
pliku binarnego. Dane muszą tworzyć tablicę prostokątną.
26
Przykładem skryptu czytającego dane, rozwiązującego układ równań liniowych i
zapisującego uzyskane wyniki na dysk komputera jest skrypt pliku axb.m. Skrypt
rozwiązuje następujący układ równań liniowych
10x
1
+ 2x
2
+ 3x
3
= 1
4x
1
+ 50x
2
+ 6x
3
= 2
7x
1
+ 8x
2
+ 90x
3
= 3
W skrypcie wykorzystano zapis macierzowy układu równań w postaci
Ax
= b
gdzie
A - macierz kwadratowa o wymiarze n razy n,
b - wektor kolumnowy o n elementach.
Przykładowy skrypt czytający i zapisujący zmienne na dysku w kodzie ASCII
% axb
% Skrypt jest zapamietany w pliku axb.m
% Uruchomienie skryptu polega na wprowadzeniu polecenia
% axb
% Skrypt axb.m, macierze A, b wystepuja w tym samym katalogu.
% Opis skryptu jest wyswietalny na ekranie
disp(' Skrypt rozwiazuje uklad liniowych rownan A*x=b');
disp(' A - macierz kwadratowa, b - wektor kolumnowy');
disp(' x - wektor kolumnowy rozwiazan');
disp(' Rozwiazanie jest wyznaczane za pomoca polecenia');
disp(' x = A\b');
disp(' Przyklad');
disp(' 10*x1 + 2*x2 + 3*x3 = 1');
disp(' 4*x1 + 50*x2 + 6*x3 = 2');
disp(' 7*x1 + 8*x2 + 90*x4 = 3');
disp(' Macierz A zapamietano w kodzie ASCII w pliku A.dat');
disp(' 10 2 3');
disp(' 4 50 6');
disp(' 7 8 90');
disp(' Wektor b zapamietano w kodzie ASCII w pliku b.dat');
disp(' 1');
disp(' 2');
disp(' 3');
disp(' Macierz A jest wczytana jako plik ASCII A.dat’);
load A.dat;');
disp(' Wektor b jest wczytany jako plik ASCII b.dat’);
disp(' Wektor x jest zapisany jako plik ASCII x.dat');
% Polecenia skryptu
load A.dat; % wczytany plik zostanie zapamietany jako macierz A
disp(' Wczytana macierz wspolczynnikow ukladu rownan A');
27
disp(A); % macierz A zostanie wyswietlona na ekranie
load b.dat; % wczytany plik zostanie zapamietany jako wektor b
disp(' Wczytany wektor prawej strony ukladu rownan b');
disp(b);% wektor b zostanie wyswietlony na ekranie
x = A\b;
disp(' Wyznaczono rozwiazanie ukladu rownan x = A\b');
disp(x); % wektor x zostanie wyswietlony na ekranie
save 'x.dat' x -ascii; %rozwiazanie x zapisano w pliku x.dat
disp(' Zapamietano rozwiazanie w pliku x.dat');
disp('koniec obliczen realizowanych przez skrypt axb');
% koniec skryptu axb.m
Skrypt
axb może być wykorzystany do rozwiązywania dowolnego układu równań
liniowych. W tym celu należy:
•
skierować ścieżkę Matlaba do własnego katalogu roboczego, np.
cd
c:\nazimi.npr,
•
za pomocą edytora ASCII przepisać treść skryptu axb do pliku axb.m, z
pominięciem fragmentów dotyczących przykładowego układu równań,
•
za pomocą edytora ASCII utworzyć we własnym katalogu plik A.dat
zawierający macierz A ze współczynnikami rozwiązywanego układu równań,
•
za pomocą edytora ASCII utworzyć we własnym katalogu plik b.dat
zawierający wektor b prawych stron układu równań,
•
uruchomić skrypt przez wpisanie w oknie poleceń Matlaba instrukcji
axb
,
•
za pomocą polecenia
dir
sprawdzić, czy po wykonaniu skryptu w aktualnym
katalogu został utworzony plik x.dat,
•
wyświetlić na ekranie zawartość pliku x.dat za pomocą polecenia
type x.dat
Rozwiązywanie zadań elektrotechnicznych w Matlabie wymaga często korzystania
z algorytmów składających się nie tylko z działań arytmetycznych, ale przede
wszystkim z logicznych wyborów, realizowanych za pomocą instrukcji
strukturalnych.
W Matlabie występują następujące instrukcje sterujące działaniem programu:
•
iteracyjne: for, while
•
warunkowa: if
•
uzupełniające: break, return
Instrukcja iteracyjna for
Instrukcja
for ma postać
28
for zmienna=wyrażenie
instrukcje
end
Pętla for służy do powtarzania wyszczególnionych instrukcji zawartych pomiędzy
for
i
end
określoną liczbę razy. Wyrażenie występuje często w postaci wektora x:y,
w którym poszczególne kolumny mogą być zwykłymi skalarami, np.
for
i=1:n
instrukcje
end
Pętle for mogą być wzajemnie zagnieżdżane.
% Tworzenie macierzy przy pomocy instrukcji for
n=5; m=10;
for i=1:n
for
j=1:m
A(i,j)=i+j-1;
end
end
disp('Utworzono macierz A');
disp('Liczba wierszy n'), disp(n);
disp('Liczba kolumn m'), disp(m);
disp('Elementy macierzy A'), disp(A);
Instrukcja warunkowa if
Instrukcja
if ma postać
if wyrażenie_logiczne
instrukcje1
elseif wyrażenie_logiczne2
instrukcje2
else
instrukcje3
end
Występowanie elseif oraz else jest opcjonalne. Ponadto może wystąpić kilka instrukcji
elseif. W wyrażeniach logicznych stosowane są operatory logiczne.
% Tworzenie macierzy quasidiagonalnej
% przy pomocy instrukcji for oraz if
n=input('Podaj liczbe wierszy n = ');
m=input('Podaj liczbe kolumn m = ');
29
b=input('Podaj wartosc elementu na diagonali b = ');
for i=1:n
for
j=1:m
if
i==j
A(i,j)=b;
elseif
abs(i-j)==1
A(i,j)=-1;
else
A(i,j)=0;
end
end
end
disp('Macierz A'),disp(A);
Instrukcja iteracyjna while
Instrukcja
while ma postać
while wyrażenie_warunkowe
instrukcje
end
Instrukcje między
while
i
end
są wykonywane dopóki wartość
wyrażenia_warunkowego ma wartość true, tzn. gdy macierz będąca wartością
wyrażenia_logicznego posiada wszystkie elementy niezerowe. Pętla while jest zatem
wykonywana nieokreśloną z góry liczbę razy. Przerwanie pętli while umożliwia
instrukcja break.
% skrwhile.m
% exp(x) = 1+ x + x^2/2 + x^3/3 + ...
eps=1e-3; % dokladnosc obliczen
a=3; % wartosc dla ktorej nalezy obliczyc exp
x=a; y=1; k=1;
while x >= eps
k=k+1; y=y+x; x=x*a/k;
end
expad=exp(a); % obliczenia wg funkcji Matlaba exp()
expap=y; % obliczenia przyblizone wg wzoru iteracyjnego
bladobl=(expap-expad)/expad*100; % procentowy blad obliczen
disp(' Obl. dokladne exp(a) = ');
expad
disp(' Obl. wg wzoru iteracyjnego exp(a)=1+a+a^2/2+ ...=);
expap
disp(' Procentowy blad obliczen przyblizonych bladobl = ');
bladobl
30
Instrukcja
break
Opuszczenie
pętli for lub while przed zakończeniem jej wykonania może być
dokonane za pomocą break. W przypadku pętli zagnieżdżonych użycie break
powoduje przejście do pętli nadrzędnej.
%Wyznaczenie dokladnosci komputera przy pomocy for oraz break
eps=1;
for i=1:10000
eps=eps/2;
if(eps+1<=1)
break
end
end
eps=eps*2;
disp('Dokladnosc komputera wynosi'); disp(eps);
Instrukcja
return
Instrukcja
pomocnicza
return powoduje opuszczenie danego skryptu lub funkcji, a
następnie powrót do jego/jej wywołania (normalnie funkcja jest opuszczana po jej
wykonaniu).
Zadania do samodzielnego rozwiązania
Zadanie
1
Dane jest zespolona macierz admitancji węzłowych
−
+
−
+
−
−
+
−
+
−
−
=
+
=
25
j
25
25
j
25
0
25
j
25
50
j
50
25
j
25
0
25
j
25
45
j
45
jB
G
Y
(3.1)
oraz zespolony wektor prądów węzłowych
−
=
+
=
1
j
1
.
0
0
0
b
a
jI
I
I
(3.2)
Należy we własnym katalogu zapamiętać część rzeczywistą G macierzy admitancji
w pliku G.dat oraz część urojoną B - w pliku B.dat. Podobnie należy postąpić z
wektorem prądów węzłowych.
Następnie utworzyć skrypt o nazwie uyi.m, realizujący następujące działania:
•
czytanie z dysku macierzy G oraz B,
•
tworzenie zespolonej macierzy admitancji węzłowych Y = G+jB ,
31
•
czytanie z dysku wektorów I
a
oraz I
b
,
•
tworzenie zespolonego wektora prądów węzłowych I = I
a
+ jI
b
,
•
rozwiązanie układu równań liniowych Y U = I ,
•
wydzielenie części rzeczywistych i urojonych napięć węzłowych U = U
a
+ jU
b
•
zapisanie na dysku wartości wyliczonych napięć węzłowych w plikach Ua.dat
oraz Ub.dat
Zadanie 2
Napisać skrypt tworzący zespoloną macierz admitancji węzłowych w oparciu o
wczytane z klawiatury numery węzłów początkowych i końcowych oraz admitancje
gałęzi liniowego obwodu elektrycznego pokazanego na rys. 3.1. Utworzyć macierz
wp - numerów węzłów początkowych gałęzi, wk - numerów węzłów końcowych
gałęzi, g - konduktancji gałęzi, b - susceptancji gałęzi.
0
1
2
3
4
5
(1.5-j2)S
(1-j2)S
(2-j2)S
(0.5-j2.5)S
(1-j2)S
(1-j2.5)S
(2-j3)S
Rys. 3.1. Schemat liniowego obwodu elektrycznego z numerami węzłów i admitancjami gałęzi.
Węzeł o numerze 0 jest węzłem odniesienia.
Do tworzenia macierzy admitancji węzłowych wykorzystać następujące instrukcje
j=sqrt(-1); ygal=g+j*b; nbr=length(ygal);
for k=1:nbr
i=wp(k); j=wk(k); y=ygal(k);
if i*j > 0
Y(i,i)=Y(i,i)+y; Y(i,j)=-y;
Y(j,j)=Y(j,j)+y; Y(j,i)=-y;
end
if i==0 Y(j,j)=Y(j,j)+y; end
if j==0 Y(i,i)=Y(i,i)+y; end
end
Utworzoną zespoloną macierz admitancji zapisać na dysku w pliku macY.mat.