DvdZero: UNA ROUTINE PER AZZERARE FUNZIONI TRAMITE METODO DICOTOMICO

Contenuto

Realizzazione di una routine in grado di azzerare funzioni non lineari

%----------------------------------------------------
%  Calcoli di Processo dell'Ingegneria Chimica
%  Davide Manca
%  29-Nov-2004 19:10:51
%
%  Azzeramento di una funzione non lineare tramite utilizzo della routine
%  "DvdZero" basata su metodo dicotomico
%----------------------------------------------------

Testo del problema

Il seguente esempio descrive la realizzazione di una routine in
linguaggio Matlab dedicata all'azzaramento di funzioni non lineari in
una sola incognita tramite metodo dicotomico.
L'aspetto fondamentale di questo esempio è quello della realizzazione di
una function riutilizzabile, capace di risolvere un generico problema di
azzeramento di funzione.
Il codice script seguente determina la temperatura di ebollizione
dell'acqua a pressione ambiente utilizzando la function "DvdZero"

Inizializzazione dell'ambiente

clear all
clc

Costanti/variabili globali presenti nello script principale e nella

funzione da azzerare "fWater"

global A B C D E PRESSIONE

Inizializzazione coefficienti pressione di vapore acqua secondo banca dati DIPPR

%  Questi coefficienti sono gli stessi descritti nell'esercizio E5.1 
A =  7.3649E+01;
B = -7.2582E+03;
C = -7.3037E+00;
D =  4.1653E-06;
E =  2.0000E+00;
%  Cerco la temperatura di ebollizione dell'acqua ad una atmosfera.
%  Il problema è semplicissimo in quanto si desidera concentrare
%  l'attenzione sulla costruzione della routine "DvdZero" capace di
%  azzerare una generica equazione non lineare in una variabile.
PRESSIONE = 101325.;    %  [Pa]

%  Assegnazione valori iniziali
a = 80. + 273.15;
b = 120. + 273.15;
epsi = 1.e-5;
iPrint = 1;    %  stampe intermedie...

Chiamata alla routine "DvdZero"

Si noti la differenza rispetto al codice dell'esempio "Azzeramento" dove
la porzione di algoritmo dicotomico è disciolta all'interno dello script
stesso. In tale esempio il codice di azzeramento non è direttamente
riutilizzabile e neppure strutturato per un uso del tutto generale.
Il pregio della routine "DvdZero" è quello di semplificare l'attività
del programmatore e al contempo di fornire tutte le informazioni
desiderate dall'utente.
Dopo aver testato approfonditamente la routine "DvdZero" si è
certi della sua affidabilità e di aver congelato al suo interno un
codice corretto e ben strutturato, riutilizzabile tutte le volte che lo
si desidererà.
[x, fx, delta] = DvdZero(@fWater,a,b,epsi,iPrint);

%  L'utente, fruitore della "DvdZero" resta concentrato sul problema da
%  risolvere, gestendo soltanto i dati di input ed i risultati finali senza
%  preoccuparsi della implementazione dell'algoritmo risolutivo.
disp('  ');
disp(['xSol = ',num2str(x),' K   ovvero ',num2str(x-273.15),' ^C     f(xSol) = ',num2str(fx)]);
disp(['Ampiezza finale dell''intervallo di incertezza = ',num2str(delta)]);
1)    c = 373.15        f(c) = -64.437     delta = 20
2)    c = 383.15        f(c) = 41798.7066  delta = 10
3)    c = 378.15        f(c) = 19376.0447  delta = 5
4)    c = 375.65        f(c) = 9303.1897   delta = 2.5
5)    c = 374.4         f(c) = 4533.6657   delta = 1.25
6)    c = 373.775       f(c) = 2213.4873   delta = 0.625
7)    c = 373.4625      f(c) = 1069.2806   delta = 0.3125
8)    c = 373.3062      f(c) = 501.1153    delta = 0.15625
9)    c = 373.2281      f(c) = 218.0131    delta = 0.078125
10)   c = 373.1891      f(c) = 76.7066     delta = 0.039063
11)   c = 373.1695      f(c) = 6.1144      delta = 0.019531
12)   c = 373.1598      f(c) = -29.1664    delta = 0.0097656
13)   c = 373.1646      f(c) = -11.5272    delta = 0.0048828
14)   c = 373.1671      f(c) = -2.7067     delta = 0.0024414
15)   c = 373.1683      f(c) = 1.7038      delta = 0.0012207
16)   c = 373.1677      f(c) = -0.50148    delta = 0.00061035
17)   c = 373.168       f(c) = 0.60115     delta = 0.00030518
18)   c = 373.1679      f(c) = 0.04983     delta = 0.00015259
19)   c = 373.1678      f(c) = -0.22583    delta = 7.6294e-005
20)   c = 373.1678      f(c) = -0.087998   delta = 3.8147e-005
21)   c = 373.1678      f(c) = -0.019084   delta = 1.9073e-005
22)   c = 373.1678      f(c) = 0.015373    delta = 9.5367e-006
  
xSol = 373.1678 K   ovvero 100.0178 ^C     f(xSol) = 0.015373
Ampiezza finale dell'intervallo di incertezza = 9.5367e-006

DvdZero: una routine di azzeramento funzioni tramite metodo dicotomico

%--------------------------------------------------------------------------
%  Calcoli di Processo dell'Ingegneria Chimica
%  Davide Manca
%  29-Nov-2004 22:19:24
%--------------------------------------------------------------------------
%
%  La routine DvdZero determina lo zero di una funzione non lineare
%  utilizzando il metodo dicotomico
%  Variabili di INPUT:
%  FUN      puntatore ad una funzione in una incognita
%  a        estremo inferiore intervallo di incertezza iniziale
%  b        estremo superiore intervallo di incertezza iniziale
%  epsi     ampiezza finale desiderata per l'intervallo di incertezza
%  iPrint   indice di stampa risultati intermedi, [0] nessuna stampa, [1] stampa
%  Variabili di OUTPUT:
%  x        soluzione finale
%  fx       valore della funzione nella soluzione finale
%  delta    ampiezza finale intervallo di incertezza
%--------------------------------------------------------------------------

function [x, fx, delta] = DvdZero(FUN,a,b,epsi,iPrint)

   %  Calcolo a priori del numero di iterazioni da compire per ottenere un
   %  intervallo di incertezza finale minore di "epsi"
   nIter = ceil((log(b-a) - log(epsi)) / log(2.));
   iConto = 0;

   %  vedi Tutorial Matlab Advanced per gestione puntatori a funzione e comando "feval"
   fa = feval(FUN,a);
   fb = feval(FUN,b);

	%  Controllo condizione necessaria applicabilità metodo dicotomico...
	if sign(fa) * sign(fb) > 0
       error('Estremi del metodo dicotomico NON consistenti. Impossibile continuare...');
   end

   %  Inizio procedura iterativa di contrazione dell'intervallo di incertezza
	for i = 1: nIter
       c = a + 0.5 * (b-a);   %  formulazione robusta
       fc = feval(FUN,c);
       if sign(fa) * sign(fc) < 0.
          b = c;
          fb = fc;
       else
          a = c;
          fa = fc;
       end
       if iPrint ~= 0
          disp([num2str(i),')   c = ',num2str(c),'      f(c) = ',num2str(fc),'  delta = ',num2str(b-a)]);
       end
   end

   %  Scaricamento risultati nelle variabili di output...
   x = c;
   fx = fc;
   delta = b - a;

fWater: esempio di funzione da azzerare

%--------------------------------------------------------------------------
%  Calcoli di Processo dell'Ingegneria Chimica
%  Davide Manca
%  29-Nov-2004 22:26:42
%--------------------------------------------------------------------------
%
%  La function "fWater" descrive la tensione di vapore dell'acqua tramite
%  una relazione interpolante proveniente dalla banca dati DIPPR.
%  Le costanti/variabili sono definite nello script principale e sono
%  visibili a questa funzione tramite l'istruzione "global"

function f = fWater(T)

   global A B C D E PRESSIONE

   f = exp(A + B / T + C * log(T) + D * T ^ E) - PRESSIONE;