Professional Documents
Culture Documents
MEMÒRIA
Resum
Aquest TFG consisteix en el disseny d’una aplicació per ordinador feta
amb Python per simular diversos cicles termodinàmics predefinits. El
programa és una calculadora capaç de resoldre els estats que conformen
el cicle, obtenir les potències i rendiments, obtenir els diagrames T-s i
P-h i, en alguns casos, realitzar l’anàlisi exergètica. A més a més, un
cop realitzat el càlcul, el programa permet canviar el valor d’alguna de
les dades inicials i veure com variacions d’aquest paràmetre afecten la
resta de resultats. Tota l’aplicació s’ha dissenyant amb la finalitat de
complementar la docència dels cicles termodinàmics, de manera que el
professorat pugui fer més dinàmiques les sessions i els estudiants puguin
verificar els resultats dels exercicis.
2
Sumari
Resum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Índex de figures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Llistat de codis Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1 Introducció 7
1.1 Motivació . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2 Objectius . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.3 Abast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.4 Metodologia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.5 Marc teòric . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.5.1 Propietats de les substàncies pures . . . . . . . . . . . . . . . . . . 11
1.5.2 Diagrames P-h i T-s . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.5.3 Criteri de signes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.5.4 Dispositius de flux estacionari . . . . . . . . . . . . . . . . . . . . . 14
1.5.5 Programari utilitzat . . . . . . . . . . . . . . . . . . . . . . . . . . 17
5 Manual d’usuari 82
5.1 Introducció de dades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
5.2 Resolució del cicle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
5.3 Visualització de resultats i diagrames termodinàmics . . . . . . . . . . . . 86
6 Anàlisi de resultats 87
6.1 Exemple 1: Cicle bàsic de Rankine . . . . . . . . . . . . . . . . . . . . . . 87
6.2 Exemple 2: Cicle de Rankine amb reescalfament intermedi . . . . . . . . . 91
6.3 Exemple 3: Cicle de Brayton . . . . . . . . . . . . . . . . . . . . . . . . . . 95
6.4 Exemple 4: Cicle de refrigeració per compressió de vapor . . . . . . . . . . 98
6.5 Exemple 5: Cicle de refrigeració per gas . . . . . . . . . . . . . . . . . . . 101
Pressupost 104
Bibliografia 110
4
Índex de figures
Capítol 1
Introducció
Amb l’arribada de les noves tecnologies la majoria d’aquestes problemàtiques s’han so-
lucionat incorporant les taules termodinàmiques dintre dels softwares que per si sols són
capaços de fer les interpolacions i resoldre els estats. D’aquests n’hi ha de més generalistes
com el Engineering Equation Solver (EES) o més específics com el CyclePad. Tanmateix,
tot avantatge té els seus inconvenients, i en aquest cas en trobem dos de molt rellevants.
Per una banda, molts d’aquests softwares són de pagament, com és el cas de l’EES, i això
fa que perdi molts punts en la seva utilització com a eina docent perquè pot ser que la
universitat no hagi comprat la llicència o que aquesta llicència sigui vàlida tan sols en
les xarxes de la universitat. En general la majoria d’aquests programaris no s’utilitzen
per a la realització dels exàmens, sinó que s’utilitzen a l’aula per a clarificar conceptes,
exemplificar continguts... Per altra banda la manipulació d’aquests softwares moltes ve-
gades requereix una formació específica, és a dir, són complicats de fer servir, i per tant
inicialment cal dedicar-los-hi un temps per aprendre a fer-los servir, bastant més temps
que el que pot costar consultar les taules termodinàmiques. Per tant, malgrat que a la
llarga evidentment són molt més ràpids que les taules (i també molt més útils), no tothom
està disposat a fer aquest esforç inicial si l’objectiu de la utilització del software només és
la verificació d’uns resultats o la de complementar la docència.
1.1 Motivació
La principal motivació per la realització d’aquest projecte és donar una alternativa l’EES,
que és el software que s’utilitza actualment com a complement a la docència a l’assignatura
Termodinàmica impartida a l’ETSEIB.
Aquest software presenta els dos grans inconvenients mencionats a la introducció. Per
una banda, malgrat que la UPC té la llicència del software pagada, aquest només es
pot fer servir utilitzant l’eduroam de la UPC. Això és un problema perquè perjudica el
treball autònom de l’estudiant, que si volgués, per exemple, verificar algun càlcul amb el
software en algun entorn fora de la universitat, no podria. Per altra banda, l’EES no és
un programari fàcil de manipular, cal aprendre el seu llenguatge per saber introduir les
dades i saber manipular les equacions. En aquesta situació els estudiants es troben que
de manera autònoma han de fer un treball addicional per aprendre a manipular aquest
software per només poder verificar resultats o entendre millor els conceptes. Amb aquest
programa es busca deixar això enrere i que d’una manera molt senzilla l’estudiant pugui
verificar resultats, veure què passa quan canvia un paràmetre d’un cicle, veure com afecta
el fluid de treball a les potències calorífiques del sistema, entre d’altres.
1.2 Objectius
L’objectiu principal d’aquest projecte és desenvolupar una aplicació informàtica que per-
meti la resolució de cicles termodinàmics predefinits a partir d’un conjunt de dades inicials
que siguin suficients perquè el problema tingui solució única.
• Se li ha de poder introduir com a dada el títol x per cada un dels estats si en tenen.
• Se li han de poder introduir les potències associades a les calors Q̇ i les potències
associades als treballs Ẇ dels dispositius que formen el cicle.
• Se li han de poder introduir els rendiments isentròpics η dels dispositius que formen
el cicle si és que estan definits
• Un cop realitzat el càlcul s’han de poder modificar les dades inicials i el seu valor
per veure com el canvi de valor d’un paràmetre afectaria el cicle.
• Un cop realitzat el càlcul s’han de poder obtenir els diagrames T-s i P-h.
• Un cop realitzat el càlcul s’ha de poder fer una anàlisi exergètica del sistema per ob-
tenir els treballs perduts dels dispositius del sistema, els seus rendiments exergètics
i el rendiment exergètic de la instal·lació.
1.3 Abast
L’abast d’aquest projecte és el disseny d’una aplicació per ordinador amb Python que
permeti resoldre cicles termodinàmics predefinits complint totes les especificacions de
disseny definides en l’apartat anterior.
Aquesta aplicació no podrà treballar amb els cicles termodinàmics que no s’hagin pre-
definit en el seu disseny. En aquest projecte se’n dissenyaran uns quants i l’usuari, és a
dir, la persona que farà servir l’aplicació, podrà treballar amb aquests. L’usuari no podrà
definir els cicles termodinàmics perquè el software no és una aplicació de disseny de cicles
termodinàmics sinó de resolució.
Per altra banda, l’aplicació no permet l’elaboració de taules paramètriques però sí que
permet anar canviant el valor d’alguna de les variables definides anteriorment com si fos
un paràmetre i tornar a resoldre el cicle per veure com aquest canvi de valor afecta el
cicle.
Finalment comentar que malgrat que el programa podria utilitzar-se per estudiar aquests
mateixos cicles en l’àmbit industrial, no es recomana, ja que l’aplicació s’ha pensat per
complementar la docència.
1.4 Metodologia
L’elaboració d’aquesta aplicació s’ha estructurat en quatre fases: fase creativa, fase de
recerca bibliogràfica, fase de programació de l’aplicació i finalment una fase de testeig a
la recerca d’errors. Cal dir que aquestes fases no han sigut seqüencials. Per descomptat
la fase creativa s’ha iniciat abans que la fase de recerca bibliogràfica, la de recerca biblio-
gràfica abans que la de programació, etc. però en el moment en què una fase s’iniciava no
tenia per què acabar-se’n una. Mentre es feia la programació de l’aplicació, per exemple,
podien anar sorgint noves idees i per implementar-les calia fer una recerca bibliogràfica,
quan s’acabava una part del codi convenia fer-li una prova per solucionar errors, ja que
detectar-los el més aviat millor permetia solucionar-los de la forma més òptima.
10 Capítol 1
Finalment la darrera etapa és la fase de testeig que s’inicia just quan s’acaba de pro-
gramar la primera part del codi del cicle “plantilla”. Aquesta etapa consisteix a detectar,
localitzar i donar una solució a tots els problemes que poden sorgir durant la programació
de l’aplicació. La majoria d’aquests errors són informàtics, per exemple, no haver declarat
alguna variable, deixar-se un parèntesi... Però també es busquen errors en els resultats
numèrics que ha de donar el programa per verificar que no hi hagi errors en les fórmules
matemàtiques que s’han traslladat a codi Python. Aquesta etapa resulta fonamental per-
què qualsevol aplicació inicialment pot presentar errors que el programador pot no haver
detectat i com més verificacions i més testos es facin més possibilitats de solucionar els
errors, que normalment acostumen a ser de fàcil correcció i són fruit d’algun factor que
no s’ha tingut en compte.
Capítol 1 11
Seguir aquesta metodologia ha sigut molt útil per l’elaboració de l’aplicació gràcies a
la flexibilitat que permet la convivència de les fases entre elles. A més a més, un gran
avantatge d’aquest mètode és que les etapes s’alimenten entre elles de manera que els errors
es converteixen en oportunitats que poden donar peu a idees per millorar l’aplicació.
Per altra banda, s’anomena substància pura a tota substància que té una composició
química fixa. Una substància pura no té per què ser un sol element o component químic,
pot ser una barreja de diversos, com per exemple l’aire, que és una barreja de diversos
gasos. L’únic requisit és que la composició química sigui uniforme. Una barreja de dues o
més fases d’una substància pura, com per exemple una barreja entre aigua líquida i vapor
d’aigua, se segueix considerant una substància pura sempre que la composició química de
les fases sigui la mateixa.
En l’estudi dels cicles termodinàmics s’acostuma a treballar amb substàncies pures en les
regions vapor, líquid-vapor i líquid. Quan el fluid es troba en fase líquida es diu que és
líquid comprimit o subrefredat, que significa que no està a punt d’evaporar-se.
Si d’aquest fluid es modifiquen les seves propietats, per exemple augmentant la tempera-
tura en cas de l’aigua, s’arriba a la saturació en què el líquid passa a ser líquid saturat i
s’entra a la regió líquid-vapor. En aquesta regió el líquid es va evaporant mantenint la
temperatura constant. Quan ja quasi s’ha completat l’evaporació, el vapor que es té és un
vapor que es troba al límit de la fase líquida. S’anomena vapor saturat que és un vapor
que està a punt de condensar-se.
En aquesta regió es defineix el títol, que es representa com x, és el quocient entre la massa
que hi ha de fase vapor i la massa total del sistema:
mv
x=
m
El títol és una magnitud compresa entre 0 (líquid saturat) i 1 (vapor saturat). Amb el
títol es pot trobar l’entalpia o l’entropia especifiques d’una substància pura que es trobi
dins la regió líquid-vapor.
h = x · hvs + (1 − x) · hls
12 Capítol 1
s = x · svs + (1 − x) · sls
La quantitat 1 − x s’anomena humitat.
Des d’un punt de vista pràctic, en les regions de líquid o vapor cal conèixer dues propietats
termodinàmiques per resoldre un estat. En canvi, en la regió líquid-vapor, coneixent una
propietat i el títol és suficient. Això és de gran importància a l’hora d’introduir les dades
a l’aplicació, per tal que aquestes siguin suficients per resoldre el cicle.
Al diagrama també es poden visualitzar diferents tipus de línies isotermes; les subcrítiques
passen a través de la campana i a dintre d’ella són paral·leles a l’eix d’entalpia (si la
substància és pura, el canvi de fase es produeix a pressió constant). La isoterma crítica
presenta un punt d’inflexió al punt crític i les isotermes supercrítiques no passen a través
de la campana de saturació.
Capítol 1 13
En aquest diagrama també es poden observar altres corbes com del que uneixen els punts
amb el mateix títol (discontinues i situades a l’interior de la campana de saturació), les
isentròpiques i les isocòriques.
A la Figura 1.2 es té un exemple d’un diagrama T-s per a una substància pura, en què es
representa la temperatura versus l’entropia. Novament en el diagrama es poden distingir
les tres regions en què acostumen a treballar els cicles termodinàmics separades per la
corba de saturació. Dins de la campana de saturació es troba la zona d’equilibri líquid-
vapor i les corbes que uneixen punts amb el mateix títol. A l’esquerra de la campana i per
sota de la temperatura crítica es troba la zona de líquid, i a la dreta i també per sota de la
temperatura crítica, la zona de vapor. En aquest diagrama també es poden veure altres
corbes com les isobàriques, les isentàlpiques, les isocòriques i el grau de reescalfament
constant (T − Tsat ).
Ambdós diagrames seran els que es podran obtenir a través de l’aplicació. En els obtinguts,
es veuran les línies isotermes i les de títol constant en el cas del diagrama P-h i les línies
isòbares i les de títol constant en el diagrama T-s.
Per tant es consideraran positives (Ẇ > 0 i Q̇ > 0) les entrades d’energia al sistema
mentre que les sortides es consideraran negatives (Ẇ < 0 i Q̇ < 0).
Els cicles termodinàmics estan formats per aquests dispositius i es plantegen balanços
de massa i energia en cadascun d’aquests dispositius per obtenir les equacions que ens
permeteren calcular les propietats termodinàmiques dels estats i resoldre el cicle.
En la majoria de dispositius, i en particular, en tots els que utilitza l’aplicació que s’està
dissenyant, es pot simplificar l’equació 1.1 negligint l’energia potencial per unitat de temps
i l’energia cinètica per unitat de temps. De manera que se simplifica com:
ṁ · (hs − he ) = Q̇ + Ẇ (1.2)
A continuació s’explicaran els diferents dispositius que formen part dels cicles termodi-
nàmics amb els quals treballarà l’aplicació i se’n presentarà, per cadascun d’ells els seus
balanços d’energia i en alguns casos l’expressió del rendiment isentròpic. Aquestes equaci-
ons posteriorment s’hauran d’introduir al programa amb Python de manera que es puguin
resoldre.
Intercanviador de calor
L’intercanviador de calor és un dispositiu en què un fluid en estat líquid, vapor o gas rep
o cedeix calor, segons si és una caldera o un condensador. A la Figura 1.3 es té l’esquema
d’una caldera. En aquest sistema es considera, a part de les suposicions fetes inicialment,
que no hi ha intercanvi de potència mecànica. Per tant l’equació 1.2 se simplifica de la
següent manera:
ṁ · (hs − he ) = Q̇ (1.3)
En els casos en què el cicle termodinàmic presenti reescalfament es dóna el cas que per la
caldera hi circulen més d’un corrents D’aquesta manera el balanç d’energia de l’equació
1.3 s’ha de generalitzar com:
k
X k
X
ṁi · (hs − he )i = Q̇i (1.4)
i=1 i=1
D’aquesta manera només cal fer la suma dels termes de l’equació 1.3 per cada un dels
corrents.
Per altra banda, l’exergia (energia disponible) de la caldera es pot calcular amb l’equació:
T0
Ex (Q̇) = Q̇ · 1 − (1.5)
TF
On T0 és la temperatura de l’entorn i TF és la temperatura de la font de la calor que rep
la caldera. En canvi, l’exergia del condensador és nula.
hs − he = 0 →
− hs = he (1.6)
Compressor
Un compressor augmenta la pressió d’un gas o d’un vapor (Ps > Pe ). Perquè això sigui
possible cal subministrar potència mecànica. A la Figura 1.5 es pot veure un esquema
d’aquest dispositiu.
16 Capítol 1
Per altra banda, el rendiment isentròpic d’un compressor real es defineix com el quocient
entre la potència isentròpica i la real.
Ẇiso h2s − h1
ηC = = (1.8)
Ẇreal h2 − h1
On l’Estat 1 correspon a l’entrada, l’Estat 2 a la sortida i l’Estat 2s correspon a la sortida
que tindria el mateix compressor si fos isentròpic (reversible i adiabàtic) en el qual es
verifica que s2s = s1 i P2s = P2 .
Turbina
A la turbina entra un fluid en estat vapor o gas a elevada pressió que genera una potència
mecànica. Això provoca una disminució de la pressió del fluid (Ps < Pe ). Es pot veure
un esquema de la turbina a la Figura 1.6.
Des d’un punt de vista pràctic les suposicions són les mateixes fetes en el compressor.
Per tant les equacions són les mateixes i l’únic que canviarà serà el signe de la potència
mecànica. Cal dir que el rendiment isentròpic tampoc serà el mateix.
Capítol 1 17
Es defineix el rendiment isentròpic d’una turbina real com el quocient entre la potència
real i la isentròpica.
Ẇreal h2 − h1
ηT = = (1.9)
Ẇiso h2s − h1
On l’Estat 1 correspon a l’entrada, l’Estat 2 a la sortida i l’Estat 2s correspon a la sortida
que tindria la mateixa turbina si fos isentròpica (reversible i adiabàtica) en el qual es
verifica que s2s = s1 i P2s = P2 .
Bomba
La bomba serveix per impulsar un líquid i augmentar al mateix temps la seva pressió
(Ps > Pe ). Per fer-ho cal subministrar-li potència mecànica. A la Figura 1.7 hi ha un
esquema d’una bomba.
Pel seu estudi se suposa que és adiabàtica, de manera que l’equacio 1.2 queda de la següent
manera:
W˙B = ṁ · (hs − he ) (1.10)
El rendiment isentròpic d’una bomba es defineix com el quocient entre la potència isen-
tròpica i la potència real:
Ẇiso h2s − h1
ηB = = (1.11)
Ẇreal h2 − h1
On l’Estat 1 correspon a l’entrada, l’Estat 2 a la sortida i l’Estat 2s correspon a la sortida
que tindria el mateix compressor si fos isentròpic (reversible i adiabàtic) en el qual es
verifica que s2s = s1 i P2s = P2 .
Finalment fer notar que l’exergia de la turbina, del compressor i de la bomba és directa-
ment el seu treball.
les llibreries Tkinter, pel disseny de tota la interfície gràfica; CoolProp, per realitzar el
càlcul de propietats termodinàmiques i també els diagrames P-h i T-s; Matplotlib per
complementar la representació dels diagrames i PyInstaller per convertir el codi Python
en un arxiu executable.
S’ha consultat [1] i [2] com a fonts bibliogràfiques per la redacció d’aquest capítol.
Totes les figures i equacions utilitzades d’aquest capítol han sigut extretes de [2].
Capítol 2 19
Capítol 2
En aquest capítol s’explicarà el fonament teòric dels cicles termodinàmics que s’imple-
mentaran amb el software. En primer lloc s’explicarà breument el funcionament del cicle
i també quins són els fluids que hi circulen habitualment. En segon lloc, es detallaran
quins dels dispositius de flux estacionari configuren els cicles i a quins estats corresponen
les seves entrades i sortides. També s’explicarà quins han de ser els sentits de les potèn-
cies mecàniques i tèrmiques del cicle. A més a més, es donaran altres equacions lligades
estrictament a cada un dels cicles, com poden ser el rendiment tèrmic o el coeficient de
funcionament. A continuació, es mostraran els diagrames termodinàmics típics perquè el
lector pugui veure’n la forma i sobretot perquè ens servirà per comprovar que els diagra-
mes obtinguts amb l’aplicació són coherents. Finalment, pels cicles de Rankine, es farà
l’anàlisi exergètica del cicle i se’n donaran les equacions, ja que aquesta funcionalitat de
l’aplicació només està disponible en aquests cicles.
A continuació, el fluid de treball entra a la caldera (Estat 2) i rep la calor generada en les
cambres de combustió o reactors nuclears de la central, a pressió constant. A la sortida el
vapor sortirà en forma de vapor saturat o sobreescalfat. El flux de calor que rep el fluid
ve donat per la següent equació:
Tot seguit, el fluid entra a la turbina (Estat 3) on s’expandeix i produeix treball al fer-
la girar l’eix connectat a un generador elèctric. La potència mecànica generada per la
turbina és:
ẆT = ṁ · (h4 − h3 ) (2.3)
Finalment, el fluid entra al condensador (Estat 4) on cedeix calor a un medi de refredament
(el riu, el mar, l’atmosfera...) i condensa completament a pressió constant. Aquesta calor
es pot calcular a partir de la següent equació:
En aquest cicle s’han de tenir en compte l’efecte de les irreversibilitats tant de la turbina
com de la bomba, que tenen un rendiment isentròpic determinat. El cabal màssic serà el
mateix per tot el cicle i la potència neta serà la suma de les potències de la turbina i la
bomba.
ẆN = ẆB + ẆT (2.5)
El rendiment tèrmic del cicle serà el quocient entre la potència neta i la calor subministrada
a la caldera en valor absolut.
Ẇ
N
ηt = (2.6)
Q̇H
Capítol 2 21
El balanç d’exergia d’aquest cicle es pot fer calculant l’exergia específica per cadascun
dels estats i segons l’equació:
Per altra banda considerant les exergies de cada un dels dispositius del cicle es pot calcular
el treball perdut com: X X
Ẇp = Ėxe − Ėxs (2.9)
D’aquesta manera els treballs perduts per cadascun dels dispositius seran:
ẆpT = Ėx3 − Ėx4 − Ėx (ẆT ) = ṁ · (ex3 − ex4 ) − ẆT (2.10)
ẆpB = Ėx1 − Ėx2 + Ėx (ẆB ) = ṁ · (ex1 − ex2 ) + ẆB (2.11)
T0
ẆpH = Ėx2 − Ėx3 + Ėx (Q̇H ) = ṁ · (ex2 − ex3 ) + Q̇H · 1 − (2.12)
TF
ẆpL = Ėx4 − Ėx1 + Ėx (Q̇L ) = ṁ · (ex4 − ex1 ) + 0 (2.13)
Ėx (ẆT )
ηexT = (2.14)
Ėx3 − Ėx4
Ėx1 − Ėx2
ηexB = (2.15)
Ėx (ẆB )
Ėx (Q̇H )
ηexC = (2.16)
Ėx2 − Ėx3
Ėx (ẆN )
ηex = (2.17)
Ėx (Q̇H )
Per tant el cicle de Rankine amb rescalfament intermedi no és més que una ampliació del
cicle de Rankine bàsic, per aquest motiu totes les equacions presentades anteriorment són
igualment vàlides en aquest cicle però tenint en compte a les fórmules que la numeració
dels estats ara és un altre. Es pot observar un esquema d’aquest cicle en la Figura 2.3.
En aquesta millora el fluid de treball passa dos cops per la caldera. Després de passar-hi
per primer cop (Estat 3) entra a la turbina a alta pressió i s’expandeix per primer cop.
Tot seguit torna a entrar novament a la caldera (Estat 4) i es reescalfa per entrar a la
turbina de baixa pressió (Estat 5). La turbina de baixa pressió i la d’alta pressió estan
acoblades i produeixen un treball mecànic.
I el flux de calor que cal cedir a la caldera es pot calcular amb la següent expressió:
Q̇H = Q̇H1 + Q̇H2 = ṁ(h3 − h2 ) + ṁ(h5 − h4 ) (2.19)
I el rendiment tèrmic d’aquest cicle és:
ẆN
ηt = (2.20)
Q̇H
El diagrama T-s característic d’aquest cicle es pot veure a la Figura 2.4:
Figura 2.4: Diagrama T-s d’un cicle ideal de Rankine amb rescalfament intermedi
Respecte a l’anàlisi exergètica és el mateix que en el Rankine bàsic ampliant les equacions
a la resta de dispositius i calculant les exergies específiques per cada estat.
24 Capítol 2
Figura 2.5: Esquema del cicle bàsic de turbina de gas en règim tancat
En aquest cicle el fluid de treball acostuma a ser aire, i habitualment es considera gas
ideal. Malgrat això, l’aplicació, en treballar amb CoolProp, considerarà l’aire com un fluid
amb unes propietats determinades. Per tant el càlcul que es farà dels treballs i calors serà
a través d’entalpies i no de temperatures. Això que a priori pot semblar un inconvenient,
ja que els resultats numèrics no seran exactament iguals als teòrics, suposa també un
avantatge perquè permet molt fàcilment considerar com a fluid de treball l’heli o el diòxid
de carboni, que són altres gasos que també s’utilitzen en aquests cicles.
Les equacions que relacionen les entalpies dels estats, el flux màssic i les potències tèr-
miques i mecàniques obtingudes són les de cada un dels dispositius que formen part del
cicle.
Capítol 2 25
Els diagrames T-s característics d’aquest cicle es pot veure a la figura 2.6:
Figura 2.6: Diagrama T-s del cicle ideal de Brayton en règim tancat
Tot seguit, el refrigerant entra al condensador (Estat 2), on perd calor i es condensa
completament. La calor que perd és:
Cal considerar que el software té en compte que en els cicles de refrigeració hi pot haver
pèrdues de pressió en el condensador i l’evaporador. Per aquest motiu cal introduir totes
les pressions dels estats termodinàmics, encara que, per exemple, la pressió de l’estat 2
sigui la mateixa que la del estat 3.
Noti’s també que en tots els processos de refrigeració el sentit del cicle és antihorari. Això
a nivell pràctic no té cap implicació, però és una diferència respecte als cicles de potència.
Considerant que el cabal màssic és el mateix per tot el circuit, aleshores el coeficient de
funcionament (COP) del cicle de refrigeració respon a l’equació:
Q̇L h1 − h4
COPM F = = (2.26)
ẆC h2 − h1
Capítol 2 27
Finalment, es pot veure a la Figura 2.8 els diagrames T-s i P-h d’aquests cicles de refri-
geració a escala qualitativa. En els cicles de potència, no s’ha mostrat el diagrama P-h
perquè no és habitual treballar amb ell, malgrat que l’aplicació permet calcular-lo. En
canvi en aquest cicle sí que és més habitual.
Figura 2.8: Diagrames T-s i P-h d’un cicle real de refrigeració per compressió de vapor
Cal dir que de la mateixa manera que el cicle anterior, en aquest cicle també s’ha considerat
que hi pot haver pèrdues en els dos intercanviadors. Per aquest motiu cal introduir totes
les pressions.
També s’ha de dir que de la mateixa manera que en el cicle de Brayton, en aquest cicle
no es farà la hipòtesi de treballar amb gas ideal, sinó que es calcularan totes les seves
propietats termodinàmiques mitjançant el CoolProp.
Les equacions de cada un dels processos són les característiques dels dispositius. El
coeficient de funcionament del procés és:
Q̇L h6 − h5
COPM F = = (2.27)
ẆN (h2 − h1 ) − (h − 5 − h4 )
A la Figura 2.10 es té un exemple del diagrama T-s d’un cicle ideal de refrigeració per
gas.
Figura 2.10: Diagrama T-s d’un cicle ideal de refrigeració per gas
S’ha consultat [1] i [2] com a fonts bibliogràfiques per la redacció d’aquest capítol.
Totes les figures i equacions utilitzades d’aquest capítol han sigut extretes de [2].
Capítol 3 29
Capítol 3
El CoolProp és l’eina que hi ha darrere del càlcul de totes les propietats termodinàmiques
que realitza l’aplicació i de la representació de tots els diagrames termodinàmics. A
la Figura 3.1 es pot veure el logotip de la llibreria. Exactament, el CoolProp és una
llibreria escrita en C++ que conté les equacions d’estat de més de 100 substàncies pures o
pseudopures, d’aquesta manera es poden modelar molts fluids com l’aire, l’aigua o diversos
refrigerants. Aquesta versatilitat i el fet que malgrat ser una llibreria de C++ permetés
treballar amb Python de manera molt còmode van ser els factors que van determinar que
era l’eina adequada per l’aplicació que s’ha desenvolupat. Altres alternatives que s’havien
considerat van ser: l’XSteam, escrit a codi MATLAB, però es va descartar perquè només
servia per a l’aigua i el REFPROP, que és un software molt conegut, però és de pagament,
mentre que el CoolProp és una llicència oberta que es pot fer servir tant per projectes
acadèmics com comercials.
D’aquesta manera es podria dir que el CoolProp és l’equivalent a les taules termodinàmi-
ques que s’utilitzen per calcular les propietats d’un estat. Això és així perquè la llibreria
també incorpora un interpolador que agilitza els càlculs.
A mode resum, es podria dir que s’utilitzaran les següents funcions i/o classes de la
llibreria CoolProp:
• Classe StateContainer : Tal com el seu nom indica, és un contenidor dels estats
termodinàmics. Emmagatzema cadascun dels estats amb les seves corresponents
propietats.
• 6) name_fluid : és el nom del fluid de treball, pot ser: aigua, aire, diòxid de
carboni, butà, ... S’introdueix a la funció com un string corresponent al nom del
fluid.
Cal dir que la funció PropsSI reconeix com a propietat termodinàmica la qualitat del
vapor, que és el títol, sempre que aquest valor òbviament estigui comprès entre el 0 i
l’1. Si es volgués calcular el títol per un líquid subrefredat o d’un vapor sobreescalfat, la
funció retornaria un -1 ja que no té sentit físic.
Figura 3.3: Taula de string inputs de la funció PropsSI que utilitzarà l’aplicació
Per altra banda, la funció pot calcular altres coses més enllà de les propietats termodinà-
miques classes, per exemple els coeficients del virial, la conductivitat tèrmica, el nombre
de Prandtl, però en l’aplicació que s’està dissenyant es limita exclusivament a les següents
propietats: pressió, temperatura, entalpia específica, entropia específica i el títol. A la
Figura 3.3 es poden veure aquests inputs, el seu string associat i les unitats amb les quals
treballa la funció PropsSI.
Finalment, respecte als fluids de treball, la llista és molt llarga. Per simplificar-ho, s’ha
decidit incloure a l’aplicació només aquells fluids que es trobin a les taules termodinà-
miques utilitzades a l’assignatura de Termodinàmica. Tanmateix, resulta molt simple
ampliar aquesta llista i incloure més fluids. A la Figura 3.4 es pot veure una llista dels
fluids disponibles al CoolProp inclosos a l’aplicació. El nom del fluid en aquesta llista
correspon al string que cal introduir a la funció.
32 Capítol 3
Figura 3.4: Taula de fluids de treball de la llibreria CoolProp que utilitzarà l’aplicació
Figura 3.6: Diagrama P-h del R-134a obtingut utilitzant la classe Property Plot
I un tercer que s’ha d’introduir igualant la classe amb el paràmetre (vegis l’exemple de la
Figura 3.7), que és:
En conclusió, es podria dir que aquesta classe actua com a pont entre l’eina de càlcul
de l’aplicació (que inclou la funció PropsSI ) i l’eina de representació de diagrames de
l’aplicació (que es basa en la classe PropertyPlot).
Al codi següent es pot veure un exemple que engloba totes les funcions i classes descrites
per representar un cicle de Rankine amb reescalfament intermedi.
1 import CoolProp as cp
2 from CoolProp.Plots import PropertyPlot
3 from CoolProp.Plots import SimpleCompressionCycle
4 from CoolProp.Plots.SimpleCycles import BaseCycle
Capítol 3 35
45 cicle = rankine.get_state_changes()
46 """
47 4) Representem el cicle amb la funcio draw_process
48 """
49 plt.close(rankine.figure)
50 pp.draw_process(cicle)
51 pp.title(’Diagrama T-s’)
52 pp.show()
Llistat 3.1: Codi Python necessari per representar un diagrama T-s
Figura 3.8: Diagrama T-s d’un cicle de Rankine amb reescalfament intermedi
S’ha consultat [3] com a font bibliogràfica per la redacció d’aquest capítol. To-
tes les figures i equacions utilitzades en aquest capítol són d’elaboració pròpia,
excepte la 3.1 que s’ha extret de [3].
Capítol 4 37
Capítol 4
L’aplicació s’ha dissenyat a partir del paquet Tkinter de Python. Tkinter concretament
és una adaptació del llenguatge Tk que permet dissenyar interfícies d’usuari gràfiques
(GUI) per Python. A l’hora d’escollir entre aquest paquet davant d’altres, com podrien
ser PyQt o PySide, es va tenir en compte que es volia dissenyar una aplicació que tingués
una interfície senzilla i molt funcional, sense grans virgueries. Va ser determinant que el
paquet Tkinter en general és simple d’entendre, no hi ha molta documentació, però la
que hi ha és bastant clara, això va que permetre familiaritzar-se amb el paquet amb poc
temps.
Entrant en detalls, el disseny de l’aplicació s’ha organitzat de manera que s’ha programat
cada cicle termodinàmic per separat, a partir d’un primer cicle, que va ser el cicle bàsic
de Rankine, que va servir com a plantilla. A partir d’aquest cicle fent modificacions es
van obtenir la resta de cicles. En alguns casos van caldre més canvis i en alguns altres
menys però l’esquema és el mateix. Això s’ha fet d’aquesta manera perquè, per una
banda és molt més ràpid i per altra banda perquè seguint sempre la mateixa plantilla es
minimitzen els errors de programació. Per aquest motiu, tots els extractes de codi Python
que s’aniran mostrant en aquest capítol seran de la plantilla que es va seguir, és a dir, del
cicle bàsic de Rankine. Malgrat això, és cert que entre els cicles hi ha diferències clares,
per exemple: els dos cicles de Rankine incorporen l’opció de fer una anàlisi exergètica, que
no està disponible en la resta; al cicle de Brayton no apareix el títol del sistema perquè
treballa amb gas. Finalment, un cop dissenyats tots els cicles, es va dissenyar un índex
que servis com a primera pàgina de l’aplicació i que donés la opció d’accedir al cicle amb
el qual es vol treballar.
Més en profunditat, el disseny de la plantilla s’ha dividit en tres etapes de disseny que es
podria dir que són independents però que estan interconnectades i són seqüencials. Totes
tres conviuen dins el mateix arxiu de codi Python, a diferència dels cicles, que cadascun
és un arxiu diferent. Aquestes etapes, per ordre, són:
38 Capítol 4
• Disseny específic del solucionador. Perquè l’aplicació sigui funcional cal que
totes les dades introduïdes s’operin i es converteixin en resultats i aquests resultats
s’han de poder visualitzar en el disseny general. Per complir aquesta missió, s’ha
dissenyat una única funció, estructurada en diferents etapes, que és el solucionador.
A continuació s’explicarà cadascuna d’aquestes etapes per separat, amb més detalls i
mostrant extractes del codi Python que s’ha utilitzat.
En aquesta classe, en primer lloc es van definir totes les variables que havia d’utilitzar
l’aplicació per treballar, aquestes variables no poden ser variables normals sinó que són
característiques del paquet Tkinter, ja que permeten que l’usuari els doni un valor a través
de la interfície gràfica.
• Variables d’entrada: Que poden ser del tipus DoubleVar(), quan emmagatzemen
un valor numèric real (és a dir, un float), aleshores serviran per emmagatzemar els
valors de totes les propietats termodinàmiques, del flux màssic, etc. O poden ser del
tipus StringVar(), quan emmagatzemen cadenes de caràcters (és a dir, un string).
Aquest darrer tipus de variable només s’ha utilitzat per escollir el valor del fluid de
treball, que és el seu nom.
• Variable de selecció: Que són del tipus IntVar(). Aquestes variables emmagat-
zemen un valor numèric enter (és a dir, un integer). En l’aplicació en particular
Capítol 4 39
aquest valor enter serà binari (0 o 1). Cada una d’aquestes variables de selecció està
lligada a una variable d’entrada i serveixen per poder-li indicar al programa quines
són les dades que se li estan introduint, és a dir, amb quines variables ha d’operar
inicialment. D’aquesta manera, si pren valor 0 significa que no està seleccionada i
si pren valor 1 significa que està seleccionada.
A la interfície gràfica, es podria dir que, totes les variables d’entrada es representen amb
caixes on es pot introduir el valor numèric de la variable i totes les variables de selecció
es representen amb quadrats que es poden seleccionar o desseleccionar. Se’n pot veure un
exemple a la Figura 4.1.
Totes les variables de treball és declaren com atributs d’aquesta classe inicial que és
CicleRankine(). Per operar millor amb elles s’han organitzat amb llistes, i amb llistes de
llistes per poder fer les iteracions necessàries. Es pot veure un retall del codi Python amb
el que s’ha programat això al Llistat 4.1.
1 class CicleRankine():
2
13 #Variables d’entrada
14 self.Qcald = tk.DoubleVar()
15 self.Qcond = tk.DoubleVar()
16 self.Wturb = tk.DoubleVar()
17 self.Wbomb = tk.DoubleVar()
18 self.eta_turb = tk.DoubleVar()
19 self.eta_bomb = tk.DoubleVar()
20
21 self.eta_termic = tk.DoubleVar()
22
23 self.lVars = [self.Qcald, self.Qcond, self.Wturb, self.Wbomb, self.
eta_turb, self.eta_bomb]
24 self.lVars_noms = ["Qcald", "Qcond", "Wturb", "Wbomb", "eta_turb",
"eta_bomb"]
25
26 self.flux = tk.DoubleVar()
27 self.Wneta = tk.DoubleVar()
28 self.fluid = tk.StringVar()
40 Capítol 4
29
30 self.Tentorn = tk.DoubleVar()
31 self.Treactor = tk.DoubleVar()
32 self.Pentorn = tk.DoubleVar()
33
34
35 #Seleccio de variables d’entrada
36 self.Qcald_chk = tk.IntVar()
37 self.Qcond_chk = tk.IntVar()
38 self.Wturb_chk = tk.IntVar()
39 self.Wbomb_chk = tk.IntVar()
40 self.eta_turb_chk = tk.IntVar()
41 self.eta_bomb_chk = tk.IntVar()
42
43 self.lVars_chk = [self.Qcald_chk, self.Qcond_chk, self.Wturb_chk,
self.Wbomb_chk, self.eta_turb_chk, self.eta_bomb_chk]
44
45 self.flux_chk = tk.IntVar()
46 self.Wneta_chk = tk.IntVar()
47
48
49 #Propietats termodinamiques
50 self.P_1, self.P_2, self.P_3, self.P_4 = tk.DoubleVar(), tk.
DoubleVar(), tk.DoubleVar(), tk.DoubleVar()
51 self.T_1, self.T_2, self.T_3, self.T_4 = tk.DoubleVar(), tk.
DoubleVar(), tk.DoubleVar(), tk.DoubleVar()
52 self.h_1, self.h_2, self.h_3, self.h_4 = tk.DoubleVar(), tk.
DoubleVar(), tk.DoubleVar(), tk.DoubleVar()
53 self.s_1, self.s_2, self.s_3, self.s_4 = tk.DoubleVar(), tk.
DoubleVar(), tk.DoubleVar(), tk.DoubleVar()
54 self.x_1, self.x_2, self.x_3, self.x_4 = tk.DoubleVar(), tk.
DoubleVar(), tk.DoubleVar(), tk.DoubleVar()
55
56 self.lProps = [[],
57 [0,self.P_1, self.T_1, self.h_1, self.s_1, self.x_1],
58 [0,self.P_2, self.T_2, self.h_2, self.s_2, self.x_2],
59 [0,self.P_3, self.T_3, self.h_3, self.s_3, self.x_3],
60 [0,self.P_4, self.T_4, self.h_4, self.s_4, self.x_4]]
61
62 self.lProps_noms = [[],
63 [0,"P_1", "T_1", "H_1", "S_1", "Q_1"],
64 [0,"P_2", "T_2", "H_2", "S_2", "Q_2"],
65 [0,"P_3", "T_3", "H_3", "S_3", "Q_3"],
66 [0,"P_4", "T_4", "H_4", "S_4", "Q_4"]]
67
68 #Seleccio de propietats termodinamiques
69 self.P_1_chk, self.P_2_chk, self.P_3_chk, self.P_4_chk = tk.IntVar
(), tk.IntVar(), tk.IntVar(), tk.IntVar()
70 self.T_1_chk, self.T_2_chk, self.T_3_chk, self.T_4_chk = tk.IntVar
(), tk.IntVar(), tk.IntVar(), tk.IntVar()
71 self.h_1_chk, self.h_2_chk, self.h_3_chk, self.h_4_chk = tk.IntVar
(), tk.IntVar(), tk.IntVar(), tk.IntVar()
72 self.s_1_chk, self.s_2_chk, self.s_3_chk, self.s_4_chk = tk.IntVar
(), tk.IntVar(), tk.IntVar(), tk.IntVar()
73 self.x_1_chk, self.x_2_chk, self.x_3_chk, self.x_4_chk = tk.IntVar
Capítol 4 41
Aquesta mateixa classe la completen tots els mètodes que s’han implementat i que a
continuació s’explicaran. Els mètodes són les funcions de les variables que anteriorment
hem definit, i es defineixen dins la classe com una funció de Python típica.
• Mètodes associats a un botó. Són aquelles funcions que s’activen quan l’usuari
prem el botó de la interfície gràfica. Dintre d’aquests mètodes trobem un mètode
que és l’eina de càlcul, que s’explicarà amb detall a l’apartat següent, i que s’activa
quan l’usuari clica el botó Calcular. També hi ha els mètodes associats a les repre-
sentacions dels diagrames termodinàmics. Però, a banda d’aquests, dintre d’aquest
tipus hi ha els mètodes que serveixen de pont entre la classe principal, CicleRanki-
ne, i les subclasses associades, que no són res més que altres finestres, que s’obriran
quan es cliqui el botó que tenen associat.
En primer lloc es té el disseny gràfic de l’esquema del cicle termodinàmic. Per la realització
de les línies, els cercles, els rectangles, etc. s’ha utilitzat l’eina Canvas que és específic pel
disseny de diagrames, dibuixos, gràfics ...
En el Llistat 4.2 es pot veure el codi Python d’aquest gràfic. No té molta complexitat,
Capítol 4 43
bàsicament s’han dibuixat tots els elements, s’ha ficat el títol, etc. Però cal destacar
que cada dispositiu que apareix al cicle termodinàmic (caldera, bomba, condensador o
turbina) són també botons, amb el seu corresponent mètode associat.
Per tant al clicar sobre cada representació gràfica d’un dispositiu s’obrirà una finestra on
es podran introduir les dades relatives al dispositiu escollit. Això significa que a l’aplicació,
cada element de flux estacionari té una classe Python pròpia, i s’hi pot accedir clicant
sobre el seu dibuix (que és un botó) i aleshores el mètode associat al botó ens conduirà
a la nova finestra. Al Llistat 4.3 es pot veure el codi Python dels mètodes associats a
aquests botons.
32 self.submasterTurb.transient(self.master)
33 self.submasterTurb.grab_set()
34 self.master.wait_window(self.submasterTurb)
Llistat 4.3: Mètodes associats als botons de l’esquema gràfic del cicle termodinàmic
Sobre els mètodes del Llistat 4.3 noti’s que en obrir la nova finestra, també hi envien les
variables inicialitzades a la classe principal (classe CicleRankine) perquè es converteixin
en variables de la nova classe. Per exemple, a la turbina se l’hi enviaran les variables
46 Capítol 4
corresponents al treball que produeix i al seu rendiment, i també les variables de selecció
associades a les anteriors. D’aquesta manera si s’introdueix un valor a aquestes variables
dins la classe Turbina, també s’estarà introduint a la classe CicleRankine i posteriorment
serà molt còmode fer tots els càlculs des d’aquesta classe principal amb totes les dades
introduïdes.
Per altra banda, en obrir una nova finestra sempre es congelarà la finestra principal, per
evitar col·lapsar l’aplicació. Caldrà tancar la finestra oberta per descongelar-la.
En segon lloc es té el disseny gràfic del visualitzador. Tal com el seu nom indica, en el
visualitzador es pot veure en tot moment el valor que pren cadascuna de les variables de
l’aplicació. A més a més, el visualitzador també li permet saber a l’usuari quines són les
variables seleccionades perquè quan ho estiguin, la seva casella es marcarà de color groc.
A la Figura 4.2 es veu un exemple del visualitzador després d’introduir-li les dades d’un
cicle bàsic de Rankine típic.
Al Llistat 4.4 es té el codi que s’ha utilitzat per programar el visualitzador. D’aquest
codi cal fixar-se en dos aspectes, per una banda que tal com s’ha dit abans és un mètode
que s’inicia amb l’aplicació i que treballa amb les variables de l’aplicació, de manera
que va actualitzant-se amb els canvis de valor que aquestes tinguin. Per altra banda,
el funcionament de les variables tipus diccionari dVisualProp i dVisualVars, que són les
responsables del canvi de color de les caselles si s’han seleccionat o desseleccionat.
12 Indexs = ["P [MPa]", "T [ C ]", "h [kJ/kg]", "s [kJ/( K k g )]", "x"]
13 for i in range(height):
14 for j in range(width):
15 if i !=0 and j !=0:
16 VisualProp = tk.Label(self.canvas1, textvariable=self.
lProps[i][j], width=9, font="Helvetica 10", borderwidth=1, relief=’solid
’, bg="white")
17 VisualProp.place(x=80+75*i,y=460+19*j)
18
19 self.dVisualProp[(i,j)]=VisualProp
20
En tercer lloc, sobre el menú, que és la barra d’eines que es troba a la part superior de la
pantalla principal (corresponent a la Figura 4.1). Al Llistat 4.5 es pot veure el codi amb
què s’ha programat.
17 VisualProp.place(x=80+75*i,y=460+19*j)
18
19 self.dVisualProp[(i,j)]=VisualProp
20
21 elif i == 0 and j !=0: #j = P, T, h, ...
22 VisualIndex = tk.Label(self.canvas1, text=Indexs[j-1],
width=11, font="Helvetica 10 bold", borderwidth=1, relief=’solid’)
23 VisualIndex.place(x=70+75*i,y=460+19*j)
24
25 elif i != 0 and j == 0: #i = Estat 1, Estat 2, ...
26 VisualEstat = tk.Label(self.canvas1, text="Estat "+str(
i), width=9, font="Helvetica 10 bold", borderwidth=1, relief=’solid’)
27 VisualEstat.place(x=80+75*i,y=460+19*j)
28
29 else:
30 pass
31
60 NomWneta.place(x=110,y=638)
61 VisualWneta = tk.Label(self.canvas1, textvariable=self.Wneta, width
=13, font="Helvetica 10", borderwidth=1, relief=’solid’, bg="white")
62 VisualWneta.place(x=300,y=638)
63 self.dVisualProp[(0,1)]=VisualWneta
64
65 NomRtermic = tk.Label(self.canvas1, text="Rendiment termic [%]",
width=24, font="Helvetica 10 bold", borderwidth=1, relief=’solid’)
66 NomRtermic.place(x=110,y=657)
67 VisualRtermic = tk.Label(self.canvas1, textvariable=self.eta_termic
, width=13, font="Helvetica 10", borderwidth=1, relief=’solid’, bg="
white")
68 VisualRtermic.place(x=300,y=657)
69
70 #Botons del visualitzador
71 BotoCalcular = tk.Button(self.canvas1, text="Calcular", font="
Helvetica 12", relief=’raised’, command=self.clickedCalcular)
72 BotoCalcular.place(x=550, y=600)
73
74 BotoNetejar = tk.Button(self.canvas1, text="Netejar", font="
Helvetica 12", relief=’raised’, command=self.clickedNetejar)
75 BotoNetejar.place(x=553, y=645)
Llistat 4.5: Codi Python del menú
Com es veu, és un codi molt simple però té una gran funcionalitat: permet tancar la
finestra principal, reiniciar-la... Però sobretot és útil perquè permet accedir a la pantalla
de selecció del fluid de treball, la pantalla d’introducció de les propietats termodinàmiques,
permet obtenir els gràfics termodinàmics i fer l’anàlisi exergètica.
A continuació es passarà a explicar cadascuna de les pantalles que poden sortir bé sigui
del menú o del diagrama del cicle termodinàmic.
1 class LlistaFluid():
2
3 def __init__(self, master, fluid):
4
5 self.master=master
6 self.fluid=fluid
7
8 self.master.title("Fluid d’estudi")
9 self.master.geometry(’300x300’)
10 self.master.minsize(300, 300)
11 self.master.maxsize(300,300)
12
13 self.Seleccio(master)
14
Capítol 4 51
Per últim comentar que perquè l’aplicació funcioni cal introduir-li o bé el flux màssic, o
bé el treball net o bé ambdues, tal com s’indica a les instruccions que es poden veure a la
Figura 4.1. També destacar que aquesta pantalla d’introducció de dades serà sempre la
mateixa amb tots els cicles excepte amb el cicle de Rankine amb reescalfament intermedi,
ja que aquest té 6 estats i per tant s’hauran d’afegir dues columnes tant a la taula com
al visualitzador.
1 class TaulaProps():
2
3 def __init__(self, master, flux, flux_chk, Wneta, Wneta_chk, lProps,
lProps_chk, dVisualProp):
4
5 self.master=master
6
7 self.flux=flux
8 self.flux_chk = flux_chk
9
10 self.Wneta = Wneta
11 self.Wneta_chk = Wneta_chk
12
13
14 self.lProps=lProps
Capítol 4 53
15 self.lProps_chk=lProps_chk
16 self.dVisualProp=dVisualProp
17
18 self.master.title(’Taula de propietats’)
19 self.master.geometry(’700x500’)
20 self.master.minsize(700, 500)
21 self.master.maxsize(700, 500)
22
23 self.Taula(master)
24
25 def show_entry(self, var, widget, index):
26 widget.delete(0, "end")
27 if var.get() == 0:
28 widget.configure(state=’disabled’)
29 self.dVisualProp[index].configure(bg="white")
30 else:
31 widget.configure(state=’normal’)
32 self.dVisualProp[index].configure(bg="yellow")
33
34 def Taula(self, master):
35 """
36 Taula de propietats
37 """
38 self.canvasTaula = tk.Canvas(self.master, width=700, height=500)
39 self.canvasTaula.configure(background="white")
40 self.canvasTaula.place(x=0, y=0)
41
42 Titol = tk.Label(self.master, text="Taula de propietats", font="
Helvetica 18 bold", bg="white", fg="black").place(relx=0.50, rely=0.05,
anchor=’n’)
43
44 height = 5 #i
45 width = 6 #j
46 Props = {}
47 Indexs = ["P [MPa]", "T [ C ]", "h [kJ/kg]", "s [kJ/( K k g )]", "x"]
48 for i in range(height): #Rows
49 for j in range(width): #Columns
50 if i !=0 and j !=0:
51 CajaProp = tk.Entry(self.canvasTaula, textvariable=self
.lProps[i][j], width=10, font="Times 12", bg="Yellow", state=’disabled’)
52 CajaProp.place(x=50+120*i,y=100+30*j)
53 chkProp = tk.Checkbutton(self.canvasTaula, variable=
self.lProps_chk[i][j], bg="white", onvalue=1, offvalue=0, command=lambda
v=self.lProps_chk[i][j], e=CajaProp, index=(i,j): self.show_entry(v,e,
index))
54 chkProp.place(x=50+120*i+85, y=100+30*j)
55 Props[(i,j)]=CajaProp
56
57 elif i == 0 and j !=0: #j = P, T, h, ...
58 EntradaIndex = tk.Label(self.canvasTaula, text=Indexs[j
-1], width=11, font="Times 12", borderwidth=2, relief=’solid’)
59 EntradaIndex.place(x=50+120*i,y=100+30*j)
60
61 elif i != 0 and j == 0: #i = Estat 1, Estat 2, ...
62 EntradaEstat = tk.Label(self.canvasTaula, text="Estat "
54 Capítol 4
13 self.submasterFluid.transient(self.master)
14 self.submasterFluid.grab_set()
15 self.master.wait_window(self.submasterFluid)
Llistat 4.8: Mètodes associats a la selecció del fluid i a la taula de propietats
Com es pot veure, l’esquema de les pantalles és bastant similar, i per tant també ho és
el codi de cada classe, que es pot veure al Llistat 4.8. De la mateixa manera que amb la
taula de propietats termodinàmiques, les dades que s’introdueixen a cada una d’aquestes
finestres s’actualitzen al visualitzador de la pantalla principal.
1 class Caldera():
2
3 def __init__(self, master, Qcald, Qcald_chk, dVisualVars):
4
5 self.master=master
6 self.Qcald=Qcald
7 self.Qcald_chk=Qcald_chk
8 self.dVisualVars=dVisualVars
9
10 self.master.title(’Caldera’)
11 self.master.geometry(’400x400’)
12 self.master.minsize(400, 400)
13 self.master.maxsize(400, 400)
14
15 self.Esquema(master)
16
17 def show_entry(self, var, widget):
18 widget.delete(0, "end")
19 if var.get() == 0:
20 widget.configure(state=’disabled’)
21 self.dVisualVars[0].configure(bg="white")
22 else:
23 widget.configure(state=’normal’)
24 self.dVisualVars[0].configure(bg="yellow")
25
26 def Esquema(self, master):
27 """
28 Esquema g r f i c de la caldera
29 """
30 self.canvasCald = tk.Canvas(self.master, width=400, height=400)
31 self.canvasCald.configure(background="white")
32 self.canvasCald.place(x=0, y=0)
33
34 Titol = tk.Label(self.master, text="Caldera", font="Helvetica 12
bold", bg="white", fg="black").place(relx=0.50, rely=0.07, anchor=’n’)
35
36 self.canvasCald.create_rectangle(120,70,280,150, fill="light grey")
37 self.canvasCald.create_line(40,110,120,110,fill="blue", arrow="last
", width=5)
38 self.canvasCald.create_line(280,110,360,110,fill="blue", arrow="
last", width=5)
39 self.canvasCald.create_line(200, 120, 200, 200, fill="red", arrow="
first", width=5)
40
41 Estat2 = self.canvasCald.create_text((80, 90), text="2", font="
Helvetica 14 bold")
42 Estat3 = self.canvasCald.create_text((320, 90), text="3", font="
Helvetica 14 bold")
43 Calor = self.canvasCald.create_text((220, 180), text="Q", font="
Capítol 4 57
Times 14 italic")
44
45 #Entrada de dades
46 EntradaCalor = tk.Label(self.canvasCald, text="Q (kW): ", font="
Times 12" ,bg="White")
47 EntradaCalor.place(x=120, y=240)
48 CajaCalor = tk.Entry(self.canvasCald, textvariable=self.Qcald,
width=10, font="Times 12", bg="Yellow", state=’disabled’)
49 CajaCalor.place(x=190, y=240)
50 chkCalor = tk.Checkbutton(self.canvasCald, variable=self.Qcald_chk,
bg="white", onvalue=1, offvalue=0, command=lambda v=self.Qcald_chk, e=
CajaCalor: self.show_entry(v,e))
51 chkCalor.place(x=270, y=240)
52
53 BotoAcceptar = tk.Button(self.canvasCald, text="Acceptar", font="
Helvetica 10", command=self.master.destroy)
54 BotoAcceptar.place(relx=0.45, rely=0.7)
55
56
57 class Turbina():
58
59 def __init__(self, master, Wturb, Wturb_chk, eta_turb, eta_turb_chk,
dVisualVars):
60
61 self.master=master
62 self.Wturb=Wturb
63 self.Wturb_chk=Wturb_chk
64 self.eta_turb=eta_turb
65 self.eta_turb_chk=eta_turb_chk
66 self.dVisualVars=dVisualVars
67
68 self.master.title(’Turbina’)
69 self.master.geometry(’400x500’)
70 self.master.minsize(400, 500)
71 self.master.maxsize(400, 500)
72
73 self.Esquema(master)
74
75 def show_entry(self, var, widget, index):
76 widget.delete(0, "end")
77 if var.get() == 0:
78 widget.configure(state=’disabled’)
79 self.dVisualVars[index].configure(bg="white")
80 else:
81 widget.configure(state=’normal’)
82 self.dVisualVars[index].configure(bg="yellow")
83
84 def Esquema(self, master):
85 """
86 Esquema g r f i c de la turbina
87 """
88 self.canvasTurb = tk.Canvas(self.master, width=400, height=500)
89 self.canvasTurb.configure(background="white")
90 self.canvasTurb.place(x=0, y=0)
91
58 Capítol 4
129 self.Wbomb=Wbomb
130 self.Wbomb_chk=Wbomb_chk
131 self.eta_bomb=eta_bomb
132 self.eta_bomb_chk=eta_bomb_chk
133 self.dVisualVars=dVisualVars
134
135 self.master.title(’Bomba’)
136 self.master.geometry(’400x500’)
137 self.master.minsize(400, 500)
138 self.master.maxsize(400, 500)
139
140 self.Esquema(master)
141
142 def show_entry(self, var, widget, index):
143 widget.delete(0, "end")
144 if var.get() == 0:
145 widget.configure(state=’disabled’)
146 self.dVisualVars[index].configure(bg="white")
147 else:
148 widget.configure(state=’normal’)
149 self.dVisualVars[index].configure(bg="yellow")
150
151 def Esquema(self, master):
152 """
153 Esquema g r f i c de la bomba
154 """
155 def circle(canvas,x,y,r,color):
156 return canvas.create_oval(x-r,y-r,x+r,y+r, fill=color)
157 self.canvasBomb = tk.Canvas(self.master, width=400, height=500)
158 self.canvasBomb.configure(background="white")
159 self.canvasBomb.place(x=0, y=0)
160
161 Titol = tk.Label(self.master, text="Bomba", font="Helvetica 12 bold
", bg="white", fg="black").place(relx=0.50, rely=0.05, anchor=’n’)
162
196 self.master=master
197 self.Qcond=Qcond
198 self.Qcond_chk=Qcond_chk
199 self.dVisualVars=dVisualVars
200
201 self.master.title(’Condensador’)
202 self.master.geometry(’400x400’)
203 self.master.minsize(400, 400)
204 self.master.maxsize(400, 400)
205
206 self.Esquema(master)
207
duït a l’aplicació, en variables Tkinter. Fer aquest pas és necessari perquè les variables
DoubleVar() no permeten operar-les entre elles i per tant seria impossible fer càlculs.
D’aquesta manera el que es fa és treballar amb diccionaris, de manera que a cada estat
termodinàmic li correspon un diccionari. I les claus d’aquest diccionari són els string
inputs de la Figura 3.3, els quals el CoolProp associa a una propietat termodinàmica. I
el valor associat a cada una d’aquestes claus serà el valor numèric de la propietat. Fent-
ho així serà molt més fàcil fer càlculs amb aquests valors, utilitzar la funció PropsSI i
emmagatzemar els resultats.
)
38
39 for elem in DadesProps:
40 Prop = elem[0]
41 Valor = elem[1]
42 Estat[int(Prop[2])][Prop[0]]=Valor #A cada diccionari/estat li
assignem com a clau la propietat amb el valor corresponent
43
44 for elem in DadesCicle: #Fem un diccionari de potencies termiques
i rendiments. Pots[’Qcald’]=valor n u m r i c de Qcald
45 Nom = elem[0]
46 Valor = elem[1]
47 Pots[Nom]=Valor
48
49 for i in range(5):
50 if ’P’ in Estat[i]:
51 Estat[i][’P’]=Estat[i][’P’]*1e6 #Passem de MPa a Pa per
treballar amb el CoolProp
52 if ’T’ in Estat[i]:
53 Estat[i][’T’]=Estat[i][’T’]+273.15 #Passem de C a K per
treballar amb el CoolProp
54 if ’H’ in Estat[i]:
55 Estat[i][’H’]=Estat[i][’H’]*1000 #Passem de kJ a J per
treballar amb el CoolProp
56 if ’S’ in Estat[i]:
57 Estat[i][’S’]=Estat[i][’S’]*1000 #Passem de kJ a J per
treballar amb el CoolProp
58
59 for elem in Pots:
60 if elem in NomsPots:
61 Pots[elem] = Pots[elem]*1000 #Passem de kW a W per
treballar amb el CoolProp
62 if elem in NomsRends:
63 Pots[elem] = Pots[elem]/100 #Passem de % a tant per u
64
65 #Hem creat els diccionaris i hem fet les converssions per treballar
amb el CoolProp.
Llistat 4.10: Codi Python de la primera etapa del solucionador
També es pot veure que a part dels diccionaris dels estats termodinàmics reals, es tre-
ballarà amb els estats termodinàmics ideals, perquè són necessaris per treballar amb els
rendiments de la turbina i la bomba.
Per altra banda, també es treballa amb dos altres diccionaris: el diccionari Pots que és
per les variables relatives a la caldera, la turbina, la bomba i el condensador: és a dir
les seves potències i rendiments. I el diccionari FluxPot que és per treballar amb el flux
màssic i la potència neta del cicle. El motiu d’aquesta separació és que a l’aplicació cal
introduir-li o el flux màssic o la potència neta, en canvi no es té perquè introduir cap
potència o rendiment dels dispositius del cicle. Per tant el
Finalment, es fa el canvi d’unitats de totes les variables per treballar amb la funció PropsSI
que treballa en les unitats que es poden veure a la Figura 3.3.
64 Capítol 4
Funció ResoldreEstat
1 """
2 ETAPA 2: Definim les funcions que farem servir per resoldre el
problema
3 """
4 def ResoldreEstat(Estat, EstatIdeal, fluid):
5 NomsPropietats = [0, ’P’, ’T’, ’H’, ’S’, ’Q’]
6 for i in range(5):
7 if len(Estat[i]) > 1: #CAS 1: Coneixem m s d’una propietat
per algun dels estats! -> Aleshores l’estat ja esta resolt!
8 for Prop in NomsPropietats[1:]:
9 if Prop not in Estat[i]:
10 PropsConec = list(Estat[i])
11 Estat[i][Prop]=PropsSI(Prop,PropsConec[0],Estat
[i][PropsConec[0]],PropsConec[1],Estat[i][PropsConec[1]],fluid)
12 #L’estat ha quedat resolt
13
14 for i in range(len(EstatIdeal)):
15 if len(EstatIdeal[i]) > 1:
16 for Prop in NomsPropietats[1:]:
17 if Prop not in EstatIdeal[i]:
18 PropsConec = list(EstatIdeal[i])
19 EstatIdeal[i][Prop]=PropsSI(Prop,PropsConec[0],
EstatIdeal[i][PropsConec[0]],PropsConec[1],EstatIdeal[i][PropsConec[1]],
fluid)
20 #L’estat ideal queda resolt
Llistat 4.11: Codi Python de la funció ResoldreEstat
Funció CalcularAltres
3 if ’P’ in Estat[i]:
4 if Estat[i][’P’] != 0: #Fent aixo apliquem les
equacions P_2=P_3, P_4=P_1, P_2 = P_2s, P_4 = P_4s
5 if i==1:
6 Estat[4][’P’] = Estat[1][’P’]
7 elif i==2:
8 Estat[3][’P’] = Estat[2][’P’]
9 EstatIdeal[0][’P’] = Estat[2][’P’] #EstatIdeal
[0] -> Estat2s
10 elif i==3:
11 Estat[2][’P’] = Estat[3][’P’]
12 elif i==4:
13 Estat[1][’P’] = Estat[4][’P’]
14 EstatIdeal[1][’P’] = Estat[4][’P’] #EstatIdeal
[1] -> Estat4s
15
16 if ’S’ in Estat[i]:
17 if Estat[i][’S’] != 0: #Fent aixo apliquem les
equacions s_1 = s_2s i s_3 = s_4s
18 if i==1:
19 EstatIdeal[0][’S’] = Estat[1][’S’]
20 elif i==3:
21 EstatIdeal[1][’S’] = Estat[3][’S’]
Llistat 4.12: Codi Python de la funció CalcularAltres
Funció CalcularFlux
Amb aquesta funció s’aplica la següent equació per calcular el flux màssic:
˙
WN
ṁ =
(h3 − h4 ) − (h2 − h1 )
Funció CalcularPotencies
Amb aquesta funció s’apliquen les equacions 2.1, 2.2, 2.3, 2.4, 2.5 i 2.7 per calcular les
potències tèrmiques, mecàniques, la potència neta i el rendiment tèrmic del cicle.
Funció RendimentTurbina
Amb aquesta funció s’aplica l’equació 1.9, corresponent al rendiment d’una turbina. Per
aplicar l’equació completament, com que hi apareixen 4 variables, es verifica que per
calcular-ne una d’elles es coneguin la resta. Aleshores s’aplica l’equació amb la varia-
ble incògnita aïllada. Aquesta estratègia és la que se seguirà sempre que es tingui un
rendiment, sigui del dispositiu que sigui.
19 if v4:
20 if Pots[’eta_turb’]==1 and ’S’ in Estat[3]:
21 Estat[4][’S’]=Estat[3][’S’]
22 if Pots[’eta_turb’]==1 and ’S’ in Estat[4]:
23 Estat[3][’S’]=Estat[4][’S’]
Llistat 4.15: Codi Python de la funció RendimentTurbina
Funció RendimentBomba
Amb aquesta funció s’aplica l’equació 1.11, corresponent al rendiment d’una bomba. S’ha
seguit la mateixa estratègia que amb la funció anterior però cal notar que en aquest cas
es pot donar la circumstància que el treball de la bomba sigui negligible (cosa que en
alguns cicles de Rankine és habitual), aleshores el càlcul del rendiment de la bomba perd
el sentit i tampoc es podrien fer la resulta de càlculs, per tant calia allargar el codi del
Llistat 4.16 per fer aquesta distinció.
24 Estat[2][’H’]=(EstatIdeal[0][’H’]-Estat[1][’H’]+Pots[’
eta_bomb’]*Estat[1][’H’])/(Pots[’eta_bomb’])
25
26 if v2 and v3 and v4 and (not v1) and (Pots[’eta_bomb’]!=1):
27 Estat[1][’H’]=(Pots[’eta_bomb’]*Estat[2][’H’]-
EstatIdeal[0][’H’])/(Pots[’eta_bomb’]-1)
28
29 if v1 and v2 and v4 and (not v3):
30 EstatIdeal[0][’H’]=Estat[1][’H’]+Pots[’eta_bomb’]*(
Estat[2][’H’]-Estat[1][’H’])
31
Funció CalcularEntalpies
Aquesta és la darrera funció i també la més llarga de totes. La funció implementa les
equacions 2.1, 2.2, 2.3 i 2.4; les quals anteriorment s’havia vist que s’implementaven
per calcular les potències. En aquest cas, s’utilitzen per calcular les entalpies, donant
per suposat que es coneix alguna potència. De fet el que s’ha fet és aplicar la mateixa
estratègia que amb els rendiments, treballant amb 4 equacions amb 2 variables cada una
d’elles.
Per tant, el que s’ha fet és en primer lloc estudiar totes les combinacions possibles de po-
tències i per cada combinació, si tenia sentit, plantejar cada equació les dues possibilitats,
aïllant la incògnita. Aquesta és la part més ineficient del codi de tota l’aplicació i seria
un punt a millorar pel treball futur perquè segurament es podria optimitzar i fer-lo més
curt. Tot i això, no suposa un problema per l’aplicació, ja que funciona de manera ràpida
i correcte.
10
11 elif (not v1) and (not v2) and (not v3) and (v4): # N o m s conec
Wbomb
12 if ’H’ in Estat[2]:
13 Estat[1][’H’]=Estat[2][’H’]-Pots[’Wbomb’]/flux
14 if ’H’ in Estat[1]:
15 Estat[2][’H’]=Estat[1][’H’]+Pots[’Wbomb’]/flux
16 #1
17
18 elif (not v1) and (not v2) and (v3) and (not v4): # N o m s conec
Wturb
19 if ’H’ in Estat[4]:
20 Estat[3][’H’]=Estat[4][’H’]-Pots[’Wturb’]/flux
21 if ’H’ in Estat[3]:
22 Estat[4][’H’]=Estat[3][’H’]+Pots[’Wturb’]/flux
23 #2
24
25
26 elif (not v1) and (not v2) and (v3) and (v4): #Conec Wbomb i
Wturb
27 if ’H’ in Estat[1]:
28 Estat[2][’H’]=Estat[1][’H’]+Pots[’Wbomb’]/flux
29 if ’H’ in Estat[2]:
30 Estat[1][’H’]=Estat[2][’H’]-Pots[’Wbomb’]/flux
31 if ’H’ in Estat[3]:
32 Estat[4][’H’]=Estat[3][’H’]+Pots[’Wturb’]/flux
33 if ’H’ in Estat[4]:
34 Estat[3][’H’]=Estat[4][’H’]-Pots[’Wturb’]/flux
35 #3
36
37 elif (not v1) and (v2) and (not v3) and (not v4): # N o m s conec
Qcond
38 if ’H’ in Estat[1]:
39 Estat[4][’H’]=Estat[1][’H’]-Pots[’Qcond’]/flux
40 if ’H’ in Estat[4]:
41 Estat[1][’H’]=Estat[4][’H’]+Pots[’Qcond’]/flux
42 #4
43
44 elif (not v1) and (v2) and (not v3) and (v4): #Conec Qcond i
Wbomb
45 if ’H’ in Estat[1]:
46 Estat[4][’H’]=Estat[1][’H’]-Pots[’Qcond’]/flux
47 Estat[2][’H’]=Estat[1][’H’]+Pots[’Wbomb’]/flux
48 if ’H’ in Estat[2]:
49 Estat[1][’H’]=Estat[2][’H’]-Pots[’Wbomb’]/flux
50 if ’H’ in Estat[4]:
51 Estat[1][’H’]=Estat[4][’H’]+Pots[’Qcond’]/flux
52 #5
53
54 elif (not v1) and (v2) and (v3) and (not v4): #Conec Qcond i
Wturb
55 if ’H’ in Estat[1]:
56 Estat[4][’H’]=Estat[1][’H’]-Pots[’Qcond’]/flux
57 if ’H’ in Estat[3]:
58 Estat[4][’H’]=Estat[3][’H’]+Pots[’Wturb’]/flux
70 Capítol 4
59 if ’H’ in Estat[4]:
60 Estat[1][’H’]=Estat[4][’H’]+Pots[’Qcond’]/flux
61 Estat[3][’H’]=Estat[4][’H’]-Pots[’Wturb’]/flux
62 #6
63
64 elif (not v1) and (v2) and (v3) and (v4): #Conec Qcond, Wturb,
Wbomb
65 if ’H’ in Estat[1]:
66 Estat[4][’H’]=Estat[1][’H’]-Pots[’Qcond’]/flux
67 Estat[2][’H’]=Estat[1][’H’]+Pots[’Wbomb’]/flux
68 if ’H’ in Estat[2]:
69 Estat[1][’H’]=Estat[2][’H’]-Pots[’Wbomb’]/flux
70 if ’H’ in Estat[3]:
71 Estat[4][’H’]=Estat[3][’H’]+Pots[’Wturb’]/flux
72 if ’H’ in Estat[4]:
73 Estat[1][’H’]=Estat[4][’H’]+Pots[’Qcond’]/flux
74 Estat[3][’H’]=Estat[4][’H’]-Pots[’Wturb’]/flux
75 #7
76
77 elif (v1) and (not v2) and (not v3) and (not v4): # N o m s conec
Qcald
78 if ’H’ in Estat[3]:
79 Estat[2][’H’]=Estat[3][’H’]-Pots[’Qcald’]/flux
80 if ’H’ in Estat[2]:
81 Estat[3][’H’]=Estat[2][’H’]+Pots[’Qcald’]/flux
82 #8
83
84 elif (v1) and (not v2) and (not v3) and (v4): #Conec Qcald i
Wbomb
85 if ’H’ in Estat[1]:
86 Estat[2][’H’]=Estat[1][’H’]+Pots[’Wbomb’]/flux
87 if ’H’ in Estat[2]:
88 Estat[3][’H’]=Estat[2][’H’]+Pots[’Qcald’]/flux
89 Estat[1][’H’]=Estat[2][’H’]-Pots[’Wbomb’]/flux
90 if ’H’ in Estat[3]:
91 Estat[2][’H’]=Estat[3][’H’]-Pots[’Qcald’]/flux
92 #9
93
94 elif (v1) and (not v2) and (v3) and (not v4): #Conec Qcald i
Wturb
95 if ’H’ in Estat[2]:
96 Estat[3][’H’]=Estat[2][’H’]+Pots[’Qcald’]/flux
97 if ’H’ in Estat[3]:
98 Estat[2][’H’]=Estat[3][’H’]-Pots[’Qcald’]/flux
99 Estat[4][’H’]=Estat[3][’H’]+Pots[’Wturb’]/flux
100 if ’H’ in Estat[4]:
101 Estat[3][’H’]=Estat[4][’H’]-Pots[’Wturb’]/flux
102 #10
103
104 elif (v1) and (not v2) and (v3) and (v4): #Conec Qcald, Wturb i
Wbomb
105 if ’H’ in Estat[1]:
106 Estat[2][’H’]=Estat[1][’H’]+Pots[’Wbomb’]/flux
107 if ’H’ in Estat[2]:
108 Estat[3][’H’]=Estat[2][’H’]+Pots[’Qcald’]/flux
Capítol 4 71
109 Estat[1][’H’]=Estat[2][’H’]-Pots[’Wbomb’]/flux
110 if ’H’ in Estat[3]:
111 Estat[2][’H’]=Estat[3][’H’]-Pots[’Qcald’]/flux
112 Estat[4][’H’]=Estat[3][’H’]+Pots[’Wturb’]/flux
113 if ’H’ in Estat[4]:
114 Estat[3][’H’]=Estat[4][’H’]-Pots[’Wturb’]/flux
115 #11
116
117 elif (v1) and (v2) and (not v3) and (not v4): #Conec Qcald i
Qcond
118 if ’H’ in Estat[1]:
119 Estat[4][’H’]=Estat[1][’H’]-Pots[’Qcond’]/flux
120 if ’H’ in Estat[2]:
121 Estat[3][’H’]=Estat[2][’H’]+Pots[’Qcald’]/flux
122 if ’H’ in Estat[3]:
123 Estat[2][’H’]=Estat[3][’H’]-Pots[’Qcald’]/flux
124 if ’H’ in Estat[4]:
125 Estat[1][’H’]=Estat[4][’H’]+Pots[’Qcond’]/flux
126 #12
127
128 elif (v1) and (v2) and (not v3) and (v4): #Conec Qcald, Qcond i
Wbomb
129 if ’H’ in Estat[1]:
130 Estat[4][’H’]=Estat[1][’H’]-Pots[’Qcond’]/flux
131 Estat[2][’H’]=Estat[1][’H’]+Pots[’Wbomb’]/flux
132 if ’H’ in Estat[2]:
133 Estat[3][’H’]=Estat[2][’H’]+Pots[’Qcald’]/flux
134 Estat[1][’H’]=Estat[2][’H’]-Pots[’Wbomb’]/flux
135 if ’H’ in Estat[3]:
136 Estat[2][’H’]=Estat[3][’H’]-Pots[’Qcald’]/flux
137 if ’H’ in Estat[4]:
138 Estat[1][’H’]=Estat[4][’H’]+Pots[’Qcond’]/flux
139 #13
140
141 elif (v1) and (v2) and (v3) and (not v4): #Conec Qcald, Qcond i
Wturb
142 if ’H’ in Estat[1]:
143 Estat[4][’H’]=Estat[1][’H’]-Pots[’Qcond’]/flux
144 if ’H’ in Estat[2]:
145 Estat[3][’H’]=Estat[2][’H’]+Pots[’Qcald’]/flux
146 if ’H’ in Estat[3]:
147 Estat[2][’H’]=Estat[3][’H’]-Pots[’Qcald’]/flux
148 Estat[4][’H’]=Estat[3][’H’]+Pots[’Wturb’]/flux
149 if ’H’ in Estat[4]:
150 Estat[1][’H’]=Estat[4][’H’]+Pots[’Qcond’]/flux
151 Estat[3][’H’]=Estat[4][’H’]-Pots[’Wturb’]/flux
152 #14
153
154 elif (v1) and (v2) and (v3) and (v4): #Conec tot: Qcald, Qcond,
Wturb, Wbomb
155 if ’H’ in Estat[1]:
156 Estat[4][’H’]=Estat[1][’H’]-Pots[’Qcond’]/flux
157 Estat[2][’H’]=Estat[1][’H’]+Pots[’Wbomb’]/flux
158 if ’H’ in Estat[2]:
159 Estat[3][’H’]=Estat[2][’H’]+Pots[’Qcald’]/flux
72 Capítol 4
160 Estat[1][’H’]=Estat[2][’H’]-Pots[’Wbomb’]/flux
161 if ’H’ in Estat[3]:
162 Estat[2][’H’]=Estat[3][’H’]-Pots[’Qcald’]/flux
163 Estat[4][’H’]=Estat[3][’H’]+Pots[’Wturb’]/flux
164 if ’H’ in Estat[4]:
165 Estat[1][’H’]=Estat[4][’H’]+Pots[’Qcond’]/flux
166 Estat[3][’H’]=Estat[4][’H’]-Pots[’Wturb’]/flux
167 #15
168 else:
169 pass
Llistat 4.17: Codi Python de la funció CalcularEntalpies
També en aquesta etapa, un cop resolt el cicle, s’aprofita i s’emmagatzemen totes les
dades dels diccionaris d’estats a un objecte de la classe StateContainer, per després poder
fer la representació gràfica del cicle de manera fàcil.
Finalment també és en aquesta etapa on s’ha decidit ficar les alertes d’error, que serveixen
per avisar l’usuari en cas que no hagi introduït suficients dades i no s’hagi pogut dur a
terme la resolució del cicle.
1 """
2 ETAPA 3: Bucle actualitzant els valors dels diccionaris i les
aprofitem per si volem fer el g r f i c
3 """
4 j=0
5 #long=0
6 while (j<10):
7 ResoldreEstat(Estat, EstatIdeal, fluid)
8 CalcularAltres(Estat, EstatIdeal)
9 CalcularFlux(Estat, Pots, FluxPot)
10 RendimentTurbina(Estat, EstatIdeal, Pots)
11 RendimentBomba(Estat, EstatIdeal, Pots)
12 if ’flux’ in FluxPot:
13 flux=FluxPot[’flux’]
14 CalcularPotencies(Estat, Pots, flux, FluxPot)
15 CalcularEntalpies(Estat, Pots, flux)
16
17 #long=len(Estat[1])+len(Estat[2])+len(Estat[3])+len(Estat[4])
18 j=j+1
19
24 if i != 0:
25 for prop in NomsPropietats[1:5]:
26 self.sc[i-1,prop]=Estat[i][prop]
27 break
28 except KeyError:
29 messagebox.showerror("Error", "No has i n t r o d u t suficients
dades")
30 break
31 except ValueError:
32 messagebox.showerror("Error", "No has i n t r o d u t suficients
dades")
33 break
Llistat 4.18: Codi Python de la tercera etapa del solucionador
També en aquesta etapa s’han col·locat avisos, per exemple, al no obtindre el títol d’un
estat l’aplicació ens informa que és degut al fet que aquell estat es troba fora de la campana
de saturació.
1 """
2 ETAPA 4: Actualitzem els valors finals i els retornem a la
interf cie g r f i c a
3 """
4 for i in range(len(self.lProps)): #i=1 -> Estat 1, i=2 -> Estat
2, i=3 -> Estat 3, i=4 -> Estat 4.
5 for j in range(len(self.lProps[i])): #j=1 -> P / j=2 -> T / j=3
-> H / j=4 -> S / j=5 -> Q /
6 if j != 0 and i != 0:
7 if j==1:
8 Estat[i][NomsPropietats[j]]=round(Estat[i][
NomsPropietats[j]]/1e6,4) #Passem de Pa a MPa
9 if j==2:
10 Estat[i][NomsPropietats[j]]=round(Estat[i][
NomsPropietats[j]]-273.15,2) #Passem de K a C
11 if j==3:
12 Estat[i][NomsPropietats[j]]=round(Estat[i][
NomsPropietats[j]]/1000,4) #Passem de J a kJ
13 if j==4:
14 Estat[i][NomsPropietats[j]]=round(Estat[i][
NomsPropietats[j]]/1000,4) #Passem de J a kJ
15 if j==5:
16 Estat[i][NomsPropietats[j]]=round(Estat[i][
NomsPropietats[j]],4)
74 Capítol 4
17 if Estat[i][NomsPropietats[j]] == -1:
18 Estat[i][NomsPropietats[j]]="-"
19 messagebox.showwarning("Advertencia", "Has
obtingut algun t t o l sense sentit f s i c ja que et trobes fora de la
campana")
20
21 self.lProps[i][j].set(Estat[i][NomsPropietats[j]])
22
23
24 for i in range(len(self.lVars)):
25 if self.lVars_noms[i] in NomsPots:
26 if self.lVars_noms[i] in Pots:
27 self.lVars[i].set(round(Pots[self.lVars_noms[i
]]/1000,0)) #Passem de W a kW
28 else:
29 self.lVars[i].set("-") #ERROR NO S’HA CALCULAT DURANT
LA ITERACIO
30 if self.lVars_noms[i] in NomsRends:
31 if self.lVars_noms[i] in Pots:
32 self.lVars[i].set(round(Pots[self.lVars_noms[i]]*100,4)
) #Passem de tant per u a 100
33 else:
34 self.lVars[i].set("-") #ERROR NO S’HA CALCULAT DURANT
LA ITERACIO
35
36 if ’flux’ in FluxPot:
37 self.flux.set(round(FluxPot[’flux’],2))
38 if ’Wneta’ in FluxPot:
39 self.Wneta.set(round(FluxPot[’Wneta’]/1000,0)) #Passem de W a
kW
40 if ’eta_termic’ in FluxPot:
41 self.eta_termic.set(round(FluxPot[’eta_termic’]*100,2)) #Passem
de tant per u a %
Llistat 4.19: Codi Python de la quarta etapa del solucionador
Anàlisi exergètica
Finalment, malgrat que no forma part estrictament del solucionador, pels cicles de Ranki-
ne (bàsic i amb reescalfament intermedi) l’aplicació permet fer l’anàlisi exergètica. Per
fer-lo s’hi pot accedir a través del menú. És una nova pantalla, que es pot veure a la
Figura 4.6.
Com que és una nova pantalla, és una nova classe, la classe AnalisiExergetic. En aquest
cas, com que l’opció de l’anàlisi exergètica es va afegir al final del treball, té una progra-
mació lleugerament diferent que a continuació es comentarà. Es pot veure el codi Python
de l’anàlisi exergètica al Llistat 4.20.
1 class AnalisiExergetic():
2
3 def __init__(self, master, Tentorn, Treactor, Pentorn, fluid, flux,
Wneta, lProps, lVars):
4
Capítol 4 75
5 self.master=master
6 self.Tentorn=Tentorn
7 self.Treactor=Treactor
8 self.Pentorn=Pentorn
9 self.Wneta=Wneta
10 self.fluid=fluid
11 self.flux=flux
12 self.lProps=lProps
13 self.lVars=lVars
14
15 self.lProps_noms = [[],
16 [0,"P_1", "T_1", "H_1", "S_1", "E_1"],
17 [0,"P_2", "T_2", "H_2", "S_2", "E_2"],
18 [0,"P_3", "T_3", "H_3", "S_3", "E_3"],
19 [0,"P_4", "T_4", "H_4", "S_4", "E_4"]]
20
26 self.etaex_instal=tk.DoubleVar()
27
28 self.lex=[0,self.ex_1, self.ex_2, self.ex_3, self.ex_4]
29 self.lWp=[0,self.Wp_cald, self.Wp_cond, self.Wp_turb, self.Wp_bomb]
30 self.letaex=[0,self.etaex_cald, self.etaex_cond, self.etaex_turb,
self.etaex_bomb]
31
32
33 self.master.title(" A n l i s i e x e r g t i c ")
34 self.master.geometry(’600x500’)
35 self.master.minsize(600, 500)
36 self.master.maxsize(600,500)
37
38 self.canvasEx = tk.Canvas(self.master, width=600, height=500, bg=’
white’)
39 self.canvasEx.place(x=0, y=0)
40
’, bg="white")
111 VisualRendiment.place(x=401,y=340)
112
113 BotoCalcular = tk.Button(self.canvasEx, text="Calcular", font="
Helvetica 12", command=self.CalculExergies)
114 BotoCalcular.place(relx=0.3, rely=0.8)
115
116 BotoAcceptar = tk.Button(self.canvasEx, text="Acceptar", font="
Helvetica 12", command=self.master.destroy)
117 BotoAcceptar.place(relx=0.55, rely=0.8)
118
119
120 def CalculExergies(self):
121 DadesProps = []
122 DadesCicle = []
123 Estat0, Estat1, Estat2, Estat3, Estat4 = {}, {}, {}, {}, {}
124 Estat = [Estat0, Estat1, Estat2, Estat3, Estat4] # Llista de
diccionaris d’estats. Volem algo tal com Estat[1][’T’]=T_1 (valor
n u m r i c de T1)
125
126 NomsPropietats = [0, ’P’, ’T’, ’H’, ’S’, ’E’]
127 NomsPots = ["Qcald", "Qcond", "Wturb", "Wbomb"]
128
154 Estat[0][’T’]=self.Tentorn.get()+273.15
155 Estat[0][’P’]=(self.Pentorn.get())*1e6
156 Estat[0][’H’]=PropsSI(’H’, ’T’, Estat[0][’T’], ’P’, Estat[0][’P’],
Capítol 4 79
fluid)
157 Estat[0][’S’]=PropsSI(’S’, ’T’, Estat[0][’T’], ’P’, Estat[0][’P’],
fluid)
158
159 Estat[0][’H’]=Estat[0][’H’]/1000
160 Estat[0][’S’]=Estat[0][’S’]/1000
161 T_f=self.Treactor.get()+273.15
162
163 """
164 C l c u l d’exergies
165 """
166 for i in range(5):
167 if i != 0:
168 Estat[i][’E’]=(Estat[i][’H’]-Estat[0][’H’])-Estat[0][’T’]*(
Estat[i][’S’]-Estat[0][’S’])
169 self.lex[i].set(round(Estat[i][’E’],4))
170
171 Pots[’ExQcald’]=abs(Pots[’Qcald’]*(1-(Estat[0][’T’]/T_f)))
172 Pots[’ExQcond’]=0
173 Pots[’ExWturb’]=abs(Pots[’Wturb’])
174 Pots[’ExWbomb’]=abs(Pots[’Wbomb’])
175
176 """
177 C l c u l de treballs perduts
178 """
179 Pots[’Wpcald’]=Pots[’ExQcald’]+FluxPot[’flux’]*(Estat[2][’E’]-Estat
[3][’E’])
180 Pots[’Wpcond’]=FluxPot[’flux’]*(Estat[4][’E’]-Estat[1][’E’])-Pots[’
ExQcond’]
181 Pots[’Wpturb’]=FluxPot[’flux’]*(Estat[3][’E’]-Estat[4][’E’])-Pots[’
ExWturb’]
182 Pots[’Wpbomb’]=Pots[’ExWbomb’]+FluxPot[’flux’]*(Estat[1][’E’]-Estat
[2][’E’])
183 """
184 C l c u l de rendiments exerg tics
185 """
186 Pots[’eta_ex_cald’]=1-((Pots[’Wpcald’])/(Pots[’ExQcald’]))
187 Pots[’eta_ex_turb’]=Pots[’ExWturb’]/(FluxPot[’flux’]*(Estat[3][’E’
]-Estat[4][’E’]))
188 Pots[’eta_ex_bomb’]=abs(FluxPot[’flux’]*(Estat[1][’E’]-Estat[2][’E’
]))/Pots[’ExWbomb’]
189 Pots[’eta_ex_instal’]=abs(self.Wneta.get())/Pots[’ExQcald’]
190 """
191 Actualitzem els valors
192 """
193 self.lWp[1].set(round(Pots[’Wpcald’],2))
194 self.lWp[2].set(round(Pots[’Wpcond’],2))
195 self.lWp[3].set(round(Pots[’Wpturb’],2))
196 self.lWp[4].set(round(Pots[’Wpbomb’],2))
197
198 self.letaex[1].set(round(Pots[’eta_ex_cald’]*100,2))
199 self.letaex[2].set("-")
200 self.letaex[3].set(round(Pots[’eta_ex_turb’]*100,2))
201 self.letaex[4].set(round(Pots[’eta_ex_bomb’]*100,2))
80 Capítol 4
202 self.etaex_instal.set(round(Pots[’eta_ex_instal’]*100,2))
Llistat 4.20: Codi Python de la classe AnalisiExergetic
La principal diferència respecte a la resta de la resta de codi és que en aquest cas les
variables que s’utilitzaran no s’han declarat a la classe principal. Això no suposa cap
problema perquè aquestes variables no s’han d’enviar a cap altra classe i es visualitzen en
aquesta mateixa finestra, en el visualitzador d’exergies i treballs perduts que es pot veure
a la Figura 4.6.
El codi per representar els diagrames del cicle bàsic de Rankine també es divideix en
aquestes 4 etapes i es pot veure al Llistat 4.21. En aquest cas però les etapes són més
simples perquè al cicle bàsic de Rankine no cal fer-li modificacions. En canvi, al cicle
de Rankine amb reescalfament intermedi cal introduir-li un codi pràcticament igual al de
l’apartat 3.4.
17 cicle._cycle_states=self.sc
18 cicle.steps = 50
19
20 grafic = cicle.get_state_changes()
21 """
22 PART 4: Mostrem el diagrama
23 """
24 plt.close(cicle.figure)
25 pp.draw_process(grafic)
26 pp.title(’Diagrama T-s’)
27 pp.show()
28
29 def clickedDiagPH(self, *args):
30 """
31 PART 1: Inicialitzem el diagrama
32 """
33 pp = PropertyPlot(self.fluid.get(), ’PH’, unit_system=’EUR’)
34 pp.calc_isolines(cp.iT)
35 pp.calc_isolines(cp.iQ)
36 """
37 PART 2: Cal haver fet el c l c u l !
38 """
39 if self.sc.__len__() == 0:
40 return "ERROR"
41 """
42 PART 3: Dibuixem el diagrama amb les dades guardades
43 """
44 cicle = SimpleCompressionCycle(self.fluid.get(), ’PH’, unit_system=
’EUR’)
45 cicle._cycle_states=self.sc
46 cicle.steps = 50
47
48 grafic = cicle.get_state_changes()
49 """
50 PART 4: Mostrem el diagrama
51 """
52 plt.close(cicle.figure)
53 pp.draw_process(grafic)
54 pp.title(’Diagrama P-h’)
55 pp.show()
Llistat 4.21: Codi Python de la representació dels diagrames T-s i P-h
Al codi es pot veure que entre representar el diagrama T-s i P-h no hi ha quasi cap dife-
rència, tan sols la indicació que cal donar-li a les classe PropertyPlot a l’hora d’inicialitzar
el diagrama i a la classe SimpleCompressionCycle. Pel que fa a la resta és la combinació
ordenada de les funcions i classes de la llibreria CoolProp que es detallen al Capítol 3.
S’ha consultat [4], [5], [6], [7] i [8] com a fonts bibliogràfiques per la redacció
d’aquest capítol.
82 Capítol 5
Capítol 5
Manual d’usuari
Aquest capítol consisteix en el manual d’instruccions que l’usuari ha de seguir per fer
servir l’aplicació. Per aquest motiu, aquest capítol està enfocat des d’una perspectiva
diferent i pretén ser autònom i independent de la resta del projecte, de manera que a
l’usuari tan sols li calgui llegir aquest manual per aprendre a utilitzar l’aplicació.
Una de les prioritats en el disseny de l’aplicació ha estat que aquesta tingués una interfície
gràfica senzilla perquè d’aquesta manera fos fàcil de fer servir, però que alhora mantingués
la funcionalitat desitjada per fer els càlculs. Per tant, aquest manual d’usuari no serà ni
llarg ni enrevessat perquè tampoc ho és l’aplicació.
La pantalla inicial de l’aplicació és la que es pot veure a la Figura 5.1. S’hi pot veure el
títol, l’autor i també els diferents cicles que s’han programat. Aquesta pantalla és també
una pantalla de selecció. Per accedir al cicle amb el qual es volen fer els càlculs, tan sols
cal clicar sobre la casella blanca amb el nom del cicle.
Per altra banda, cal anar amb compte i fixar-se en les unitats indicades a la taula. Pels
cicles de Rankine i refrigeració per compressió de vapor, la temperatura és en graus
Celsius (°C) i la pressió en MPa. En canvi, pels cicles de Brayton i refrigeració per gas,
la temperatura és en Kevlin (K) i la pressió en bar.
Per últim comentar que treure el check d’una casella, queda un espai en blanc en lloc d’un
zero. Això no és un problema, és equivalent. Com que no està seleccionada a l’aplicació
no l’afecta.
poder introduir la informació primer cal activar la casella amb un check. Es pot veure un
exemple d’aquest procés a la Figura 5.4.
Un cop feta la resolució del cicle és possible modificar les dades que s’havien introduït,
repetint els passos de l’apartat anterior. D’aquesta manera es pot parametritzar una
dada, com per exemple el rendiment de la turbina, i veure com canvis de valor en aquest
paràmetre afectarien als estats termodinàmics.
86 Capítol 5
Cal tenir en compte que només es pot tenir la finestra d’un diagrama oberta, és a dir,
no es poden visualitzar els dos diagrames alhora, perquè sinó l’aplicació se satura i es
tanca. L’eina de visualització de diagrames és la clàssica de la llibreria Matplotlib i permet
guardar el diagrama com una imatge, fer zoom en alguna zona específica, canviar l’escala
dels eixos...
Per últim lloc, pel cicle bàsic de Rankine i pel cicle de Rankine amb reescalfament inter-
medi, existeix l’opció de fer una anàlisi exergètica, prèviament a aquesta anàlisi cal haver
resolt el cicle. Per fer aquesta anàlisi cal clicar: Obtenir ⇒ Anàlisi exergètica. I se’ns
obrirà la finestra de la Figura 5.6.
Capítol 6
Anàlisi de resultats
Resolució:
Figura 6.5: Ampliació del diagrama T-s per diferenciar els Estats 1 i 2
90 Capítol 6
Figura 6.8: Esquema del cicle de Rankine amb reescalfament intermedi de l’enunciat
92 Capítol 6
Resolució:
Per la resolució del problema amb l’aplicació es fa la hipòtesi que el treball net és el treball
produït per les dues turbina. Si no es fes això, no es podria resoldre el problema.
També cal anar amb molt de compte en què els estats del problema tenen una numeració
diferent dels de l’aplicació. En aquest exemple es prendrà com a referència l’ordre d’estats
de l’aplicació.
En aquest exemple hi haurà una diferència més significativa entre els resultats de l’aplica-
ció i els obtinguts per l’EES, en comparació amb la resta d’exemples. Això és així perquè
l’aplicació tracta l’aire com un fluid més, amb una equació d’estat donada per la llibreria
CoolProp, mentre que en l’EES els càlculs estan fets considerant l’aire com un gas ideal.
Resolució:
Per resoldre el problema però cal treballar amb el flux màssic calculat segons l’equació
dels gasos ideals, que són 5,8 kg/s, perquè fem la comparació per un mateix flux màssic.
96 Capítol 6
Figura 6.18: Esquema del cicle de refrigeració per compressió de vapor de l’enunciat
En aquest exemple passa el mateix que en l’exemple 3 (Cicle de Brayton) ja que també
es treballa amb aire. Per tant és possible que hi hagi certes diferències entre els resultats
obtinguts per l’aplicació i els obtinguts amb l’EES siguin diferents.
Resolució:
Per resoldre el problema, com en l’enunciat no es dóna el flux màssic, es treballarà amb
un flux d’1 kg/s per tenir els resultats per unitat de massa d’aire.
QH [kW] −165
QL [kW] 44
Wturb [kW] −64, 19
Wcomp [kW] 185, 4
S’ha consultat [9] i [10] com a fonts bibliogràfiques per la redacció d’aquest capítol.
104
Pressupost
Aquest projecte està destinat a un ús acadèmic i educatiu. El que es vol aconseguir amb
aquesta aplicació és complementar la docència dels cicles termodinàmics i exemplificar
millor el seu funcionament. Tanmateix, també podria haver-se comercialitzat, ja que tot
el programari que s’ha utilitzat és codi lliure i la llibreria CoolProp permet el seu ús tant
per fins educatius com per fins comercials.
El projecte s’ha dut a terme al llarg de vint-i-una setmanes, des de la setmana del 27 de
gener del 2020 fins a la setmana del 22 de juny del 2020. A l’apartat 1.4 (Metodologia)
es detallen quines són les 4 grans fases en les quals s’ha estructurat el projecte, que com
es diu, conviuen entre elles i es realimenten. En el diagrama de Gantt de la Figura 6.27
es pot veure l’ordenació d’aquestes etapes i de les seves subetapes en la cronologia.
Conegut el repartiment del temps invertit en el projecte, cal determinar-ne els costos. S’ha
estimat que a cada casella del diagrama de Gantt de la Figura 6.27 li corresponen 5 hores
de feina. S’ha fet així perquè s’ha considerat que és una representació més realista, ja
que no totes les setmanes s’ha treballat la mateixa quantitat d’hores. D’aquesta manera
si es conten les caselles, en total n’hi ha 80, que representen 400 hores de feina, que
vindrien a ser aproximadament 12 crèdits ECTS. En paral·lel, cal tenir en compte també
el temps que s’ha dedicat a la redacció d’informes parcials i de la memòria, que serien
aproximadament unes 20 hores.
Un altre factor a tenir en compte és que no totes les tasques tenen el mateix valor. Per
aquest motiu s’han considerat quatre tipus de feines diferents. En primer lloc, unes feines
de tipus creatiu (caselles de color verd), relacionades amb el disseny de tota l’aplicació:
tant de la interfície gràfica com del solucionador, que s’han valorat en 15 A C l’hora. En
segon lloc, les feines de tipus recerca (caselles de color vermell i taronja), que consisteixen
en investigar com transformar aquelles idees en un codi Python i també en solucionar els
errors que poden anar sorgint durant la programació. Aquestes s’han valorat en 15 A C l’ho-
ra. En tercer lloc les feines de tipus programació (caselles de color blau), que consisteixen
en escriure el codi Python, que s’han valorat en 10 A C l’hora. Finalment les feines de tipus
redacció, que consisteixen en la redacció d’informes i de la memòria final, valorades en
8AC l’hora. El valor d’aquests salaris s’ha extret de [11] suposant que s’és un professional
que acaba d’incorporar-se al mercat.
Per altra banda, cal tenir en compte les despeses materials, que en aquest cas corresponen
al cost de l’ordinador amb què s’ha realitzat tot el projecte, que és de 140 A
C.
També s’ha de considerar el cost de la llicència acadèmica de l’EES, que s’ha utilitzat en
el capítol 6 per verificar els resultats obtinguts amb l’aplicació. El cost de la llicència de
la qual disposa la UPC correspon al cost de la llicència acadèmica, que és de 1.765 A C. [12]
A la Taula 6.11 es pot veure el còmput final de tot el pressupost, deixant un cost total de
l’aplicació de 7.603,40 A
C.
106
Impacte ambiental
D’acord amb el document [13] el factor d’emissions de kg de CO2 /kWh per l’empresa
ENDESA ENERGIA, S.A de l’any 2019 és de 0,27. En l’apartat anterior s’ha calculat
que el consum total d’energia ha sigut de 92,40 kWh. Per tant, en total s’han emès 25 kg
de CO2 a l’atmosfera aproximadament. Per tenir una referència, per produir un llibre de
100 pàgines s’emeten 21 kg de CO2 . [14]
Per últim, remarcar que l’aplicació és per ús docent, de manera que no té una finalitat
comercial per millorar l’eficiència dels cicles termodinàmics d’una indústria. Si aquest
fos el cas, aleshores sí que hi hauria un impacte ambiental considerable perquè els cicles
termodinàmics estudiats emeten gasos a l’atmosfera i utilitzen combustibles fòssils o nu-
clears per funcionar. Tanmateix, no forma part de l’abast del projecte perquè com s’ha
dit l’ús de l’aplicació es limita a l’àmbit acadèmic.
108
En aquest projecte s’ha descrit el desenvolupament d’una aplicació per ordinador, capaç
de simular cinc cicles termodinàmics diferents. Del programa se’n destaca una interfície
molt senzilla per l’usuari, de manera que, malgrat poder realitzar menys coses que altres
aplicacions existents del mateix estil, ho compensa sent gratuïta i tenint una interfície
intuïtiva, que no requereix cap mena de coneixement previ per fer-la servir.
Pel que fa a l’aspecte informàtic del projecte, es va decidir que s’escriuria el codi de
l’aplicació amb Python per tot el bagatge acumulat durant el grau. Per descomptat
aquests coneixements eren només el tronc indispensable a partir del qual un mateix havia
de ser capaç d’aprendre, de forma autònoma, tots aquells conceptes nous (paquets Tkinter
i CoolProp) que havien de permetre programar aquest software.
Pel que fa al vessant termodinàmic del treball, no s’aprofundeix en nous conceptes més
enllà dels vistos durant el grau, sinó que el que persegueix el projecte és millorar la
docència dels cicles termodinàmics. Per aquest motiu es van escollir cinc dels cicles més
habituals (Rankine bàsic i amb reescalfament; Brayton bàsic; i refrigeració, tant per
compressió de vapor com per gas) perquè en primer lloc, des d’un punt de vista educatiu,
són els més bàsics i els primers a explicar-se als alumnes, de manera que, es va veure
necessari que l’aplicació simulés aquests cicles, per tal que l’estudiantat comprengués
millor el seu funcionament, ja que a partir d’aquests cicles se’n construeixen la resta.
Per altra banda, des d’un punt de vista pràctic, perquè aquest projecte tenia un marge
temporal de quatre mesos i el fet que els 5 cicles tinguessin estructures semblants facilitava
la tasca.
En el treball s’inclou un manual d’usuari i un conjunt d’exemples perquè qui vulgui pugui
aprendre a fer funcionar l’aplicació, la qual cosa resulta molt senzilla, i també verificar-ne
la fiabilitat perquè en els exemples es comparen els resultats obtinguts per l’aplicació amb
els resultats obtinguts fent la resolució amb l’EES, que és l’eina utilitzada actualment a
l’assignatura de Termodinàmica.
Sobre el treball futur d’aquest projecte, en tractar-se de la primera versió d’una aplicació
es dóna per fet que apareixeran petits errors en el codi que s’hauran d’anar corregint.
Per altra banda, s’hauria de millorar l’eficiència del codi de l’eina de càlcul, ja que per
cicles amb més estats termodinàmics s’allarga molt. Des d’un punt de vista funcional
l’aplicació pot millorar-se de dues maneres diferents: la primera és anar programant cicles,
com per exemple el Brayton amb reescalfament o el Rankine amb regeneració, i afegir-los
109
a l’aplicació. Aquesta línia de treball és costosa quant a temps però no difícil, ja que la
metodologia a seguir és la mateixa que la seguida per programar els cicles anteriors. Una
segona línia de millora seria aconseguir que els cicles no s’haguessin de predefinir, sinó
que l’usuari pogués dissenyar-los. Això és un salt a escala de dificultat que requeriria
molt més temps i pot ser només amb les eines informàtiques emprades en el disseny de
l’aplicació no fos suficient.
En últim lloc, destacar que pel disseny de l’aplicació s’ha buscat un compromís entre la
funcionalitat del programa, l’ergonomia que havia de tenir la interfície de cara a l’usuari,
i el límit d’hores de feina que s’han de dedicar a un treball de fi de grau.
110
Bibliografia
[1] Çengel, Y. A., & Boles, M. A, Termodinámica (7a. ed.). McGraw Hill Intera-
mericana Editores, S.A. 2012.
[3] Bell, Ian H. & Wronski, Jorrit & Quoilin, Sylvain & Lemort, Vin-
cent, Pure and Pseudo-pure Fluid Thermophysical Property Evaluation and the
Open-Source Thermophysical Property Library CoolProp. Industrial & Engineering
Chemistry Research, 53(6):2498–2508. 2014.
http://www.coolprop.org
Última consulta feta el 05/06/2020
https://github.com/CoolProp/CoolProp/wiki
Última consulta feta el 23/05/2020
[6] Shipman, J. W., Tkinter 8.5 reference: a GUI for Python. New Mexico Tech.
Computer Center. 2013
[10] Klein, S.A., Engineering Equation Solver for Microsoft Windows Operating Sys-
tems. F-Chart Software. 2018.
[12] F-Chart Software, EES Academic Site Licenses. F-Chart Software 2020.
http://fchartsoftware.com/ees/academic-site-licenses.php
Última consulta feta el 10/06/2020