Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
lIngegnere
Chimico
Struttura di Matlab
Quando aprirai il programma noterai quattro aree principali: Current Folder, Command Window, Workspace
e Command History. La loro funzione risulta essere la seguente:
Command Window: in questa finestra possibile inserire i comandi che vuoi che Matlab esegua.
Utilizzare direttamente la Command Window per programmare risulta essere sconveniente. La via
pi agevole aprire un nuovo script (pulsante solitamente in alto a sinistra), che consente di scrivere
righe di comando e di salvarle successivamente a computer. Quando si vogliono eseguire quelle
specifiche righe di comando, basta aprire lo script con Matlab ed eseguirlo.
Current Folder: il percorso utilizzato da Matlab per risalire ai programmi che gli chiedi di eseguire.
Se chiedi a Matlab di eseguire un programma che non nella sua attuale folder, Matlab ti chieder
di cambiare folder, in modo tale da poter risalire alle righe di codice in questione. Da questo derivano
delle importanti implicazioni: se una risoluzione distribuita in pi script o function (vediamo dopo
di cosa si tratta), importante che siano tutte nella medesima cartella, affinch Matlab possa
eseguire la risoluzione.
Workspace: lo spazio in cui possono essere ricercate le varie variabili definite durante la
programmazione. Quando Matlab esegue il programma, definisce le variabili e queste possono
essere ricercate allinterno della Workspace.
Command History: contiene la cronologia dei comandi eseguiti nella Command Window.
Ora che abbiamo visto la struttura del programma, ti consiglio di aprire un nuovo script, in modo tale da fare
pratica con i seguenti comandi che vedremo.
% e %%
In Matlab, tutto ci che risulta essere preceduto dal simbolo di percentuale non viene letto come riga di
comando (e appare colorato di verde). Dunque, se vogliamo inserire allinterno dello script dei commenti o
delle indicazioni utili (ad esempio procedure risolutive o unit di misura), bene farle precedere dal %. Se si
affiancano due simboli di percentuale (%%) si ottiene una suddivisione del programma stesso, e risulta essere
utile per avere una distinzione formale tra i diversi step risolutivi (definizione variabili, calcoli preliminari,
algoritmi di risoluzione, etc etc). Per commentare unintera porzione di testo basta selezionarla e premere
ctrl+r, mentre per de-commentarla basta eseguire la medesima operazione premendo per ctrl+t.
clc
Prima di eseguire un nuovo programma, risulta essere opportuno cancellare tutto quello che attualmente
presente sulla Command Window. Il comando clc, scritto tipicamente allinizio dello script, permette
proprio di fare questo.
clear all
La funzione precedentemente descritta (clc) permette di pulire la Command Window, ma non ha alcuna
influenza sulle variabili gi salvate allinterno del Workspace. Prima di eseguire dei nuovi comandi vale la
pena cancellare tutte le variabili attualmente presenti nel Workspace, e il comando clear all ha proprio
questa funzione.
close all
I precedenti script potrebbero aver generato dei grafici. A volte risulta essere scomodo chiuderli
manualmente, e si pu quindi utilizzare il comando close all per chiudere tutti i grafici attualmente aperti in
Matlab.
Riassumendo, risulta quindi utile iniziare i propri algoritmi con questi tre comandi:
%% Esempio di algoritmo in Matlab
clc
clear all
close all
help
Se hai dei dubbi su come operi una certa funzione di Matlab, della quale ti ricordi il nome ma di cui non ricordi
la struttura e gli effetti, puoi ricercarla nella Command Window utilizzando il comando help. Ammettiamo ad
esempio che io non ricordi come utilizzare il comando plot. Basta che io scriva sulla Command Window:
help plot
% J/(mol K)
Nota che dopo la scrittura del valore numerico della variabile compare un ;
Mettere il ; dopo la definizione di una variabile permette di non farne comparire il valore sulla Command
Window. Infatti, senza il ;, Matlab farebbe comparire sulla Command Window tutte le variabili definite, e
questo rende difficile la visualizzazione di risultati che sono invece di interesse. Per questo motivo, dopo aver
definito una nuova variabile, un nuovo vettore o una nuova matrice risulta essere sempre opportuno inserire
il ;
Definizione di un vettore
Per alcune quantit risulta essere pi comoda una definizione vettoriale. Si pensi ad esempio alla
composizione di una corrente in ingresso ad unapparecchiatura chimica, contenente cinque diversi
composti. Se volessimo esprimere la composizione di tale corrente mediante delle frazioni molari,
risulterebbe opportuno creare un singolo vettore che contiene tutte le informazioni di nostro interesse.
Immaginando, ad esempio, che tutti i composti siano caratterizzati dalla medesima frazione molare,
risulterebbe opportuno definire il vettore delle frazioni molari come segue:
x=[0.2 0.2 0.2 0.2 0.2];
x=[0.2,0.2,0.2,0.2,0.2];
Le diciture ora espresse permettono di generare dei vettori riga, specificandone i singoli elementi. I singoli
elementi possono essere separati da uno spazio (come nel primo caso) oppure da una virgola (come nel
secondo caso).
Se volessimo invece generare un vettore colonna, basta sostituire le , con dei ;
x=[0.2;0.2;0.2;0.2;0.2];
Questi comandi risultano essere comodi ed opportuni quando bisogna creare vettori aventi un numero
limitato di elementi. Immaginiamo ora di voler definire un nuovo vettore, che abbia come valori estremi 0 e
100 e i cui elementi siano distanziati di 1e-3 (10^-3, in linguaggio Matlab). Se dovessimo inserire a mano tutti
i valori non finiremmo pi. Per creare un vettore come questo, basta utilizzare il seguente comando:
s=0:1e-3:100;
Tra i due : riportata la spaziatura desiderata, mentre nelle zone esterne sono riportati gli estremi del
vettore. Nel caso in cui il valore della spaziatura venisse omesso, Matlab lo porrebbe automaticamente
uguale ad 1. Se volessimo trasformare il vettore ora introdotto in un vettore colonna, basterebbe trasporlo
nel seguente modo, utilizzando :
s=s';
linspace e logspace
Immaginiamo di voler generare un nuovo vettore riga avente estremi 0 e 100, come nel caso precedente.
Questa volta per, invece che voler specificare la spaziatura dei singoli elementi, vogliamo definire il numero
di elementi contenuti dal vettore (e lasciare a Matlab la determinazione della spaziatura). Ammettiamo nel
nostro caso di voler ottenere un vettore contenente 1000 elementi. Questo pu essere fatto con il comando
linspace, cos definito:
y=linspace(0,100,1000);
I primi due input del comando linspace corrispondono agli estremi del vettore desdierato, mentre il terzo
input corrisponde al numero totale di elementi che si desiderano nel vettore.
Funziona in modo analogo il comando logspace, con la differenza che crea una spaziatura logaritmica invece
che lineare.
y=logspace(a,b,n);
2 : 2 + 2 + 2
Coefficienti stechiometrici
2
2
2
3
1
-1
0
-2
0
+1
2
+1
-1
-1
+1
0
In Matlab possibile creare una matrice come quella descritta in modo del tutto analogo a come sono stati
definiti i vettori. In particolar modo, si definiscono le varie righe separando gli elementi mediante delle virgole
o degli spazi, e le varie colonne distinguendo le righe con dei ;
nu=[-1 +1;0 -1;-2 -1;0 +1;+1 0];
Un altro possibile metodo per creare delle matrici definendo prima i vettori che le compongono, e poi
unendo i due vettori per creare la matrice di interesse. Costruiamo ora la matrice precedentemente descritta,
ma unendo i vettori colonna che la caratterizzano.
nuR1=[-1;0;-2;0;+1];
nuR2=[+1;-1;-1;+1;0];
nu=[nuR1 nuR2];
Vi sono altri comandi, che permettono di definire delle matrici o dei vettori speciali. Essi sono riassunti nella
seguente tabella:
Linea di comando:
Descrizione:
Crea una matrice identit n x n
Crea una matrice n x n avente tutti gli elementi
uguali a 1
Crea una matrice m x n avente tutti gli elementi
uguali a 1
Crea una matrice n x n avente tutti gli elementi
uguali a 0
Crea una matrice m x n avente tutti gli elementi
uguali a 0
eye(n)
ones(n)
ones(m,n)
zeros(n)
zeros(m,n)
Ora che abbiamo imparato a definire delle variabili scalari, dei vettori e delle matrici, possiamo vedere come
effettuare operazioni tra questi elementi.
%
%
%
%
%
Possono ovviamente essere applicate ad uno scalare unampia serie di funzioni matematiche (esponenziali,
logaritmiche, goniometriche, etc etc). In seguito presente lelenco di questi comandi:
Funzione
ceil(x)
fix(x)
floor(x)
round(x)
sign(x)
exp(x)
sqrt(x)
log(x)
log10(x)
abs(x)
angle(x)
conj(x)
imag(x)
real(x)
cos(x)
cot(x)
csc(x)
sin(x)
sec(x)
tan(x)
acos(x)
acot(x)
acsc(x)
asin(x)
asec(x)
atan(x)
cosh(x)
coth(x)
csch(x)
sinh(x)
sech(x)
tanh(x)
acosh(x)
Scopo
Arrotonda per eccesso allintero pi vicino
Arrotonda al numero intero pi vicino verso 0
Arrotonda per difetto allintero pi vicino
Arrotonda al numero intero pi vicino
Determina il segno della quantit x
Calcola il numero di Nepero elevato alla x
Calcola la radice quadrata di x
Calcola il logaritmo naturale di x
Calcola il logaritmo in base 10 di x
Calcola il valore assoluto di x
Calcola langolo di un numero complesso x
Calcola il complesso coniugato di un numero complesso x
Determina la parte immaginaria di un numero complesso x
Determina la parte reale di un numero complesso x
Calcola il coseno di x
Calcola la cotangente di x
Calcola la cosecante di x
Calcola il seno di x
Calcola la secante di x
Calcola la tangente di x
Calcola larcocoseno di x
Calcola larcocotangente di x
Calcola larcocosecante di x
Calcola larcoseno di x
Calcola larcosecante di x
Calcola larcotangente di x
Calcola il coseno iperbolico di x
Calcola la cotangente iperbolica di x
Calcola la cosecante iperbolica di x
Calcola il seno iperbolico di x
Calcola la secante iperbolica di x
Calcola la tangente iperbolica di x
Calcola larcocoseno iperbolico di x
7
acoth(x)
acsch(x)
asinh(x)
asech(x)
atanh(x)
Selezione di elementi
Ad esempio, alcuni elementi di un vettore potrebbero non interessarci, e potremmo dunque essere
interessati a considerare una sola porzione del vettore stesso. Ammettiamo di considerare un vettore avente
8 elementi, ma che ci interessino solamente gli elementi che vanno dal terzo al quinto. Tali elementi possono
essere selezionati con il seguente comando:
v=[1 2 3 4 5 6 7 8];
v(3:5)
ans =
3
In particolar modo, se fossimo interessati al valore di uno specifico elemento del vettore, basterebbe mettere
tra parentesi la posizione corrispondente a quellelemento, e Matlab ce ne restituisce il valore:
v=[10 20 30 40 50 60 70 80];
v(5)
ans =
50
Con le matrici ci si pu comportare in modo del tutto analogo. Consideriamo una matrice 3 x 3, e ammettiamo
di voler considerare solamente i primi due elementi della seconda riga. possibile fare questo utilizzando il
seguente comando:
A=[1 2 3;4 5 6;7 8 9];
A(2,1:2)
ans =
4
Il primo elemento presente tra parentesi corrisponde alla riga nella quale vogliamo considerare gli elementi.
Il secondo elemento (dopo la virgola) corrisponde alla selezione degli elementi che vogliamo prendere in
quella riga. Pu essere effettuata unoperazione analoga per selezionare gli elementi appartenenti ad una
determinata colonna:
A(1:2,2)
ans =
2
5
Come possiamo operare se vogliamo considerare tutti gli elementi di una riga o di una colonna? In questo
caso, invece che imporre una selezione di elementi, basta specificare la riga o la colonna che si vogliono
considerare, e utilizzare il simbolo : (che consente di prendere tutti gli elementi in quella riga o in quella
colonna)
A(:,2)
ans =
2
5
8
A(1,:)
ans =
1
Se volessimo invece considerare uno specifico valore allinterno della matrice, basta specificarne la posizione
(riga, colonna). Ad esempio, se nella matrice A volessimo selezionare lelemento 6, basterebbe specificare
che si trova nella seconda riga e nella terza colonna:
A(2,3)
ans =
6
possibile effettuare una procedura analoga nel caso delle matrici, utilizzando per questa volta il comando
size. Tale comando restituisce come output due diversi valori: il primo corrisponde al numero delle righe di
della matrice, mentre il secondo corrisponde al numero delle sue colonne:
A=[1 2 3;4 5 6;7 8 9];
size(A)
ans =
3
Applicando i comandi min e max ad una matrice otteniamo invece dei vettori riga che contengono, per ogni
posizione, rispettivamente gli elementi minimi e massimi delle colonne associate a quella posizione. Ad
esempio, se ho una matice 3 x 3, ottengo nelle terze posizioni del vettore riga rispettivamente lelemento pi
grande e lelemento pi piccolo della terza colonna:
A=[-9 -5 -8; 1 -6 7; 7 2 6];
min(A)
ans =
-9
-6
-8
max(A)
ans =
7
Per trovare gli elementi massimi e minimi di tutta la matrice, basta applicare due volte i comandi max e min,
e utilizzare cos in modo congiunto le due regole che abbiamo visto ora:
min(min(A))
ans =
-9
max(max(A))
ans =
7
Un altro comando utile, nel caso delle matrici, la determinazione del suo rango. Basta utilizzare il comando
rank.
10
rank(A)
ans =
3
Se applichiamo invece il comando ad una matrice, otteniamo come output un vettore riga, in cui ciascun
elemento corrisponde alla somma degli elementi della matrice presenti nella medesima colonna:
A=[-9 -5 -8; 1 -6 7; 7 2 6];
sum(A)
ans =
-1
-9
Anche in questo caso, come con i comandi min e max, se si vuole determinare la somma degli elementi di
tutta la matrice bisogna applicare il comando sum due volte:
sum(sum(A))
ans =
-5
Trasposizione
Una matrice o un vettore possono essere trasposti utilizzando
A=[1 2 3; 4 5 6; 7 8 9];
A'
ans =
1
2
3
4
5
6
7
8
9
v=[1 2 3];
v'
11
ans =
1
2
3
-0.0606
0.4848
0.0455
0.1212
0.0303
-0.0909
A livello teorico, loperazione effettuata per calcolare linversa di una matrice quadrata la seguente:
11
21
= [
1
12
22
1
11
1
2
21
] = det()[
1
12
22
1
2
] , = (1)+
Nella precedente formula, la grandezza corrisponde al minore complementare dellelemento (i,j). In altri
termini, corrisponde al determinante della matrice che si otterrebbe eliminando dalla matrice di partenza la
i-esima riga e la j-esima colonna.
21
12
22 ]; :
+
+ = [ 11
21 +
12 +
]
22 +
= [ 11
21
12
]
22
= [ 11
21
12
]
22
12
/
/ = [ 11
21 /
12 /
]
22 /
Complessivamente, effettuare unoperazione tra una matrice ed uno scalare corrisponde ad effettuare tale
procedura matematica tra i diversi elementi della matrice e lo scalare stesso. Dunque, se si parte con una
matrice avente dimensioni n x m, si ottiene infine una matrice avente sempre dimensioni n x m. Le stesse
considerazioni valgono utilizzando le funzioni matematiche goniometriche, esponenziali e logaritmiche: esse
vengono applicate indipendentemente a ciascun elemento della matrice, ottenendo cos sempre una matrice
n x m.
Somma e sottrazione
Due matrici o due vettori possono essere sommati o sottratti se e solo se hanno le stesse dimensioni (le
dimensioni sono riportate sotto i vettori e le matrici):
=
(1, ) (1, ) (1, )
=
(, 1) (, 1) (, 1)
=
(, ) (, ) (, )
Se le dimensioni delle matrici o dei vettori non fossero le medesime, Matlab restituirebbe un messaggio di
errore. La somma di due matrici o di due vettori consente di sommare gli elementi che occupano le medesime
posizioni, in modo tale di ottenere come risultato una matrice o un vettore avente le stesse dimensioni degli
elementi di partenza.
A=[1 2 3;4 5 6;7 8 9];
B=[10 11 12;13 14 15;16 17 18];
A+B
ans =
11
17
23
13
19
25
15
21
27
-9
-9
-9
-9
-9
-9
A-B
ans =
-9
-9
-9
Quando si effettua la somma o la sottrazione di due vettori, importante controllare non solo che abbiano
le medesime dimensioni, ma anche che siano entrambi dei vettori riga o dei vettori colonna. Se si effettuasse
13
la somma tra un vettore riga ed un vettore colonna, anche se con un medesimo numero di elementi, Matlab
restituirebbe un messaggio di errore:
a=[1 2 3];
b=[1;2;3];
a+b
??? Error using ==> plus
Matrix dimensions must agree.
=
, =
(, ) (, ) (, )
=1
Dalla precedente formula, notiamo subito come il numero delle colonne della prima matrice debba essere
uguale al numero di righe della seconda. Il risultato una matrice che ha il numero di righe della prima
matrice e il numero di colonne della seconda. Questo molto importante. Infatti, se in Matlab effettuiamo
un prodotto matriciale fra due matrici che non rispettano le condizioni ora esposte, esce un messaggio di
errore. Dalla precedente espressione, notiamo subito che se moltiplichiamo per se stesso un vettore riga o
un vettore colonna uscir un messaggio di errore. Se moltiplichiamo un vettore riga per un vettore colonna
(delle medesime dimensioni), otterremo come risultato del prodotto uno scalare. Se moltiplichiamo un
vettore colonna per un vettore riga, otteniamo come risultato delloperazione una matrice n x n, dove n il
numero di elementi presenti in ciascun vettore.
A=[1 2;3 4;5 6;7 8];
B=[1 2 3 4;5 6 7 8];
A*B
ans =
11
23
35
47
14
30
46
62
17
37
57
77
20
44
68
92
Come esempio del prodotto tra un vettore riga e un vettore colonna, effettuiamo la determinazione del peso
molecolare medio di una corrente gassosa. Consideriamo una corrente gassosa avente la seguente
composizione:
Composto
2
2
=
=1
14
Frazione molare
0.2
0.4
0.15
0.25
= [1
2
]; = [ ] = =
=1
Se moltiplicassimo invece il vettore frazioni molari per il vettore masse molecolari, otterremmo una matrice
n x n contenente il prodotto di ciascun elemento di x per ciascun elemento di PM:
x*PM
ans =
0.4000
0.8000
0.3000
0.5000
3.6000
7.2000
2.7000
4.5000
5.6000
11.2000
4.2000
7.0000
8.8000
17.6000
6.6000
11.0000
12
22
1
1
1
2
2
]; = [ ]; = [ ] =
Se conosciamo la matrice dei coefficienti e il vettore dei termini noti , possibile calcolare il vettore
delle incognite utilizzando due diversi metodi.
Il primo metodo quello di riduzione di Gauss. Per utilizzare questo metodo, basta utilizzare la divisione a
sinistra, nel seguente modo:
A=[0 4 6;5 1 9;7 10 5];
b=[2;5;3];
x=A\b
x =
0.2927
-0.1073
0.4049
Un altro metodo per risolvere il sistema lineare consiste nellutilizzo della matrice inversa:
[1 ] = [1 ]
15
1 ]
= [
x=inv(A)*b
x =
0.2927
-0.1073
0.4049
12
22
1
11
2
21
]; = [
1
11 11
. = [ 21 21
1 1
12 12
22 22
2 2
12
22
1
2
]
1 1
2 1
]
11 /11
/
./ = [ 21 21
1 /1
12 /12
22 /22
2 /2
1 /1
2 /1
]
11 ^11
^
. ^ = [ 21 21
1 ^1
12 ^12
22 ^22
2 ^2
1 ^1
2 ^1
]
Come possiamo vedere nelle precedenti espressioni, per effettuare delle operazioni elemento per elemento
le matrici o i vettori di partenza devono avere esattamente le stesse dimensioni. Ad esempio, non risulta
possibile effettuare unoperazione elemento per elemento che coinvolge un vettore riga e un vettore
colonna.
Per vedere un esempio con i vettori, consideriamo lo stesso esempio di prima, ossia quello del calcolo del
peso molecolare medio di una corrente gassosa. Stavolta, invece che definire il vettore dei pesi molecolari
come un vettore riga, e il vettore delle frazioni molari come un vettore colonna, decidiamo di definire
entrambi i vettori come vettori riga, e di utilizzare il prodotto elemento per elemento e il comando sum per
effettuare il calcolo del peso molecolare medio:
PM=[2 18 28 44]; % g/mol
x=[0.2 0.4 0.15 0.25];
16
PMmix=sum(PM.*x)
PMmix =
22.8000
Ciclo for
Consideriamo un vettore, avente lunghezza n. Un ciclo for ci consente di effettuare delle operazioni su tale
vettore, facendo variare lindice dopo ogni operazione in modo tale che questultima venga ripetuta per
ciascun elemento del vettore stesso. I cicli for risultano essere dunque di estrema utilit quando vogliono
essere effettuate delle medesime operazioni per i diversi elementi che caratterizzano dei vettori. Si pensi ad
esempio alla determinazione di un equilibrio termodinamico. Se siamo interessati a valutare le composizioni
allequilibrio a diverse T, basta creare un vettore di T desiderate e far variare la temperatura stessa mediante
un ciclo for, ripetendo ad ogni step le medesime operazioni di determinazione dellequilibrio termodinamico.
Vediamo un esempio applicato alle matrici. Ammettiamo di voler calcolare il prodotto tra due diverse matrici
A e B, senza per ricorrere a *. In altri termini, vogliamo creare noi un algoritmo che permetta di calcolare il
prodotto tra due matrici. Questo pu essere fatto nel seguente modo:
=
, =
(, ) (, ) (, )
=1
Come puoi notare, loperazione da fare risulta essere la medesima per ciascun elemento (i,j) della matrice.
Scrivere dunque la stessa operazione per ciascun elemento della matrice risulterebbe essere poco pratico.
Meglio inserire il comando allinterno di due cicli for diversi: il primo che faccia variare le i (fino al numero
totale di righe), il secondo che faccia variare le j (fino al numero totale di colonne.
17
N=a(1);
M=b(2);
%
%
%
%
C=zeros(N,M);
% Implementiamo due cicli for, che permettano di calcolare ciascun elemento
% della nuova matrice.
for i=1:N
for j=1:M
C(i,j)=sum(A(i,:).*B(:,j)');
%
%
%
%
%
%
end
C
C =
62
158
123
311
49
125
Da questo algoritmo possiamo notare la struttura del ciclo for. In ciascun ciclo, si specificano gli estremi tra
cui varia la variabile (nel caso di i, tra 1 e N, mentre nel caso di j tra 1 e M). Ciascun ciclo for viene quindi
concluso mediante un end. Nel nostro specifico caso, prima viene fissato un valore di i, poi con il ciclo for
interno si fa la stessa operazione per tutte le colonne (j viene fatto variare). Dunque, cambiando valore di i,
si cambia riga, e viene nuovamente effettuata la medesima operazione per tutte le colonne. In questo modo,
variano i e j, riusciamo ad effettuare la medesima operazione a tutti gli elementi della matrice di nostro
interesse.
Un altro utilizzo dei cicli for quello mirato alla risoluzione di equazioni differenziali. Matlab contiene
numerose funzioni che permettono di risolvere sistemi di equazioni differenziali (e le vedremo pi avanti in
18
questa guida). Ammettiamo di voler risolvere una semplice equazione differenziale a livello numerico
(discretizzandola). Prendiamo una reazione chimica caratterizzata da una cinetica del primo ordine:
= , = 0.010 = 2
Lespressione che permette di valutare le concentrazione di A nel tempo ricavabile risolvendo il seguente
problema di Cauchy (ammettendo di lavorare in un reattore batch):
=
{
( = 0) = 0
= ; ( + 1) = () ()
Lequazione differenziale, accompagnata dalla sua condizione al contorno, potrebbe essere tranquillamente
integrata matematicamente, per giungere in questo modo ad una soluzione analitica (esatta). Ammettiamo
per di voler procedere in via numerica, e di voler determinare landamento di nel tempo mediante una
procedura di discretizzazione. Come prima cosa, effettuiamo una discretizzazione dellintervallo temporale
nel quale vogliamo stimare i valori di concentrazione. Ciascun elemento dellintervallo temporale distante
dal precedente di una grandezza pari a .
= [0
A questo vettore di tempi sar associato un vettore ci concentrazioni, ciascuna della quale valutata nel
relativo istante temporale:
= [0
() (2) ( )]
19
close all
% Dati:
k=0.01;
CA0=2;
% Hz
% mol/m^3
% Risoluzione:
% Generiamo il vettore temporale, che nel nostro caso ha una spaziatura di
% 0.01 s e un valore massimo di 1000 s.
dt=1e-3;
t=0:dt:6e2;
%
%
%
%
CA=zeros(1,length(t));
DCA=zeros(1,length(t));
% Impostiamo lo step (1) dell'equazione differenziale:
CA(1)=CA0;
DCA(1)=-k*CA(1)*dt;
%
%
%
%
%
for i=2:length(t)
CA(i)=CA(i-1)+DCA(i-1);
DCA(i)=-k*CA(i)*dt;
end
% Questi comandi servono a generare il grafico: vedremo pi avanti nella
% guida il loro funzionamento
figure('Name','Andamento della concentrazione di A','NumberTitle','off')
plot(t,CA)
grid on
legend('C_{A}')
xlabel('t [s]')
ylabel('Concentrazione di A [mol/m_{3}]')
title('Andamento della concentrazione di A')
20
Ciclo if
Prima di effettuare la trattazione del ciclo if, introduciamo una serie di connettivi logici che risulteranno
essere funzionali nella nostra analisi.
Connettivo logico
<
>
<=
>=
==
~=
~
&
|
Il ciclo if permette di eseguire delle istruzioni diverse in funzione della casistica esaminata. In particolar
modo, se determinate condizioni di nostro interesse sono verificate, diciamo al programma di proseguire in
un determinato modo. Se tali condizioni non dovessero invece essere verificate, diciamo al programma di
proseguire in modo diverso.
21
Vediamone un esempio applicativo, prendendo in esame la struttura precedentemente creata per effettuare
il prodotto matriciale. Come abbiamo visto precedentemente, dal punto di vista teorico possibile effettuare
il prodotto tra due matrici o tra due vettori se e solo se il numero di colonne della prima matrice uguale al
numero di righe della seconda. Nel programma creato in precedenza, possiamo implementare un ciclo if,
che ci restituisca un messaggio di errore nel caso in cui le dimensioni delle due matrici non siano compatibili.
Per il messaggio di errore utilizzeremo il comando disp, che permette di visualizzare sulla Command Window
la stringa che viene racchiusa tra parentesi tonde e tra virgolette .
Come nel caso del ciclo for, il ciclo if va chiuso mediante un end.
A=[1 2 3 4;5 6 7 8];
B=[5 9 6;4 7 2;11 24 5;4 7 6];
a=size(A);
b=size(B);
%
%
%
%
%
%
%
if a(2)==b(1)
N=a(1);
M=b(2);
C=zeros(N,M);
for i=1:N
for j=1:M
C(i,j)=sum(A(i,:).*B(:,j)');
22
end
end
else
disp('Non possibile effettuare l''operazione')
end
C
C =
62
123
49
158
311
125
Nel caso appena visto le due matrici sono adatte per loperazione di prodotto matriciale, e dunque
loperazione viene effettuata. Vediamo ora un caso in cui le due matrici non sono tra di loro compatibili.
A=[1 2 3 4 5;6 7 8 9 10];
B=[5 9 6;4 7 2;11 24 5;4 7 6];
a=size(A);
b=size(B);
if a(2)==b(1)
N=a(1);
M=b(2);
C=zeros(N,M);
for i=1:N
for j=1:M
C(i,j)=sum(A(i,:).*B(:,j)');
end
end
else
disp('Non possibile effettuare l''operazione')
end
Non possibile effettuare l'operazione
Se volessimo essere ancora pi precisi, potremmo avvalerci della struttura if-elseif. In particolar modo,
immaginiamo che oltre a voler sapere che loperazione non pu essere effettuata, vogliamo anche sapere se
il numero delle colonne di A maggiore del numero delle righe di B, o viceversa. Questo pu essere effettuato
mediante il seguente algoritmo.
A=[1 2 3 4 5;6 7 8 9 10];
B=[5 9 6;4 7 2;11 24 5;4 7 6];
23
a=size(A);
b=size(B);
if a(2)==b(1)
N=a(1);
M=b(2);
C=zeros(N,M);
for i=1:N
for j=1:M
C(i,j)=sum(A(i,:).*B(:,j)');
end
end
elseif a(2)>b(1)
disp('Non possibile effettuare l''operazione: il numero di colonne di A
maggiore del numero di righe di B')
elseif a(2)<b(1)
disp('Non possibile effettuare l''operazione: il numero di colonne di A
minore del numero di righe di B')
end
Non possibile effettuare l'operazione: il numero di colonne di A maggiore del
numero di righe di B
Ciclo while
Il ciclo while permette di continuare a fare una determinata operazione fino a quando un certo criterio, da
noi deciso, viene soddisfatto. Come esempio, consideriamo nuovamente la cinetica del primo ordine
precedentemente analizzata.
= , = 0.010 = 2
Il sistema differenziale risulta essere il medesimo di quello analizzato nel caso del ciclo for. In questo caso,
immaginiamo di voler svolgere il medesimo processo di integrazione, ma di volerlo svolgere solamente fino
a quando la conversione del reagente A raggiunge il valore 0.99.
=
0
= 0.99
0
In questo caso risulta essere molto utile al nostro scopo un ciclo while. Fino a quando la conversione
inferiore al valore 0.99, proseguiamo con lintegrazione numerica. Quando raggiungiamo il valore 0.99, ci
fermiamo.
%% Risoluzione di un'equazione differenziale con un ciclo while
clc
clear all
close all
24
% Dati:
k=0.01;
CA0=2;
% Hz
% mol/m^3
% Risoluzione:
dt=1e-3;
t(1)=0;
CA(1)=CA0;
DCA(1)=-k*CA(1)*dt;
conv(1)=(CA0-CA(1))/CA0;
t(2)=dt;
CA(2)=CA(1)+DCA(1);
DCA(2)=-k*CA(2)*dt;
conv(2)=(CA0-CA(2))/CA0;
i=2;
while conv(i)<0.99
%
%
%
%
%
25
Ora che abbiamo esaminato il funzionamento dei pi importanti cicli di programmazione, proseguiamo la
nostra trattazione con un elemento fondamentale: le function.
Function
Spesso, nelle scienze, vi sono una serie di calcoli che vengono ripetuti frequentemente. Ripetere ogni volta,
allinterno dello script, le strutture di calcolo necessarie risulterebbe palloso e ingombrante. Sarebbe bello
poter scrivere i comandi necessari in una funzione esterna, e richiamarla nel nostro script quando necessario.
Questo proprio lobiettivo delle function: creare delle strutture esterne che possono essere richiamate ed
eseguire allinterno degli script.
Ti faccio subito un esempio. Prima ti ho mostrato come creare un programma che effettua il prodotto tra
due diverse matrici, e abbiamo applicato tale programma a due specifiche matrici A e B. Se questa operazione
dovesse essere effettuata frequentemente, risulterebbe assai comodo definire una function con quella
sequenza di comandi, in modo tale da poterla richiamare e da poterla applicare a due qualsiasi matrici.
La struttura di una function la seguente:
[1 , , ] = . (1 , , )
Una function un programma che, avendo a disposizione una serie di dati di input, fornisce una serie di dati
di output, effettuando delle operazioni.
Consideriamo lesempio del prodotto tra le due matrici A e B. Se vogliamo definire una function che ne faccia
il prodotto, gli input saranno proprio le matrici A e B, mentre loutput sar la matrice C, risultato del prodotto
tra A e B. Volendo, potremmo definire una serie di output maggiore, come ad esempio le dimensioni della
matrice ottenuta con loperazione di prodotto matriciale. Vediamo unapplicazione.
26
function C=prodmat(A,B)
a=size(A);
b=size(B);
if a(2)==b(1)
N=a(1);
M=b(2);
C=zeros(N,M);
for i=1:N
for j=1:M
C(i,j)=sum(A(i,:).*B(:,j)');
end
end
elseif a(2)>b(1)
C='Non possibile effettuare l''operazione: il numero di colonne di A
maggiore del numero di righe di B';
elseif a(2)<b(1)
C='Non possibile effettuare l''operazione: il numero di colonne di A
maggiore del numero di righe di B';
end
end
Ora che abbiamo creato la function prodmat e labbiamo salvata (attenzione: le function vanno salvate
esattamente con il nome che stato dato loro), possiamo applicarla a due generiche matrici, a nostro
piacimento.
A=[1 2 3;4 5 6;7 8 9];
B=[3 4;5 6];
C=prodmat(A,B)
C =
Non possibile effettuare l'operazione: il numero di colonne di A maggiore del
numero di righe di B
A=[1 2 3;4 5 6;7 8 9];
B=[3 4 5;5 6 7;9 4 3];
C=prodmat(A,B)
C =
27
40
28
28
91
70
73
142
112
118
Immaginiamo ora di voler creare unaltra applicazione, utile per gli scopi dellingegneria chimica.
Consideriamo nuovamente la corrente gassosa di uno degli esempi precedenti.
Composto
2
2
Frazione molare
0.2
0.4
0.15
0.25
Spesso, nellIngegneria Chimica, risulta essere assai utile passare da composizioni molari a composizioni
massive, e viceversa. Creiamo dunque una function che permette di effettuare entrambi questi processi.
Questa function avr tre dati di input e uno di output:
[] = (, , )
function y=convcomp(x,PM,n)
% Per n=1 convertiamo una composizione molare in una composizione massiva
if n==1
y=PM.*x/sum(PM.*x);
% Per n=2 convertiamo una composizione massiva in una composizione molare
elseif n==2
y=(x./PM)/sum(x./PM);
end
x=[0.2 0.4 0.15 0.25];
PM=[2 18 28 44];
om=convcomp(x,PM,1)
om =
28
0.0175
0.3158
0.1842
0.4825
Come si pu notare, non necessario chiamare la variabile di output con il medesimo nome che le stato
assegnato nella function. Mentre nel caso della function abbiamo chiamato la variabile di output y, in questo
caso labbiamo chiamata om. Nel caso in cui vi fossero pi variabili di output, esse possono essere chiamate
in modo diverso, tenendo conto del fatto che Matlab le restituisce con lordine in cui sono state inserite negli
output della function. Immaginiamo ora di avere un sistema analogo al precedente, ma in cui il vettore di
composizione iniziale non corrisponde alle frazioni molari ma alle frazioni massive:
Composto
2
2
Frazione massiva
0.2
0.4
0.15
0.25
x =
0.7504
0.1668
0.0402
0.0426
Rappresentazione di grafici
Nei precedenti argomenti, in particolar modo nella trattazione della risoluzione di equazioni differenziali
mediante cicli for e cicli while, abbiamo rappresentato dei grafici. La rappresentazione di grafici un
argomento molto importante, dal momento che consente di visualizzare a livello visivo informazioni su
quanto stato fatto con i precedenti step risolutivi. Vediamo ora insieme come rappresentare un grafico
monodimensionale, mediante un algoritmo commentato.
Rappresentazione di grafici 1D
%% Rappresentazione di un grafico
clc
clear all
close all
% Come prima cosa, definiamo un vettore di x (variabile indipendente) e un
% vettore di y (variabile dipendente). Immaginiamo ad esempio di voler
% rappresentare la funzione seno.
x=0:pi*1e-2:6*pi; % La grandezza pi, in Matlab, corrisponde a pi greco
y=sin(x);
% Questo primo comando permette di aprire una nuova figura, con il nome che
% desideriamo darle e senza contrassegnarla con un numero. Volendo, se non
29
% si volesse dare uno specifico nome alla figura, basterebbe scrivere figure(1):
figure('Name','Grafico della funzione sen(x)','NumberTitle','off')
% Il comando plot permette di effettuare dei grafici monodimensionali,
% specificando coma dati di input prima il vettore di variabile
% indipendenti e poi il vettore di variabili dipendenti.
plot(x,y)
% Il comando grid permette di inserire all'interno del grafico una griglia,
% in modo tale da vedere meglio i valori dei vari punti.
grid on
% Il comando legend pone una legenda all'interno del grafico, che permette di
% visualizzare il significato di ciascuna curva.
legend('sen(x)')
% Il comando axis permette di effettuare una scelta sui valori limite degli
% assi cartesiani. Ha struttura axis([xmin xmax ymin ymax)]. Il comando pu
% anche essere omesso, e Matlab si regola da solo.
axis([0 6*pi -1.5 1.5])
Vediamo ora maggiormente nel dettaglio le caratteristiche dei comandi precedentemente elencati. Partiamo
dal comando plot. Nel programma precedente, abbiamo inserito allinterno di plot solamente il vettore delle
ascisse e il vettore delle ordinate. In realt, si possono specificare anche delle informazioni in merito alla linea
con cui vogliamo che plot crei il grafico.
30
Colore
Significato
Blu
Verde
Rosso
Cyan
Magenta
Giallo
Nero
Bianco
b
g
r
c
m
y
k
w
Simbolo
.
X
+
*
s
d
v
^
<
>
p
h
Significato
Punto
Cerchio
X
Pi
Stella
Quadrato
Diamante
Triangolo (in gi)
Triangolo (in su)
Triangolo (a
sinistra)
Trangolo (a destra)
Pentagono
Esagono
Linea
:
-.
-(none)
Significato
Continua
A puntini
Tratto-punto
Tratteggiata
Nessuna
Ad esempio, se nel programma precedente avessimo utilizzato il seguente comando per plot e se avessimo
utilizzato una spaziatura sulle x di pi*1e-1, avremmo ottenuto il seguente risultato.
plot(x,y,'rd-.')
Allinterno del comando plot, in realt, possono essere inseriti pi comandi ancora, presenti nella seguente
tabella:
Comando
Effetto
Il presente comando regola lo spessore della linea
(n) con la quale viene disegnata la funzione.
Questo comando regola il colore del contorno del
simbolo scelto per rappresentare il grafico. Al
LineWidth,n
'MarkerEdgeColor','color',
31
'MarkerFaceColor','color'
'Color',[.6 0 0]
%% Rappresentazione di un grafico
clc
clear all
close all
x=0:pi*1e-1:6*pi;
y=sin(x);
figure('Name','Grafico della funzione sen(x)','NumberTitle','off')
% I tre punti servono per andare a capo
plot(x,y,'s-','Color',[.2 .6 .2],'LineWidth',2,...
'MarkerEdgeColor','r','MarkerFaceColor','b')
grid on
legend('sen(x)')
axis([0 6*pi -1.5 1.5])
xlabel('x')
ylabel('y')
title('Grafico della funzione sen(x)')
32
Se volessimo inserire allinterno di una medesima figura pi grafici, basta inserire i nuovi dati allinterno del
medesimo comando plot, a fianco dei dati precedenti. In questo caso, risulta essere opportuno aggiornare
anche il comando legend, in modo tale che fornisca delle indicazioni su entrambi i grafici. In alternativa, si
pu utilizzare un altro comando plot, specificando per prima il comando hold on. Rappresentiamo, ad
esempio, anche la funzione coseno allinterno del medesimo grafico.
%% Rappresentazione di seno e coseno sullo stesso grafico
clc
clear all
close all
x=0:pi*1e-1:6*pi;
y1=sin(x);
y2=cos(x);
figure('Name','Grafico delle funzioni sen(x) e cos(x)','NumberTitle','off')
plot(x,y1,'r-',x,y2,'b--')
grid on
legend('sen(x)','cos(x)')
axis([0 6*pi -1.5 1.5])
xlabel('x')
ylabel('sen(x),cos(x)')
title('Grafico delle funzioni sen(x) e cos(x)')
% In questo algoritmo stato aggiunto anche il comando gtext, che permette
% di inserire all'interno del grafico una stringa, specificando con il
% mouse dove posizionarla.
gtext('sen(x),cos(x)')
33
Se volessimo invece rappresentare le funzioni in due grafici distinti? In questo caso potremmo avvalerci del
comando subplot(m,n,p). Allinterno della precedente espressione, m corrisponde al numero di righe di
grafici che vogliamo creare, mentre n al numero delle colonne di grafici che vogliamo creare. In altri termini,
come se il comando subplot dividesse la figura in una matrice m x n, e raffigurasse in ogni posizione diversa
un diverso grafico. Ammettiamo, ad esempio, di voler rappresentare le funzioni seno e coseno tra di loro
affiancate, invece che sul medesimo grafico.
%% Rappresentazione di seno e coseno su grafici distinti
clc
clear all
close all
x=0:pi*1e-1:6*pi;
y1=sin(x);
y2=cos(x);
figure('Name','Grafico delle funzioni sen(x) e cos(x)','NumberTitle','off')
subplot(1,2,1)
plot(x,y1,'r-')
grid on
legend('sen(x)')
axis([0 6*pi -1.5 1.5])
xlabel('x')
ylabel('sen(x)')
title('Grafico della funzione sen(x)')
subplot(1,2,2)
plot(x,y2,'b--')
grid on
legend('cos(x)')
axis([0 6*pi -1.5 1.5])
xlabel('x')
ylabel('cos(x)')
title('Grafico della funzione cos(x)')
34
Oltre al comando plot, possono esserne utilizzati degli altri per creare dei grafici aventi delle caratteristiche
diverse.
Comando
Scopo
Crea un diagramma logaritmico di y in funzione di x
Crea un diagramma semilogaritmico di y in
funzione di x, con lasse x in scala logaritmica
Crea un diagramma semilogaritmico di y in
funzione di x, con lasse y in scala logaritmica
Crea un diagramma a gradini di y in funzione di x
Crea un diagramma a steli di y in funzione di x
Crea un diagramma a barre di y in funzione di x
Crea un diagramma polare di coordinate teta e r,
utilizzando la tipologia di linea specificata in tipo
loglog(x,y)
semilogx(x,y)
semilogy(x,y)
stairs(x,y)
stem(x,y)
bar(x,y)
polar(teta,r,tipo)
Se vogliamo rappresentare una linea non in un piano, ma in uno spazio, possiamo utilizzare il comando
plot3. Il suo funzionamento risulta essere del tutto analogo rispetto a quello del comando plot. Vediamo
un esempio di rappresentazione di una curva nello spazio, le cui coordinate sono funzione di un parametro.
() = sin() exp(0.02 ), () = cos() exp(0.02 ), () = 2 t
clc
clear all
close all
t=0:pi*1e-1:12*pi;
x=sin(t).*exp(-0.02*t);
y=cos(t).*exp(-0.02*t);
z=2*t;
figure('Name','Grafico della funzione','NumberTitle','off')
plot3(x,y,z)
grid on
xlabel('x')
ylabel('y')
zlabel('z')
35
Rappresentazione di grafici 2D
Consideriamo la seguente funzione di due variabili:
= ( 3)2 + 3 2 + 3
Rappresentiamo questa superficie in uno spazio tridimensionale. I vari comandi utilizzati sono commentati
allinterno dellalgoritmo stesso.
%% Rappresentazione di una superficie in 3D
clc
clear all
close all
% Come prima cosa, definiamo i vettore x e y, che andranno a costituire le
% ampiezze dei due assi di variabili indipendenti, con i quali valori
% vogliamo effettuare una stima della funzione in due variabili.
x=-3:1e-2:3;
y=-4:1e-2:4;
% Utilizziamo i due vettori ora creati per creare un piano (rettangolare o
% quadrato) che utilizzeremo come base per la rappresentazione della nostra
% funzione.
[X,Y]=meshgrid(x,y);
% Definiamo la funzione Z:
Z=(X-3).^3+3*X.*2.*Y+Y.^3;
figure('Name','Rappresentazione di una superficie','NumberTitle','off')
mesh(X,Y,Z)
xlabel('x')
ylabel('y')
zlabel('z')
title('Rappresentazione di una superficie')
Possono essere utilizzati anche altri comandi per generare una superficie (meshc,meshz,surf,surfc).
Essi forniscono i seguenti risultati.
Nel caso di meshc, possono anche essere visualizzate le curve di livello sul piano (x,y).
36
Con il comando meshz, vengono visualizzate delle linee di riferimento verticali sotto la superficie.
37
Nel caso del comando surf, vengono utilizzati dei pannelli colorati, invece che delle semplici linee:
Nel caso in cui si utilizzi il comando surfc, si ottengono i medesimi effetti del comando surf ma si visualizzano
anche le curve di livello sul piano (x,y):
38
Nel caso in cui non si volessero visualizzare le superfici, ma solamente le linee di livello in un piano (x,y), si
pu utilizzare il comando contour(X,Y,Z,n). Il valore n allinterno del comando corrisponde al numero di
curve di livello che si vogliono disegnare.
X =
Se si volessero visualizzare i risultati ottenuti in modo pi fine, si potrebbe utilizzare il comando disp. Il
comando disp permette di visualizzare sulla Command Window le stringe che sono poste come argomento
del comando disp stesso. Come possibile notare nel seguente comando, le stringhe vengono inserite tra .
disp('Oggi una bella giornata!')
Oggi una bella giornata!
39
Il comando disp permette d visualizzare delle stringhe, mentre noi siamo interessati a visualizzare dei numeri.
Per poter utilizzare il comando disp, risulta dunque essere necessario convertire i numeri in stringhe, e
questo pu essere effettuato con il comando num2str. Ammettiamo ad esempio di aver ottenuto come
risultato di unoperazione una temperatura di 346,2 [K].
T=346.2;
disp(['La temperatura del sistema di ',num2str(T),' [K]'])
La temperatura del sistema di 346.2 [K]
fprintf
Ammettiamo ora di voler salvare i risultati su un file di testo (.txt) esterno. Come prima cosa, creiamo un file
di testo in cui effettuare il salvataggio. Nel nostro caso chiamiamolo dati.txt. Il salvataggio possibile grazie
alla funzione fprintf, e il suo funzionamento pu essere compreso dal seguente algoritmo commentato.
%% Salvataggio di dati su file mediante fprintf
clc
clear all
close all
% Come prima cosa, generiamo un vettore di ascisse
x = 0:.1:2;
%
%
%
A
Costruiamo una matrice che ha come prima riga il vettore delle ascisse, e
come seconda e terza riga le funzioni seno e exp calcolate per ciascun
elemento del vettore delle ascisse
= [x; sin(x); exp(x)];
40
sin(x)
exp(x)
0.00
0.00000000
1.00000000
0.10
0.09983342
1.10517092
0.20
0.19866933
1.22140276
0.30
0.29552021
1.34985881
0.40
0.38941834
1.49182470
0.50
0.47942554
1.64872127
0.60
0.56464247
1.82211880
0.70
0.64421769
2.01375271
0.80
0.71735609
2.22554093
0.90
0.78332691
2.45960311
1.00
0.84147098
2.71828183
1.10
0.89120736
3.00416602
1.20
0.93203909
3.32011692
1.30
0.96355819
3.66929667
1.40
0.98544973
4.05519997
1.50
0.99749499
4.48168907
1.60
0.99957360
4.95303242
1.70
0.99166481
5.47394739
1.80
0.97384763
6.04964746
1.90
0.94630009
6.68589444
2.00
0.90929743
7.38905610
Integrazione
Integrazione numerica
Molte volte, nellambito dellIngegneria Chimica, capita di dover effettuare dei processi di integrazione.
Alcuni integrali possono essere risolti analiticamente e dunque essere determinati in modo esatto. Vi sono
per un buon numero di casistiche in cui non risulta conveniente (o non risulta possibile) calcolare un
integrale a livello analitico. In questi casi, viene in nostro aiuto il calcolo numerico, che ci consente una
determinazione non esatta degli integrali ma vicina al valore reale.
Una prima funzione che consente il calcolo numerico degli integrali trapz. Questo comando, una volta
definito un vettore di ascisse e un vettore di ordinate calcolate in corrispondenza di quelle ascisse, permette
di calcolare lintegrale definito della funzione = (), tra gli estremi definiti dal vettore delle ascisse,
mediante il metodo dei trapezi. Immaginiamo ad esempio di voler calcolare il seguente integrale definito.
41
2
0
-37.9988
Unalternativa luso delle funzioni quad o quadl. Queste funzioni hanno la seguente sintassi:
= ( , , , )
Nella precedente formula:
funzione corrisponde alla funzione che desideriamo integrare. Se vi sono operazioni come
prodotto, divisioni oppure elevamenti a potenza, in questo contesto bisogna utilizzare loperatore
preceduto dal punto.
a e b corrispondono agli estremi di integrazione.
tol un parametro che pu essere omesso, e che fornisce informazioni sulla tolleranza assoluta di
errore. Il valore di default 1e-6.
Vediamo un esempio delluso di queste funzioni per il calcolo dellintegrale visto in precedenza. La funzione
quad utilizza il metodo di Simpson, mentre la funzione quadl (che ha la stessa sintassi) utilizza il metodo di
quadratura di Lobatto.
%% Integrazione numerica: funzioni quad e quadl
clc
clear all
close all
% Effettuo il calcolo dell'integrale definito della funzione con quad:
I1=quad('x.^2.*sin(x)',0,6);
% Effettuo il calcolo dell'integrale definito della funzione con quadl:
I2=quadl('x.^2.*sin(x)',0,6);
I1 =
42
-37.9988
I2 =
-37.9988
Integrazione simbolica
Unalternativa allutilizzo dellintegrazione numerica lintegrazione simbolica. Matlab in grado di
effettuare dei calcoli analitici di integrali definiti e indefiniti, restituendone cos lespressione finale. Per
utilizzare questa potente funzione, bisogna operare in ambiente simbolico, mediante lausilio del comando
syms. Ammettiamo ad esempio di voler determinare lintegrale indefinito della precedente funzione.
Possiamo farlo utilizzando il comando int.
%% Integrazione simbolica
clc
clear all
close all
syms x
y=int(x^2*sin(x));
y =
2*cos(x) - x^2*cos(x) + 2*x*sin(x)
Per effettuare unintegrazione definita, risulta essere sufficiente specificare allinterno del commando int
gli estremi di integrazione. In questo modo otteniamo una nuova variabile simbolica, che pu essere tradotta
a quantitativo numerico mediante il comando eval.
%% Integrazione simbolica definita
clc
clear all
close all
syms x
y=int(x^2*sin(x),0,6)
I=eval(y)
y =
12*sin(6) - 34*cos(6) - 2
I =
-37.9988
43
Risulta essere assai comodo tenere a mente questi comandi, dal momento che sono di ampio utilizzo
nellambito dellIngegneria Chimica. Per vedere un esempio di utilizzo di questo comando, si consideri un
sistema termodinamico che raggiunge lequilibrio in un contesto adiabatico (capitolo sullequilibrio chimico
del libro di Termodinamica dellIngegneria Chimica, di Rota Renato).
Comando fzero
Il comando fzero risulta essere molto comodo per la risoluzione di unequazione in una singola incognita, che
vogliamo risolvere a livello numerico. Consideriamo ad esempio la seguente equazione:
+ sin = 2
Questa equazione non pu essere risolta a livello analitico, e dunque per risolverla possono essere utilizzati
degli strumenti numerici. Vediamo, ad esempio, come poter utilizzare il comando fzero.
%% Azzeramento di un'equazione in una variabile
clc
clear all
close all
% Scelgo un valore di primo tentativo da immettere nell'algoritmo di
% azzeramento.
X0=0.2;
% Struttura dellalgoritmo fzero
X=fzero('expsin',X0)
----------------------------------------------------------------------------------------------------------------------------------------------X =
0.4487
Come possiamo notare nel precedente algoritmo, nel comando fzero bisogna inserire prima il nome della
funzione da azzerare (che viene definita in una function a parte), poi fornire un valore di primo tentativo, dal
quale il comando partir per effettuare lazzeramento numerico. Allinterno della function definiamo la
funzione che vogliamo azzerare. Dal momento che vogliamo azzerare la funzione F, tutti i termini della
funzione di partenza sono stati portati da un medesimo lato delluguale:
= + sin 2 = 0
Vediamo ora un esempio applicativo di questo comando in una tipica applicazione dellIngegneria Chimica.
Ammettiamo di voler costruire il diagramma delle T di bolla e rugiada e il diagramma y-x di una miscela
44
binaria, dove x corrisponde alla frazione molare in fase liquida del composto pi leggero, y alla sua frazione
molare in fase vapore e T alla temperatura del sistema. In particolar modo, ammettiamo di considerare un
sistema binario benzene-toluene, caratterizzato dai seguenti dati:
= 1
Benzene
Toluene
A
15.9008
16.0137
B
2788.51
3096.52
ln () =
C
-52.36
-53.67
[]
353.3
383.8
, ()[][]
+
Immaginiamo di poter utilizzare il modello di gas perfetto. In questo caso, la relazione di equilibrio
termodinamico tra specie espressa dalla legge di Raoult:
() =
() =
Imponendo che la sommatoria delle frazioni molari in fase vapore delle due specie debba essere 1, otteniamo
che:
() + () = ( + ) =
Per trovare le T di bolla a diverse composizioni, lequazione che vogliamo azzerare :
= () + () = 0
Tale equazione contiene la sola incognita T. Facendo variare la composizione del sistema, possiamo calcolare
la T di bolla a diverse condizioni. Per ciascuna condizione si pu determinare la corrispondente frazione
molare in fase vapore utilizzando lequilibrio tra fasi:
=
()
=
Con queste informazioni possiamo costruire il diagramma delle T di bolla e delle T di rugiada (per la curva di
rugiada basta rappresentare T in funzione di y, invece che di x), e il diagramma y/x. Lalgoritmo di calcolo il
seguente:
%% Creazione di un diagramma di T bolla e di T rugiada
clc
clear all
close all
global A B C P xb xt i
%% Dati: Si riferiscono alle specie S=[benzene toluene]
P=1; %[atm]
A=[15.9008 16.0137]; % Parametri della Antoine
B=[2788.51 3096.52];
C=[-52.36 -53.67];
Tebn=[353.3 383.8]; %[K]
45
%% Risoluzione:
xb=0:0.001:1;
xt=1-xb;
% Creiamo dei vettori, aventi la medesima lunghezza di xb, costituiti
inizialmente da soli 0, ma che conterranno poi I valori di T0 (temperature di
primo tentativo) e di T
T0=zeros(1,length(xb));
T=zeros(1,length(xb));
for i=1:length(xb)
T0(i)=Tebn(2)+xb(i).*(Tebn(1)-Tebn(2)); % Valore lineare di primo tentativo
T(i)=fzero('fTbollrug',T0(i));
end
Pev=exp(A(1)-B(1)./(T+C(1)))/760;
k=Pev./P;
yb=k.*xb;
% Creazione dei diagrammi
figure('Name','Diagramma Tbolla-Trugiada e diagramma y/x','NumberTitle','off')
subplot(1,2,1)
plot(xb,T,'b-','LineWidth',2)
% Il comando hold on permette di sovrascrivere sul medesimo grafico
hold on
plot(yb,T,'k-','LineWidth',2)
grid on
xlabel('Frazione molare di benzene')
ylabel('T [K]')
legend('Curva bolla','Curva rugiada')
subplot(1,2,2)
plot(xb,xb,'b-','LineWidth',2)
hold on
plot(xb,yb,'k-','LineWidth',2)
grid on
xlabel('Frazione molare di benzene (fase L)')
ylabel('Frazione molare di benzene (fase V)')
legend('Bisettrice','Curva y/x')
46
Nel precedente algoritmo tutti I comandi sono gi stati spiegati nelle sezioni precedenti, tranne uno. Mi
riferisco al comando global.
Il comando global serve a fare in modo che la function attinga ai dati gi presenti allinterno dello script
principale, senza doverli riscrivere allinterno della function stessa. Tale comando va inserito sia allinterno
dello script principale che allinterno della function, in entrambi i casi allinizio dellalgoritmo stesso e con le
variabili nel medesimo ordine. Nel caso dello script il comando global viene inserito dopo i comandi clc,
clear all e close all, mentre nel caso della function dopo la definizione iniziale dei dati di input e
output della medesima. I dati condivisi mediante il comando global appaiono nello script e nella function
di colore azzurro.
Nel nostro caso, abbiamo fatto in modo che la function potesse risalire direttamente dallo script principale
ai valori dei parametri delle leggi di Antoine (A,B,C), al valore della pressione (P), ai valori di frazioni molari
di benzene e toluene e al valore dellindice i. Risulta molto importante, nel nostro caso, trasferire alla function
informazioni sul valore dellindice i, che cambia ad ogni passaggio del ciclo for. Infatti, in questo modo, la
function sa in qualsiasi contesto quali elementi dei vettore xb e xt deve considerare. Lutilizzo del comando
global rende la procedura risolutiva e gli algoritmi pi snelli, in quanto permette di non dover riportare ogni
volta i dati anche allinterno delle function.
Comando fsolve
Mentre il comando fzero consente di effettuare azzeramenti di una funzione in una variabile, il comando
fsolve consente la risoluzione di sistemi di N equazioni linearmente indipendenti in N incognite. Il comando
fsolve pu essere utilizzato anche per unequazione in una singola incognita, al posto del comando fzero.
Il funzionamento del comando risulta essere molto simile a quello di fzero, con la differenza che in questo
caso dovremo fornire non un singolo valore di primo tentativo ma un vettore N-dimensionale di valori di
primo tentativo. Inoltre, non dovremo scrivere una sola funzione F, ma tante funzioni F quante sono le
47
incognite. Avremo dunque un vettore F di equazioni allinterno della function, e dobbiamo sempre stare
attenti al fatto che tale vettore sia strutturato come vettore colonna. Se cos non fosse, fsolve restituirebbe
un errore.
Vediamo ora un algoritmo commentato, allinterno del quale viene utilizzato il comando fsolve e in cui
vengono usati molti altri comandi gi descritti in precedenza. Consideriamo la reazione di sintesi del
metanolo, e determiniamo la conversione di monossido di carbonio in diverse condizioni di P e T (prima
esercitazione di Chimica Industriale Organica). Nel farlo, utilizziamo lequazione di stato PR. Le reazioni che
avvengono nel sistema sono le seguenti:
1
+ 22 3
2
2 + 2 + 2 0
IN
1
0.01
2
0
0
3.01
2
2
2 0
3
TOT
,1 =
3
2 2
,2 =
2
2 2
OUT
1 1 + 2
0.01 2
2 21 2
2
1
3.01 21
Tenendo conto che lo stato di riferimento corrisponde a gas ideale 1 [bar], possiamo riformulare
matematicamente le precedenti espressioni come segue:
,1 = (
(3.01 21 )2 1 3
2
)
(1 1 + 2 ) (2 21 2 )2 2 2
(1) = ,1 (
) (1 1 + 2 ) (2 21 2 )2 2 2 (3.01 21 )2 1 3 = 0
,2 =
2 (1 1 + 2 )2
2 2 (0.01 2 )(2 21 2 )
48
close all
%% Dati:
% Considero il vettore delle specie S=[CO CO2 H2 H2O CH3OH]
% Condividiamo con le function i dati utili allo sviluppo di calcoli
global Keq1 Keq2 i P j phi
% Forniamo i dati sul punto critico dei vari elementi, pi il fattore
% acentrico di Pitzer.
Tc=[132.92 304.19 33.18 647.13 512.58]; % [K]
Pc=[34.99 73.82 13.13 220.55 80.96]*1e5; % [Pa]
om=[0.066 0.228 -0.220 0.345 0.566]; % [ad]
% Forniamo i dati utili al calcolo del DG di formazione dei composti, in
% funzione della temperatura
AdG=[-109.885 -393.360 0 -241.74 -201.86]*1e3; % [J/mol]
BdG=[-9.2218e-2 -3.8212e-3 0 4.1740e-2 1.2542e-1]*1e3; % [J/(mol K)]
CdG=[1.4547e-6 1.3322e-6 0 7.4281e-6 2.0345e-5]*1e3; % [J/(mol K^2)]
R=8.314; % [J/(mol K)]
% Creiamo dei vettori di pressione e di temperatura ai quali valutare
% l'equilibrio termodinamico.
T=400:50:700; % [K]
P=50e5:50e5:300e5; % [Pa]
% Creiamo i vettori che saranno di supporto ai seguenti calcoli. I loro
% elementi verranno modificati man mano che i calcoli proseguiranno.
Keq1=zeros(length(T),1);
Keq2=zeros(length(T),1);
Z=zeros(length(Tc),1);
A=zeros(length(Tc),1);
B=zeros(length(Tc),1);
phi=zeros(length(Tc),1);
phiCO=zeros(length(T),length(P));
phiCO2=zeros(length(T),length(P));
phiH2=zeros(length(T),length(P));
phiH2O=zeros(length(T),length(P));
phiCH3OH=zeros(length(T),length(P));
lam1=zeros(length(T),length(P));
lam2=zeros(length(T),length(P));
%Come ciclo pi esterno poniamo un ciclo for sull temperatura, e per ogni
%temperatura calcoliamo i DG di formazione dei composti e le costanti di
%equilibrio delle due reazioni che caratterizzano il sistema.
for i=1:length(T)
DG0=AdG+BdG*T(i)+CdG*T(i)^2; % [J/mol]
DGR1=DG0(5)-DG0(1); % [J/mol]
DGR2=DG0(1)+DG0(4)-DG0(2); % [J/mol]
Keq1(i)=exp(-DGR1/(R*T(i)));
49
Keq2(i)=exp(-DGR2/(R*T(i)));
%All'interno del ciclo for sulla temperatura, apriamo un nuovo ciclo
%for sulla pressione.
for j=1:length(P)
%Ad ogni pressione e ad ogni temperatura, calcoliamo le grandezze
%che ci permettono di determinare il coefficiente di fugacit di
%ciascun composto. Questo fatto mediante una function esterna,
%che si chiama Eos_v (pu essere trovata sul libro di Termodinamica
%dell'Ingegneria Chimica). Notiamo che i valori dei parametri Z, A
%e B dei composti vengono aggiornati ad ogni ciclo, dal momento che
%sono di nostro interesse solamente per l'azzeramento del sistema
%di equazioni.
for k=1:length(Tc);
[Z(k),A(k),B(k)]=Eos_v(T(i),P(j),Tc(k),Pc(k),om(k),4);
phi(k)=exp(Z(k)-1-log(Z(k)-B(k))+(A(k)/(2*sqrt(2)*B(k)))*...
log((Z(k)+B(k)*(1-sqrt(2)))/(Z(k)+B(k)*(1+sqrt(2)))));
end
%
%
%
%
%
%
%
X=fsolve('EqMetanolo',[0.1 1e-4]);
% Salviamo i valori di lambda1 e lambda2 alla i-esima temperatura e
% j-esima pressione
lam1(i,j)=X(1);
lam2(i,j)=X(2);
% Salviamo i valori dei coefficienti di fugacit dei composti
phiCO(i,j)=phi(1);
phiCO2(i,j)=phi(2);
phiH2(i,j)=phi(3);
phiH2O(i,j)=phi(4);
phiCH3OH(i,j)=phi(5);
end
end
% Cancelliamo nuovamente la Command Window, dal momento che fsolve scrive
% dei messaggi in merito ai suoi processi di azzeramento.
clc
% Calcoliamo le matrici di moli e di frazioni molari finali per ciascun
% composto.
nout=3.01-2*lam1;
noutCO=1-lam1+lam2;
50
noutCO2=0.01-lam2;
noutCH3OH=lam1;
noutH2=2-2*lam1-lam2;
noutH2O=lam2;
convCO=lam1-lam2;
xoutCO=noutCO./nout;
xoutCO2=noutCO2./nout;
xoutH2=noutH2./nout;
xoutH2O=noutH2O./nout;
xoutCH3OH=noutCH3OH./nout;
% Creiamo delle matrici di ausilio per la funzione fprint
A1=[(P./1e5)',xoutCO(1,:)',xoutCO2(1,:)',xoutH2(1,:)',xoutH2O(1,:)',...
xoutCH3OH(1,:)',noutCO(1,:)',noutCO2(1,:)',noutH2(1,:)',...
noutH2O(1,:)',noutCH3OH(1,:)'];
A2=[(P./1e5)',xoutCO(2,:)',xoutCO2(2,:)',xoutH2(2,:)',xoutH2O(2,:)',...
xoutCH3OH(2,:)',noutCO(2,:)',noutCO2(2,:)',noutH2(2,:)',...
noutH2O(2,:)',noutCH3OH(2,:)'];
A3=[(P./1e5)',xoutCO(3,:)',xoutCO2(3,:)',xoutH2(3,:)',xoutH2O(3,:)',...
xoutCH3OH(3,:)',noutCO(3,:)',noutCO2(3,:)',noutH2(3,:)',...
noutH2O(3,:)',noutCH3OH(3,:)'];
A4=[(P./1e5)',xoutCO(4,:)',xoutCO2(4,:)',xoutH2(4,:)',xoutH2O(4,:)',...
xoutCH3OH(4,:)',noutCO(4,:)',noutCO2(4,:)',noutH2(4,:)',...
noutH2O(4,:)',noutCH3OH(4,:)'];
A5=[(P./1e5)',xoutCO(5,:)',xoutCO2(5,:)',xoutH2(5,:)',xoutH2O(5,:)',...
xoutCH3OH(5,:)',noutCO(5,:)',noutCO2(5,:)',noutH2(5,:)',...
noutH2O(5,:)',noutCH3OH(5,:)'];
A6=[(P./1e5)',xoutCO(6,:)',xoutCO2(6,:)',xoutH2(6,:)',xoutH2O(6,:)',...
xoutCH3OH(6,:)',noutCO(6,:)',noutCO2(6,:)',noutH2(6,:)',...
noutH2O(6,:)',noutCH3OH(6,:)'];
A7=[(P./1e5)',xoutCO(7,:)',xoutCO2(7,:)',xoutH2(7,:)',xoutH2O(7,:)',...
xoutCH3OH(7,:)',noutCO(7,:)',noutCO2(7,:)',noutH2(7,:)',...
noutH2O(7,:)',noutCH3OH(7,:)'];
% Salviamo i dati su un file esterno. Per farlo, necessario salvare un
% file in formato di testo con il nome EqMetanolo.txt
fileID = fopen('EqMetanolo.txt','wt');
fprintf(fileID,'T=400 [K]\n\n');
fprintf(fileID,'%8s %11s %11s %11s %11s %11s %11s %11s %11s %11s %11s\n',...
'P [bar]','xCO','xCO2','xH2','xH2O','xCH3OH',...
'nCO','nCO2','nH2','nH2O','nCH3OH');
fprintf(fileID,'%8.2f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f
%10.9f %10.9f\n',A1');
fprintf(fileID,'\n');
fprintf(fileID,'T=450 [K]\n\n');
fprintf(fileID,'%8s %11s %11s %11s %11s %11s %11s %11s %11s %11s %11s\n',...
'P [bar]','xCO','xCO2','xH2','xH2O','xCH3OH',...
'nCO','nCO2','nH2','nH2O','nCH3OH');
fprintf(fileID,'%8.2f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f
%10.9f %10.9f\n',A2');
fprintf(fileID,'\n');
fprintf(fileID,'T=500 [K]\n\n');
fprintf(fileID,'%8s %11s %11s %11s %11s %11s %11s %11s %11s %11s %11s\n',...
'P [bar]','xCO','xCO2','xH2','xH2O','xCH3OH',...
'nCO','nCO2','nH2','nH2O','nCH3OH');
fprintf(fileID,'%8.2f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f
%10.9f %10.9f\n',A3');
51
fprintf(fileID,'\n');
fprintf(fileID,'T=550 [K]\n\n');
fprintf(fileID,'%8s %11s %11s %11s %11s %11s %11s %11s %11s %11s %11s\n',...
'P [bar]','xCO','xCO2','xH2','xH2O','xCH3OH',...
'nCO','nCO2','nH2','nH2O','nCH3OH');
fprintf(fileID,'%8.2f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f
%10.9f %10.9f\n',A4');
fprintf(fileID,'\n');
fprintf(fileID,'T=600 [K]\n\n');
fprintf(fileID,'%8s %11s %11s %11s %11s %11s %11s %11s %11s %11s %11s\n',...
'P [bar]','xCO','xCO2','xH2','xH2O','xCH3OH',...
'nCO','nCO2','nH2','nH2O','nCH3OH');
fprintf(fileID,'%8.2f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f
%10.9f %10.9f\n',A5');
fprintf(fileID,'\n');
fprintf(fileID,'T=650 [K]\n\n');
fprintf(fileID,'%8s %11s %11s %11s %11s %11s %11s %11s %11s %11s %11s\n',...
'P [bar]','xCO','xCO2','xH2','xH2O','xCH3OH',...
'nCO','nCO2','nH2','nH2O','nCH3OH');
fprintf(fileID,'%8.2f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f
%10.9f %10.9f\n',A6');
fprintf(fileID,'\n');
fprintf(fileID,'T=700 [K]\n\n');
fprintf(fileID,'%8s %11s %11s %11s %11s %11s %11s %11s %11s %11s %11s\n',...
'P [bar]','xCO','xCO2','xH2','xH2O','xCH3OH',...
'nCO','nCO2','nH2','nH2O','nCH3OH');
fprintf(fileID,'%8.2f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f %10.9f
%10.9f %10.9f\n',A7');
fclose(fileID);
type('Es1CIO2.txt')
% Creiamo una superficie di conversioni di CO per vari valori di pressione
% e di temperatura.
[X,Y]=meshgrid(P*1e-5,T);
meshc(X,Y,convCO)
xlabel('Pressione [bar]')
ylabel('Temperatura [K]')
zlabel('Conversione CO')
% Effettuiamo una medesima rappresentazione in un grafico bidimensionale,
% modificando come parametro la pressione.
figure('Name','Andamento della conversione di CO','NumberTitle','off')
plot(T,convCO(:,1),T,convCO(:,2),T,convCO(:,3),T,convCO(:,4),T,convCO(:,5),T,con
vCO(:,6))
grid on
legend('50 [bar]','100 [bar]','150 [bar]','200 [bar]','250 [bar]','300 [bar]')
xlabel('T [K]')
ylabel('Conversione di CO [adl]')
title('Andamento della conversione di CO')
----------------------------------------------------------------------------------------------------------------------------------------------function F=EqMetanolo(X)
% Definiamo le function da azzerare. F corrisponde al vettore colonna delle
% equazioni da azzerare, mentre X corrisponde alle variabili di azzeramento
% del sistema.
global Keq1 Keq2 i P j phi
52
---------------------------------------------------------------------------------------------------------------------------------------------function [Z,A,B,alT,k]=Eos_v(T,P,Tc,Pc,om,tipo)
% Questa funzione permette di effettuare il calcolo dei parametri utili
% alla stima del coefficiente di fugacit, e permette di scegliere tra pi
% funzioni di stato.
%% 1) Dati:
R=8.314;
RT=R*T;
RTc=R*Tc;
TR=T/Tc;
%% 2) Calcolo dei parametri dell'equazione nella forma
Z^3+alfa*Z^2+beta*Z+gamma=0
if tipo==1 %VdW
a=27*RTc^2/(64*Pc);
b=RTc/(8*Pc);
A=a*P/(RT)^2;
B=b*P/(RT);
alfa=-1-B;
beta=A;
gamma=-(A*B);
end
if tipo==2 %RK
a=0.42748*RTc^2/(Pc*sqrt(TR));
b=0.08664*RTc/Pc;
A=a*P/(RT)^2;
B=b*P/(RT);
alfa=-1;
beta=A-B-B^2;
gamma=-(A*B);
end
if tipo==3 %RKS
k=0.48+1.574*om-0.176*om^2;
alT=(1+k*(1-sqrt(T/Tc)))^2;
a=0.42748*alT*RTc^2/Pc;
53
b=0.08664*RTc/Pc;
A=a*P/(RT)^2;
B=b*P/(RT);
alfa=-1;
beta=A-B-B^2;
gamma=-(A*B);
end
if tipo==4 %PR
k=0.37464+1.54226*om-0.26992*om^2;
alT=(1+k*(1-sqrt(T/Tc)))^2;
a=0.45724*alT*RTc^2/Pc;
b=0.07780*RTc/Pc;
A=a*P/(RT)^2;
B=b*P/(RT);
alfa=-1+B;
beta=A-2*B-3*B^2;
gamma=-(A*B)+B^2+B^3;
end
%% 3) Risoluzione analitica della cubica:
p=beta-alfa^2/3;
q=2*alfa^3/27-alfa*beta/3+gamma;
q2=q/2;
a3=alfa/3;
D=q^2/4+p^3/27;
if D>0
if (q2+sqrt(D))>0 && (-q2+sqrt(D))>0
Z1=(-q2+sqrt(D))^(1/3)+(-(q2+sqrt(D))^(1/3))-a3;
elseif (q2+sqrt(D))>0 && (-q2+sqrt(D))<0
Z1=(-(+q2-sqrt(D)))^(1/3)+(-(q2+sqrt(D))^(1/3))-a3;
elseif (q2+sqrt(D))<0 && (-q2+sqrt(D))>0
Z1=(-q2+sqrt(D))^(1/3)+((-q2-sqrt(D))^(1/3))-a3;
else
Z1=(-(+q2-sqrt(D)))^(1/3)+((-q2-sqrt(D))^(1/3))-a3;
end
Z=[Z1 Z1 Z1];
elseif D==0
Z1=-2*(q2)^(1/3)-a3;
Z2=(q2)^(1/3)-a3;
Z=[Z1 Z2 Z2];
else
r=sqrt(-p^3/27);
teta=acos(-q2*sqrt(-27/p^3));
Z1=2*r^(1/3)*cos(teta/3)-a3;
Z2=2*r^(1/3)*cos((2*pi+teta)/3)-a3;
Z3=2*r^(1/3)*cos((4*pi+teta)/3)-a3;
Z=[Z1 Z2 Z3];
end
% Ordiniamo in senso crescente gli elementi di Z
Z=sort(Z);
% Scegliamo il valore di Z corrispondente alla fase gas
Z=Z(3);
54
55
, 1 = 0.7[]2 = 0.4[]
= 1
= 1 2
= 2
( = 0) = 5 [ 3 ]
{ ( = 0) = ( = 0) = 0
%% Risoluzione di un sistema di equazioni differenziali
clc
clear all
close all
global k1 k2
%% Dati:
k1=0.7;
k2=0.4;
CA0=5;
% Hz
% Hz
% mol/m^3
%% Risoluzione:
% Costruiamo il vettore di condizioni iniziali
C0=[CA0 0 0];
% Nel risolvere le equazioni differenziali, risulta essere utile
% specificare le seguenti opzioni, per migliorare le performance del
% risolutore numerico:
options=odeset('RelTol',1E-8,'AbsTol',1E-12);
% tSpan il vettore che caratterizza i tempi di derivazione.
56
tSpan=0:1e-4:5;
%
%
%
%
%
%
%
[t,C] = ode45('fEqDiff',tSpan,C0,options);
% Definiamo i vettori delle concentrazioni di ciascuna specie:
CA=C(:,1);
CB=C(:,2);
CC=C(:,3);
% possibile trovare l'istante temporale corrispondente alla massima
% concentrazione di B nel seguente modo:
CBmax=max(CB);
% Il seguente comando permette di trovare l'indice vettoriale
% corrispondente alla concentrazione massima di B.
i=find(CB==CBmax);
tmax=t(i);
% Rappresentiamo a livello grafico l'andamento delle concentrazioni delle
% specie
figure('Name','Andamento delle concentrazioni di A,B e C','NumberTitle','off')
plot(t,CA,t,CB,t,CC)
grid on
legend('C_{A}','C_{B}','C_{C}')
xlabel('t [s]')
ylabel('Concentrazione [mol/m^{3}]')
title('Andamento delle concentrazioni di A,B e C')
gtext('C_{A}')
gtext('C_{B}')
gtext('C_{C}')
----------------------------------------------------------------------------------------------------------------------------------------------function dcdt=fEqDiff(t,C)
%
%
%
%
%
global k1 k2
% Scriviamo per prima l'equazione differenziale che governa la
% concentrazione della specie A, poi quelle delle specie B e C. Infinte,
57
Allinterno del programma stato utilizzato il comando ode45. Matlab in realt dispone di pi funzioni utili
alla risoluzione di equazioni differenziali, che usano metodi diversi e che risultano essere appropriate a diversi
contesti. In particolar modo, alcune ode risultano essere particolarmente adatte alla risoluzione di problemi
stiff, caratterizzati da ordini di grandezza molto diversi. Nella seguente tabella (presa da Matlab 6 per
lIngegneria e la Scienza) sono riassunti i vari comandi, con specificate le loro caratteristiche:
Funzione
Descrizione
Risolutore di ordine basso. Non complessa.
Risolutore di ordine medio. Non complessa.
Risolutore di ordine variabile. Non complessa.
Risolutore di ordine basso. Complessa.
Risolutore basato sul metodo dei trapezi.
Moderatamente complessa.
Risolutore di ordine basso. Complessa.
Risolutore di ordine variabile. Complessa.
ode23
ode45
ode113
ode23s
ode23t
ode23tb
ode15s
58
Abbiamo visto come risolvere, mediante le ode, sistemi di equazioni differenziali. Ora analizziamo come poter
risolvere delle equazioni differenziali di grado superiore al primo.
59
----------------------------------------------------------------------------------------------------------------------------------------------function dxdt=fEqDiff2(t,X)
dxdt(1)=X(2);
dxdt(2)=(t^2+3*t)/4+0.5*X(2)-1.5*X(1);
dxdt=dxdt';
60