Per studiare il moto di un fluido in condotta:
Nella forma più semplice possibile, abbiamo che:
H1−H2=W12
Dove:
H1
ed H2
sono i valori del carico totale ai due estremiH1−H2
rappresenta la forza motriceW12
rappresenta le perdite di caricoEntrando un po' più nei dettagli, abbiamo che:
Il carico totale è dato da:
Hi=piρg+z+v2i2g
Dove:
p
è la pressioneρ
è la densità del fluidog
è l'accelerazione di gravitàz
è la quotav
è la velocitàEntrando un po' più nei dettagli, abbiamo che:
Per quanto riguarda le perdite di carico:
W12=n∑i=1(W(dist)i+W(conc)i)
Dove:
n
è il numero di tratte della condottaW(dist)i
sono le perdite distribuite per la tratta i
W(conc)i
sono le perdite concentrate per la tratta i
Entrando un po' più nei dettagli, abbiamo che:
Sviluppando i due termini W(dist)i
e W(conc)i
, otteniamo:
W(conc)i+W(dist)i=4fiDiv2i2gLi+mi∑j=1ki,jv2i2g
Dove:
Di
è il diametro idraulico della tratta i
-maLi
è la lunghezza della tratta i
-mavi
è la velocità nella tratta i
-maki,j
sono i coefficienti per le m
perdite concentratef
è il fattore di attrito e dipende dalla velocitàEntrando un po' più nei dettagli, abbiamo che:
In particolare, per il fattore di attrito sappiamo che:
fi=f(Rei,εiDi)
Dove:
εi
è la scabrezza nella tratta i
-maRei
è il numero di Reynolds per la tratta i
-maRei=viDiν
Entrando un po' più nei dettagli, abbiamo che:
Per calcolare fi
possiamo usare per esempio l'equazione di Churchill
fi=((8Rei)12+1(Ai+Bi)3/2)1/12
Con:
Ai=(2.457log(1(7/Rei)0.9+0.27(εi/Di)))16Bi=(37530Rei)16
Entrando un po' più nei dettagli, abbiamo che:
Infine sappiamo che la portata Q
è data da:
Q=πD2i4vi
vi
e D2i
per ogni trattaH1−H2
Partiamo dal caso più semplice:
H1−H2
H1−H2
Partiamo dal caso più semplice:
H1−H2
Questo tipo di problema è molto semplice!
H1−H2=4fDv22gL+m∑j=1kjv22g
v
e Q
Consideriamo una situazione più interessante:
v
e Q
Consideriamo una situazione più interessante:
L'equazione principale è la stessa di prima:
H1−H2=4fDv22gL+m∑j=1kjv22g
v
non è nota e compare nell'espressione di f
f=f(Re,ε/D)
...v
e Q
Possiamo risolverlo utilizzando la IPF
Ci serve una espressione per v
, che chiameremo g(f)
:
v=g(f)=√2g(H1−H2)(4fLD+∑mj=1kj)
v
è nascosta: f
dipende da Re
e quindi da v
v
e Q
Possiamo risolverlo utilizzando la IPF
Ci serve una espressione per v
, che chiameremo g(f)
:
v=g(f)=√2g(H1−H2)(4fLD+∑mj=1kj)
v
è nascosta: f
dipende da Re
e quindi da v
Quindi per ogni iterazione di IPF dobbiamo calcolare:
v(k)Re=vDν→Re(k)f=f(Re,ε/D)→f(k)v=g(f)→⏟funzione di transizionev(k+1)
v
e Q
Questa volta usare il calcolatore è una buona idea
Ci rimane un problema da risolvere:
Da quale valore di v
possiamo partire?
v(0)=2m/s
è una buona ideav(0)
a partire da altri valoriVediamo qualche esempio...
v
e Q
Per esempio, possiamo partire da f
:
f(−1)
f
in molti casi è 0.005
f(−1)
possiamo calcolare v(0)
:f(−1)v=g(f)→v(0)
v(k)Re=vDν→Re(k)f=f(Re,ε/D)→f(k)v=g(f)→v(k+1)
Si può usare lo stesso metodo per altre grandezze
Re
se abbiamo una idea del tipo di motov
e Q
Se abbiamo più di una tratta:
La velocità in ogni tratta dipende dal Di
, ma la portata è costante
Quindi, conviene concentrarsi sull'ottenere la portata
v
e Q
Se abbiamo più di una tratta:
La velocità in ogni tratta dipende dal Di
, ma la portata è costante
Quindi, conviene concentrarsi sull'ottenere la portata
Possiamo ottenere una espressione per la portata:
Q=h(f1,f2,…)=√(H1−H2)π2g8∑ni=11D4i(4fiLiDi+∑mij=1ki,j)
h(f1,f2,…)
f1,f2,...
dipendono a loro volta da Q
v
e Q
A questo punto possiamo applicare la IPF
Lo schema è il seguente:
Q(k)vi=4QπD2i→v(k)iRei=viDiν→Re(k)ifi=f(Rei,ε/Di)→f(k)iQ=h(f1,f2,…)→Q(k+1)
Come nel caso precedente:
I calcoli sono tanti e conviene automatizzarli
v
e Q
Per quanto riguarda il valore di partenza:
Q(0)
a partire da altri valoriPer esempio:
f0=f1=f2=0.005
Q(0)
e procediamo come al solitoPossiamo usare lo stesso metodo con altre grandezze:
vi
oppure Rei
D
Consideriamo un ultimo tipo di problema:
È un esempio di problema di progetto
D
Consideriamo un ultimo tipo di problema:
È un esempio di problema di progetto
Partiamo da una espressione per D
D=d(f)=(32Lfπ2g(H1−H2)Q2)1/5
d(f)
f
dipende a sua volta da D
D
A questo punto possiamo usare IPF
Lo schema è il seguente:
D(k)v=4QπD2i→v(k)Re=vDν→Re(k)f=f(Re,ε/D)→f(k)D=d(f)→D(k+1)
Per ottenere una stima iniziale possiamo:
f
(e.g. f=0.005
) ed ottenere D(0)
v
(e.g. v=2m/s
)Re
(se abbiamo una idea sul tipo di moto)Possiamo usare IPF per risolvere l'equazione di Bernoulli
Per una buona ragione:
Purtroppo IPF ha anche diversi limitazioni:
Principali Limitazioni di IPF: |
---|
Convergenza non garantita |
Difficile controllare a quale punto fisso si converge |
Necessità di trasformare l'equazione |
La convergenza dipende dalla trasformazione |
Alcune trasformazioni (e.g. √⋅ ) possono eliminare punti fissi |
Possiamo però formulare lo stesso problema in modo diverso
Data una equazione non lineare, è molto facile portarla nella forma:
f(x)=0
g(x)=h(x)
g(x)−h(x)=0
Possiamo però formulare lo stesso problema in modo diverso
Se abbiamo un sistema di m
equazioni in n
incognite
g1(x1,x2,…xn)=0g2(x1,x2,…xn)=0…gm(x1,x2,…xn)=0
Possiamo vederlo come:
f(x)=0
In sostanza per risolvere un sistema/equazione non lineare...
...Possiamo concentrarci nel trovare una soluzione per:
f(x)=0
f(x)
un valore x∗
tale che f(x∗)=0
Questa formulazione offre due grossi vantaggi:
Consideriamo l'equazione di Bernoulli (singola tratta)
Possiamo portarla nella forma:
(H1−H2)−4fDv22gL−m∑j=1kjv22g=0
v
(e quindi Q
)...D
...Ora ci serve solo un metodo per trovare lo zero di una funzione!
Cominciamo facendo qualche ipotesi semplificativa:
f(x)
è univariata e scalare:f:R→R
f(x)
è continuaÈ un caso semplificato, ma comunque molto utile
Come primo esempio, supponiamo di voler risolvere:
f(x)=x3−32x2+1=0
Il plot della Il plot della funzione, con l'unico zero in rosso
Come primo esempio, supponiamo di voler risolvere:
f(x)=x3−32x2+1=0
Come possiamo trovare uno zero?
Partiamo da una osservazione:
f(x)
attraversa l'asse delle x
a
e b
, f(x)
cambia di segnoVediamo di essere un po' più formali...
Teorema del valore intermedio:
Sia data una funzione f:R→R
:
f
è continua su un intervallo [a,b]
[a,b]
assumerà tutti i valori tra f(a)
e f(b)
Corollario importante (teorema di Bolzano):
Sia data una funzione f:R→R
continua su [a,b]
f(a)
e f(b)
hanno segno oppostof(x)
ha uno zero nell'intervallo [a,b]
Quindi, per trovare un intervallo contenente uno zero:
f(x)
in vari puntia
e b
tali che f(a)f(b)<0
...a
e b
A questo punto, per trovare uno zero:
[a,b]
...Possiamo farlo utilizzando il metodo della bisezione
Partiamo da un intervallo [a,b]
tale che f(a)f(b)<0
Otteniamo un nuovo punto c
a metà tra a
e b
Aggiorniamo l'intervallo [a,b]
Ripetiamo il processo
Ripetiamo il processo
Ripetiamo il processo
Ripetiamo il processo
Ripetiamo il processo
Ci fermiamo quando la distanza tra a
(o b
) e c
è abbastanza piccola
Le operazioni critiche sono due:
Op 1: Il calcolo del valore di c
, che è dato da:
c=12(a+b)
Le operazioni critiche sono due:
Op 1: Il calcolo del valore di c
, che è dato da:
c=12(a+b)
Op 2: L'aggiornamento dell'intervallo [a,b]
f(c)
ha lo stesso segno di f(a)
, viene rimpiazzato b
b
f(a)f(b)<0
Possiamo descrivere l'algoritmo mediante pseudo-codice:
for <numero massimo di iterazioni>
c = (a + b)/2
if |a−c| < ε
break
end
if <f(a) e f(c) hanno lo stesso segno>
a = c
else
b = c
end
end
Il metodo della bisezione ha ottime proprietà di convergenza:
Proviamo a caratterizzare meglio la convergenza
Per farlo, dobbiamo:
e=x−x∗
)lim
e^{(0)} = \frac{1}{2}\left|a - b \right|
[a, b]
si dimezza:
e^{(1)} = \frac{1}{2}\frac{\left|a - b \right|}{2}
Generalizzando, abbiamo che:
e^{(k)} = \frac{1}{2^{k+1}}\left|a - b \right|
È ora di dare qualche definizione in più sulla convergenza:
Un metodo iterativo converge se:
\lim_{k \rightarrow \infty} \left|e^{(k)}\right| = 0
Consideriamo poi il rapporto tra errori consecutivi:
\lim_{k \rightarrow \infty}
\frac{\left|e^{(k+1)}\right|}{\left|e^{(k)}\right|} = \mu
\mu < 1
A seconda del valore di \mu
, distinguiamo diversi tipi di convergenza
In particolare abbiamo che:
Caso 1: 0 < \mu < 1
, la convergenza è lineare
Caso 2: Se \mu = 1^-
, la convergenza a sub-lineare
Caso 2: Se \mu = 0
, la convergenza è super-lineare
Vediamo come si comporta il metodo della bisezione...
Innanzitutto possiamo osservare che il metodo converge:
\lim_{k \rightarrow \infty} e^{(k)} =
\lim_{k \rightarrow \infty} \frac{1}{2^{k+1}}\left|a - b \right| = 0
La convergenza è di tipo lineare, perché:
\lim_{k \rightarrow \infty} =
\frac{\left|e^{(k+1)}\right|}{\left|e^{(k)}\right|} =
\frac{1}{2}
\log_2 10 \simeq 3.3
iterazioniSe l'intervallo [a, b]
contiene più di uno zero
Dipende tutto dai valori scelti per [a, b]
Consideriamo una versione modificata del nostro problema:
x^3 - \frac{5}{2} x^2 + 1 = 0
a
e b
In questo plot vediamo i tre zeri:
Con questa scelta di a
e b
, convergiamo allo zero di sx
Con questa scelta di a
e b
, convergiamo allo zero di dx
Se l'intervallo [a, b]
contiene più di uno zero
Dipende tutto dai valori scelti per [a, b]
In generale "scegliere" verso quale zero convergere è difficile:
Il metodo di bisezione da due grandi vantaggi:
Il metodo di bisezione da due grandi vantaggi:
...Un difetto tollerabile (nel nostro caso):
Il metodo di bisezione da due grandi vantaggi:
...Un difetto tollerabile (nel nostro caso):
...E due grossi problemi:
[a, b]
che racchiude uno zeroVediamo un secondo metodo di soluzione...
Il nostro secondo approccio è il metodo di Newton-Raphson:
Ha caratteristiche complementari rispetto al metodo della bisezione
È uno dei metodi più noti per la soluzione di equazioni non lineari
f : \mathbb{R} \rightarrow \mathbb{R}
Partiamo da un singolo valore di x
Approssimiamo la funzione con la tangente in x^{(0)}
Troviamo uno zero per la funzione approssimata
Ripetiamo il processo
Ripetiamo il processo
Ripetiamo il processo
Finché non arriviamo a convergenza
L'idea principale del metodo è:
f(x)
con il suo sviluppo in serie di Taylor di ordine 1
f(x)
sia derivabileAll'iterazione k
-ma abbiamo quindi:
f(x) \simeq f(x^{(k)}) + f'(x^{(k)}) (x - x^{(k)})
Da cui possiamo ottenere lo zero della funzione approssimata:
x = x^{(k)} - \frac{f(x^{(k)})}{f'(x^{(k)})}
L'iterazione fondamentale del metodo è quindi:
x^{(k+1)} = x^{(k)} - \frac{f(x^{(k)})}{f'(x^{(k)})}
Lo pseudo-codice dell'algoritmo è:
x = <stima iniziale>
for <numero massimo di iterazioni>
x_p = x
x = x - f(x) / f^\prime(x)
if |x - x_p| < \varepsilon
break
end
end
Vediamo un esempio numerico, con:
x^{(k)} |
f(x^{(k)}) |
f'(x^{(k)}) |
x^{(k+1)} |
---|---|---|---|
-0.2500 |
0.8281 |
1.4375 |
-0.8261 |
-0.8261 |
-1.2698 |
6.1777 |
-0.6205 |
-0.6205 |
-0.2016 |
4.2579 |
-0.5732 |
-0.5732 |
-0.0097 |
3.8516 |
-0.5707 |
-0.5707 |
0.0000 |
3.8304 |
-0.5707 |
Proviamo a caratterizzare la convergenza
Partiamo dall'iterazione fondamentale
x^{(k+1)} = x^{(k)} - \frac{f(x^{(k)})}{f'(x^{(k)})}
x = g(x) = x - \frac{f(x)}{f'(x)}
Possiamo applicare un risultato noto per IPF
x^*
, abbiamo:
\frac{\left|e^{(k+1)}\right|}{\left|e^{(k)}\right|} = \left|g'(x)\right|
\left|g'(x)\right|
:
g'(x) = \left(x - \frac{f(x)}{f'(x)}\right)' = 1 - \frac{f'(x)^2 - f(x) f''(x)}{f'(x)^2} = \frac{f(x) f''(x)}{f'(x)^2}
Per avere convergenza, in un intorno di x^*
deve valere:
\left|g'(x)\right| = \left|\frac{f(x) f''(x)}{f'(x)^2}\right| = \frac{\left|f(x)\right| \left|f''(x)\right|}{f'(x)^2} < 1
A questo punto ci limitiamo a delle considerazioni informali
Considerazione 1:
f(x^*)
vale 0
...f
è continua il valore di \left|f(x)\right|
sarà molto piccolof
è continua è probabile che il metodo convergaPer avere convergenza, in un intorno di x^*
deve valere:
\left|g'(x)\right| = \left|\frac{f(x) f''(x)}{f'(x)^2}\right| = \frac{\left|f(x)\right| \left|f''(x)\right|}{f'(x)^2} < 1
A questo punto ci limitiamo a delle considerazioni informali
Considerazione 2:
f'(x^*) \neq 0
, f''(x^*)
è limitata e f
è continua, allora:
\lim_{k \rightarrow \infty} \frac{\left|e^{(k+1)}\right|}{\left|e^{(k)}\right|} = \lim_{k \rightarrow \infty} \left|g'(x^{(k)})\right| = 0
Per avere convergenza, in un intorno di x^*
deve valere:
\left|g'(x)\right| = \left|\frac{f(x) f''(x)}{f'(x)^2}\right| = \frac{\left|f(x)\right| \left|f''(x)\right|}{f'(x)^2} < 1
A questo punto ci limitiamo a delle considerazioni informali
Considerazione 3:
f'(x^*) = 0
(lo zero è su un estremo), il denominatore è piccolof'
è continua la convergenza c'è, ma è solo linearePer avere convergenza, in un intorno di x^*
deve valere:
\left|g'(x)\right| = \left|\frac{f(x) f''(x)}{f'(x)^2}\right| = \frac{\left|f(x)\right| \left|f''(x)\right|}{f'(x)^2} < 1
A questo punto ci limitiamo a delle considerazioni informali
Considerazione 4:
f''(x^*) =
(lo zero è su un flesso), il numeratore sarà piccoloPer avere convergenza, in un intorno di x^*
deve valere:
\left|g'(x)\right| = \left|\frac{f(x) f''(x)}{f'(x)^2}\right| = \frac{\left|f(x)\right| \left|f''(x)\right|}{f'(x)^2} < 1
A questo punto ci limitiamo a delle considerazioni informali
In generale:
f'
non è continuax^{(k)}
abbiamo f'(x^{(k)}) = 0
, il metodo non funzionaf'(x)
Il metodo di Newton-Raphson richiede di conoscere la derivata di f
A volte però f'(x)
è difficile da ottenere per via analitica
v
dell'equazioni di Bernoulli:
(H_1 - H_2) - \frac{4f}{D} \frac{v^2}{2g}L - \sum_{j = 1}^{m} k_{j} \frac{v^2}{2g} = 0
v
!Per fortuna, si può evitare di farlo
f'(x)
Partiamo da una osservazione:
f'(x)
...Per definizione, abbiamo che:
f'(x) = \lim_{\delta \rightarrow 0} \frac{f(x+\delta) - f(x)}{\delta}
Quindi possiamo calcolare una approssimazione di f'(x)
con:
f'(x) \simeq \frac{f(x+\varepsilon) - f(x)}{\varepsilon}
\varepsilon
sufficientemente piccolof'(x)
Si tratta di un calcolo approssimato
f'(x)
...Inoltre, possiamo sempre migliorare l'approssimazione:
f'(x) \simeq \frac{f(x+\varepsilon) - f(x)}{\varepsilon}
\varepsilon
molto piccolo, no?Vediamo perché...
Il problema è legato all'utilizzo dei numeri in virgola mobile
Supponiamo di avere:
\varepsilon = 0.001
f(x) = 1,000,000,000
f(x + \varepsilon) = 1,000,000,001
E di rappresentare i numeri in virgola mobile, con:
Per semplicità, lavoriamo con cifre decimali (anziché con i bit)
Con le ipotesi specificate, abbiamo:
\varepsilon = 0.001 = 1.000 \times 10^{-3}
f(x) = 1,000,000,000 = 1.000 \times 10^{9}
f(x + \varepsilon) = 1,000,000,001 = \underline{1.000 \times 10^{9}}
[e qui butta male]E quindi:
\frac{f(x+\varepsilon) - f(x)}{\varepsilon} = \frac{1.000 \times 10^{9} - 1.000 \times 10^{9}}{1.000 \times 10^{-3}} = 0
Mentre il vero risultato è
\frac{f(x+\varepsilon) - f(x)}{\varepsilon} = \frac{1}{0.001} = 1,000
Questo è un esempio di errore di cancellazione
Nel nostro caso:
f(x+\varepsilon)
e f(x)
hanno la stessa rappresentazione!Vediamo un altro esempio classico:
a = 1,000,000,000
(molto grande)b = 1,000
(piccolo rispetto ad a
)a + b = 1,000,001,000
Invece, con le stesse assunzioni di prima, abbiamo:
a = 1.000 \times 10^9
b = 1.000 \times 10^3
a + b = 1.000 \times 10^9 + \underline{0.000 \times 10^9} = 1.000 \times 10^9
Perché per poter sommare i numeri, l'esponente deve essere identico
In generale, bisogna stare in guardia ogni volta che:
In generale:
Infatti, i numeri in virgola mobile:
Tornando alla nostra derivata approssimata:
\frac{f(x+\varepsilon) - f(x)}{\varepsilon}
Esiste una buona regola per ottenere...
In particolare:
\epsilon
è il più piccolo numero rappresentabile sul calcolatore\varepsilon
è \sqrt{\epsilon}\,x
...\sqrt{\epsilon}
se x = 0
Però, Il metodo di N-R funziona anche per sistemi non lineari
n
eq., n
incognite)L'idea di base resta la stessa:
f(x)
Questa volta però abbiamo f : \mathbb{R}^n \rightarrow \mathbb{R}^n
Formalmente, dobbiamo risolvere:
f(x) = 0
f : \mathbb{R}^n \rightarrow \mathbb{R}^n
Possiamo rappresentare l'equazione vettoriale nella forma:
\begin{align}
f_1(x_1, x_2, \ldots, x_n) &= 0\\
f_2(x_1, x_2, \ldots, x_n) &= 0\\
\ldots\\
f_n(x_1, x_2, \ldots, x_n) &= 0
\end{align}
f_i(x)
è la i
-ma componente di f
Applichiamo una approssimazione lineare ad ogni componente:
\begin{align}
f_1(x^{(k)}) + \nabla f_1(x^{(k)}) (x - x^{(k)}) &= 0\\
f_2(x^{(k)}) + \nabla f_2(x^{(k)}) (x - x^{(k)}) &= 0\\
\ldots\\
f_n(x^{(k)}) + \nabla f_n(x^{(k)}) (x - x^{(k)}) &= 0
\end{align}
Dove:
x
è il vettore delle variabili x_1, x_2, \ldots
x^{(k)}
è un vettore con i valori di x_1^{(k)}, x_2^{(k)}, \ldots
\nabla f_1(x^{(k)})
è il gradiente di f_i
calcolato in x^{(k)}
In forma matriciale, abbiamo:
f(x^{(k)}) + J_f(x^{(k)}) (x - x^{(k)}) = 0
Dove:
f(x^{(k)})
è il vettore con f_1(x^{(k)}), f_2(x^{(k)}), \ldots
J_f(x^{(k)})
è lo Jacobiano di f
calcolato in x^{(k)}
i
-ma dello Jacobiano coincide con il gradiente \nabla f_i(x)
Lo Jacobiano si può calcolare con le stesse tecniche viste per f'(x)
:
Di fatto, abbiamo un normale sistema lineare:
f(x^{(k)}) + J_f(x^{(k)}) (x - x^{(k)}) = 0
La soluzione è data da:
x^{(k+1)} = x^{(k)} - J_f^{-1}(x^{(k)}) f(x^{(k)})
^1/_{f'(x)}
nel caso scalareIl resto dell'algoritmo rimane pressoché invariato:
x = <stima iniziale>
for <numero massimo di iterazioni>
x_p = x
x = x - J_f(x) / f(x) % divisione sinistra
if \|x - x_p\| < \varepsilon
break
end
end
\|\cdot\|
invece di |\cdot|
...x
e x_p
sono vettoriAbbiamo visto due metodi per risolvere equazioni non lineari
Entrambi trovano uno zero di una funzione
Detto questo IPF rimane un po' più flessibile:
I due metodi visti hanno caratteristiche complementari:
Il metodo della bisezione ha una convergenza molto robusta...
Il metodo di Newton-Raphson:
In pratica, si utilizza spesso una combinazione di metodi