Funzioni di programmazione psicrometrica

Libreria di funzioni psicrometriche per calcolare le proprietà termodinamiche dell'aria per Python, C, C#, Fortran, JavaScript e VBA/Excel

Panoramica

La psicrometria è lo studio delle proprietà fisiche e termodinamiche dell'aria umida. Queste proprietà includono, ad esempio, la temperatura del punto di rugiada dell'aria, la temperatura del bulbo umido, l'umidità relativa, il rapporto di umidità, l'entalpia.

La stima di queste proprietà è fondamentale in diverse applicazioni scientifiche e ingegneristiche come il riscaldamento, la ventilazione e il condizionamento dell'aria (HVAC) e la meteorologia. Sebbene le formule per calcolare le proprietà psicrometriche dell’aria siano ampiamente disponibili in letteratura (@Stull2011;@Wexler1983;@Stoecker1982;@Dilley1968;@Humphreys1920), la loro implementazione in programmi informatici o fogli di calcolo può essere impegnativa e richiedere molto tempo.

PsychroLib è una libreria di funzioni per consentire il calcolo delle proprietà psicrometriche dell'aria umida e secca. La libreria è disponibile per Python, C, C#, Fortran, JavaScript, Microsoft Excel Visual Basic for Applications (VBA). Funziona sia con il sistema di unità metrico (SI) che imperiale (IP). Le funzioni si basano sulle formule del Manuale ASHRAE 2017 – Fondamenti, Capitolo 1, edizioni SI e IP. Le funzioni possono essere raggruppate in due categorie:

  1. Funzioni per il calcolo della temperatura del punto di rugiada, della temperatura di bulbo umido, della pressione parziale di vapore dell'acqua, del rapporto di umidità o umidità relativa, conoscendo qualsiasi altro di questi, nonché la temperatura di bulbo secco e la pressione atmosferica.
  2. Funzioni per il calcolo di altre proprietà dell'aria umida. Tutti questi utilizzano il rapporto di umidità come input.

Pitone

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
# PsychroLib (versione 2.3.0) (https://github.com/psychrometrics/psychrolib)
# Copyright (c) 2018 D. Thevenard e D. Meyer per l'attuale implementazione della libreria
# Copyright (c) Manuale ASHRAE 2017 — Fondamenti per equazioni e coefficienti ASHRAE
# Concesso in licenza con la licenza MIT.

""" psychrolib.py
Contiene funzioni per il calcolo delle proprietà termodinamiche delle miscele gas-vapore
e atmosfera standard adatta alla maggior parte delle applicazioni ingegneristiche, fisiche e meteorologiche
applicazioni.
La maggior parte delle funzioni sono un'implementazione delle formule trovate nel file
Manuale ASHRAE 2017 - Fondamenti, in entrambi i sistemi internazionali (SI),
e unità imperiali (IP). Si prega di fare riferimento alle informazioni incluse nel
ciascuna funzione per il rispettivo riferimento.
Esempio
    >>> importa psychrolib
    >>> # Imposta il sistema di unità, ad esempio su SI (può essere psychrolib.SI o psychrolib.IP)
    >>> psicrolib.SetUnitSystem(psicrolib.SI)
    >>> # Calcola la temperatura del punto di rugiada per una temperatura a bulbo secco di 25 C e un'umidità relativa dell'80%
    >>> TDewPoint = psychrolib.GetTDewPointFromRelHum(25.0, 0.80)
    >>> stampa(TDewPoint)
    21.309397163661785
Copyright
    - Per l'attuale implementazione della libreria
        Copyright (c) 2018 D. Thevenard e D. Meyer.
    - Per equazioni e coefficienti pubblicato ASHRAE Handbook — Fundamentals, capitolo 1
        Copyright (c) Manuale ASHRAE 2017 – Fondamenti (https://www.ashrae.org)
Licenza
    MIT (https://github.com/psychrometrics/psychrolib/LICENSE.txt)
Nota degli autori
    Abbiamo fatto ogni sforzo per garantire che il codice sia adeguato, tuttavia, facciamo no
    rappresentazione rispetto alla sua accuratezza. Utilizzare a proprio rischio. Dovresti notarlo
    un errore o se hai un suggerimento, segnalacelo tramite GitHub all'indirizzo
    https://github.com/psychromometrics/psychrolib/issues.
"""


importare matematica
da enum importare Enum, auto
da digitando importare Opzionale


################################################## ################################################## ###
# Costanti globali
################################################## ################################################## ###

ZERO_FAHRENHEIT_AS_RANKINE = 459.67
"""float: Zero gradi Fahrenheit (°F) espressi in gradi Rankine (°R)
        Unità:
                °R
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 39
"""

ZERO_CELSIUS_AS_KELVIN = 273.15
"""float: Zero gradi Celsius (°C) espressi in Kelvin (K)
        Unità:
                K
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 39
"""

R_DA_IP = 53.350
"""galleggiante: costante del gas universale per aria secca (versione IP)
        Unità:
        ft lb_Force lb_DryAir⁻¹ R⁻¹
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1
"""

R_DA_SI = 287.042
"""galleggiante: costante universale del gas per aria secca (versione SI)
        Unità:
        J kg_DryAir⁻¹ K⁻¹
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1
"""

MAX_ITER_COUNT = 100
"""int: numero massimo di iterazioni prima di uscire dai cicli while.
"""

MIN_HUM_RATIO = 1e-7
"""galleggiante: rapporto di umidità minimo accettabile utilizzato/restituito da qualsiasi funzione.
          Qualsiasi valore superiore a 0 o inferiore a MIN_HUM_RATIO verrà reimpostato su questo valore.
"""

FREEZING_POINT_WATER_IP = 32.0
"""galleggiante: Punto di congelamento dell'acqua in Fahrenheit.
"""

FREEZING_POINT_WATER_SI = 0.0
"""galleggiante: punto di congelamento dell'acqua in gradi Celsius.
"""

TRIPLO_POINT_ACQUA_IP = 32.018
"""galleggiante: Punto triplo dell'acqua in Fahrenheit.
"""

TRIPLO_POINT_ACQUA_SI = 0.01
"""galleggiante: Punto triplo dell'acqua in gradi Celsius.
"""

################################################## ################################################## ###
# Funzioni di supporto
################################################## ################################################## ###

# Sistema di unità da utilizzare.
classe UnitSystem(Enum):
    """
    Classe privata non esposta utilizzata per impostare i valori di enumerazione automatica.
        """
    IP = auto()
    SI = auto()

IP = UnitSystem.IP
SI = UnitSystem.SI

PSYCHROLIB_UNITÀ = Nessuno

PSYCROLIB_TOLERANZA = 1.0
# Tolleranza dei calcoli della temperatura

def Impostasistemaunità(Unità: UnitàSistema) -> Nessuno:
    """
    Imposta il sistema di unità da utilizzare (SI o IP).
        Argomenti:
        Unità: stringa indicante il sistema di unità scelto (SI o IP)
        Appunti:
        Questa funzione *DEVE ESSERE CHIAMATA* prima di poter utilizzare la libreria
        """
    globale PSYCHROLIB_UNITÀ
    globale PSYCROLIB_TOLERANZA

    se non isistanza(Unità, Unità Sistema):
        aumentare ValoreErrore("Il sistema di unità deve essere SI o IP.")

    PSYCHROLIB_UNITÀ = Unità

    # Definire la tolleranza sui calcoli della temperatura
    # La tolleranza è la stessa in IP e SI
    se Unità == IP:
        PSYCROLIB_TOLERANZA = 0.001 * 9. / 5.
    altro:
        PSYCROLIB_TOLERANZA = 0.001

def GetUnitSystem() -> Opzionale[SistemaUnità]:
    """
    Sistema di restituzione delle unità in uso.
        """
    ritorno PSYCHROLIB_UNITÀ

def isIP() -> bool:
    """
    Verificare se il sistema in uso è IP o SI.
        """
    se PSYCHROLIB_UNITÀ == IP:
        ritorno Vero
    elifa PSYCHROLIB_UNITÀ == SI:
        ritorno falso
    altro:
        aumentare ValoreErrore("Il sistema di unità non è stato definito.")


################################################## ################################################## ###
# Conversione tra unità di temperatura
################################################## ################################################## ###

def OttieniTRankineFromTFahrenheit(TFahrenheit: galleggiante) -> galleggiante:
    """
    Funzione di utilità per convertire la temperatura in gradi Rankine (°R)
    data la temperatura in gradi Fahrenheit (°F).
        Argomenti:
        TRankine: temperatura in gradi Fahrenheit (°F)
    Ritorna:
        Temperatura in gradi Rankine (°R)
    Riferimento:
        Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
        Appunti:
        Conversione esatta.
        """
    TRankin = TFahrenheit + ZERO_FAHRENHEIT_AS_RANKINE
    ritorno TRankin

def Ottieni TFahrenheit da TRankine(Tranchina: galleggiante) -> galleggiante:
    """
    Funzione di utilità per convertire la temperatura in gradi Fahrenheit (°F)
    data temperatura in gradi Rankine (°R).
        Argomenti:
        TRankine: Temperatura in gradi Rankine (°R)
    Ritorna:
        Temperatura in gradi Fahrenheit (°F)
    Riferimento:
        Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
        Appunti:
        Conversione esatta.
        """
    ritorno TRankin - ZERO_FAHRENHEIT_AS_RANKINE

def OttieniTKelvinDaTCelsius(Tcelsio: galleggiante) -> galleggiante:
    """
    Funzione di utilità per convertire la temperatura in Kelvin (K)
    data temperatura in gradi Celsius (°C).
        Argomenti:
        TCelsius: temperatura in gradi Celsius (°C)
    Ritorna:
        Temperatura in Kelvin (K)
    Riferimento:
        Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
        Appunti:
        Conversione esatta.
        """
    TKelvin = TCelsius + ZERO_CELSIUS_AS_KELVIN
    ritorno TKelvin

def OttieniTCelsiusDaTKelvin(TKelvin: galleggiante) -> galleggiante:
    """
    Funzione di utilità per convertire la temperatura in gradi Celsius (°C)
    data la temperatura in Kelvin (K).
        Argomenti:
        TKelvin: temperatura in Kelvin (K)
    Ritorna:
        Temperatura in gradi Celsius (°C)
    Riferimento:
        Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
        Appunti:
        Conversione esatta.
        """
    ritorno TKelvin - ZERO_CELSIUS_AS_KELVIN


################################################## ################################################## ###
# Conversioni tra punto di rugiada, bulbo umido e umidità relativa
################################################## ################################################## ###

def OttieniTWetBulbFromTDewPoint(TDryBulb: galleggiante, Punto di rugiada: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    La temperatura di ritorno del bulbo umido è data dalla temperatura del bulbo secco, dalla temperatura del punto di rugiada e dalla pressione.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        TDewPoint: temperatura del punto di rugiada in °F [IP] o °C [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Temperatura del bulbo umido in °F [IP] o °C [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1
        """
    se TDewPoint > TDryBulb:
        aumentare ValoreErrore("La temperatura del punto di rugiada è superiore alla temperatura del bulbo secco")

    HumRatio = OttieniRapportoRum.DaPuntoDiTew(PuntoDiTew, Pressione)
    TWetBulb = OttieniTWetBulbFromHumRatio(TDryBulb, HumRatio, Pressione)
    ritorno TWetBulb

def GetTWetBulbFromRelHum(TDryBulb: galleggiante, RelHum: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    La temperatura di ritorno del bulbo umido è data dalla temperatura del bulbo secco, dall'umidità relativa e dalla pressione.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        RelHum: Umidità relativa nell'intervallo [0, 1]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Temperatura del bulbo umido in °F [IP] o °C [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1
        """
    se RelHum < 0 o RelHum > 1:
        aumentare ValoreErrore("L'umidità relativa è fuori dall'intervallo [0, 1]")

    HumRatio = OttieniRapportoHumFromRelHum(TDryBulb, RelHum, Pressione)
    TWetBulb = OttieniTWetBulbFromHumRatio(TDryBulb, HumRatio, Pressione)
    ritorno TWetBulb

def OttieniRelHumFromTDewPoint(TDryBulb: galleggiante, Punto di rugiada: galleggiante) -> galleggiante:
    """
    Umidità relativa restituita data la temperatura di bulbo secco e la temperatura del punto di rugiada.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        TDewPoint: temperatura del punto di rugiada in °F [IP] o °C [SI]
    Ritorna:
        Umidità relativa nell'intervallo [0, 1]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 22
        """
    se TDewPoint > TDryBulb:
        aumentare ValoreErrore("La temperatura del punto di rugiada è superiore alla temperatura del bulbo secco")

    VapPres = OttieniSatVapPres(TDewPoint)
    SatVapPres = OttieniSatVapPres(TDryBulb)
    RelHum = VapPres / SatVapPres
    ritorno RelHum

def GetRelHumFromTWetBulb(TDryBulb: galleggiante, TWetLampadina: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    Umidità relativa restituita data la temperatura a bulbo secco, la temperatura a bulbo umido e la pressione.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        TWetBulb: temperatura del bulbo umido in °F [IP] o °C [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Umidità relativa nell'intervallo [0, 1]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1
        """
    se TWetBulb > TDryBulb:
        aumentare ValoreErrore("La temperatura del bulbo umido è superiore alla temperatura del bulbo secco")

    HumRatio = Ottieni rapporto humumFromTWetBulb(TDryBulb, TWetLampadina, Pressione)
    RelHum =  OttieniRapportoRelHumFromHum(TDryBulb, HumRatio, Pressione)
    ritorno RelHum

def OttieniTDewPointFromRelHum(TDryBulb: galleggiante, RelHum: galleggiante) -> galleggiante:
    """
    Temperatura del punto di rugiada di ritorno data la temperatura a bulbo secco e l'umidità relativa.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        RelHum: Umidità relativa nell'intervallo [0, 1]
    Ritorna:
        Temperatura del punto di rugiada in °F [IP] o °C [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1
        """
    se RelHum < 0 o RelHum > 1:
        aumentare ValoreErrore("L'umidità relativa è fuori dall'intervallo [0, 1]")

    VapPres = GetVapPresFromRelHum(TDryBulb, RelHum)
    TDewPoint = OttieniTDewPointFromVapPres(TDryBulb, VapPres)
    ritorno TDewPoint

def OttieniTDewPointFromTWetBulb(TDryBulb: galleggiante, TWetLampadina: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    Temperatura del punto di rugiada di ritorno data la temperatura di bulbo secco, la temperatura di bulbo umido e la pressione.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        TWetBulb: temperatura del bulbo umido in °F [IP] o °C [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Temperatura del punto di rugiada in °F [IP] o °C [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1
        """
    se TWetBulb > TDryBulb:
        aumentare ValoreErrore("La temperatura del bulbo umido è superiore alla temperatura del bulbo secco")

    HumRatio = Ottieni rapporto humumFromTWetBulb(TDryBulb, TWetLampadina, Pressione)
    TDewPoint = OttieniTDewPointFromHumRatio(TDryBulb, HumRatio, Pressione)
    ritorno TDewPoint


################################################## ################################################## ###
# Conversioni tra punto di rugiada o umidità relativa e pressione di vapore
################################################## ################################################## ###

def GetVapPresFromRelHum(TDryBulb: galleggiante, RelHum: galleggiante) -> galleggiante:
    """
    Restituisce la pressione parziale del vapore acqueo in funzione dell'umidità relativa e della temperatura.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        RelHum: Umidità relativa nell'intervallo [0, 1]
    Ritorna:
        Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 12, 22
        """
    se RelHum < 0 o RelHum > 1:
        aumentare ValoreErrore("L'umidità relativa è fuori dall'intervallo [0, 1]")

    VapPres = RelHum * OttieniSatVapPres(TDryBulb)
    ritorno VapPres

def GetRelHumFromVapPres(TDryBulb: galleggiante, VapPres: galleggiante) -> galleggiante:
    """
    Umidità relativa restituita data la temperatura a bulbo secco e la pressione del vapore.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        VapPres: pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
    Ritorna:
        Umidità relativa nell'intervallo [0, 1]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 12, 22
        """
    se VapPres < 0:
        aumentare ValoreErrore("La pressione parziale del vapore acqueo nell'aria umida non può essere negativa")

    RelHum = VapPres / OttieniSatVapPres(TDryBulb)
    ritorno RelHum

def dLnPws_(TDryBulb: galleggiante) -> galleggiante:
    """
    Funzione di supporto che restituisce la derivata del logaritmo naturale della pressione del vapore di saturazione 
    in funzione della temperatura a bulbo secco.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
    Ritorna:
        Derivata del logaritmo naturale della tensione di vapore dell'aria satura in Psi [IP] o Pa [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 5 e 6
        """
    se isIP():
        T = OttieniTRankineFromTFahrenheit(TDryBulb)
        se TDryBulb <= TRIPLO_POINT_ACQUA_IP:
            dLnPws = 1.0214165E+04 / matematica.pow(T, 2) - 5.3765794E-03 + 2 * 1.9202377E-07 * T \
                  + 3 * 3.5575832E-10 * matematica.pow(T, 2) - 4 * 9.0344688E-14 * matematica.pow(T, 3) + 4.1635019 / T
        altro:
            dLnPws = 1.0440397E+04 / matematica.pow(T, 2) - 2.7022355E-02 + 2 * 1.2890360E-05 * T \
                  - 3 * 2.4780681E-09 * matematica.pow(T, 2) + 6.5459673 / T
    altro:
        T = OttieniTKelvinDaTCelsius(TDryBulb)
        se TDryBulb <= TRIPLO_POINT_ACQUA_SI:
            dLnPws = 5.6745359E+03 / matematica.pow(T, 2) - 9.677843E-03 + 2 * 6.2215701E-07 * T \
                  + 3 * 2.0747825E-09 * matematica.pow(T, 2) - 4 * 9.484024E-13 * matematica.pow(T, 3) + 4.1635019 / T
        altro:
            dLnPws = 5.8002206E+03 / matematica.pow(T, 2) - 4.8640239E-02 + 2 * 4.1764768E-05 * T \
                  - 3 * 1.4452093E-08 * matematica.pow(T, 2) + 6.5459673 / T

    ritorno dLnPws

def OttieniTDewPointFromVapPres(TDryBulb: galleggiante, VapPres: galleggiante) -> galleggiante:
    """
    Temperatura del punto di rugiada di ritorno data la temperatura a bulbo secco e la pressione del vapore.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        VapPres: pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
    Ritorna:
        Temperatura del punto di rugiada in °F [IP] o °C [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 5 e 6
        Appunti:
        La temperatura del punto di rugiada viene risolta invertendo l'equazione fornendo la pressione del vapore acqueo
        alla saturazione dalla temperatura anziché utilizzare le regressioni fornite
        di ASHRAE (eqn. 37 e 38) che sono molto meno accurati e hanno a
        intervallo di validità più ristretto.
        Il metodo Newton-Raphson (NR) viene utilizzato sul logaritmo del vapore acqueo
        pressione in funzione della temperatura, che è una funzione molto regolare
        La convergenza viene solitamente raggiunta in 3-5 iterazioni. 
        TDryBulb non è realmente necessario in questo caso, viene utilizzato solo per comodità.
        """
    se isIP():
        CONFINI = [-148, 392]
    altro:
        CONFINI = [-100, 200]

    # Controllo di validità: limiti al di fuori dei quali non è possibile trovare una soluzione
    se VapPres < GetSatVapPres(LIMITI[0]) o VapPres > GetSatVapPres(LIMITI[1]):
        aumentare ValoreErrore("La pressione parziale del vapore acqueo è fuori dal campo di validità delle equazioni")

    # Usiamo NR per approssimare la soluzione.
    # Prima ipotesi
    TDewPoint = TDryBulb        # Valore calcolato delle temperature del punto di rugiada, risolto in modo iterativo
    lnVP = matematica.log(VapPres)    # Pressione parziale del vapore acqueo nell'aria umida

    indice = 1

    mentre Vero:
        TDewPoint_iter = TDewPoint   # TDewPoint utilizzato nel calcolo NR
        lnVP_iter = math.log(GetSatVapPres(TDewPoint_iter))

        # Derivato della funzione, calcolato analiticamente
        d_lnVP = dLnPws_(TDewPoint_iter)

        # Nuova stima, delimitata dal dominio di ricerca definito sopra
        TDewPoint = TDewPoint_iter - (lnVP_iter - lnVP) / d_lnVP
        TDewPoint = max(TDewPoint, CONFINI[0])
        TDewPoint = min(TDewPoint, CONFINI[1])

        se ((math.fabs(TDewPoint - TDewPoint_iter) <= PSYCHROLIB_TOLERANCE)):
            rompere

        se (indice > MAX_ITER_COUNT):
            aumentare ValoreErrore("Convergenza non raggiunta in GetTDewPointFromVapPres. Arresto.")

        indice = indice + 1

    TDewPoint = min(TDewPoint, TDryBulb)
    ritorno TDewPoint

def OttieniVapPresFromTDewPoint(TDewPoint: galleggiante) -> galleggiante:
    """
    Pressione del vapore di ritorno data la temperatura del punto di rugiada.
        Argomenti:
        TDewPoint: temperatura del punto di rugiada in °F [IP] o °C [SI]
    Ritorna:
        Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 36
        """
    VapPres = OttieniSatVapPres(TDewPoint)
    ritorno VapPres


################################################## ################################################## ###
# Conversioni dalla temperatura del bulbo umido, dalla temperatura del punto di rugiada o dal rapporto umidità relativa/umidità
################################################## ################################################## ###

def Rapporto GetTWetBulbFromHum(TDryBulb: galleggiante, Rapporto um: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    La temperatura di ritorno a bulbo umido è data dalla temperatura di bulbo secco, dal rapporto di umidità e dalla pressione.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        HumRatio: rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Temperatura del bulbo umido in °F [IP] o °C [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 33 e 35 risolti per Tstar
        """
    se HumRatio < 0:
        aumentare ValoreErrore("Il rapporto di umidità non può essere negativo")
    Rapporto Hum limitato = max(Rapporto ronzio, MIN_HUM_RATIO)

    TDewPoint = OttieniTDewPointFromHumRatio(TDryBulb, Rapporto Hum limitato, Pressione)

    # Ipotesi iniziali
    TWetBulbSup = TDryBulb
    TWetBulbInf = TDewPoint
    TWetBulb = (TWetBulbInf + TWetBulbSup) / 2

    indice = 1
    # Ciclo di bisezione
    mentre ((TWetBulbSup - TWetBulbInf) > PSYCHROLIB_TOLERANZA):

        # Calcola il rapporto di umidità alla temperatura Tstar
        Wstar = Ottieni rapporto humumFromTWetBulb(TDryBulb, TWetLampadina, Pressione)

        # Ottieni nuovi limiti
        se Wstar > Rapporto Hum limitato:
            TWetBulbSup = TWetBulb
        altro:
            TWetBulbInf = TWetBulb

        # Nuova ipotesi sulla temperatura del bulbo umido
        TWetBulb = (TWetBulbSup + TWetBulbInf) / 2

        se (indice >= MAX_ITER_COUNT):
            aumentare ValoreErrore("Convergenza non raggiunta in GetTWetBulbFromHumRatio. Arresto.")

        indice = indice + 1
    ritorno TWetBulb

def OttieniHumRatioFromTWetBulb(TDryBulb: galleggiante, TWetLampadina: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    Rapporto di umidità di ritorno data la temperatura di bulbo secco, la temperatura di bulbo umido e la pressione.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        TWetBulb: temperatura del bulbo umido in °F [IP] o °C [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 33 e 35
        """
    se TWetBulb > TDryBulb:
        aumentare ValoreErrore("La temperatura del bulbo umido è superiore alla temperatura del bulbo secco")

    Wsstar = Ottieni rapporto humSat(TWetBulb, Pressione)

    se isIP():
       se TWetBulb >= FREEZING_POINT_WATER_IP:
           HumRatio = ((1093 - 0.556 * TWetBulb) * Wsstar - 0.240 * (TDryBulb - TWetBulb)) \
                    / (1093 + 0.444 * TDryBulb - TWetBulb)
       altro:
           HumRatio = ((1220 - 0.04 * TWetBulb) * Wsstar - 0.240 * (TDryBulb - TWetBulb)) \
                    / (1220 + 0.444 * TDryBulb - 0.48*TWetBulb)
    altro:
       se TWetBulb >= FREEZING_POINT_WATER_SI:
           HumRatio = ((2501. - 2.326 * TWetBulb) * Wsstar - 1.006 * (TDryBulb - TWetBulb)) \
                    / (2501. + 1.86 * TDryBulb - 4.186 * TWetBulb)
       altro:
           HumRatio = ((2830. - 0.24 * TWetBulb) * Wsstar - 1.006 * (TDryBulb - TWetBulb)) \
                    / (2830. + 1.86 * TDryBulb - 2.1 * TWetBulb)
    # Controllo di validità.
    ritorno max(Rapporto ronzio, MIN_HUM_RATIO)

def OttieniHumRatioFromRelHum(TDryBulb: galleggiante, RelHum: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    Rapporto di umidità di ritorno data la temperatura a bulbo secco, l'umidità relativa e la pressione.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        RelHum: Umidità relativa nell'intervallo [0, 1]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1
        """
    se RelHum < 0 o RelHum > 1:
        aumentare ValoreErrore("L'umidità relativa è fuori dall'intervallo [0, 1]")

    VapPres = GetVapPresFromRelHum(TDryBulb, RelHum)
    HumRatio = Ottieni rapporto humum da VapPres(VapPres, Pressione)
    ritorno HumRatio

def Ottieni rapporto RelHumFromHum(TDryBulb: galleggiante, Rapporto um: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    Restituisce l'umidità relativa data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        HumRatio: rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Umidità relativa nell'intervallo [0, 1]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1
        """
    se HumRatio < 0:
        aumentare ValoreErrore("Il rapporto di umidità non può essere negativo")

    VapPres = GetVapPresFromHumRatio(Rapporto hum, Pressione)
    RelHum = OttieniRelHumFromVapPres(TDryBulb, VapPres)
    ritorno RelHum

def OttieniHumRatioFromTDewPoint(TDewPoint: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    Rapporto dell'umidità di ritorno data la temperatura e la pressione del punto di rugiada.
        Argomenti:
        TDewPoint: temperatura del punto di rugiada in °F [IP] o °C [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 13
        """
    VapPres = OttieniSatVapPres(TDewPoint)
    HumRatio = Ottieni rapporto humum da VapPres(VapPres, Pressione)
    ritorno HumRatio

def OttieniTDewPointFromHumRatio(TDryBulb: galleggiante, Rapporto um: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    Temperatura del punto di rugiada di ritorno data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        HumRatio: rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Temperatura del punto di rugiada in °F [IP] o °C [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1
        """
    se HumRatio < 0:
        aumentare ValoreErrore("Il rapporto di umidità non può essere negativo")

    VapPres = GetVapPresFromHumRatio(Rapporto hum, Pressione)
    TDewPoint = OttieniTDewPointFromVapPres(TDryBulb, VapPres)
    ritorno TDewPoint


################################################## ################################################## ###
# Conversioni tra rapporto di umidità e pressione di vapore
################################################## ################################################## ###

def OttieniHumRatioFromVapPres(VapPres: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    Rapporto dell'umidità di ritorno data la pressione del vapore acqueo e la pressione atmosferica.
        Argomenti:
        VapPres: pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 20
        """
    se VapPres < 0:
        aumentare ValoreErrore("La pressione parziale del vapore acqueo nell'aria umida non può essere negativa")

    HumRatio = 0.621945 * VapPres / (Pressione - VapPres)

    # Controllo di validità.
    ritorno max(Rapporto ronzio, MIN_HUM_RATIO)

def OttieniVapPresFromHumRatio(Rapporto ronzio: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    Pressione del vapore di ritorno dato il rapporto di umidità e la pressione.
        Argomenti:
        HumRatio: rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 20 risolto per pw
        """
    se HumRatio < 0:
        aumentare ValoreErrore("Il rapporto di umidità è negativo")
    Rapporto Hum limitato = max(Rapporto ronzio, MIN_HUM_RATIO)

    VapPres = Pressione * Rapporto Hum limitato / (0.621945 + Rapporto Hum limitato)
    ritorno VapPres


################################################## ################################################## ###
# Conversioni tra rapporto di umidità e umidità specifica
################################################## ################################################## ###

def Ottieni rapporto HumFromHum specifico(Rapporto ronzio: galleggiante) -> galleggiante:
    """
    Restituisce l'umidità specifica dal rapporto di umidità (noto anche come rapporto di miscelazione).
        Argomenti:
        HumRatio: rapporto di umidità in lb_H₂O lb_Dry_Air⁻¹ [IP] o kg_H₂O kg_Dry_Air⁻¹ [SI]
    Ritorna:
        Umidità specifica in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 9b
        """
    se HumRatio < 0:
        aumentare ValoreErrore("Il rapporto di umidità non può essere negativo")
    Rapporto Hum limitato = max(Rapporto ronzio, MIN_HUM_RATIO)

    SpecificHum = Rapporto Hum limitato / (1.0 + Rapporto Hum limitato)
    ritorno SpecificHum

def Ottieni rapporto humum da hum specifico(SpecificHum: galleggiante) -> galleggiante:
    """
    Restituisce il rapporto di umidità (noto anche come rapporto di miscelazione) dall'umidità specifica.
        Argomenti:
        SpecificHum: Umidità specifica in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    Ritorna:
        Rapporto di umidità in lb_H₂O lb_Dry_Air⁻¹ [IP] o kg_H₂O kg_Dry_Air⁻¹ [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 9b (risolto per il rapporto di umidità)
        """
    se SpecificHum < 0.0 o SpecificHum >= 1.0:
        aumentare ValoreErrore("L'umidità specifica è fuori dall'intervallo [0, 1[")

    HumRatio = SpecificHum / (1.0 - SpecificHum)

    # Controllo di validità.
    ritorno max(Rapporto ronzio, MIN_HUM_RATIO)


################################################## ################################################## ###
# Calcoli dell'aria secca
################################################## ################################################## ###

def OttieniEntalpiaAriaSecca(TDryBulb: galleggiante) -> galleggiante:
    """
    Entalpia di ritorno dell'aria secca data la temperatura di bulbo secco.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
    Ritorna:
        Entalpia dell'aria secca in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 28
        """
    se isIP():
        Entalpia dell'aria secca = 0.240 * TDryBulb
    altro:
        Entalpia dell'aria secca = 1006 * TDryBulb
    ritorno Entalpia dell'aria secca

def OttieniDryAirDensity(TDryBulb: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    Densità dell'aria secca di ritorno date la temperatura e la pressione del bulbo secco.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Densità dell'aria secca in lb ft⁻³ [IP] o kg m⁻³ [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1
        Appunti:
        Eqn 14 per la perfetta relazione tra i gas per l'aria secca.
        Eqn 1 per la costante universale dei gas.
        Il fattore 144 in IP serve per la conversione di Psi = lb in⁻² in lb ft⁻².
        """
    se isIP():
        Densità dell'aria secca = (144 * Pressione) / R_DA_IP / OttieniTRankineFromTFahrenheit(TDryBulb)
    altro:
        Densità dell'aria secca = Pressione / R_DA_SI / OttieniTKelvinDaTCelsius(TDryBulb)
    ritorno Densità dell'aria secca

def OttieniDryAirVolume(TDryBulb: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    Volume di aria secca di ritorno data la temperatura e la pressione del bulbo secco.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Volume di aria secca in ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1
        Appunti:
        Eqn 14 per la perfetta relazione tra i gas per l'aria secca.
        Eqn 1 per la costante universale dei gas.
        Il fattore 144 in IP serve per la conversione di Psi = lb in⁻² in lb ft⁻².
        """
    se isIP():
        VolumeAriaSecca = R_DA_IP * OttieniTRankineFromTFahrenheit(TDryBulb) / (144 * Pressione)
    altro:
        VolumeAriaSecca = R_DA_SI * OttieniTKelvinDaTCelsius(TDryBulb) / Pressione
    ritorno VolumeAriaSecca


def OttieniTDryBulbFromEnthalpyAndHumRatio(Entalpia dell'aria umida: galleggiante, Rapporto um: galleggiante) -> galleggiante:
    """
    Ritorna la temperatura del bulbo secco dal rapporto entalpia e umidità.
        Argomenti:
        MoistAirEntalpy: entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹
        HumRatio: rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    Ritorna:
        Temperatura a bulbo secco in °F [IP] o °C [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 30
        Appunti:
        Basato sulla funzione "GetMoistAirEnthalpy", riorganizzata per la temperatura.
        """
    se HumRatio < 0:
        aumentare ValoreErrore("Il rapporto di umidità è negativo")
    Rapporto Hum limitato = max(Rapporto ronzio, MIN_HUM_RATIO)

    se isIP():
        TDryBulb  = (Entalpia dell'aria umida - 1061.0 * Rapporto Hum limitato) / (0.240 + 0.444 * Rapporto Hum limitato)
    altro:
        TDryBulb  = (Entalpia dell'aria umida / 1000.0 - 2501.0 * Rapporto Hum limitato) / (1.006 + 1.86 * Rapporto Hum limitato)
    ritorno TDryBulb

def Ottieni rapporto hum dall'entalpia e dal bulbo secco(Entalpia dell'aria umida: galleggiante, TDryBulb: galleggiante) -> galleggiante:
    """
    Rapporto dell'umidità di ritorno tra entalpia e temperatura di bulbo secco.
        Argomenti:
        MoistAirEntalpy: entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
    Ritorna:
        Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 30.
        Appunti:
        Basato sulla funzione "GetMoistAirEnthalpy", riorganizzato per il rapporto di umidità.
        """
    se isIP():
        HumRatio  = (Entalpia dell'aria umida - 0.240 * TDryBulb) / (1061.0 + 0.444 * TDryBulb)
    altro:
        HumRatio  = (Entalpia dell'aria umida / 1000.0 - 1.006 * TDryBulb) / (2501.0 + 1.86 * TDryBulb)

    # Controllo di validità.
    ritorno max(Rapporto ronzio, MIN_HUM_RATIO)


################################################## ################################################## ###
# Calcoli dell'aria satura
################################################## ################################################## ###

def OttieniSatVapPres(TDryBulb: galleggiante) -> galleggiante:
    """
    Pressione del vapore di saturazione di ritorno data la temperatura a bulbo secco.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
    Ritorna:
        Pressione di vapore dell'aria satura in Psi [IP] o Pa [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 5 e 6
        Nota importante: le formule ASHRAE sono definite sopra e sotto il punto di congelamento ma hanno
        una discontinuità al punto di congelamento. Questa è una piccola imprecisione da parte di ASHRAE: le formule
        dovrebbe essere definito sopra e sotto il punto triplo dell'acqua (non il punto di alimentazione), nel qual caso
        la discontinuità svanisce. È essenziale utilizzare il punto triplo dell'acqua altrimenti funzionerà
        GetTDewPointFromVapPres, che inverte la funzione presente, non converge correttamente
        il punto di congelamento.
        """
    se isIP():
        se (TDryBulb < -148 o TDryBulb > 392):
            aumentare ValoreErrore("La temperatura del bulbo secco deve essere compresa nell'intervallo [-148, 392]°F")

        T = OttieniTRankineFromTFahrenheit(TDryBulb)

        se (TDryBulb <= TRIPLE_POINT_WATER_IP):
            LnPws = (-1.0214165E+04 / T - 4.8932428 - 5.3765794E-03 * T + 1.9202377E-07 * T**2 \
                  + 3.5575832E-10 * matematica.pow(T, 3) - 9.0344688E-14 * matematica.pow(T, 4) + 4.1635019 * math.log(T))
        altro:
            LnPws = -1.0440397E+04 / T - 1.1294650E+01 - 2.7022355E-02* T + 1.2890360E-05 * T**2 \
                  - 2.4780681E-09 * matematica.pow(T, 3) + 6.5459673 * matematica.log(T)
    altro:
        se (TDryBulb < -100 o TDryBulb > 200):
            aumentare ValoreErrore("La temperatura del bulbo secco deve essere compresa nell'intervallo [-100, 200]°C")

        T = OttieniTKelvinDaTCelsius(TDryBulb)

        se (TDryBulb <= TRIPLE_POINT_WATER_SI):
            LnPws = -5.6745359E+03 / T + 6.3925247 - 9.677843E-03 * T + 6.2215701E-07 * T**2 \
                  + 2.0747825E-09 * matematica.pow(T, 3) - 9.484024E-13 * matematica.pow(T, 4) + 4.1635019 * matematica.log(T)
        altro:
            LnPws = -5.8002206E+03 / T + 1.3914993 - 4.8640239E-02 * T + 4.1764768E-05 * T**2 \
                  - 1.4452093E-08 * matematica.pow(T, 3) + 6.5459673 * matematica.log(T)

    SatVapPres = matematica.exp(LnPws)
    ritorno SatVapPres

def Ottieni rapporto SatHum(TDryBulb: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    Rapporto di umidità di ritorno dell'aria satura data la temperatura e la pressione a bulbo secco.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Rapporto di umidità dell'aria satura in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 36, risolto per W
        """
    SatVaporPres = OttieniSatVapPres(TDryBulb)
    SatHumRatio = 0.621945 * SatVaporPres / (Pressione - SatVaporPres)

    # Controllo di validità.
    ritorno max(Rapporto SatHum, MIN_HUM_RATIO)

def OttieniSatAirEntalpia(TDryBulb: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    Entalpia di ritorno dell'aria satura data la temperatura e la pressione a bulbo secco.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Entalpia dell'aria satura in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1
        """
    SatHumRatio = Ottieni rapporto humSat(TDryBulb, Pressione)
    EntalpiaSatAir = GetMoistAirEntalpia(TDryBulb, Rapporto SatHum)
    ritorno EntalpiaSatAir


################################################## ################################################## ###
# Calcoli dell'aria umida
################################################## ################################################## ###

def OttieniVaporPressureDeficit(TDryBulb: galleggiante, Rapporto um: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    Ritorno Deficit di pressione del vapore data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        HumRatio: rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Deficit di pressione del vapore in Psi [IP] o Pa [SI]
    Riferimento:
        Oke (1987) eq. 2.13a
        """
    se HumRatio < 0:
        aumentare ValoreErrore("Il rapporto di umidità è negativo")

    RelHum = OttieniRapportoRelHumFromHum(TDryBulb, HumRatio, Pressione)
    Deficit di pressione del vapore = OttieniSatVapPres(TDryBulb) * (1 - RelHum)
    ritorno Deficit di pressione del vapore

def Ottieni Grado di Saturazione(TDryBulb: galleggiante, Rapporto um: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    Restituisce il grado di saturazione (ovvero il rapporto umidità dell'aria/rapporto umidità dell'aria alla saturazione
    alla stessa temperatura e pressione) data la temperatura a bulbo secco, il rapporto di umidità e la pressione atmosferica.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        HumRatio: rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Grado di saturazione in unità arbitraria
    Riferimento:
        Manuale ASHRAE - Fondamenti (2009) cap. 1 eq 12
        Appunti:
        Questa definizione è assente nel Manuale del 2017. Utilizzando invece la versione 2009.
        """
    se HumRatio < 0:
        aumentare ValoreErrore("Il rapporto di umidità è negativo")
    Rapporto Hum limitato = max(Rapporto ronzio, MIN_HUM_RATIO)

    SatHumRatio = Ottieni rapporto humSat(TDryBulb, Pressione)
    Grado Di Saturazione = Rapporto Hum limitato / SatHumRatio
    ritorno Grado Di Saturazione

def OttieniEntalpiaAriaMostra(TDryBulb: galleggiante, Rapporto um: galleggiante) -> galleggiante:
    """
    L'entalpia dell'aria umida di ritorno data la temperatura a bulbo secco e il rapporto di umidità.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        HumRatio: rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    Ritorna:
        Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 30
        """
    se HumRatio < 0:
        aumentare ValoreErrore("Il rapporto di umidità è negativo")
    Rapporto Hum limitato = max(Rapporto ronzio, MIN_HUM_RATIO)

    se isIP():
        Entalpia dell'aria umida = 0.240 * TDryBulb + Rapporto Hum limitato * (1061 + 0.444 * TDryBulb)
    altro:
        Entalpia dell'aria umida = (1.006 * TDryBulb + Rapporto Hum limitato * (2501. + 1.86 * TDryBulb)) * 1000
    ritorno Entalpia dell'aria umida

def OttieniMoistAirVolume(TDryBulb: galleggiante, Rapporto um: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    Restituisce il volume specifico dell'aria umida data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        HumRatio: rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Volume specifico di aria umida in ft³ lb⁻¹ di aria secca [IP] o in m³ kg⁻¹ di aria secca [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 26
        Appunti:
        In unità IP, R_DA_IP / 144 equivale a 0,370486 che è il coefficiente che appare nell'eqn 26
        Il fattore 144 serve per la conversione di Psi = lb in⁻² in lb ft⁻².
        """
    se HumRatio < 0:
        aumentare ValoreErrore("Il rapporto di umidità è negativo")
    Rapporto Hum limitato = max(Rapporto ronzio, MIN_HUM_RATIO)

    se isIP():
        Volume Aria Umida = R_DA_IP * OttieniTRankineFromTFahrenheit(TDryBulb) * (1 + 1.607858 * Rapporto Hum limitato) / (144 * Pressione)
    altro:
        Volume Aria Umida = R_DA_SI * OttieniTKelvinDaTCelsius(TDryBulb) * (1 + 1.607858 * Rapporto Hum limitato) / Pressione
    ritorno Volume Aria Umida

def OttieniTDryBulbFromMoistAirVolumeAndHumRatio(Volume Aria Umida: galleggiante, Rapporto um: galleggiante, Pressione: galleggiante) -> galleggiante:
    """
    Temperatura di ritorno a bulbo secco dato il volume specifico dell'aria umida, il rapporto di umidità e la pressione.
        Argomenti:
        MoistAirVolume: volume specifico di aria umida in ft³ lb⁻¹ di aria secca [IP] o in m³ kg⁻¹ di aria secca [SI]
        HumRatio: rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 26
        Appunti:
        In unità IP, R_DA_IP / 144 equivale a 0,370486 che è il coefficiente che appare nell'eqn 26
        Il fattore 144 serve per la conversione di Psi = lb in⁻² in lb ft⁻².
        Basato sulla funzione "GetMoistAirVolume", riorganizzato per la temperatura a bulbo secco.
        """
    se HumRatio < 0:
        aumentare ValoreErrore("Il rapporto di umidità è negativo")
    Rapporto Hum limitato = max(Rapporto ronzio, MIN_HUM_RATIO)

    se isIP():
        TDryBulb = OttieniTFahrenheitFromTRankine(MoistAirVolume * (144 * Pressione)
                        / (R_DA_IP * (1 + 1.607858 * Rapporto Hum limitato)))
    altro:
        TDryBulb = OttieniTCelsiusFromTKelvin(MoistAirVolume * Pressione
                        / (R_DA_SI * (1 + 1.607858 * Rapporto Hum limitato)))
    ritorno TDryBulb

def GetMoistAirDensity(TDryBulb: galleggiante, Rapporto um: galleggiante, Pressione:galleggiante) -> galleggiante:
    """
    Restituisce la densità dell'aria umida in base al rapporto di umidità, alla temperatura del bulbo secco e alla pressione.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        HumRatio: rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        MoistAirDensity: densità dell'aria umida in lb ft⁻³ [IP] o kg m⁻³ [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 11
        """
    se HumRatio < 0:
        aumentare ValoreErrore("Il rapporto di umidità è negativo")
    Rapporto Hum limitato = max(Rapporto ronzio, MIN_HUM_RATIO)

    Volume Aria Umida = GetMoistAirVolume(TDryBulb, Rapporto Hum limitato, Pressione)
    Densità dell'aria umida = (1 + Rapporto Hum limitato) / Volume Aria Umida
    ritorno Densità dell'aria umida


################################################## ################################################## ###
# Atmosfera standard
################################################## ################################################## ###

def OttieniPressioneAtmStandard(Altitudine: galleggiante) -> galleggiante:
    """
    Restituisce la pressione barometrica atmosferica standard, data l'elevazione (altitudine).
        Argomenti:
        Altitudine: altitudine in piedi [IP] o m [SI]
    Ritorna:
        Pressione barometrica atmosferica standard in Psi [IP] o Pa [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 3
        """

    se isIP():
        PressioneAtmStandard = 14.696 * math.pow(1 - 6.8754e-06 * Altitudine, 5.2559)
    altro:
        PressioneAtmStandard = 101325 * math.pow(1 - 2.25577e-05 * Altitudine, 5.2559)
    ritorno PressioneAtmStandard

def OttieniTemperaturaAtmStandard(Altitudine: galleggiante) -> galleggiante:
    """
    Restituisce la temperatura atmosferica standard, data l'elevazione (altitudine).
        Argomenti:
        Altitudine: altitudine in piedi [IP] o m [SI]
    Ritorna:
        Temperatura atmosfera standard a bulbo secco in °F [IP] o °C [SI]
    Riferimento:
        Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 4
        """
    se isIP():
        TemperaturaAtmStandard = 59 - 0.00356620 * Altitudine
    altro:
        TemperaturaAtmStandard = 15 - 0.0065 * Altitudine
    ritorno TemperaturaAtmStandard

def Ottieni la pressione del livello del mare(Pressionestazione: galleggiante, Altitudine: galleggiante, TDryBulb: galleggiante) -> galleggiante:

    """
    Pressione di ritorno al livello del mare data la temperatura a bulbo secco, l'altitudine sul livello del mare e la pressione.
        Argomenti:
        StationPressure: pressione osservata della stazione in Psi [IP] o Pa [SI]
        Altitudine: altitudine in piedi [IP] o m [SI]
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
    Ritorna:
        Pressione barometrica al livello del mare in Psi [IP] o Pa [SI]
    Riferimento:
        Hess SL, Introduzione alla meteorologia teorica, Holt Rinehart e Winston, NY 1959,
        cap. 6,5; Stull RB, Meteorologia per scienziati e ingegneri, 2a edizione,
        Brooks/Cole 2000, cap. 1.
        Appunti:
        La procedura standard per gli Stati Uniti prevede l'utilizzo della media per TDryBulb
        della temperatura attuale della stazione e della temperatura della stazione di 12 ore fa.
        """
    se isIP():
        # Calcola la temperatura media nella colonna d'aria, assumendo un intervallo di tempo
        N. di 3,6 °F/1000 piedi
        TColonna = TDryBulb + 0.0036 * Altitudine / 2

        # Determinare l'altezza della scala
        H = 53.351 * OttieniTRankineFromTFahrenheit(TConmina)
    altro:
        # Calcola la temperatura media nella colonna d'aria, assumendo un intervallo di tempo
        N. di 6,5 °C/km
        TColonna = TDryBulb + 0.0065 * Altitudine / 2

        # Determinare l'altezza della scala
        H = 287.055 * OttieniTKelvinDaTCelsius(TColonna) / 9.807

    # Calcola la pressione a livello del mare
    Pressione al livello del mare = StazionePressione * math.exp(Altitudine / H)
    ritorno Pressione al livello del mare

def Ottieni pressione stazione(Pressione al livello del mare: galleggiante, Altitudine: galleggiante, TDryBulb: galleggiante) -> galleggiante:
    """
    Pressione della stazione di ritorno dalla pressione a livello del mare.
        Argomenti:
        SeaLevelPressure: pressione barometrica al livello del mare in Psi [IP] o Pa [SI]
        Altitudine: altitudine in piedi [IP] o m [SI]
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
    Ritorna:
        Pressione della stazione in Psi [IP] o Pa [SI]
    Riferimento:
        Vedi 'Ottieni pressione livello mare'
        Appunti:
        Questa funzione è esattamente l'inverso di "GetSeaLevelPressure".
        """
    StazionePressione = Pressione al livello del mare / Ottieni pressione livello mare (1, Altitudine, TDryBulb)
    ritorno StazionePressione


################################################## ################################################## ##
# Funzioni per impostare tutti i valori psicrometrici
################################################## ################################################## ###

def CalcPsychrometricsFromTWetBulb(TDryBulb: galleggiante, TWetLampadina: galleggiante, Pressione: galleggiante) -> tupla:
    """
    Funzione di utilità per calcolare il rapporto di umidità, la temperatura del punto di rugiada, l'umidità relativa,
    pressione del vapore, entalpia dell'aria umida, volume dell'aria umida e grado di saturazione dell'aria fornita
    temperatura di bulbo secco, temperatura di bulbo umido e pressione.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        TWetBulb: temperatura del bulbo umido in °F [IP] o °C [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
        Temperatura del punto di rugiada in °F [IP] o °C [SI]
        Umidità relativa nell'intervallo [0, 1]
        Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
        Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
        Volume specifico di aria umida in ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
        Grado di saturazione [senza unità]
        """
    HumRatio = Ottieni rapporto humumFromTWetBulb(TDryBulb, TWetLampadina, Pressione)
    TDewPoint = OttieniTDewPointFromHumRatio(TDryBulb, HumRatio, Pressione)
    RelHum = OttieniRapportoRelHumFromHum(TDryBulb, HumRatio, Pressione)
    VapPres = GetVapPresFromHumRatio(Rapporto hum, Pressione)
    Entalpia dell'aria umida = GetMoistAirEntalpia(TDryBulb, HumRatio)
    Volume Aria Umida = GetMoistAirVolume(TDryBulb, HumRatio, Pressione)
    Grado Di Saturazione = Ottieni Grado di saturazione (TDryBulb, HumRatio, Pressione)
    ritorno HumRatio, punto di rugiada, RelHum, VapPres, Entalpia dell'aria umida, Volumeariaumida, Grado Di Saturazione

def CalcPsychrometricsFromTDewPoint(TDryBulb: galleggiante, Punto di rugiada: galleggiante, Pressione: galleggiante) -> tupla:
    """
    Funzione di utilità per calcolare il rapporto di umidità, la temperatura a bulbo umido, l'umidità relativa,
    pressione del vapore, entalpia dell'aria umida, volume dell'aria umida e grado di saturazione dell'aria fornita
    temperatura di bulbo secco, temperatura del punto di rugiada e pressione.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        TDewPoint: temperatura del punto di rugiada in °F [IP] o °C [SI]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
        Temperatura del bulbo umido in °F [IP] o °C [SI]
        Umidità relativa nell'intervallo [0, 1]
        Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
        Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
        Volume specifico di aria umida in ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
        Grado di saturazione [senza unità]
        """
    HumRatio = OttieniRapportoRum.DaPuntoDiTew(PuntoDiTew, Pressione)
    TWetBulb = OttieniTWetBulbFromHumRatio(TDryBulb, HumRatio, Pressione)
    RelHum = OttieniRapportoRelHumFromHum(TDryBulb, HumRatio, Pressione)
    VapPres = GetVapPresFromHumRatio(Rapporto hum, Pressione)
    Entalpia dell'aria umida = GetMoistAirEntalpia(TDryBulb, HumRatio)
    Volume Aria Umida = GetMoistAirVolume(TDryBulb, HumRatio, Pressione)
    Grado Di Saturazione = Ottieni Grado di saturazione (TDryBulb, HumRatio, Pressione)
    ritorno HumRatio, TWetLampadina, RelHum, VapPres, Entalpia dell'aria umida, Volumeariaumida, Grado Di Saturazione

def CalcPsychrometricsFromRelHum(TDryBulb: galleggiante, RelHum: galleggiante, Pressione: galleggiante) -> tupla:
    """
    Funzione di utilità per calcolare il rapporto di umidità, la temperatura del bulbo umido, la temperatura del punto di rugiada,
    pressione del vapore, entalpia dell'aria umida, volume dell'aria umida e grado di saturazione dell'aria fornita
    temperatura a bulbo secco, umidità relativa e pressione.
        Argomenti:
        TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
        RelHum: Umidità relativa nell'intervallo [0, 1]
        Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
    Ritorna:
        Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
        Temperatura del bulbo umido in °F [IP] o °C [SI]
        Temperatura del punto di rugiada in °F [IP] o °C [SI].
        Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
        Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
        Volume specifico di aria umida in ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
        Grado di saturazione [senza unità]
        """
    HumRatio = OttieniRapportoHumFromRelHum(TDryBulb, RelHum, Pressione)
    TWetBulb = OttieniTWetBulbFromHumRatio(TDryBulb, HumRatio, Pressione)
    TDewPoint = OttieniTDewPointFromHumRatio(TDryBulb, HumRatio, Pressione)
    VapPres = GetVapPresFromHumRatio(Rapporto hum, Pressione)
    Entalpia dell'aria umida = GetMoistAirEntalpia(TDryBulb, HumRatio)
    Volume Aria Umida = GetMoistAirVolume(TDryBulb, HumRatio, Pressione)
    Grado Di Saturazione = Ottieni Grado di saturazione (TDryBulb, HumRatio, Pressione)
    ritorno HumRatio, TWetLampadina, punto di rugiada, VapPres, Entalpia dell'aria umida, Volumeariaumida, Grado Di Saturazione

C_diesis

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
/ *
 * PsychroLib (versione 2.3.0) (https://github.com/psychrometrics/psychrolib)
 * Copyright (c) 2018 D. Thevenard e D. Meyer, D. Gosnell per l'attuale implementazione della libreria
 * Copyright (c) Manuale ASHRAE 2017 — Fondamenti per equazioni e coefficienti ASHRAE
 * Portato in C# da https://github.com/DJGosnell
 * Concesso in licenza con la licenza MIT.
  * /

utilizzando Sistema;

namespace PsychroLib
{
    /// <riepilogo>
    /// Classe di funzioni per consentire il calcolo delle proprietà psicrometriche dell'aria umida e secca.
    /// </summary>
    pubblico classe Psicrometria
    {
        /**************************************************** ************************************************** ***
         * Costanti globali
         ************************************************** ************************************************** */

        /// <riepilogo>
        /// Zero gradi Fahrenheit (°F) espressi in gradi Rankine (°R).
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 39.
        /// </summary>
        privato cost doppio ZERO_FAHRENHEIT_AS_RANKINE = 459.67;

        /// <riepilogo>
        /// Zero gradi Celsius (°C) espressi in Kelvin (K).
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 39.
        /// </summary>
        privato cost doppio ZERO_CELSIUS_AS_KELVIN = 273.15;

        /// <riepilogo>
        /// Costante universale del gas per aria secca (versione IP) in ft lb_Force lb_DryAir⁻¹ R⁻¹.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1.
        /// </summary>
        privato cost doppio R_DA_IP = 53.350;

        /// <riepilogo>
        /// Costante universale dei gas per aria secca (versione SI) in J kg_DryAir⁻¹ K⁻¹.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1.
        /// </summary>
        privato cost doppio R_DA_SI = 287.042;

        /// <riepilogo>
        /// Valore non valido (adimensionale).
        /// </summary>
        privato cost doppio NON VALIDO = -99999;

        /// <riepilogo>
        /// Numero massimo di iterazioni prima di uscire dai cicli while.
        /// </summary>
        privato cost doppio MAX_ITER_COUNT = 100;

        /// <riepilogo>
        /// Rapporto di umidità minimo accettabile utilizzato/restituito da qualsiasi funzione.
        /// Qualsiasi valore superiore a 0 o inferiore a MIN_HUM_RATIO verrà reimpostato su questo valore.
        /// </summary>
        privato cost doppio MIN_HUM_RATIO = 1e-7;

        /// <riepilogo>
        /// Punto di congelamento dell'acqua in Fahrenheit.
        /// </summary>
        privato cost doppio FREEZING_POINT_WATER_IP = 32.0;

        /// <riepilogo>
        /// Punto di congelamento dell'acqua in gradi Celsius.
        /// </summary>
        privato cost doppio FREEZING_POINT_WATER_SI = 0.0;

        /// <riepilogo>
        /// Punto triplo dell'acqua in Fahrenheit.
        /// </summary>
        privato cost doppio TRIPLO_POINT_ACQUA_IP = 32.018;

        /// <riepilogo>
        /// Punto triplo dell'acqua in gradi Celsius.
        /// </summary>
        privato cost doppio TRIPLO_POINT_ACQUA_SI = 0.01;

        /// <riepilogo>
        /// Ottiene o imposta il sistema di unità corrente per i calcoli.
        /// </summary>
        pubblico UnitSystem UnitSystem
        {
            ottenere => _unitàSistema;
            set
            {
                _unitSystem = valore;
                se (valore == UnitSystem.IP)
                    PSYCROLIB_TOLERANZA = 0.001 * 9.0 / 5.0;
                altro
                    PSYCROLIB_TOLERANZA = 0.001;
            }
        }

        privato doppio PSYCROLIB_TOLLERANZA;
        privato UnitSystem _unitàSistema;

        /// <riepilogo>
        /// Costruttore per creare un'istanza con il sistema di unità specificato.
        /// </summary>
        /// <param name="unitSystem">Sistema di unità da utilizzare per i calcoli.</param>
        pubblico Psicrometria(SistemaUnità unitàSistema)
        {
            UnitSystem = unitàSistema;
        }


        /**************************************************** ************************************************** ***
         * Conversione tra unità di temperatura
         ************************************************** ************************************************** */

        /// <riepilogo>
        /// Funzione di utilità per convertire la temperatura in gradi Rankine (°R)
        /// temperatura indicata in gradi Fahrenheit (°F).
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
        /// </summary>
        /// <param name="tF">Temperatura in Fahrenheit (°F)</param>
        /// <returns>Rankine (°R)</returns>
        pubblico doppio OttieniTRankineFromTFahrenheit(doppio tF)
        {
            ritorno tF + ZERO_FAHRENHEIT_AS_RANKINE; /* esatto */
        }

        /// <riepilogo>
        /// Funzione di utilità per convertire la temperatura in gradi Fahrenheit (°F)
        /// temperatura indicata in gradi Rankine (°R).
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
        /// </summary>
        /// <param name="tR">Temperatura in Rankine (°R)</param>
        /// <returns>Fahrenheit (°F)</returns>
        pubblico doppio Ottieni TFahrenheit da TRankine(doppio tR)
        {
            ritorno tR - ZERO_FAHRENHEIT_AS_RANKINE; /* esatto */
        }

        /// <riepilogo>
        /// Funzione di utilità per convertire la temperatura in Kelvin (K)
        /// temperatura indicata in gradi Celsius (°C).
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
        /// </summary>
        /// <param name="tC">Temperatura in gradi Celsius (°C)</param>
        /// <returns>Rankine (°R)</returns>
        pubblico doppio OttieniTKelvinDaTCelsius(doppio tC)
        {
            ritorno tC + ZERO_CELSIUS_AS_KELVIN; /* esatto */
        }

        /// <riepilogo>
        /// Funzione di utilità per convertire la temperatura in gradi Celsius (°C)
        /// temperatura indicata in Kelvin (K).
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
        /// </summary>
        /// <param name="tK">Temperatura in Rankine (°R)</param>
        /// <returns>Celsius (°C)</returns>
        pubblico doppio OttieniTCelsiusDaTKelvin(doppio tK)
        {
            ritorno tK - ZERO_CELSIUS_AS_KELVIN; /* esatto */
        }


        /**************************************************** ************************************************** ***
         * Conversioni tra punto di rugiada, bulbo umido e umidità relativa
         ************************************************** ************************************************** */

        /// <riepilogo>
        /// Temperatura di ritorno del bulbo umido data la temperatura del bulbo secco, la temperatura del punto di rugiada e la pressione.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="tDewPoint">Temperatura del punto di rugiada in °F [IP] o °C [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Temperatura a bulbo umido in °F [IP] o °C [SI]</returns>
        pubblico doppio OttieniTWetBulbFromTDewPoint(doppio tLampadina secca, doppio punto di rugiada, doppio pressione)
        {
            se (!(tPunto di rugiada <= tDryBulb))
                gettare nuovo InvalidOperationException("La temperatura del punto di rugiada è superiore alla temperatura del bulbo secco");

            var humRatio = GetHumRatioFromTDewPoint(tDewPoint, pressione);
            ritorno Rapporto GetTWetBulbFromHum(tDryBulb, humRatio, pressione);
        }


        /// <riepilogo>
        /// Temperatura di ritorno del bulbo umido data la temperatura del bulbo secco, l'umidità relativa e la pressione.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="relHum">Umidità relativa [0-1]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Temperatura a bulbo umido in °F [IP] o °C [SI]</returns>
        pubblico doppio GetTWetBulbFromRelHum(doppio tLampadina secca, doppio relHum, doppio pressione)
        {
            se (!(relHum >= 0.0 && relHum <= 1.0))
                gettare nuovo InvalidOperationException("L'umidità relativa è fuori dall'intervallo [0,1]");

            var humRatio = OttieniRapportoHumFromRelHum(tDryBulb, relHum, pressione);
            ritorno Rapporto GetTWetBulbFromHum(tDryBulb, humRatio, pressione);
        }


        /// <riepilogo>
        /// Umidità relativa restituita data la temperatura di bulbo secco e la temperatura del punto di rugiada.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 22
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="tDewPoint">Temperatura del punto di rugiada in °F [IP] o °C [SI]</param>
        /// <returns>Umidità relativa [0-1]</returns>
        pubblico doppio OttieniRelHumFromTDewPoint(doppio tLampadina secca, doppio punto di rugiada)
        {
            se (!(tPunto di rugiada <= tDryBulb))
                gettare nuovo InvalidOperationException("La temperatura del punto di rugiada è superiore alla temperatura del bulbo secco");

            var vapPres = GetSatVapPres(tPuntoRugiada);
            var satVapPres = GetSatVapPres(tDryBulb);
            ritorno vapPres / satVapPres;
        }

        /// <riepilogo>
        /// Umidità relativa restituita data la temperatura a bulbo secco, la temperatura a bulbo umido e la pressione.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="tWetBulb">Temperatura del bulbo umido in °F [IP] o °C [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Umidità relativa [0-1]</returns>
        pubblico doppio GetRelHumFromTWetBulb(doppio tLampadina secca, doppio tLampadina umida, doppio pressione)
        {
            se (!(tLampadina bagnata <= tDryBulb))
                gettare nuovo InvalidOperationException("La temperatura del bulbo umido è superiore alla temperatura del bulbo secco");

            var humRatio = Ottieni rapporto humumFromTWetBulb(tDryBulb, tLampadina umida, pressione);
            ritorno Ottieni rapporto RelHumFromHum(tDryBulb, humRatio, pressione);
        }

        /// <riepilogo>
        /// Temperatura del punto di rugiada di ritorno data la temperatura a bulbo secco e l'umidità relativa.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="relHum">Umidità relativa [0-1]</param>
        /// <returns>Temperatura del punto di rugiada in °F [IP] o °C [SI]</returns>
        pubblico doppio OttieniTDewPointFromRelHum(doppio tLampadina secca, doppio relHum)
        {
            se (!(relHum >= 0.0 && relHum <= 1.0))
                gettare nuovo InvalidOperationException("L'umidità relativa è fuori dall'intervallo [0,1]");

            var vapPres = GetVapPresFromRelHum(tDryBulb, relHum);
            ritorno OttieniTDewPointFromVapPres(tDryBulb, vapPres);
        }

        /// <riepilogo>
        /// Temperatura del punto di rugiada di ritorno data la temperatura di bulbo secco, la temperatura di bulbo umido e la pressione.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="tWetBulb">Temperatura del bulbo umido in °F [IP] o °C [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Temperatura del punto di rugiada in °F [IP] o °C [SI]</returns>
        pubblico doppio OttieniTDewPointFromTWetBulb(doppio tLampadina secca, doppio tLampadina umida, doppio pressione)
        {
            se (!(tLampadina bagnata <= tDryBulb))
                gettare nuovo InvalidOperationException("La temperatura del bulbo umido è superiore alla temperatura del bulbo secco");

            var humRatio = Ottieni rapporto humumFromTWetBulb(tDryBulb, tLampadina umida, pressione);
            ritorno OttieniTDewPointFromHumRatio(tDryBulb, humRatio, pressione);
        }


        /**************************************************** ************************************************** ***
         * Conversioni tra punto di rugiada o umidità relativa e pressione di vapore
         ************************************************** ************************************************** */

        /// <riepilogo>
        /// Restituisce la pressione parziale del vapore acqueo in funzione dell'umidità relativa e della temperatura.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 12, 22
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="relHum">Umidità relativa [0-1]</param>
        /// <returns>Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]</returns>
        pubblico doppio GetVapPresFromRelHum(doppio tLampadina secca, doppio relHum)
        {
            se (!(relHum >= 0.0 && relHum <= 1.0))
                gettare nuovo InvalidOperationException("L'umidità relativa è fuori dall'intervallo [0,1]");

            ritorno relHum * GetSatVapPres(tDryBulb);
        }

        /// <riepilogo>
        /// Umidità relativa restituita data la temperatura a bulbo secco e la pressione del vapore.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 12, 22
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="vapPres">Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]</param>
        /// <returns>Umidità relativa [0-1]</returns>
        pubblico doppio GetRelHumFromVapPres(doppio tLampadina secca, doppio vapPres)
        {
            se (!(vapPres >= 0.0))
                gettare nuovo InvalidOperationException("La pressione parziale del vapore acqueo nell'aria umida è negativa");

            ritorno vapPres / GetSatVapPres(tDryBulb);
        }

        /// <riepilogo>
        /// Funzione di supporto che restituisce la derivata del logaritmo naturale della pressione del vapore di saturazione
        /// in funzione della temperatura a bulbo secco.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 5 e 5 6
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <returns>Derivata del logaritmo naturale della tensione di vapore dell'aria satura in Psi [IP] o Pa [SI]</returns>
        privato doppio dLnPws_(doppio tDryBulb)
        {
            doppio dLnPw, T;

            se (SistemaUnità == UnitSystem.IP)
            {
                T = GetTRankineFromTFahrenheit(tDryBulb);

                se (tDryBulb <= TRIPLE_POINT_WATER_IP)
                    dLnPws = 1.0214165E+04 / Matematica.Pow(T, 2) - 5.3765794E-03 + 2 * 1.9202377E-07 * T
                             + 3 * 3.5575832E-10 * Matematica.Pow(T, 2) - 4 * 9.0344688E-14 * Matematica.Pow(T, 3) 
                             + 4.1635019 / T;
                altro
                    dLnPws = 1.0440397E+04 / Matematica.Pow(T, 2) - 2.7022355E-02 + 2 * 1.2890360E-05 * T
                             - 3 * 2.4780681E-09 * Matematica.Pow(T, 2) + 6.5459673 / T;
            }
            altro
            {
                T = OttieniTKelvinFromTCelsius(tDryBulb);

                se (tDryBulb <= TRIPLE_POINT_WATER_SI)
                    dLnPws = 5.6745359E+03 / Matematica.Pow(T, 2) - 9.677843E-03 + 2 * 6.2215701E-07 * T
                             + 3 * 2.0747825E-09 * Matematica.Pow(T, 2) - 4 * 9.484024E-13 * Matematica.Pow(T, 3) 
                             + 4.1635019 / T;
                altro
                    dLnPws = 5.8002206E+03 / Matematica.Pow(T, 2) - 4.8640239E-02 + 2 * 4.1764768E-05 * T
                             - 3 * 1.4452093E-08 * Matematica.Pow(T, 2) + 6.5459673 / T;
            }

            ritorno dLnPw;
        }

        /// <riepilogo>
        /// Temperatura del punto di rugiada di ritorno data la temperatura a bulbo secco e la pressione del vapore.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 5 e 6
        /// Note: la temperatura del punto di rugiada si risolve invertendo l'equazione dando la pressione del vapore acqueo
        /// a saturazione dalla temperatura anziché utilizzare le regressioni fornite
        /// da ASHRAE (eqn. 37 e 38) che sono molto meno accurati e hanno un
        /// intervallo di validità più ristretto.
        /// Il metodo Newton-Raphson (NR) viene utilizzato sul logaritmo del vapore acqueo
        /// pressione in funzione della temperatura, che è una funzione molto fluida
        /// La convergenza viene solitamente raggiunta in 3-5 iterazioni.
        /// tDryBulb non è realmente necessario qui, viene utilizzato solo per comodità.
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="vapPres">Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]</param>
        /// <returns>(o) Temperatura del punto di rugiada in °F [IP] o °C [SI]</returns>
        pubblico doppio OttieniTDewPointFromVapPres(doppio tLampadina secca, doppio vapPres)
        {
            // Funzione dei limiti del sistema di unità

            var limiti = UnitSystem == UnitSystem.IP
                ? nuovo[] {-148.0, 392.0}
                : nuovo[] {-100.0, 200.0};

            // Limiti oltre i quali non è possibile trovare una soluzione
            se (vapPres < GetSatVapPres(limiti[0]) || vapPres > GetSatVapPres(limiti[1]))
                gettare nuovo InvalidOperationException(
                    "La pressione parziale del vapore acqueo è fuori dal campo di validità delle equazioni");

            // Usiamo NR per approssimare la soluzione.
            // Prima ipotesi
            var tDewPoint =
                tLampadina secca; // Valore calcolato delle temperature del punto di rugiada, risolto iterativamente in °F [IP] o °C [SI]
            var lnVP = Log.Matematico(vapPres); // Logaritmo naturale della pressione parziale della pressione del vapore acqueo nell'aria umida

            doppio tPuntoRugiada_iter; // Valore di tDewPoint utilizzato nel calcolo NR
            doppio lnVP_iter; // Valore del logaritmo della pressione del vapore acqueo utilizzato nel calcolo NR
            var indice = 1;
            fare
            {
                // Punto corrente
                tPuntoRugiada_iter = punto di rugiada;
                lnVP_iter = Math.Log(GetSatVapPres(tDewPoint_iter));

                // Derivato della funzione, calcolato analiticamente
                var d_lnVP = dLnPws_(tPuntoRugiada_iter);

                // Nuova stima, delimitata dal dominio di validità dell'eqn. 5 e 6
                tDewPoint = tPuntoRugiada_iter - (lnVP_iter - lnVP) / d_lnVP;
                tDewPoint = Math.Max(tPunto di rugiada, limiti[0]);
                tDewPoint = Math.Min(tPunto di rugiada, limiti[1]);

                se (indice > MAX_ITER_COUNT)
                    gettare nuovo InvalidOperationException(
                        "Convergenza non raggiunta in GetTDewPointFromVapPres. Arresto.");

                indice++;
            } mentre (Math.Abs(tPuntoRugiada - tPuntoRugiada_iter) > PSYCHROLIB_TOLERANZA);

            ritorno Math.Min(tPunto di rugiada, tDryBulb);
        }

        /// <riepilogo>
        /// Pressione del vapore di ritorno data la temperatura del punto di rugiada.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 36
        /// </summary>
        /// <param name="tDewPoint">Temperatura del punto di rugiada in °F [IP] o °C [SI]</param>
        /// <returns>Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]</returns>
        pubblico doppio OttieniVapPresFromTDewPoint(doppio punto di rugiada)
        {
            ritorno OttieniSatVapPres(tPunto di rugiada);
        }


        /**************************************************** ************************************************** ***
         * Conversioni dalla temperatura del bulbo umido, dalla temperatura del punto di rugiada o dal rapporto umidità relativa/umidità
         ************************************************** ************************************************** */

        /// <riepilogo>
        /// Temperatura di ritorno del bulbo umido data la temperatura del bulbo secco, il rapporto di umidità e la pressione.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 33 e 35 risolti per Tstar
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="humRatio">Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Temperatura a bulbo umido in °F [IP] o °C [SI]</returns>
        pubblico doppio Rapporto GetTWetBulbFromHum(doppio tLampadina secca, doppio humRatio, doppio pressione)
        {
            // Dichiarazioni
            doppio stella;
            doppio punto di rugiada, tLampadina umida, tWetBulbSup, tWetBulbInf, rapportoHum delimitato;
            var indice = 1;

            se (!(rapporto ronzio >= 0.0))
                gettare nuovo InvalidOperationException("Il rapporto di umidità è negativo");
            boundedHumRatio = Math.Max(rapporto ronzio, MIN_UM_RATIO);

            tDewPoint = OttieniTDewPointFromHumRatio(tDryBulb, rapporto hum limitato, pressione);

            // Ipotesi iniziali
            tWetBulbSup = tLampadina secca;
            tBulbo bagnatoInf = punto di rugiada;
            tWetBulb = (tBulbumidoInf + tWetBulbSup) / 2.0;

            // Ciclo di bisezione
            mentre ((tLampadina bagnataSup - tBulbo umidoInf) > PSYCHROLIB_TOLERANZA)
            {
                // Calcola il rapporto di umidità alla temperatura Tstar
                Wstar = Ottieni rapporto humumFromTWetBulb(tDryBulb, tLampadina umida, pressione);

                // Ottieni nuovi limiti
                se (Wstar > rapporto Hum limitato)
                    tWetBulbSup = tLampadina umida;
                altro
                    tBulbo bagnatoInf = tLampadina umida;

                // Nuova ipotesi sulla temperatura del bulbo umido
                tWetBulb = (tWetBulbSup + tBulbo umidoInf) / 2.0;

                se (indice > MAX_ITER_COUNT)
                    gettare nuovo InvalidOperationException(
                        "Convergenza non raggiunta in GetTWetBulbFromHumRatio. Arresto.");

                indice++;
            }

            ritorno tLampadina umida;
        }

        /// <riepilogo>
        /// Rapporto di umidità di ritorno data la temperatura di bulbo secco, la temperatura di bulbo umido e la pressione.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 33 e 35
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="tWetBulb">Temperatura del bulbo umido in °F [IP] o °C [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]</returns>
        pubblico doppio OttieniHumRatioFromTWetBulb(doppio tLampadina secca, doppio tLampadina umida, doppio pressione)
        {
            doppio wsstar;
            doppio humRatio = NON VALIDO;

            se (!(tLampadina bagnata <= tDryBulb))
                gettare nuovo InvalidOperationException("La temperatura del bulbo umido è superiore alla temperatura del bulbo secco");

            wsstar = Ottieni rapporto humSat(tbulbo umido, pressione);

            se (SistemaUnità == UnitSystem.IP)
            {
                se (tWetBulb >= FREEZING_POINT_WATER_IP)
                    humRatio = ((1093.0 - 0.556 * tLampadina umida) * wsstar - 0.240 * (tDryBulb - tLampadina umida))
                               / (1093.0 + 0.444 * tDryBulb - tWetBulb);
                altro
                    humRatio = ((1220.0 - 0.04 * tLampadina umida) * wsstar - 0.240 * (tDryBulb - tLampadina umida))
                               / (1220.0 + 0.444 * tDryBulb - 0.48 * tWetBulb);
            }
            altro
            {
                se (tWetBulb >= FREEZING_POINT_WATER_SI)
                    humRatio = ((2501.0 - 2.326 * tLampadina umida) * wsstar - 1.006 * (tDryBulb - tLampadina umida))
                               / (2501.0 + 1.86 * tDryBulb - 4.186 * tWetBulb);
                altro
                    humRatio = ((2830.0 - 0.24 * tLampadina umida) * wsstar - 1.006 * (tDryBulb - tLampadina umida))
                               / (2830.0 + 1.86 * tDryBulb - 2.1 * tWetBulb);
            }

            // Controllo di validità.
            ritorno Math.Max(rapporto ronzio, MIN_UM_RATIO);
        }


        /// <riepilogo>
        /// Rapporto di umidità di ritorno data la temperatura a bulbo secco, l'umidità relativa e la pressione.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="relHum">Umidità relativa [0-1]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]</returns>
        pubblico doppio OttieniHumRatioFromRelHum(doppio tLampadina secca, doppio relHum, doppio pressione)
        {
            se (!(relHum >= 0.0 && relHum <= 1.0))
                gettare nuovo InvalidOperationException("L'umidità relativa è fuori dall'intervallo [0,1]");

            var vapPres = GetVapPresFromRelHum(tDryBulb, relHum);
            ritorno OttieniHumRatioFromVapPres(vapPres, pressione);
        }


        /// <riepilogo>
        /// Restituisce l'umidità relativa data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="humRatio">Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Umidità relativa [0-1]</returns>
        pubblico doppio Ottieni rapporto RelHumFromHum(doppio tLampadina secca, doppio humRatio, doppio pressione)
        {
            se (!(rapporto ronzio >= 0.0))
                gettare nuovo InvalidOperationException("Il rapporto di umidità è negativo");

            var vapPres = GetVapPresFromHumRatio(humRatio, pressione);
            ritorno GetRelHumFromVapPres(tDryBulb, vapPres);
        }

        /// <riepilogo>
        /// Rapporto di umidità di ritorno data la temperatura e la pressione del punto di rugiada.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
        /// </summary>
        /// <param name="tDewPoint">Temperatura del punto di rugiada in °F [IP] o °C [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]</returns>
        pubblico doppio OttieniHumRatioFromTDewPoint(doppio punto di rugiada, doppio pressione)
        {
            var vapPres = GetSatVapPres(tPuntoRugiada);
            ritorno OttieniHumRatioFromVapPres(vapPres, pressione);
        }

        /// <riepilogo>
        /// Temperatura del punto di rugiada di ritorno data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="humRatio">Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Temperatura del punto di rugiada in °F [IP] o °C [SI]</returns>
        pubblico doppio OttieniTDewPointFromHumRatio(doppio tLampadina secca, doppio humRatio, doppio pressione)
        {
            se (!(rapporto ronzio >= 0.0))
                gettare nuovo InvalidOperationException("Il rapporto di umidità è negativo");

            var vapPres = GetVapPresFromHumRatio(humRatio, pressione);
            ritorno OttieniTDewPointFromVapPres(tDryBulb, vapPres);
        }


        /**************************************************** ************************************************** ***
         * Conversioni tra rapporto di umidità e pressione di vapore
         ************************************************** ************************************************** */

        /// <riepilogo>
        /// Rapporto dell'umidità di ritorno data la pressione del vapore acqueo e la pressione atmosferica.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 20
        /// </summary>
        /// <param name="vapPres">Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]</returns>
        pubblico doppio OttieniHumRatioFromVapPres(doppio vapPres, doppio pressione)
        {
            se (!(vapPres >= 0.0))
                gettare nuovo InvalidOperationException("La pressione parziale del vapore acqueo nell'aria umida è negativa");

            var humRatio = 0.621945 * vapPres / (pressione - vapPres);

            // Controllo di validità.
            ritorno Math.Max(rapporto ronzio, MIN_UM_RATIO);
        }


        /// <riepilogo>
        /// Pressione del vapore di ritorno dati il ​​rapporto di umidità e la pressione.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 20 risolto per pw
        /// </summary>
        /// <param name="humRatio">Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]</returns>
        pubblico doppio OttieniVapPresFromHumRatio(doppio humRatio, doppio pressione)
        {
            se (!(rapporto ronzio >= 0.0))
                gettare nuovo InvalidOperationException("Il rapporto di umidità è negativo");
            var boundedHumRatio = Math.Max(rapporto ronzio, MIN_UM_RATIO);

            var vapPres = pressione * boundedHumRatio / (0.621945 + rapporto Hum limitato);
            ritorno vapPres;
        }


        /**************************************************** ************************************************** ***
         *Conversioni tra rapporto di umidità e umidità specifica
         ************************************************** ************************************************** */

        /// <riepilogo>
        /// Restituisce l'umidità specifica dal rapporto di umidità (noto anche come rapporto di miscelazione)
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 9b
        /// </summary>
        /// <param name="humRatio">Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <returns>Rapporto di umidità specifica in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]</returns>
        pubblico doppio Ottieni rapporto HumFromHum specifico(doppio humRatio)
        {
            se (!(rapporto ronzio >= 0.0))
                gettare nuovo InvalidOperationException("Il rapporto di umidità è negativo");
            var boundedHumRatio = Math.Max(rapporto ronzio, MIN_UM_RATIO);

            ritorno boundedHumRatio / (1.0 + rapporto Hum limitato);
        }


        /// <riepilogo>
        /// Restituisce il rapporto di umidità (noto anche come rapporto di miscelazione) dall'umidità specifica
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 9b (risolto per il rapporto di umidità)
        /// </summary>
        /// <param name="specificHum"></param>
        /// <returns>Rapporto di umidità in lb_H₂O lb_Dry_Air⁻¹ [IP] o kg_H₂O kg_Dry_Air⁻¹ [SI]</returns>
        pubblico doppio Ottieni rapporto humum da hum specifico(doppio specificoHum)
        {
            se (!(specificHum >= 0.0 && specificoHum < 1.0))
                gettare nuovo InvalidOperationException("L'umidità specifica è fuori dall'intervallo [0, 1]");

            var humRatio = specificoHum / (1.0 - specificoHum);

            // Controllo di validità
            ritorno Math.Max(rapporto ronzio, MIN_UM_RATIO);
        }


        /**************************************************** ************************************************** ***
         * Calcoli dell'aria secca
         ************************************************** ************************************************** */

        /// <riepilogo>
        /// Entalpia dell'aria secca restituita data la temperatura a bulbo secco.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 28
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <returns>Entalpia dell'aria secca in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]</returns>
        pubblico doppio OttieniEntalpiaAriaSecca(doppio tDryBulb)
        {
            se (SistemaUnità == UnitSystem.IP)
                ritorno 0.240 * tLampadina secca;

            ritorno 1006.0 * tLampadina secca;
        }


        /// <riepilogo>
        /// Densità di ritorno dell'aria secca date la temperatura e la pressione del bulbo secco.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
        /// Note: eqn 14 per la perfetta relazione di gas per l'aria secca.
        /// Eqn 1 per la costante universale dei gas.
        /// Il fattore 144 in IP serve per la conversione di Psi = lb in⁻² in lb ft⁻².
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Densità dell'aria secca in lb ft⁻³ [IP] o kg m⁻³ [SI]</returns>
        pubblico doppio OttieniDryAirDensity(doppio tLampadina secca, doppio pressione)
        {
            se (SistemaUnità == UnitSystem.IP)
                ritorno (144.0 * pressione) / R_DA_IP / GetTRankineFromTFahrenheit(tDryBulb);

            ritorno pressione / R_DA_SI / OttieniTKelvinFromTCelsius(tDryBulb);
        }


        /// <riepilogo>
        /// Volume di aria secca restituita in base alla temperatura e alla pressione del bulbo secco.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1.
        /// Note: eqn 14 per la perfetta relazione di gas per l'aria secca.
        /// Eqn 1 per la costante universale dei gas.
        /// Il fattore 144 in IP serve per la conversione di Psi = lb in⁻² in lb ft⁻².
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Volume di aria secca ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]</returns>
        pubblico doppio OttieniDryAirVolume(doppio tLampadina secca, doppio pressione)
        {
            se (SistemaUnità == UnitSystem.IP)
                ritorno R_DA_IP * OttieniTRankineFromTFahrenheit(tDryBulb) / (144.0 * pressione);

            ritorno R_DA_SI * OttieniTKelvinDaTCelsius(tDryBulb) / pressione;
        }


        /// <riepilogo>
        /// Restituisce la temperatura del bulbo secco dal rapporto entalpia e umidità.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 30.
        /// Note: basato sulla funzione `GetMoistAirEnthalpy`, riorganizzato per la temperatura.
        /// </summary>
        /// <param name="moistAirEnthalpy">Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹</param>
        /// <param name="humRatio">Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <returns>Temperatura a bulbo secco in °F [IP] o °C [SI]</returns>
        pubblico doppio OttieniTDryBulbFromEnthalpyAndHumRatio(doppio entalpia dell'aria umida, doppio humRatio)
        {
            se (!(rapporto ronzio >= 0.0))
                gettare nuovo InvalidOperationException("Il rapporto di umidità è negativo");
            var boundedHumRatio = Math.Max(rapporto ronzio, MIN_UM_RATIO);

            se (SistemaUnità == UnitSystem.IP)
                ritorno (Entalpia dell'aria umida - 1061.0 * rapporto Hum limitato) / (0.240 + 0.444 * rapporto Hum limitato);

            ritorno (Entalpia dell'aria umida / 1000.0 - 2501.0 * rapporto Hum limitato) / (1.006 + 1.86 * rapporto Hum limitato);
        }


        /// <riepilogo>
        /// Rapporto dell'umidità di ritorno tra entalpia e temperatura a bulbo secco.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 30.
        /// Note: basato sulla funzione `GetMoistAirEnthalpy`, riorganizzato per il rapporto di umidità.
        /// </summary>
        /// <param name="moistAirEnthalpy">Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹</param>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <returns>Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻</returns>
        pubblico doppio Ottieni rapporto hum dall'entalpia e dal bulbo secco(doppio entalpia dell'aria umida, doppio tDryBulb)
        {
            {
                doppio rapporto hum;
                se (SistemaUnità == UnitSystem.IP)
                    humRatio = (Entalpia dell'aria umida - 0.240 * tDryBulb) / (1061.0 + 0.444 * tDryBulb);
                altro
                    humRatio = (Entalpia dell'aria umida / 1000.0 - 1.006 * tDryBulb) / (2501.0 + 1.86 * tDryBulb);

                // Controllo di validità.
                ritorno Math.Max(rapporto ronzio, MIN_UM_RATIO);
            }
        }


        /**************************************************** ************************************************** ***
         * Calcoli dell'aria satura
         ************************************************** ************************************************** */

        /// <riepilogo>
        /// Pressione del vapore di saturazione di ritorno data la temperatura a bulbo secco.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 5 e 5 6
        /// Nota importante: le formule ASHRAE sono definite sopra e sotto il punto di congelamento ma hanno
        /// una discontinuità al punto di congelamento. Questa è una piccola imprecisione da parte di ASHRAE: le formule
        /// dovrebbe essere definito sopra e sotto il punto triplo dell'acqua (non il punto di contatto), nel qual caso
        /// la discontinuità svanisce. È essenziale utilizzare il punto triplo dell'acqua altrimenti funzionerà
        /// GetTDewPointFromVapPres, che inverte la funzione presente, non converge correttamente
        /// il punto di congelamento.
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <returns>Pressione di vapore dell'aria satura in Psi [IP] o Pa [SI]</returns>
        pubblico doppio OttieniSatVapPres(doppio tDryBulb)
        {
            doppio lnPw;

            se (SistemaUnità == UnitSystem.IP)
            {
                se (!(tDryBulb >= -148.0 && tDryBulb <= 392.0))
                    gettare nuovo InvalidOperationException("La temperatura del bulbo secco è fuori dall'intervallo [-148, 392]");

                var T = GetTRankineFromTFahrenheit(tDryBulb);
                se (tDryBulb <= TRIPLE_POINT_WATER_IP)
                    lnPws = (-1.0214165E+04 / T - 4.8932428 - 5.3765794E-03 * T + 1.9202377E-07 * T * T
                                                                                + 3.5575832E-10 * Matematica.Pow(T, 3) -
                             9.0344688E-14 * Matematica.Pow(T, 4) + 4.1635019 * Log.Matematico(T));
                altro
                    lnPws = -1.0440397E+04 / T - 1.1294650E+01 - 2.7022355E-02 * T + 1.2890360E-05 * T * T
                            - 2.4780681E-09 * Matematica.Pow(T, 3) + 6.5459673 * Log.Matematico(T);
            }
            altro
            {
                se (!(tDryBulb >= -100.0 && tDryBulb <= 200.0))
                    gettare nuovo InvalidOperationException("La temperatura del bulbo secco è fuori dall'intervallo [-100, 200]");

                var T = OttieniTKelvinFromTCelsius(tDryBulb);
                se (tDryBulb <= TRIPLE_POINT_WATER_SI)
                    lnPws = -5.6745359E+03 / T + 6.3925247 - 9.677843E-03 * T + 6.2215701E-07 * T * T
                                                                              + 2.0747825E-09 * Matematica.Pow(T, 3) -
                            9.484024E-13 * Matematica.Pow(T, 4) + 4.1635019 * Log.Matematico(T);
                altro
                    lnPws = -5.8002206E+03 / T + 1.3914993 - 4.8640239E-02 * T + 4.1764768E-05 * T * T
                            - 1.4452093E-08 * Matematica.Pow(T, 3) + 6.5459673 * Log.Matematico(T);
            }

            ritorno Esp.matematica(lnPws);
        }


        /// <riepilogo>
        /// Rapporto di umidità di ritorno dell'aria satura data la temperatura e la pressione a bulbo secco.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 36, risolto per W
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Rapporto di umidità dell'aria satura in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]</returns>
        pubblico doppio Ottieni rapporto SatHum(doppio tLampadina secca, doppio pressione)
        {
            var satVaporPres = GetSatVapPres(tDryBulb);
            var satHumRatio = 0.621945 * satVaporPres / (pressione - satVaporPres);

            // Controllo di validità.
            ritorno Math.Max(rapporto satHum, MIN_UM_RATIO);
        }

        /// <riepilogo>
        /// Entalpia dell'aria satura restituita date la temperatura e la pressione a bulbo secco.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Entalpia dell'aria satura in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]</returns>
        pubblico doppio OttieniSatAirEntalpia(doppio tLampadina secca, doppio pressione)
        {
            ritorno OttieniEntalpiaAriaMostra(tDryBulb, Ottieni rapporto humSat(tDryBulb, pressione));
        }


        /**************************************************** ************************************************** ***
         * Calcoli dell'aria umida
         ************************************************** ************************************************** */

        /// <riepilogo>
        /// Ritorno Deficit di pressione del vapore data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
        /// Riferimento: vedere Oke (1987) eqn. 2.13a
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="humRatio">Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Deficit della pressione di vapore in Psi [IP] o Pa [SI]</returns>
        pubblico doppio OttieniVaporPressureDeficit(doppio tLampadina secca, doppio humRatio, doppio pressione)
        {
            se (!(rapporto ronzio >= 0.0))
                gettare nuovo InvalidOperationException("Il rapporto di umidità è negativo");

            var relHum = OttieniRelHumFromHumRatio(tDryBulb, humRatio, pressione);
            ritorno OttieniSatVapPres(tLampadina secca) * (1.0 - relHum);
        }


        /// <riepilogo>
        /// Restituisce il grado di saturazione (ovvero il rapporto di umidità dell'aria/rapporto di umidità dell'aria alla saturazione
        /// alla stessa temperatura e pressione) data la temperatura a bulbo secco, il rapporto di umidità e la pressione atmosferica.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2009) cap. 1 eq. 12
        /// Note: la definizione è assente nel Manuale 2017
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="humRatio">Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Grado di saturazione (senza unità)</returns>
        pubblico doppio Ottieni Grado di Saturazione(doppio tLampadina secca, doppio humRatio, doppio pressione)
        {
            se (!(rapporto ronzio >= 0.0))
                gettare nuovo InvalidOperationException("Il rapporto di umidità è negativo");
            var boundedHumRatio = Math.Max(rapporto ronzio, MIN_UM_RATIO);

            ritorno boundedHumRatio / Ottieni rapporto humSat(tDryBulb, pressione);
        }

        /// <riepilogo>
        /// Entalpia dell'aria umida di ritorno data la temperatura a bulbo secco e il rapporto di umidità.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 30
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="humRatio">Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <returns>Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]</returns>
        pubblico doppio OttieniEntalpiaAriaMostra(doppio tLampadina secca, doppio humRatio)
        {
            se (!(rapporto ronzio >= 0.0))
                gettare nuovo InvalidOperationException("Il rapporto di umidità è negativo");

            var boundedHumRatio = Math.Max(rapporto ronzio, MIN_UM_RATIO);

            se (SistemaUnità == UnitSystem.IP)
                ritorno 0.240 * tDryBulb + boundedHumRatio * (1061.0 + 0.444 * tDryBulb);

            ritorno (1.006 * tDryBulb + boundedHumRatio * (2501.0 + 1.86 * tDryBulb)) * 1000.0;
        }


        /// <riepilogo>
        /// Volume specifico di aria umida restituita in base alla temperatura a bulbo secco, al rapporto di umidità e alla pressione.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 26
        /// Note: in unità IP, R_DA_IP / 144 equivale a 0,370486 che è il coefficiente che appare nell'eqn 26.
        /// Il fattore 144 serve per la conversione di Psi = lb in⁻² in lb ft⁻².
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="humRatio">Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Volume specifico ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]</returns>
        pubblico doppio OttieniMoistAirVolume(doppio tLampadina secca, doppio humRatio, doppio pressione)
        {
            se (!(rapporto ronzio >= 0.0))
                gettare nuovo InvalidOperationException("Il rapporto di umidità è negativo");
            var boundedHumRatio = Math.Max(rapporto ronzio, MIN_UM_RATIO);

            se (SistemaUnità == UnitSystem.IP)
                ritorno R_DA_IP * OttieniTRankineFromTFahrenheit(tDryBulb) * (1.0 + 1.607858 * rapporto Hum limitato) /
                       (144.0 * pressione);

            ritorno R_DA_SI * OttieniTKelvinDaTCelsius(tDryBulb) * (1.0 + 1.607858 * rapporto Hum limitato) / pressione;
        }


        /// <riepilogo>
        /// Temperatura di ritorno a bulbo secco dato il volume specifico dell'aria umida, il rapporto di umidità e la pressione.
        /// Riferimento:
        /// Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 26
        /// Appunti:
        /// In unità IP, R_DA_IP / 144 equivale a 0,370486 che è il coefficiente che appare nell'eqn 26
        /// Il fattore 144 serve per la conversione di Psi = lb in⁻² in lb ft⁻².
        /// Basato sulla funzione "GetMoistAirVolume", riorganizzato per la temperatura a bulbo secco.
        /// </summary>
        /// <param name="MoistAirVolume">Volume specifico di aria umida in ft³ lb⁻¹ di aria secca [IP] o in m³ kg⁻¹ di aria secca [SI]</param>
        /// <param name="humRatio">Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Temperatura a bulbo secco in °F [IP] o °C [SI]</returns>
        pubblico doppio OttieniTDryBulbFromMoistAirVolumeAndHumRatio(doppio Volumeariaumida, doppio humRatio, doppio pressione)
        {
            se (!(rapporto ronzio >= 0.0))
                gettare nuovo InvalidOperationException("Il rapporto di umidità è negativo");
            var boundedHumRatio = Math.Max(rapporto ronzio, MIN_UM_RATIO);

            se (SistemaUnità == UnitSystem.IP)
                ritorno  Ottieni TFahrenheit da TRankine(Volume Aria Umida * (144 * pressione) / (R_DA_IP * (1 + 1.607858 * rapporto Hum limitato)));

            ritorno OttieniTCelsiusDaTKelvin(Volume Aria Umida * pressione / (R_DA_SI * (1 + 1.607858 * rapporto Hum limitato)));
        }


        /// <riepilogo>
        /// Restituisce la densità dell'aria umida in base al rapporto di umidità, alla temperatura del bulbo secco e alla pressione.
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 11
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="humRatio">Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Densità dell'aria umida in lb ft⁻³ [IP] o kg m⁻³ [SI]</returns>
        pubblico doppio GetMoistAirDensity(doppio tLampadina secca, doppio humRatio, doppio pressione)
        {
            se (!(rapporto ronzio >= 0.0))
                gettare nuovo InvalidOperationException("Il rapporto di umidità è negativo");

            var boundedHumRatio = Math.Max(rapporto ronzio, MIN_UM_RATIO);

            ritorno (1.0 + rapporto Hum limitato) / GetMoistAirVolume(tDryBulb, rapporto hum limitato, pressione);
        }


        /**************************************************** ************************************************** ***
         *Atmosfera standard
         ************************************************** ************************************************** */

        /// <riepilogo>
        /// Restituisce la pressione barometrica atmosferica standard, data l'elevazione (altitudine).
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 3
        /// </summary>
        /// <param name="altitude">altitudine in piedi [IP] o m [SI]</param>
        /// <returns>Pressione barometrica atmosferica standard in Psi [IP] o Pa [SI]</returns>
        pubblico doppio OttieniPressioneAtmStandard(doppio altitudine)
        {
            se (SistemaUnità == UnitSystem.IP)
                ritorno 14.696 * Math.Pow(1.0 - 6.8754e-06 * altitudine, 5.2559);

            ritorno 101325.0 * Math.Pow(1.0 - 2.25577e-05 * altitudine, 5.2559);
        }


        /// <riepilogo>
        /// Restituisce la temperatura atmosferica standard, data l'elevazione (altitudine).
        /// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 4
        /// </summary>
        /// <param name="altitude">altitudine in piedi [IP] o m [SI]</param>
        /// <returns>Temperatura a bulbo secco dell'atmosfera standard in °F [IP] o °C [SI]</returns>
        pubblico doppio OttieniTemperaturaAtmStandard(doppio altitudine)
        {
            se (SistemaUnità == UnitSystem.IP)
                ritorno 59.0 - 0.00356620 * altitudine;

            ritorno 15.0 - 0.0065 * altitudine;
        }

        /// <riepilogo>
        /// Pressione di ritorno al livello del mare data la temperatura a bulbo secco, l'altitudine sul livello del mare e la pressione.
        /// Riferimento: Hess SL, Introduzione alla meteorologia teorica, Holt Rinehart e Winston, NY 1959,
        /// cap. 6,5; Stull RB, Meteorologia per scienziati e ingegneri, 2a edizione,
        /// Brooks/Cole 2000, cap. 1.
        /// Note: la procedura standard per gli Stati Uniti prevede l'utilizzo della media per tDryBulb
        /// della temperatura attuale della stazione e della temperatura della stazione di 12 ore fa.
        /// </summary>
        /// <param name="stnPressure">Pressione osservata della stazione in Psi [IP] o Pa [SI]</param>
        /// <param name="altitude">Altitudine sopra il livello del mare in piedi [IP] o m [SI]</param>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <returns>Pressione barometrica al livello del mare in Psi [IP] o Pa [SI]</returns>
        pubblico doppio Ottieni la pressione del livello del mare(doppio stnPressione, doppio altitudine, doppio tDryBulb)
        {
            doppio h;
            se (SistemaUnità == UnitSystem.IP)
            {
                // Calcola la temperatura media nella colonna d'aria, assumendo un intervallo di tempo
                // di 3,6 °F/1000 piedi
                var tColonna = tDryBulb + 0.0036 * altitudine / 2.0;

                // Determina l'altezza della scala
                h = 53.351 * GetTRankineFromTFahrenheit(tColonna);
            }
            altro
            {
                // Calcola la temperatura media nella colonna d'aria, assumendo un intervallo di tempo
                // di 6,5 °C/km
                var tColonna = tDryBulb + 0.0065 * altitudine / 2.0;

                // Determina l'altezza della scala
                h = 287.055 * OttieniTKelvinDaTCelsius(tColonna) / 9.807;
            }

            // Calcola la pressione a livello del mare
            var pressione del livello del mare = stnPressione * Math.Exp(altitudine / h);
            ritorno pressione del livello del mare;
        }


        /// <riepilogo>
        /// Pressione della stazione di ritorno dalla pressione a livello del mare
        /// Riferimento: vedere 'GetSeaLevelPressure'
        /// Note: questa funzione è esattamente l'inverso di 'GetSeaLevelPressure'.
        /// </summary>
        /// <param name="seaLevelPressure">Pressione barometrica al livello del mare in Psi [IP] o Pa [SI]</param>
        /// <param name="altitude">Altitudine sopra il livello del mare in piedi [IP] o m [SI]</param>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <returns>Pressione della stazione in Psi [IP] o Pa [SI]</returns>
        pubblico doppio Ottieni pressione stazione(doppio pressione del livello del mare, doppio altitudine, doppio tDryBulb)
        {
            ritorno pressione del livello del mare / Ottieni pressione livello mare (1.0, altitudine, tDryBulb);
        }


        /**************************************************** ************************************************** ***
         * Funzioni per impostare tutti i valori psicrometrici
         ************************************************** ************************************************** */

        /// <riepilogo>
        /// Funzione di utilità per calcolare il rapporto di umidità, la temperatura del punto di rugiada, l'umidità relativa,
        /// pressione del vapore, entalpia dell'aria umida, volume dell'aria umida e grado di saturazione dell'aria fornita
        /// temperatura a bulbo secco, temperatura a bulbo umido e pressione.
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="tWetBulb">Temperatura del bulbo umido in °F [IP] o °C [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Valori calcolati.</returns>
        pubblico Valore psicrometrico CalcPsychrometricsFromTWetBulb(doppio tLampadina secca, doppio tLampadina umida, doppio pressione)
        {
            var valore = nuovo Valore psicrometrico
            {
                TDryBulb = tLampadina secca,
                TWetBulb = tLampadina umida,
                Pressione = pressione
            };

            valore.HumRatio = Ottieni rapporto humumFromTWetBulb(tDryBulb, tLampadina umida, pressione);
            valore.TDewPoint = OttieniTDewPointFromHumRatio(tDryBulb, valore.HumRatio, pressione);
            valore.RelHum = OttieniRelHumFromHumRatio(tDryBulb, valore.HumRatio, pressione);
            valore.VapPres = Ottieni rapporto VapPresFromHum(valore.HumRatio, pressione);
            valore.Entalpia dell'aria umida = GetMoistAirEntalpia(tDryBulb, valore.HumRatio);
            valore.MoistAirVolume = GetMoistAirVolume(tDryBulb, valore.HumRatio, pressione);
            valore.Grado di saturazione = Ottieni Grado di saturazione (tBulb secco, valore.HumRatio, pressione);

            ritorno valore;
        }


        /// <riepilogo>
        /// Funzione di utilità per calcolare il rapporto di umidità, la temperatura del bulbo umido, l'umidità relativa,
        /// pressione del vapore, entalpia dell'aria umida, volume dell'aria umida e grado di saturazione dell'aria fornita
        /// temperatura del bulbo secco, temperatura del punto di rugiada e pressione.
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="tDewPoint">Temperatura del punto di rugiada in °F [IP] o °C [SI]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Valori calcolati.</returns>
        pubblico Valore psicrometrico CalcPsychrometricsFromTDewPoint(doppio tLampadina secca, doppio punto di rugiada, doppio pressione)
        {
            var valore = nuovo Valore psicrometrico
            {
                TDryBulb = tLampadina secca,
                TDewPoint = punto di rugiada,
                Pressione = pressione
            };

            valore.HumRatio = GetHumRatioFromTDewPoint(tDewPoint, pressione);
            valore.TWetBulb = OttieniTBulbumidoFromHumRatio(tDryBulb, valore.HumRatio, pressione);
            valore.RelHum = OttieniRelHumFromHumRatio(tDryBulb, valore.HumRatio, pressione);
            valore.VapPres = Ottieni rapporto VapPresFromHum(valore.HumRatio, pressione);
            valore.Entalpia dell'aria umida = GetMoistAirEntalpia(tDryBulb, valore.HumRatio);
            valore.MoistAirVolume = GetMoistAirVolume(tDryBulb, valore.HumRatio, pressione);
            valore.Grado di saturazione = Ottieni Grado di saturazione (tBulb secco, valore.HumRatio, pressione);

            ritorno valore;
        }


        /// <riepilogo>
        /// Funzione di utilità per calcolare il rapporto di umidità, la temperatura del bulbo umido, la temperatura del punto di rugiada,
        /// pressione del vapore, entalpia dell'aria umida, volume dell'aria umida e grado di saturazione dell'aria fornita
        /// temperatura a bulbo secco, umidità relativa e pressione.
        /// </summary>
        /// <param name="tDryBulb">Temperatura a bulbo secco in °F [IP] o °C [SI]</param>
        /// <param name="relHum">Umidità relativa [0-1]</param>
        /// <param name="pressione">Pressione atmosferica in Psi [IP] o Pa [SI]</param>
        /// <returns>Valori calcolati.</returns>
        pubblico Valore psicrometrico CalcPsychrometricsFromRelHum(doppio tLampadina secca, doppio relHum, doppio pressione)
        {
            var valore = nuovo Valore psicrometrico
            {
                TDryBulb = tLampadina secca,
                RelHum = relHum,
                Pressione = pressione
            };

            valore.HumRatio = OttieniRapportoHumFromRelHum(tDryBulb, relHum, pressione);
            valore.TWetBulb = OttieniTBulbumidoFromHumRatio(tDryBulb, valore.HumRatio, pressione);
            valore.TDewPoint = OttieniTDewPointFromHumRatio(tDryBulb, valore.HumRatio, pressione);
            valore.VapPres = Ottieni rapporto VapPresFromHum(valore.HumRatio, pressione);
            valore.Entalpia dell'aria umida = GetMoistAirEntalpia(tDryBulb, valore.HumRatio);
            valore.MoistAirVolume = GetMoistAirVolume(tDryBulb, valore.HumRatio, pressione);
            valore.Grado di saturazione = Ottieni Grado di saturazione (tBulb secco, valore.HumRatio, pressione);

            ritorno valore;
        }
    }

    /// <riepilogo>
    /// Contiene i risultati di output di un calcolo psicrometrico.
    /// </summary>
    pubblico classe Valore psicrometrico
    {
        /// <riepilogo>
        /// Temperatura a bulbo secco in °F [IP] o °C [SI]
        /// </summary>
        pubblico doppio TDryBulb { ottenere; set; }

        /// <riepilogo>
        /// Temperatura del bulbo umido in °F [IP] o °C [SI]
        /// </summary>
        pubblico doppio TWetBulb { ottenere; set; }

        /// <riepilogo>
        /// Pressione atmosferica in Psi [IP] o Pa [SI]
        /// </summary>
        pubblico doppio Pressione { ottenere; set; }

        /// <riepilogo>
        /// Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
        /// </summary>
        pubblico doppio HumRatio { ottenere; set; }

        /// <riepilogo>
        /// Temperatura del punto di rugiada in °F [IP] o °C [SI]
        /// </summary>
        pubblico doppio TDewPoint { ottenere; set; }

        /// <riepilogo>
        /// Umidità relativa [0-1]
        /// </summary>
        pubblico doppio RelHum { ottenere; set; }

        /// <riepilogo>
        /// Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
        /// </summary>
        pubblico doppio VapPres { ottenere; set; }

        /// <riepilogo>
        /// Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
        /// </summary>
        pubblico doppio Entalpia dell'aria umida { ottenere; set; }

        /// <riepilogo>
        /// Volume specifico ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
        /// </summary>
        pubblico doppio Volume Aria Umida { ottenere; set; }

        /// <riepilogo>
        /// Grado di saturazione [senza unità]
        /// </summary>
        pubblico doppio Grado Di Saturazione { ottenere; set; }
    }

    /// <riepilogo>
    /// Sistemi di unità standard
    /// </summary>
    pubblico enum UnitSystem
    {
        /// <riepilogo>
        /// Unità imperiali
        /// </summary>
        IP = 1,

        /// <riepilogo>
        /// Unità del sistema metrico
        /// </summary>
        SI = 2
    }
}

Fortran

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
! PsychroLib (versione 2.3.0) (https://github.com/psychrometrics/psychrolib)
! Copyright (c) 2018 D. Thevenard e D. Meyer per l'attuale implementazione della libreria
! Copyright (c) Manuale ASHRAE 2017 — Fondamenti per equazioni e coefficienti ASHRAE
! Concesso in licenza con la licenza MIT.

modulo  psicolibero
  !+ Panoramica del modulo
  !+ Contiene funzioni per il calcolo delle proprietà termodinamiche delle miscele gas-vapore
  !+ e atmosfera standard adatta alla maggior parte delle applicazioni ingegneristiche, fisiche e meteorologiche
  !+ applicazioni.
  !+
  !+ La maggior parte delle funzioni sono un'implementazione delle formule trovate nel file
  !+ 2017 Manuale ASHRAE - Fondamenti, in entrambi i sistemi internazionali (SI),
  !+ e unità imperiali (IP). Si prega di fare riferimento alle informazioni incluse nel
  !+ ciascuna funzione per il rispettivo riferimento.
  !+
  !+ Esempio
  !+ usa psychrolib, solo: GetTDewPointFromRelHum, SetUnitSystem, SI
  !+ ! Imposta il sistema di unità, ad esempio su SI (può essere 'SI' o 'IP')
  !+ chiama SetUnitSystem(SI)
  !+ ! Calcolare la temperatura del punto di rugiada per una temperatura a bulbo secco di 25 C e un'umidità relativa dell'80%
  !+ print *, GetTDewPointFromRelHum(25.0, 0.80)
  !+ 21.3094
  !+
  !+ Diritto d'autore
  !+ - Per l'implementazione corrente della libreria
  !+ Copyright (c) 2018 D. Thevenard e D. Meyer.
  !+ - Per equazioni e coefficienti pubblicati ASHRAE Handbook — Fundamentals, capitolo 1
  !+ Copyright (c) Manuale ASHRAE 2017 – Fondamenti (https://www.ashrae.org)
  !+
  !+ Licenza
  !+ MIT (https://github.com/psychromometrics/psychrolib/LICENSE.txt)
  !+
  !+ Nota degli autori
  !+ Abbiamo fatto ogni sforzo per garantire che il codice sia adeguato, tuttavia, facciamo no
  !+ rappresentazione rispetto alla sua accuratezza. Utilizzare a proprio rischio. Dovresti notarlo
  !+ un errore o se hai un suggerimento, avvisacelo tramite GitHub all'indirizzo
  !+ https://github.com/psychromometrics/psychrolib/issues.


  implicito nessuno

    privato
    pubblico :: IP
  pubblico :: SI
  pubblico :: Impostasistemaunità
  pubblico :: GetUnitSystem
  pubblico :: isIP
  pubblico :: OttieniTRankineFromTFahrenheit
  pubblico :: Ottieni TFahrenheit da TRankine
  pubblico :: OttieniTKelvinDaTCelsius
  pubblico :: OttieniTCelsiusDaTKelvin
  pubblico :: OttieniTWetBulbFromTDewPoint
  pubblico :: GetTWetBulbFromRelHum
  pubblico :: OttieniRelHumFromTDewPoint
  pubblico :: GetRelHumFromTWetBulb
  pubblico :: OttieniTDewPointFromRelHum
  pubblico :: OttieniTDewPointFromTWetBulb
  pubblico :: GetVapPresFromRelHum
  pubblico :: GetRelHumFromVapPres
  pubblico :: OttieniTDewPointFromVapPres
  pubblico :: OttieniVapPresFromTDewPoint
  pubblico :: Rapporto GetTWetBulbFromHum
  pubblico :: OttieniHumRatioFromTWetBulb
  pubblico :: OttieniHumRatioFromRelHum
  pubblico :: Ottieni rapporto RelHumFromHum
  pubblico :: OttieniHumRatioFromTDewPoint
  pubblico :: OttieniTDewPointFromHumRatio
  pubblico :: OttieniHumRatioFromVapPres
  pubblico :: OttieniVapPresFromHumRatio
  pubblico :: OttieniEntalpiaAriaSecca
  pubblico :: OttieniDryAirDensity
  pubblico :: OttieniDryAirVolume
  pubblico :: OttieniTDryBulbFromEnthalpyAndHumRatio
  pubblico :: Ottieni rapporto hum dall'entalpia e dal bulbo secco
  pubblico :: OttieniSatVapPres
  pubblico :: Ottieni rapporto SatHum
  pubblico :: OttieniSatAirEntalpia
  pubblico :: OttieniVaporPressureDeficit
  pubblico :: Ottieni Grado di Saturazione
  pubblico :: OttieniEntalpiaAriaMostra
  pubblico :: OttieniMoistAirVolume
  pubblico :: OttieniTDryBulbFromMoistAirVolumeAndHumRatio
  pubblico :: GetMoistAirDensity
  pubblico :: OttieniPressioneAtmStandard
  pubblico :: OttieniTemperaturaAtmStandard
  pubblico :: Ottieni la pressione del livello del mare
  pubblico :: Ottieni pressione stazione
  pubblico :: Ottieni rapporto HumFromHum specifico
  pubblico :: Ottieni rapporto humum da hum specifico
  pubblico :: CalcPsychrometricsFromTWetBulb
  pubblico :: CalcPsychrometricsFromTDewPoint
  pubblico :: CalcPsychrometricsFromRelHum
  pubblico :: dLnPws_


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Costanti globali
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  vero, parametro ::  ZERO_FAHRENHEIT_AS_RANKINE = 459.67
    !+ Zero gradi Fahrenheit (°F) espressi come gradi Rankine (°R).
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 39.

  vero, parametro ::  ZERO_CELSIUS_AS_KELVIN = 273.15
    !+ Zero gradi Celsius (°C) espressi in Kelvin (K).
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 39.

  vero, parametro ::  R_DA_IP = 53.350
    !+ Costante del gas universale per aria secca (versione IP) in ft lb_Force lb_DryAir⁻¹ R⁻¹.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1.

  vero, parametro ::  R_DA_SI = 287.042
    !+ Costante universale dei gas per aria secca (versione SI) in J kg_DryAir⁻¹ K⁻¹.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1.

  numero intero, parametro :: IP = 1
  numero intero, parametro :: SI = 2

  numero intero  :: PSYCHROLIB_UNITÀ = 0 ! 0 = indefinito.
    !+ Sistema di unità da utilizzare.

  vero ::  PSYCROLIB_TOLERANZA = 1.0
    !+ Tolleranza dei calcoli della temperatura.

  numero intero, parametro  :: MAX_ITER_COUNT = 100
    !+ Numero massimo di iterazioni prima di uscire dai cicli while.

  vero, parametro  :: MIN_HUM_RATIO = 1e-7
    !+ Rapporto di umidità minimo accettabile utilizzato/restituito da qualsiasi funzione.
    !+ Qualsiasi valore superiore a 0 o inferiore a MIN_HUM_RATIO verrà reimpostato su questo valore.

  vero, parametro  :: FREEZING_POINT_WATER_IP = 32.0
    !+ float: punto di congelamento dell'acqua in Fahrenheit.

  vero, parametro  :: FREEZING_POINT_WATER_SI = 0.0
    !+ float: punto di congelamento dell'acqua in gradi Celsius.

  vero, parametro  :: TRIPLO_POINT_ACQUA_IP = 32.018
    !+ galleggiante: Punto triplo dell'acqua in Fahrenheit.

  vero, parametro  :: TRIPLO_POINT_ACQUA_SI = 0.01
    !+ float: Punto triplo dell'acqua in gradi Celsius.


  contiene


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Funzioni di aiuto
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  sottoprogramma Impostasistemaunità(UnitSystem)
  !+ Imposta il sistema di unità da utilizzare (SI o IP).
  !+ Note: questa funzione *DEVE ESSERE CHIAMATA* prima di poter utilizzare la libreria

    numero intero, intento(in)    :: UnitSystem
    !+ Unità: stringa indicante il sistema di unità scelto (SI o IP)

    se (.non. (UnitSystem == SI .o. UnitSystem == IP)) poi
      errore Stop "Il sistema di unità deve essere SI o IP."
    finisci se

    PSYCHROLIB_UNITÀ = UnitSystem

    ! Definire la tolleranza sui calcoli della temperatura
    ! La tolleranza è la stessa in IP e SI
    se (UnitSystem == IP) poi
      PSYCROLIB_TOLERANZA = 0.001 * 9.0 / 5.0
    altro
      PSYCROLIB_TOLERANZA = 0.001
    finisci se
  fine della subroutine Impostasistemaunità

  funzione  GetUnitSystem() risultato(UnitSystem)
    !+ Restituisce il sistema di unità in uso.
    numero intero :: UnitSystem
    UnitSystem = PSYCHROLIB_UNITÀ
  funzione finale GetUnitSystem

  funzione  isIP()
    !+ Verificare se il sistema in uso è IP o SI
    logico :: isIP
    se (PSYCHROLIB_UNITÀ == IP) poi
      isIP = .vero.
    altrimenti se (PSYCHROLIB_UNITÀ == SI) poi
      isIP = .falso.
    altro
      errore Stop "Il sistema di unità non è stato definito."
    finisci se
  funzione finale isIP


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Conversione tra unità di temperatura
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  funzione  OttieniTRankineFromTFahrenheit(TFahrenheit) risultato(TRankin)
    !+ Funzione di utilità per convertire la temperatura in gradi Rankine (°R)
    !+ temperatura indicata in gradi Fahrenheit (°F).
    !+ Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3

    vero, intento(in)  :: TFahrenheit
      !+ Temperatura in gradi Fahrenheit
    vero              :: TRankin
      !+ Temperatura in gradi Rankine

    TRankin = TFahrenheit + ZERO_FAHRENHEIT_AS_RANKINE
  funzione finale OttieniTRankineFromTFahrenheit

  funzione  Ottieni TFahrenheit da TRankine(TRankin) risultato(TFahrenheit)
    !+ Funzione di utilità per convertire la temperatura in gradi Fahrenheit (°F)
    !+ temperatura data in gradi Rankine (°R).
    !+ Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3

    vero, intento(in)  :: TRankin
      !+ Temperatura in gradi Rankine
    vero              :: TFahrenheit
      !+ Temperatura in gradi Fahrenheit

    TFahrenheit = TRankin - ZERO_FAHRENHEIT_AS_RANKINE
  funzione finale Ottieni TFahrenheit da TRankine

  funzione  OttieniTKelvinDaTCelsius(TCelsius) risultato(TKelvin)
    !+ Funzione di utilità per convertire la temperatura in Kelvin (K)
    !+ temperatura indicata in gradi Celsius (°C).
    !+ Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3

    vero, intento(in)  :: TCelsius
      !+ Temperatura in gradi Celsius
    vero              :: TKelvin
      !+ Tempearatyre in Kelvin

    TKelvin = TCelsius + ZERO_CELSIUS_AS_KELVIN
  funzione finale OttieniTKelvinDaTCelsius

  funzione  OttieniTCelsiusDaTKelvin(TKelvin) risultato(TCelsius)
    !+ Funzione di utilità per convertire la temperatura in gradi Celsius (°C)
    !+ data la temperatura in Kelvin (K).
    !+ Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3

    vero, intento(in)  :: TKelvin
      !+ Tempearatyre in Kelvin
    vero              :: TCelsius
      !+ Temperatura in gradi Celsius

    TCelsius = TKelvin - ZERO_CELSIUS_AS_KELVIN
  funzione finale OttieniTCelsiusDaTKelvin


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Conversioni tra punto di rugiada, bulbo umido e umidità relativa
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  funzione  OttieniTWetBulbFromTDewPoint(TDryBulb, TDewPoint, Pressione) risultato(TWetBulb)
    !+ Temperatura di ritorno del bulbo umido data la temperatura del bulbo secco, la temperatura del punto di rugiada e la pressione.
    !+ Riferimenti:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1

    vero, intento(in)  :: TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  :: TDewPoint
      !+ Temperatura del punto di rugiada in °F [IP] o °C [SI]
    vero, intento(in)  :: Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              :: TWetBulb
      !+ Temperatura del bulbo umido in °F [IP] o °C [SI]
    vero              :: HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]

    se (TDewPoint > TDryBulb) poi
      errore Stop "Errore: la temperatura del punto di rugiada è superiore alla temperatura del bulbo secco"
    finisci se

    HumRatio = OttieniHumRatioFromTDewPoint(TDewPoint, Pressione)
    TWetBulb = Rapporto GetTWetBulbFromHum(TDryBulb, HumRatio, Pressione)
  funzione finale OttieniTWetBulbFromTDewPoint

  funzione  GetTWetBulbFromRelHum(TDryBulb, RelHum, Pressione) risultato(TWetBulb)
    !+ Ritorna la temperatura a bulbo umido data la temperatura a bulbo secco, l'umidità relativa e la pressione.
    !+ Riferimenti:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  RelHum
      !+ Umidità relativa nell'intervallo [0, 1]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  TWetBulb
      !+ Temperatura del bulbo umido in °F [IP] o °C [SI]
    vero              ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]

    se (RelHum < 0.0 .o. RelHum > 1.0) poi
      errore Stop "Errore: l'umidità relativa è fuori dall'intervallo [0,1]"
    finisci se

    HumRatio = OttieniHumRatioFromRelHum(TDryBulb, RelHum, Pressione)
    TWetBulb = Rapporto GetTWetBulbFromHum(TDryBulb, HumRatio, Pressione)
  funzione finale GetTWetBulbFromRelHum

  funzione  OttieniRelHumFromTDewPoint(TDryBulb, TDewPoint) risultato(RelHum)
    !+ Umidità relativa restituita data la temperatura di bulbo secco e la temperatura del punto di rugiada.
    !+ Riferimenti:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 22

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  TDewPoint
      !+ Temperatura del punto di rugiada in °F [IP] o °C [SI]
    vero              ::  RelHum
      !+ Umidità relativa nell'intervallo [0, 1]
    vero              ::  VapPres
      !+ Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
    vero              ::  SatVapPres
      !+ Pressione di vapore dell'aria satura in Psi [IP] o Pa [SI]

    se (TDewPoint > TDryBulb) poi
      errore Stop "Errore: la temperatura del punto di rugiada è superiore alla temperatura del bulbo secco"
    finisci se

    VapPres     = OttieniSatVapPres(TDewPoint)
    SatVapPres  = OttieniSatVapPres(TDryBulb)
    RelHum      = VapPres / SatVapPres
  funzione finale OttieniRelHumFromTDewPoint

  funzione  GetRelHumFromTWetBulb(TDryBulb, TWetBulb, Pressione) risultato(RelHum)
    !+ Umidità relativa restituita data la temperatura a bulbo secco, la temperatura a bulbo umido e la pressione.
    !+ Riferimenti:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  TWetBulb
      !+ Temperatura del bulbo umido in °F [IP] o °C [SI]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  RelHum
      !+ Umidità relativa nell'intervallo [0, 1]
    vero              ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]

    se (TWetBulb > TDryBulb) poi
      errore Stop "Errore: la temperatura del bulbo umido è superiore alla temperatura del bulbo secco"
    finisci se

    HumRatio = OttieniHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pressione)
    RelHum   = Ottieni rapporto RelHumFromHum(TDryBulb, HumRatio, Pressione)
  funzione finale GetRelHumFromTWetBulb

  funzione  OttieniTDewPointFromRelHum(TDryBulb, RelHum) risultato(TDewPoint)
    !+ Temperatura del punto di rugiada di ritorno data la temperatura a bulbo secco e l'umidità relativa.
    !+ Riferimenti:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  RelHum
      !+ Umidità relativa nell'intervallo [0, 1]
    vero              ::  TDewPoint
      !+ Temperatura del punto di rugiada in °F [IP] o °C [SI]
    vero              ::  VapPres
      !+ Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]

    se (RelHum < 0.0 .o. RelHum > 1.0) poi
      errore Stop "Errore: l'umidità relativa è fuori dall'intervallo [0,1]"
    finisci se

    VapPres   = GetVapPresFromRelHum(TDryBulb, RelHum)
    TDewPoint = OttieniTDewPointFromVapPres(TDryBulb, VapPres)
  funzione finale OttieniTDewPointFromRelHum

  funzione  OttieniTDewPointFromTWetBulb(TDryBulb, TWetBulb, Pressione) risultato(TDewPoint)
    !+ Temperatura del punto di rugiada di ritorno data la temperatura di bulbo secco, la temperatura di bulbo umido e la pressione.
    !+ Riferimenti:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  TWetBulb
      !+ Temperatura del bulbo umido in °F [IP] o °C [SI]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  TDewPoint
      !+ Temperatura del punto di rugiada in °F [IP] o °C [SI]
    vero              ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]

    se (TWetBulb > TDryBulb) poi
      errore Stop "Errore: la temperatura del bulbo umido è superiore alla temperatura del bulbo secco"
    finisci se

    HumRatio  = OttieniHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pressione)
    TDewPoint = OttieniTDewPointFromHumRatio(TDryBulb, HumRatio, Pressione)
  funzione finale OttieniTDewPointFromTWetBulb


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Conversioni tra punto di rugiada o umidità relativa e pressione di vapore
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  funzione  GetVapPresFromRelHum(TDryBulb, RelHum) risultato(VapPres)
    !+ Restituisce la pressione parziale del vapore acqueo in funzione dell'umidità relativa e della temperatura.
    !+ Riferimenti:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 12, 22

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  RelHum
      !+ Umidità relativa nell'intervallo [0, 1]
    vero              ::  VapPres
      !+ Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]

    se (RelHum < 0.0 .o. RelHum > 1.0) poi
      errore Stop "Errore: l'umidità relativa è fuori dall'intervallo [0,1]"
    finisci se

    VapPres = RelHum * OttieniSatVapPres(TDryBulb)
  funzione finale GetVapPresFromRelHum

  funzione  GetRelHumFromVapPres(TDryBulb, VapPres) risultato(RelHum)
    !+ Umidità relativa restituita data la temperatura a bulbo secco e la pressione del vapore.
    !+ Riferimenti:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 12, 22

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  VapPres
      !+ Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
    vero              ::  RelHum
      !+ Umidità relativa nell'intervallo [0, 1]

    se (VapPres < 0.0) poi
      errore Stop "Errore: la pressione parziale del vapore acqueo nell'aria umida non può essere negativa"
    finisci se

    RelHum = VapPres / OttieniSatVapPres(TDryBulb)
  funzione finale GetRelHumFromVapPres

  funzione  dLnPws_(TDryBulb) risultato(dLnPws)
    !+ Funzione di supporto che restituisce la derivata del logaritmo naturale della pressione del vapore di saturazione
    !+ in funzione della temperatura a bulbo secco.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 5

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero              ::  dLnPws
      !+ Derivata del logaritmo naturale della tensione di vapore dell'aria satura in Psi [IP] o Pa [SI]
    vero              ::  T
      !+ Temperatura a bulbo secco in R [IP] o K [SI]

    se (isIP()) poi

      T = OttieniTRankineFromTFahrenheit(TDryBulb)

      se (TDryBulb <= TRIPLO_POINT_ACQUA_IP) poi
        dLnPws = 1.0214165E+04 / T**2 - 5.3765794E-03 + 2 * 1.9202377E-07 * T &
                 + 3 * 3.5575832E-10 * T**2 - 4 * 9.0344688E-14 * T**3 + 4.1635019 / T
      altro
        dLnPws = 1.0440397E+04 / T**2 - 2.7022355E-02 + 2 * 1.2890360E-05 * T &
                 - 3 * 2.4780681E-09 * T**2 + 6.5459673 / T
      finisci se

        altro

      T = OttieniTKelvinDaTCelsius(TDryBulb)

      se (TDryBulb <= TRIPLO_POINT_ACQUA_SI) poi
        dLnPws = 5.6745359E+03 / T**2 - 9.677843E-03 + 2 * 6.2215701E-07 * T &
                 + 3 * 2.0747825E-09 * T**2 - 4 * 9.484024E-13 * T**3 + 4.1635019 / T
      altro
        dLnPws = 5.8002206E+03 / T**2 - 4.8640239E-02 + 2 * 4.1764768E-05 * T &
                 - 3 * 1.4452093E-08 * T**2 + 6.5459673 / T
      finisci se
        finisci se
  funzione finale dLnPws_

  funzione  OttieniTDewPointFromVapPres(TDryBulb, VapPres) risultato(TDewPoint)
    !+ Temperatura del punto di rugiada di ritorno data la temperatura a bulbo secco e la pressione del vapore.
    !+ Riferimenti:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 5 e 6
    !+ Note:
    !+ La temperatura del punto di rugiada viene risolta invertendo l'equazione fornendo la pressione del vapore acqueo
    !+ alla saturazione dalla temperatura anziché utilizzare le regressioni fornite
    !+ di ASHRAE (eqn. 37 e 38) che sono molto meno accurati e hanno un
    !+ intervallo di validità più ristretto.
    !+ Il metodo Newton-Raphson (NR) viene utilizzato sul logaritmo del vapore acqueo
    !+ pressione in funzione della temperatura, che è una funzione molto fluida
    !+ La convergenza viene solitamente raggiunta in 3-5 iterazioni.
    !+ TDryBulb non è realmente necessario in questo caso, viene utilizzato solo per comodità.

    vero, intento(in)    ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)    ::  VapPres
      !+ Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
    vero                ::  TDewPoint
      !+ Temperatura del punto di rugiada in °F [IP] o °C [SI]
    vero                ::  lnVP
      !+ Logaritmo naturale della pressione parziale della pressione del vapore acqueo nell'aria umida
    vero                ::  d_lnVP
      !+ Derivato della funzione, calcolato numericamente
    vero                ::  lnVP_iter
      !+ Valore del logaritmo della pressione del vapore acqueo utilizzato nel calcolo NR
    vero                ::  TDewPoint_iter
      !+ Valore di TDewPoint utilizzato nel calcolo NR
    vero, dimensione(2)  ::  CONFINI
      !+ Intervallo di temperatura valido in °F [IP] o °C [SI]
    numero intero             :: indice
      !+ Indice utilizzato nel calcolo

    ! Limiti e ampiezza del passo in funzione del sistema di unità
    se (isIP()) poi
        CONFINI(1) = -148.0
        CONFINI(2) =  392.0
    altro
        CONFINI(1) = -100.0
        CONFINI(2) =  200.0
    finisci se

    ! Controllo di validità: limiti oltre i quali non è possibile trovare una soluzione
    se (VapPres < OttieniSatVapPres(CONFINI(1)) .o. VapPres > OttieniSatVapPres(CONFINI(2))) poi
      errore Stop "Errore: la pressione parziale del vapore acqueo non rientra nell'intervallo di validità delle equazioni"
    finisci se

    ! Usiamo NR per approssimare la soluzione.
    TDewPoint = TDryBulb
    lnVP = ceppo(VapPres)
    indice = 1

    fare mentre (.vero.)
      TDewPoint_iter = TDewPoint ! TDewPoint_iter utilizzato nel calcolo NR
      lnVP_iter = ceppo(OttieniSatVapPres(TDewPoint_iter))

      ! Derivata della funzione, calcolata analiticamente
      d_lnVP = dLnPws_(TDewPoint_iter)

      ! Nuova stima, delimitata dal dominio di ricerca sopra definito
      TDewPoint = TDewPoint_iter - (lnVP_iter - lnVP) / d_lnVP
      TDewPoint = max(TDewPoint, CONFINI(1))
      TDewPoint = min(TDewPoint, CONFINI(2))

      se (addominali(TDewPoint - TDewPoint_iter) <= PSYCROLIB_TOLERANZA) poi
        Uscita
      finisci se

            Se (indice > MAX_ITER_COUNT) poi
        errore Stop "Convergenza non raggiunta in GetTDewPointFromVapPres. Arresto."
      finisci se

      indice = indice + 1
    finisci

  TDewPoint = min(TDewPoint, TDryBulb)
  funzione finale OttieniTDewPointFromVapPres

  funzione  OttieniVapPresFromTDewPoint(TDewPoint) risultato(VapPres)
    !+ Pressione del vapore di ritorno data la temperatura del punto di rugiada.
    !+ Riferimenti:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 36

    vero, intento(in)  ::  TDewPoint
      !+ Temperatura del punto di rugiada in °F [IP] o °C [SI]
    vero              ::  VapPres
      !+ Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]

    VapPres = OttieniSatVapPres(TDewPoint)
  funzione finale OttieniVapPresFromTDewPoint


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Conversioni dalla temperatura del bulbo umido, dalla temperatura del punto di rugiada o dal rapporto umidità relativa/umidità
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  funzione  Rapporto GetTWetBulbFromHum(TDryBulb, HumRatio, Pressione) risultato(TWetBulb)
    !+ Temperatura di ritorno del bulbo umido data la temperatura del bulbo secco, il rapporto di umidità e la pressione.
    !+ Riferimenti:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 33 e 35 risolti per Tstar

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  TWetBulb
      !+ Temperatura del bulbo umido in °F [IP] o °C [SI]
    vero              ::  TDewPoint
      !+ TDewPoint: temperatura del punto di rugiada in °F [IP] o °C [SI]
    vero              ::  TWetBulbSup
      !+ Valore superiore della temperatura a bulbo umido nel metodo di bisezione (l'ipotesi iniziale deriva dalla temperatura a bulbo secco) in °F [IP] o °C [SI]
    vero              ::  TWetBulbInf
      !+ Valore più basso della temperatura del bulbo umido nel metodo di bisezione (l'ipotesi iniziale è dalla temperatura del punto di rugiada) in °F [IP] o °C [SI]
    vero              ::  Wstar
      !+ Rapporto di umidità alla temperatura Tstar in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero              ::  Rapporto Hum limitato
      !+ Rapporto di umidità limitato a MIN_HUM_RATIO
    numero intero           ::  indice
      !+ indice utilizzato nell'iterazione

    se (HumRatio < 0.0) poi
      errore Stop "Errore: il rapporto di umidità non può essere negativo"
    finisci se
    Rapporto Hum limitato = max(HumRatio, MIN_HUM_RATIO)

    TDewPoint = OttieniTDewPointFromHumRatio(TDryBulb, Rapporto Hum limitato, Pressione)

    ! Ipotesi iniziali
    TWetBulbSup = TDryBulb
    TWetBulbInf = TDewPoint
    TWetBulb = (TWetBulbInf + TWetBulbSup) / 2.0

    indice = 1
    ! Ciclo di bisezione
    fare mentre ((TWetBulbSup - TWetBulbInf) > PSYCROLIB_TOLERANZA)

    ! Calcolare il rapporto di umidità alla temperatura Tstar
    Wstar = OttieniHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pressione)

    ! Ottieni nuovi limiti
    se (Wstar > Rapporto Hum limitato) poi
      TWetBulbSup = TWetBulb
    altro
      TWetBulbInf = TWetBulb
    finisci se

    ! Nuova ipotesi sulla temperatura del bulbo umido
    TWetBulb = (TWetBulbSup + TWetBulbInf) / 2.0

      se (indice > MAX_ITER_COUNT) poi
        errore Stop "Convergenza non raggiunta in GetTWetBulbFromHumRatio. Arresto."
      finisci se

    indice = indice + 1
    finisci
  funzione finale Rapporto GetTWetBulbFromHum

  funzione  OttieniHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pressione) risultato(HumRatio)
    !+ Rapporto dell'umidità di ritorno data la temperatura di bulbo secco, la temperatura di bulbo umido e la pressione.
    !+ Riferimenti:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 33 e 35

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  TWetBulb
      !+ Temperatura del bulbo umido in °F [IP] o °C [SI]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero              ::  Wsstar
      !+ Rapporto di umidità alla temperatura Tstar in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]

    se (TWetBulb > TDryBulb) poi
      errore Stop "Errore: la temperatura del bulbo umido è superiore alla temperatura del bulbo secco"
    finisci se

    Wsstar = Ottieni rapporto SatHum(TWetBulb, Pressione)

    se (isIP()) poi
            Se (TWetBulb >= FREEZING_POINT_WATER_IP) poi
        HumRatio = ((1093.0 - 0.556 * TWetBulb) * Wsstar - 0.240 * (TDryBulb - TWetBulb))   &
                   / (1093.0 + 0.444 * TDryBulb - TWetBulb)
      altro
        HumRatio = ((1220.0 - 0.04 * TWetBulb) * Wsstar - 0.240 * (TDryBulb - TWetBulb))    &
                   / (1220.0 + 0.444 * TDryBulb - 0.48 * TWetBulb)
      finisci se
        altro
            Se (TWetBulb >= FREEZING_POINT_WATER_SI) poi
        HumRatio = ((2501.0 - 2.326 * TWetBulb) * Wsstar - 1.006 * (TDryBulb - TWetBulb))   &
                   / (2501.0 + 1.86 * TDryBulb - 4.186 * TWetBulb)
      altro
           HumRatio = ((2830.0 - 0.24 * TWetBulb) * Wsstar - 1.006 * (TDryBulb - TWetBulb)) &
                      / (2830.0 + 1.86 * TDryBulb - 2.1 * TWetBulb)
      finisci se
        finisci se

    ! Controllo di validità.
    HumRatio = max(HumRatio, MIN_HUM_RATIO)
  funzione finale OttieniHumRatioFromTWetBulb

  funzione  OttieniHumRatioFromRelHum(TDryBulb, RelHum, Pressione) risultato(HumRatio)
    !+ Rapporto dell'umidità di ritorno data la temperatura a bulbo secco, l'umidità relativa e la pressione.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  RelHum
      !+ Umidità relativa nell'intervallo [0, 1]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero              ::  VapPres
      !+ Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]

    se (RelHum < 0.0 .o. RelHum > 1.0) poi
      errore Stop "Errore: l'umidità relativa è fuori dall'intervallo [0,1]"
    finisci se

    VapPres   = GetVapPresFromRelHum(TDryBulb, RelHum)
    HumRatio  = OttieniHumRatioFromVapPres(VapPres, Pressione)
  funzione finale OttieniHumRatioFromRelHum

  funzione  Ottieni rapporto RelHumFromHum(TDryBulb, HumRatio, Pressione) risultato(RelHum)
  !+ Restituisce l'umidità relativa data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
  !+ Riferimento:
  !+ Manuale ASHRAE - Fondamenti (2017) cap. 1

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  RelHum
      !+ Umidità relativa nell'intervallo [0, 1]
    vero              ::  VapPres
      !+ Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]

    se (HumRatio < 0.0) poi
      errore Stop "Errore: il rapporto di umidità non può essere negativo"
    finisci se

    VapPres = OttieniVapPresFromHumRatio(HumRatio, Pressione)
    RelHum  = GetRelHumFromVapPres(TDryBulb, VapPres)
  funzione finale Ottieni rapporto RelHumFromHum

  funzione  OttieniHumRatioFromTDewPoint(TDewPoint, Pressione) risultato(HumRatio)
    !+ Rapporto dell'umidità di ritorno data la temperatura e la pressione del punto di rugiada.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1

    vero, intento(in)  ::  TDewPoint
      !+ Temperatura del punto di rugiada in °F [IP] o °C [SI]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero              ::  VapPres
      !+ Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]

    VapPres   = OttieniSatVapPres(TDewPoint)
    HumRatio  = OttieniHumRatioFromVapPres(VapPres, Pressione)
  funzione finale OttieniHumRatioFromTDewPoint

  funzione  OttieniTDewPointFromHumRatio(TDryBulb, HumRatio, Pressione) risultato(TDewPoint)
    !+ Temperatura del punto di rugiada di ritorno data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  TDewPoint
      !+ Temperatura del punto di rugiada in °F [IP] o °C [SI]
    vero              ::  VapPres
      !+ Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]

    se (HumRatio < 0.0) poi
      errore Stop "Errore: il rapporto di umidità non può essere negativo"
    finisci se

    VapPres   = OttieniVapPresFromHumRatio(HumRatio, Pressione)
    TDewPoint = OttieniTDewPointFromVapPres(TDryBulb, VapPres)
  funzione finale OttieniTDewPointFromHumRatio


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Conversioni tra rapporto di umidità e tensione di vapore
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  funzione  OttieniHumRatioFromVapPres(VapPres, Pressione) risultato(HumRatio)
    !+ Rapporto dell'umidità di ritorno data la pressione del vapore acqueo e la pressione atmosferica.
    !+ Riferimento:
    !+ Fondamenti ASHRAE (2005) cap. 6 eq. 22;
    !+ Fondamenti ASHRAE (2009) cap. 1 eq. 22.

    vero, intento(in)  ::  VapPres
      !+ Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]

    se (VapPres < 0.0) poi
      errore Stop "Errore: la pressione parziale del vapore acqueo nell'aria umida non può essere negativa"
    finisci se

    HumRatio = 0.621945 * VapPres / (Pressione-VapPres)

    ! Controllo di validità.
    HumRatio = max(HumRatio, MIN_HUM_RATIO)
  funzione finale OttieniHumRatioFromVapPres

  funzione  OttieniVapPresFromHumRatio(HumRatio, Pressione) risultato(VapPres)
    !+ Pressione del vapore di ritorno dati il ​​rapporto di umidità e la pressione.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 20 risolto per pw

    vero, intento(in)  ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  VapPres
      !+ Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
    vero              ::  Rapporto Hum limitato
      !+ Rapporto di umidità limitato a MIN_HUM_RATIO

    se (HumRatio < 0.0) poi
      errore Stop "Errore: il rapporto di umidità è negativo"
    finisci se
    Rapporto Hum limitato = max(HumRatio, MIN_HUM_RATIO)

    VapPres = Pressione * Rapporto Hum limitato / (0.621945 + Rapporto Hum limitato)
  funzione finale OttieniVapPresFromHumRatio


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Conversioni tra rapporto di umidità e umidità specifica
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  funzione  Ottieni rapporto HumFromHum specifico(HumRatio) risultato(SpecificHum)
    !+ Restituisce l'umidità specifica dal rapporto di umidità (noto anche come rapporto di miscelazione).
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 9b

    vero, intento(in) :: HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Dry_Air⁻¹ [IP] o kg_H₂O kg_Dry_Air⁻¹ [SI]
    vero             :: SpecificHum
      !+ Umidità specifica in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero              ::  Rapporto Hum limitato
      !+ Rapporto di umidità limitato a MIN_HUM_RATIO

    se (HumRatio < 0.0) poi
      errore Stop "Errore: il rapporto di umidità non può essere negativo"
    finisci se
    Rapporto Hum limitato = max(HumRatio, MIN_HUM_RATIO)

    SpecificHum = Rapporto Hum limitato / (1.0 + Rapporto Hum limitato)
  funzione finale Ottieni rapporto HumFromHum specifico

  funzione  Ottieni rapporto humum da hum specifico(SpecificHum) risultato(HumRatio)
    !+ Restituisce il rapporto di umidità (noto anche come rapporto di miscelazione) dall'umidità specifica.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 9b (risolto per il rapporto di umidità)

    vero, intento(in)  :: SpecificHum
      !+ Umidità specifica in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero              :: HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Dry_Air⁻¹ [IP] o kg_H₂O kg_Dry_Air⁻¹ [SI]

    se (SpecificHum < 0.0 .o. SpecificHum >= 1.0) poi
      errore Stop "Errore: l'umidità specifica è fuori dall'intervallo [0, 1["
    finisci se

    HumRatio = SpecificHum / (1.0 - SpecificHum)

    ! Controllo di validità.
    HumRatio = max(HumRatio, MIN_HUM_RATIO)
  funzione finale Ottieni rapporto humum da hum specifico


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Calcoli dell'aria secca
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  funzione  OttieniEntalpiaAriaSecca(TDryBulb) risultato(Entalpia dell'aria secca)
    !+ Restituisce l'entalpia dell'aria secca data la temperatura a bulbo secco.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 28

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero              ::  Entalpia dell'aria secca
      !+ Entalpia dell'aria secca in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]

    se (isIP()) poi
      Entalpia dell'aria secca = 0.240 * TDryBulb
    altro
      Entalpia dell'aria secca = 1006 * TDryBulb
    finisci se
  funzione finale OttieniEntalpiaAriaSecca

  funzione  OttieniDryAirDensity(TDryBulb, Pressione) risultato(Densità dell'aria secca)
    !+ Restituisce la densità dell'aria secca date la temperatura e la pressione del bulbo secco.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1
    !+ Note:
    !+ Eqn 14 per la perfetta relazione tra i gas per l'aria secca.
    !+ Eqn 1 per la costante universale dei gas.
    !+ Il fattore 144 in IP serve per la conversione di Psi = lb in⁻² in lb ft⁻².

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  Densità dell'aria secca
      !+ Densità dell'aria secca in lb ft⁻³ [IP] o kg m⁻³ [SI]

    se (isIP()) poi
      Densità dell'aria secca = (144 * Pressione) / R_DA_IP / OttieniTRankineFromTFahrenheit(TDryBulb)
    altro
      Densità dell'aria secca = Pressione / R_DA_SI / OttieniTKelvinDaTCelsius(TDryBulb)
    finisci se
  funzione finale OttieniDryAirDensity

  funzione  OttieniDryAirVolume(TDryBulb, Pressione) risultato(VolumeAriaSecca)
    !+ Volume di aria secca restituita in base alla temperatura e alla pressione del bulbo secco.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1
    !+ Note:
    !+ Eqn 14 per la perfetta relazione tra i gas per l'aria secca.
    !+ Eqn 1 per la costante universale dei gas.
    !+ Il fattore 144 in IP serve per la conversione di Psi = lb in⁻² in lb ft⁻².

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  VolumeAriaSecca
      !+ Volume di aria secca in ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]

    se (isIP()) poi
      VolumeAriaSecca = OttieniTRankineFromTFahrenheit(TDryBulb) * R_DA_IP / (144 * Pressione)
    altro
      VolumeAriaSecca = OttieniTKelvinDaTCelsius(TDryBulb) * R_DA_SI / Pressione
    finisci se
  funzione finale OttieniDryAirVolume

  funzione  OttieniTDryBulbFromEnthalpyAndHumRatio(Entalpia dell'aria umida, HumRatio) risultato(TDryBulb)
    !+ Restituisce la temperatura del bulbo secco dal rapporto entalpia e umidità.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 30
    !+ Note:
    !+ Basato sulla funzione `GetMoistAirEnthalpy`, riorganizzato per la temperatura.

    vero, intento(in)  ::  Entalpia dell'aria umida
      !+ Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹
    vero, intento(in)  ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero              ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero              ::  Rapporto Hum limitato
      !+ Rapporto di umidità limitato a MIN_HUM_RATIO

    se (HumRatio < 0.0) poi
      errore Stop "Errore: il rapporto di umidità è negativo"
    finisci se
    Rapporto Hum limitato = max(HumRatio, MIN_HUM_RATIO)

    se (isIP()) poi
      TDryBulb  = (Entalpia dell'aria umida - 1061.0 * Rapporto Hum limitato) / (0.240 + 0.444 * Rapporto Hum limitato)
    altro
      TDryBulb  = (Entalpia dell'aria umida / 1000.0 - 2501.0 * Rapporto Hum limitato) / (1.006 + 1.86 * Rapporto Hum limitato)
    finisci se
  funzione finale OttieniTDryBulbFromEnthalpyAndHumRatio

  funzione  Ottieni rapporto hum dall'entalpia e dal bulbo secco(Entalpia dell'aria umida, TDryBulb) risultato(HumRatio)
    !+ Rapporto dell'umidità di ritorno tra entalpia e temperatura a bulbo secco.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 30
    !+ Note:
    !+ Basato sulla funzione `GetMoistAirEnthalpy`, riorganizzato per il rapporto di umidità.

    vero, intento(in)  ::  Entalpia dell'aria umida
      !+ Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹
    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero              ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]

    se (isIP()) poi
      HumRatio  = (Entalpia dell'aria umida - 0.240 * TDryBulb) / (1061.0 + 0.444 * TDryBulb)
    altro
      HumRatio  = (Entalpia dell'aria umida / 1000.0 - 1.006 * TDryBulb) / (2501.0 + 1.86 * TDryBulb)
    finisci se

    ! Controllo di validità.
    HumRatio = max(HumRatio, MIN_HUM_RATIO)
  funzione finale Ottieni rapporto hum dall'entalpia e dal bulbo secco


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Calcoli dell'aria satura
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  funzione  OttieniSatVapPres(TDryBulb) risultato(SatVapPres)
    !+ Ritorna la pressione del vapore saturato data la temperatura a bulbo secco.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 5
    !+ Nota importante: le formule ASHRAE sono definite sopra e sotto il punto di congelamento ma hanno
    !+ una discontinuità al punto di congelamento. Questa è una piccola imprecisione da parte di ASHRAE: le formule
    !+ dovrebbe essere definito sopra e sotto il punto triplo dell'acqua (non il punto di contatto), nel qual caso 
    !+ la discontinuità svanisce. È essenziale utilizzare il punto triplo dell'acqua altrimenti funzionerà
    !+ GetTDewPointFromVapPres, che inverte la funzione presente, non converge correttamente
    !+ il punto di congelamento.

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero              ::  SatVapPres
      !+ Pressione di vapore dell'aria satura in Psi [IP] o Pa [SI]
    vero              ::  LnPws
      !+ Logaritmo della pressione di vapore dell'aria satura (adimensionale)
    vero              ::  T
      !+ Temperatura a bulbo secco in R [IP] o K [SI]

    se (isIP()) poi
            Se (TDryBulb < -148.0 .o. TDryBulb > 392.0) poi
        errore Stop "Errore: la temperatura del bulbo secco deve essere compresa nell'intervallo [-148, 392]°F"
      finisci se

      T = OttieniTRankineFromTFahrenheit(TDryBulb)

      se (TDryBulb <= TRIPLO_POINT_ACQUA_IP) poi
        LnPws = (-1.0214165E+04 / T - 4.8932428 - 5.3765794E-03 * T + 1.9202377E-07 * T**2    &
                + 3.5575832E-10 * T**3 - 9.0344688E-14 * T**4 + 4.1635019 * ceppo(T))
      altro
        LnPws = -1.0440397E+04 / T - 1.1294650E+01 - 2.7022355E-02* T + 1.2890360E-05 * T**2  &
                - 2.4780681E-09 * T**3 + 6.5459673 * ceppo(T)
      finisci se

            altro
                Se (TDryBulb < -100.0 .o. TDryBulb > 200.0) poi
          errore Stop "Errore: la temperatura del bulbo secco deve essere compresa nell'intervallo [-100, 200]°C"
        finisci se

        T = OttieniTKelvinDaTCelsius(TDryBulb)

        se (TDryBulb <= TRIPLO_POINT_ACQUA_SI) poi
          LnPws = -5.6745359E+03 / T + 6.3925247 - 9.677843E-03 * T + 6.2215701E-07 * T**2    &
                  + 2.0747825E-09 * T**3 - 9.484024E-13 * T**4 + 4.1635019 * ceppo(T)
        altro
          LnPws = -5.8002206E+03 / T + 1.3914993 - 4.8640239E-02 * T + 4.1764768E-05 * T**2   &
                  - 1.4452093E-08 * T**3 + 6.5459673 * ceppo(T)
        finisci se
      finisci se

    SatVapPres = esp(LnPws)
  funzione finale OttieniSatVapPres

  funzione  Ottieni rapporto SatHum(TDryBulb, Pressione) risultato(SatHumRatio)
    !+ Rapporto di umidità di ritorno dell'aria satura data la temperatura e la pressione a bulbo secco.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 36, risolto per W

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  SatHumRatio
      !+ Rapporto di umidità dell'aria satura in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero              ::  SatVaporPres
      !+ Pressione di vapore dell'aria satura in in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]

    SatVaporPres  = OttieniSatVapPres(TDryBulb)
    SatHumRatio   = 0.621945 * SatVaporPres / (Pressione-SatVaporPres)

    ! Controllo di validità.
    SatHumRatio = max(SatHumRatio, MIN_HUM_RATIO)
  funzione finale Ottieni rapporto SatHum

  funzione  OttieniSatAirEntalpia(TDryBulb, Pressione) risultato(EntalpiaSatAir)
    !+ Restituisce l'entalpia dell'aria satura data la temperatura e la pressione a bulbo secco.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  EntalpiaSatAir
      !+ Entalpia dell'aria satura in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]

    EntalpiaSatAir = OttieniEntalpiaAriaMostra(TDryBulb, Ottieni rapporto SatHum(TDryBulb, Pressione))
  funzione finale OttieniSatAirEntalpia


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Calcoli dell'aria umida
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  funzione  OttieniVaporPressureDeficit(TDryBulb, HumRatio, Pressione) risultato(Deficit di pressione del vapore)
    !+ Return Deficit di pressione del vapore data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
    !+ Riferimento:
    !+ Oke (1987) eq. 2.13a

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  Deficit di pressione del vapore
      !+ Deficit di pressione del vapore in Psi [IP] o Pa [SI]
    vero              ::  RelHum
      !+ Umidità relativa nell'intervallo [0, 1]

    se (HumRatio < 0.0) poi
      errore Stop "Errore: il rapporto di umidità è negativo"
    finisci se

    RelHum = Ottieni rapporto RelHumFromHum(TDryBulb, HumRatio, Pressione)
    Deficit di pressione del vapore = OttieniSatVapPres(TDryBulb) * (1.0 - RelHum)
  funzione finale OttieniVaporPressureDeficit

  funzione  Ottieni Grado di Saturazione(TDryBulb, HumRatio, Pressione) risultato(Grado Di Saturazione)
    !+ Restituisce il grado di saturazione (ovvero il rapporto di umidità dell'aria/rapporto di umidità dell'aria alla saturazione
    !+ alla stessa temperatura e pressione) data la temperatura a bulbo secco, il rapporto di umidità e la pressione atmosferica.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2009) cap. 1 eq 12
    !+ Note:
    !+ Questa definizione è assente nel Manuale del 2017. Utilizzando invece la versione 2009.

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  Grado Di Saturazione
      !+ Grado di saturazione in unità arbitrarie
    vero              ::  Rapporto Hum limitato
      !+ Rapporto di umidità limitato a MIN_HUM_RATIO

    se (HumRatio < 0.0) poi
      errore Stop "Errore: il rapporto di umidità è negativo"
    finisci se
    Rapporto Hum limitato = max(HumRatio, MIN_HUM_RATIO)

    Grado Di Saturazione = Rapporto Hum limitato / Ottieni rapporto SatHum(TDryBulb, Pressione)
  funzione finale Ottieni Grado di Saturazione

  funzione  OttieniEntalpiaAriaMostra(TDryBulb, HumRatio) risultato(Entalpia dell'aria umida)
    !+ Restituisce l'entalpia dell'aria umida data la temperatura a bulbo secco e il rapporto di umidità.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 30

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero              ::  Entalpia dell'aria umida
      !+ Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹
    vero              ::  Rapporto Hum limitato
      !+ Rapporto di umidità limitato a MIN_HUM_RATIO

    se (HumRatio < 0.0) poi
      errore Stop "Errore: il rapporto di umidità è negativo"
    finisci se
    Rapporto Hum limitato = max(HumRatio, MIN_HUM_RATIO)

    se (isIP()) poi
        Entalpia dell'aria umida = 0.240 * TDryBulb + Rapporto Hum limitato * (1061.0 + 0.444 * TDryBulb)
    altro
        Entalpia dell'aria umida = (1.006 * TDryBulb + Rapporto Hum limitato * (2501.0 + 1.86 * TDryBulb)) * 1000.0
    finisci se
  funzione finale OttieniEntalpiaAriaMostra

  funzione  OttieniMoistAirVolume(TDryBulb, HumRatio, Pressione) risultato(Volume Aria Umida)
    !+ Restituisce il volume specifico dell'aria umida in base alla temperatura a bulbo secco, al rapporto di umidità e alla pressione.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 26
    !+ Note:
    !+ In unità IP, R_DA_IP / 144 equivale a 0,370486 che è il coefficiente che appare nell'eqn 26
    !+ Il fattore 144 serve per la conversione di Psi = lb in⁻² in lb ft⁻².

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  Volume Aria Umida
      !+ Volume specifico di aria umida in ft³ lb⁻¹ di aria secca [IP] o in m³ kg⁻¹ di aria secca [SI]
    vero              ::  Rapporto Hum limitato
      !+ Rapporto di umidità limitato a MIN_HUM_RATIO

    se (HumRatio < 0.0) poi
      errore Stop "Errore: il rapporto di umidità è negativo"
    finisci se
    Rapporto Hum limitato = max(HumRatio, MIN_HUM_RATIO)

    se (isIP()) poi
        Volume Aria Umida = R_DA_IP * OttieniTRankineFromTFahrenheit(TDryBulb) * (1.0 + 1.607858 * Rapporto Hum limitato) / (144.0 * Pressione)
    altro
        Volume Aria Umida = R_DA_SI * OttieniTKelvinDaTCelsius(TDryBulb) * (1.0 + 1.607858 * Rapporto Hum limitato) / Pressione
    finisci se
  funzione finale OttieniMoistAirVolume

  funzione  OttieniTDryBulbFromMoistAirVolumeAndHumRatio(Volume Aria Umida, HumRatio, Pressione) risultato(TDryBulb)
    !+ Temperatura di ritorno a bulbo secco dato il volume specifico dell'aria umida, il rapporto di umidità e la pressione.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 26
    !+ Note:
    !+ In unità IP, R_DA_IP / 144 equivale a 0,370486 che è il coefficiente che appare nell'eqn 26
    !+ Il fattore 144 serve per la conversione di Psi = lb in⁻² in lb ft⁻².
    !+ Basato sulla funzione `GetMoistAirVolume`, riorganizzato per la temperatura a bulbo secco.

    vero, intento(in)  ::  Volume Aria Umida
      !+ Volume specifico di aria umida in ft³ lb⁻¹ di aria secca [IP] o in m³ kg⁻¹ di aria secca [SI]
    vero, intento(in)  ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero              ::  Rapporto Hum limitato
      !+ Rapporto di umidità limitato a MIN_HUM_RATIO

    se (HumRatio < 0.0) poi
      errore Stop "Errore: il rapporto di umidità è negativo"
    finisci se
    Rapporto Hum limitato = max(HumRatio, MIN_HUM_RATIO)

    se (isIP()) poi
      TDryBulb = Ottieni TFahrenheit da TRankine(Volume Aria Umida * (144 * Pressione) &
                                / (R_DA_IP * (1 + 1.607858 * Rapporto Hum limitato)))
    altro
      TDryBulb = OttieniTCelsiusDaTKelvin(Volume Aria Umida * Pressione &
                                / (R_DA_SI * (1 + 1.607858 * Rapporto Hum limitato)))
    finisci se
  funzione finale OttieniTDryBulbFromMoistAirVolumeAndHumRatio

  funzione  GetMoistAirDensity(TDryBulb, HumRatio, Pressione) risultato(Densità dell'aria umida)
    !+ Restituisce la densità dell'aria umida in base al rapporto di umidità, alla temperatura a bulbo secco e alla pressione.
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 11

    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)  ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero, intento(in)  ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero              ::  Densità dell'aria umida
      !+ Densità dell'aria umida in lb ft⁻³ [IP] o kg m⁻³ [SI]
    vero              ::  Rapporto Hum limitato
      !+ Rapporto di umidità limitato a MIN_HUM_RATIO

    se (HumRatio < 0.0) poi
      errore Stop "Errore: il rapporto di umidità è negativo"
    finisci se
    Rapporto Hum limitato = max(HumRatio, MIN_HUM_RATIO)

    Densità dell'aria umida = (1.0 + Rapporto Hum limitato) / OttieniMoistAirVolume(TDryBulb, Rapporto Hum limitato, Pressione)
  funzione finale GetMoistAirDensity


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Atmosfera standard
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  funzione  OttieniPressioneAtmStandard(Altitudine) risultato(PressioneAtmStandard)
    !+ Restituisce la pressione barometrica atmosferica standard, data l'elevazione (altitudine).
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 3

    vero, intento(in)  ::  Altitudine
      !+ Altitudine in piedi [IP] o m [SI]
    vero              ::  PressioneAtmStandard
      !+ Pressione barometrica atmosferica standard in Psi [IP] o Pa [SI]

    se (isIP()) poi
        PressioneAtmStandard = 14.696 * (1.0 - 6.8754e-06 * Altitudine)**5.2559
    altro
        PressioneAtmStandard = 101325 * (1 - 2.25577e-05 * Altitudine)**5.2559
    finisci se
  funzione finale OttieniPressioneAtmStandard

  funzione  OttieniTemperaturaAtmStandard(Altitudine) risultato(TemperaturaAtmStandard)
    !+ Restituisce la temperatura atmosferica standard, data l'elevazione (altitudine).
    !+ Riferimento:
    !+ Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 4

    vero, intento(in)  ::  Altitudine
      !+ Altitudine in piedi [IP] o m [SI]
    vero              ::  TemperaturaAtmStandard
      !+ Temperatura atmosfera standard a bulbo secco in °F [IP] o °C [SI]

    se (isIP()) poi
        TemperaturaAtmStandard = 59.0 - 0.00356620 * Altitudine
    altro
        TemperaturaAtmStandard = 15.0 - 0.0065 * Altitudine
    finisci se
  funzione finale OttieniTemperaturaAtmStandard

  funzione  Ottieni la pressione del livello del mare(StnPressione, Altitudine, TDryBulb) risultato(Pressione al livello del mare)
    !+ Pressione di ritorno al livello del mare data la temperatura a bulbo secco, l'altitudine sul livello del mare e la pressione.
    !+ Riferimento:
    !+ Hess SL, Introduzione alla meteorologia teorica, Holt Rinehart e Winston, NY 1959,
    !+ cap. 6,5; Stull RB, Meteorologia per scienziati e ingegneri, 2a edizione,
    !+ Brooks/Cole 2000, cap. 1.
    !+ Note:
    !+ La procedura standard per gli Stati Uniti consiste nell'utilizzare la media per TDryBulb
    !+ della temperatura attuale della stazione e della temperatura della stazione di 12 ore fa.

    vero, intento(in)  ::  StnPressione
      !+ Pressione osservata nella stazione in Psi [IP] o Pa [SI]
    vero, intento(in)  ::  Altitudine
      !+ Altitudine in piedi [IP] o m [SI]
    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero              ::  Pressione al livello del mare
      !+ Pressione barometrica al livello del mare in Psi [IP] o Pa [SI]
    vero              ::  TColonna
      !+ Temperatura media in colonna d'aria in R [IP] o K [SI]
    vero              ::  H
      !+ altezza scala (adimensionale)

    se (isIP()) poi
      ! Calcolare la temperatura media nella colonna d'aria, assumendo un lapse rate
      ! di 3,6 °F/1000 piedi
      TColonna = TDryBulb + 0.0036 * Altitudine / 2.0

      ! Determinare l'altezza della scala
      H = 53.351 * OttieniTRankineFromTFahrenheit(TColonna)
    altro
      ! Calcolare la temperatura media nella colonna d'aria, assumendo un lapse rate
      ! di 6,5 °C/km
      TColonna = TDryBulb + 0.0065 * Altitudine / 2.0

      ! Determinare l'altezza della scala
      H = 287.055 * OttieniTKelvinDaTCelsius(TColonna) / 9.807
    finisci se

    ! Calcolare la pressione a livello del mare
    Pressione al livello del mare = StnPressione * esp(Altitudine / H)
  funzione finale Ottieni la pressione del livello del mare

  funzione  Ottieni pressione stazione(Pressione al livello del mare, Altitudine, TDryBulb) risultato(StazionePressione)
    !+ Ritorna la pressione della stazione dalla pressione a livello del mare.
    !+ Riferimento:
    !+ Vedi 'Ottieni pressione livello mare'
    !+ Note:
    !+ Questa funzione è esattamente l'inverso di 'GetSeaLevelPressure'.

    vero, intento(in)  ::  Pressione al livello del mare
      !+ Pressione barometrica al livello del mare in Psi [IP] o Pa [SI]
    vero, intento(in)  ::  Altitudine
      !+ Altitudine in piedi [IP] o m [SI]
    vero, intento(in)  ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero              ::  StazionePressione
      !+ Pressione della stazione in Psi [IP] o Pa [SI]

    StazionePressione = Pressione al livello del mare / Ottieni la pressione del livello del mare(1.0, Altitudine, TDryBulb)
  funzione finale Ottieni pressione stazione


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Funzioni per impostare tutti i valori psicrometrici
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  sottoprogramma CalcPsychrometricsFromTWetBulb(TDryBulb,           &
                                            TWetBulb,           &
                                            Pressione,           &
                                            HumRatio,           &
                                            TDewPoint,          &
                                            RelHum,             &
                                            VapPres,            &
                                            Entalpia dell'aria umida,   &
                                            Volume Aria Umida,     &
                                            Grado Di Saturazione)

    !+ Funzione di utilità per calcolare il rapporto di umidità, la temperatura del punto di rugiada, l'umidità relativa,
    !+ pressione del vapore, entalpia dell'aria umida, volume dell'aria umida e grado di saturazione dell'aria fornita
    !+ temperatura di bulbo secco, temperatura di bulbo umido e pressione.

    vero, intento(in)    ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)    ::  TWetBulb
      !+ Temperatura del bulbo umido in °F [IP] o °C [SI]
    vero, intento(in)    ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero, intento(fuori)   ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero, intento(fuori)   ::  TDewPoint
      !+ Temperatura del punto di rugiada in °F [IP] o °C [SI]
    vero, intento(fuori)   ::  RelHum
      !+ Umidità relativa nell'intervallo [0, 1]
    vero, intento(fuori)   ::  VapPres
      !+ Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
    vero, intento(fuori)   ::  Entalpia dell'aria umida
      !+ Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
    vero, intento(fuori)   ::  Volume Aria Umida
      !+ Volume specifico di aria umida in ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
    vero, intento(fuori)   ::  Grado Di Saturazione
      !+ Grado di saturazione [senza unità]

    HumRatio            = OttieniHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pressione)
    TDewPoint           = OttieniTDewPointFromHumRatio(TDryBulb, HumRatio, Pressione)
    RelHum              = Ottieni rapporto RelHumFromHum(TDryBulb, HumRatio, Pressione)
    VapPres             = OttieniVapPresFromHumRatio(HumRatio, Pressione)
    Entalpia dell'aria umida    = OttieniEntalpiaAriaMostra(TDryBulb, HumRatio)
    Volume Aria Umida      = OttieniMoistAirVolume(TDryBulb, HumRatio, Pressione)
    Grado Di Saturazione  = Ottieni Grado di Saturazione(TDryBulb, HumRatio, Pressione)
  fine della subroutine CalcPsychrometricsFromTWetBulb

  sottoprogramma CalcPsychrometricsFromTDewPoint(TDryBulb,           &
                                             TDewPoint,          &
                                             Pressione,           &
                                             HumRatio,           &
                                             TWetBulb,           &
                                             RelHum,             &
                                             VapPres,            &
                                             Entalpia dell'aria umida,   &
                                             Volume Aria Umida,     &
                                             Grado Di Saturazione)

    !+ Funzione di utilità per calcolare il rapporto di umidità, la temperatura a bulbo umido, l'umidità relativa,
    !+ pressione del vapore, entalpia dell'aria umida, volume dell'aria umida e grado di saturazione dell'aria fornita
    !+ temperatura di bulbo secco, temperatura del punto di rugiada e pressione.

    vero, intento(in)    ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)    ::  TDewPoint
      !+ Temperatura del punto di rugiada in °F [IP] o °C [SI]
    vero, intento(in)    ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero, intento(fuori)   ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero, intento(fuori)   ::  TWetBulb
      !+ Temperatura del bulbo umido in °F [IP] o °C [SI]
    vero, intento(fuori)   ::  RelHum
      !+ Umidità relativa nell'intervallo [0, 1]
    vero, intento(fuori)   ::  VapPres
      !+ Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
    vero, intento(fuori)   ::  Entalpia dell'aria umida
      !+ Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
    vero, intento(fuori)   ::  Volume Aria Umida
      !+ Volume specifico di aria umida in ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
    vero, intento(fuori)   ::  Grado Di Saturazione
      !+ Grado di saturazione [senza unità]

    HumRatio            = OttieniHumRatioFromTDewPoint(TDewPoint, Pressione)
    TWetBulb            = Rapporto GetTWetBulbFromHum(TDryBulb, HumRatio, Pressione)
    RelHum              = Ottieni rapporto RelHumFromHum(TDryBulb, HumRatio, Pressione)
    VapPres             = OttieniVapPresFromHumRatio(HumRatio, Pressione)
    Entalpia dell'aria umida    = OttieniEntalpiaAriaMostra(TDryBulb, HumRatio)
    Volume Aria Umida      = OttieniMoistAirVolume(TDryBulb, HumRatio, Pressione)
    Grado Di Saturazione  = Ottieni Grado di Saturazione(TDryBulb, HumRatio, Pressione)
  fine della subroutine CalcPsychrometricsFromTDewPoint

  sottoprogramma CalcPsychrometricsFromRelHum(TDryBulb,           &
                                          RelHum,             &
                                          Pressione,           &
                                          HumRatio,           &
                                          TWetBulb,           &
                                          TDewPoint,          &
                                          VapPres,            &
                                          Entalpia dell'aria umida,   &
                                          Volume Aria Umida,     &
                                          Grado Di Saturazione)

    !+ Funzione di utilità per calcolare il rapporto di umidità, la temperatura del bulbo umido, la temperatura del punto di rugiada,
    !+ pressione del vapore, entalpia dell'aria umida, volume dell'aria umida e grado di saturazione dell'aria fornita
    !+ temperatura a bulbo secco, umidità relativa e pressione.

    vero, intento(in)    ::  TDryBulb
      !+ Temperatura a bulbo secco in °F [IP] o °C [SI]
    vero, intento(in)    ::  RelHum
      !+ Umidità relativa nell'intervallo [0, 1]
    vero, intento(in)    ::  Pressione
      !+ Pressione atmosferica in Psi [IP] o Pa [SI]
    vero, intento(fuori)   ::  HumRatio
      !+ Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    vero, intento(fuori)   ::  TWetBulb
      !+ Temperatura del bulbo umido in °F [IP] o °C [SI]
    vero, intento(fuori)   ::  TDewPoint
      !+ Temperatura del punto di rugiada in °F [IP] o °C [SI]
    vero, intento(fuori)   ::  VapPres
      !+ Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
    vero, intento(fuori)   ::  Entalpia dell'aria umida
      !+ Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
    vero, intento(fuori)   ::  Volume Aria Umida
      !+ Volume specifico di aria umida in ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
    vero, intento(fuori)   ::  Grado Di Saturazione
      !+ Grado di saturazione [senza unità]

    HumRatio            = OttieniHumRatioFromRelHum(TDryBulb, RelHum, Pressione)
    TWetBulb            = Rapporto GetTWetBulbFromHum(TDryBulb, HumRatio, Pressione)
    TDewPoint           = OttieniTDewPointFromHumRatio(TDryBulb, HumRatio, Pressione)
    VapPres             = OttieniVapPresFromHumRatio(HumRatio, Pressione)
    Entalpia dell'aria umida    = OttieniEntalpiaAriaMostra(TDryBulb, HumRatio)
    Volume Aria Umida      = OttieniMoistAirVolume(TDryBulb, HumRatio, Pressione)
    Grado Di Saturazione  = Ottieni Grado di Saturazione(TDryBulb, HumRatio, Pressione)
  fine della subroutine CalcPsychrometricsFromRelHum


modulo finale psicolibero

Visual Basic, VBA

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
' PsychroLib (versione 2.3.0) (https://github.com/psychrometrics/psychrolib)
' Copyright (c) 2018 D. Thevenard e D. Meyer per l'attuale implementazione della libreria
' Copyright (c) Manuale ASHRAE 2017 - Fondamenti per equazioni e coefficienti ASHRAE
' Concesso in licenza con la licenza MIT.
'
' psychrolib.vba
'
' Contiene funzioni per il calcolo delle proprietà termodinamiche delle miscele gas-vapore
' e atmosfera standard adatta alla maggior parte delle applicazioni ingegneristiche, fisiche e meteorologiche
' applicazioni.
'
' La maggior parte delle funzioni sono un'implementazione delle formule trovate nel file
' Manuale ASHRAE 2017 - Fondamenti, in entrambi i sistemi internazionali (SI),
' e unità imperiali (IP). Si prega di fare riferimento alle informazioni incluse nel
' ciascuna funzione per il rispettivo riferimento.
'
' Esempio
' 'Imposta il sistema di unità, ad esempio su SI (può essere 'SI' o 'IP')
' ' decommentando la riga seguente nel modulo psychrolib
' Const PSYCHROLIB_UNITS = UnitSystem.SI
'
' ' Calcola la temperatura del punto di rugiada per una temperatura a bulbo secco di 25 C e un'umidità relativa dell'80%
' TDewPoint = OttieniTDewPointFromRelHum(25.0, 0.80)
' Debug.Print(TDewPoint)
'21.309397163661785
'
' Diritto d'autore
' - Per l'implementazione corrente della libreria
' Copyright (c) 2018 D. Thevenard e D. Meyer.
' - Per equazioni e coefficienti pubblicato ASHRAE Handbook — Fundamentals, capitolo 1
' Copyright (c) Manuale ASHRAE 2017 – Fondamenti (https://www.ashrae.org)
'
' Licenza
' MIT (https://github.com/psychromometrics/psychrolib/LICENSE.txt)
'
'Nota degli autori
'Abbiamo fatto ogni sforzo per garantire che il codice sia adeguato, tuttavia, facciamo no
' rappresentazione rispetto alla sua accuratezza. Utilizzare a proprio rischio. Dovresti notarlo
' un errore o se hai un suggerimento, avvisacelo tramite GitHub all'indirizzo
' https://github.com/psychromometrics/psychrolib/issues.
'

Opzione Esplicito


'**************************************************** ************************************************** ***
' IMPORTANTE: rimuovere manualmente il commento dal sistema di unità da utilizzare
'**************************************************** ************************************************** ***

'Enumerazione per definire sistemi di unità
Enum UnitSystem
  IP = 1
  SI = 2
Fine Enum

' Togli il commento da una di queste due righe per definire il sistema di unità ("IP" o "SI")
'Const PSYCHROLIB_UNITS = UnitSystem.IP
'Const PSYCHROLIB_UNITS = UnitSystem.SI


'**************************************************** ************************************************** ***
' Costanti globali
'**************************************************** ************************************************** ***

Privato Const ZERO_FAHRENHEIT_AS_RANKINE = 459.67   ' Zero gradi Fahrenheit (°F) espressi come gradi Rankine (°R).
                                                    "Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 39.

Privato Const ZERO_CELSIUS_AS_KELVIN = 273.15       ' Zero gradi Celsius (°C) espressi in Kelvin (K).
                                                    Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 39.

Privato Const R_DA_IP = 53.35                 ' Costante del gas universale per aria secca (versione IP) in ft lbf/lb_DryAir/R.

Privato Const R_DA_SI = 287.042               ' Costante universale del gas per aria secca (versione SI) in J/kg_AriaSecca/K.

Privato Const MAX_ITER_COUNT = 100            ' Numero massimo di iterazioni prima di uscire dai cicli while.

Privato Const MIN_HUM_RATIO = 1e-7            ' Rapporto minimo accettabile di umidità utilizzato/restituito da qualsiasi funzione.
                                              ' Qualsiasi valore superiore a 0 o inferiore a MIN_HUM_RATIO verrà reimpostato su questo valore.

Privato Const FREEZING_POINT_WATER_IP = 32.0  ' Punto di congelamento dell'acqua, in °F

Privato Const FREEZING_POINT_WATER_SI = 0.0   ' Punto di congelamento dell'acqua, in °C

Privato Const TRIPLO_POINT_ACQUA_IP = 32.018  ' Punto triplo dell'acqua, in °F

Privato Const TRIPLO_POINT_ACQUA_SI = 0.01    ' Punto triplo dell'acqua, in °C

'**************************************************** ************************************************** ***
'Funzioni di supporto
'**************************************************** ************************************************** ***

Funzione GetUnitSystem() Come UnitSystem
'
' Questa funzione restituisce il sistema di unità attualmente in uso (SI o IP).
'
' Argomenti:
' nessuno
'
' Ritorna:
' Il sistema di unità attualmente in uso ("SI" o "IP")
'
' Nota:
'
' Se ricevi un errore qui, è perché non hai decommentato una delle due righe
' definendo PSYCHROLIB_UNITS (vedere la sezione Costanti globali)
'
    GetUnitSystem = PSYCHROLIB_UNITÀ

Fine Funzione

Privato Funzione isIP() Come Variante
'
' Questa funzione controlla se il sistema di unità attualmente in uso è IP o SI.
'
' Argomenti:
' nessuno
'
' Ritorna:
' Vero se IP, Falso se SI e genera errore se non definito
'
  Se (PSYCHROLIB_UNITS = UnitSystem.IP) Poi
    isIP = Vero
  ElseIf (PSYCHROLIB_UNITS = UnitSystem.SI) Poi
    isIP = falso
  Altro
    MsgBox ("Il sistema di unità non è stato definito.")
    isIP = CVErr(xlErrNA)
  Fine Se

Fine Funzione

Privato Funzione GetTol() Come Variante
'
' Questa funzione restituisce la tolleranza sulle temperature utilizzate per la risoluzione iterativa.
' Il valore è fisicamente lo stesso in IP o SI.
'
' Argomenti:
' nessuno
'
' Ritorna:
' Tolleranza sulle temperature
'
  Se (PSYCHROLIB_UNITS = UnitSystem.IP) Poi
    GetTol = 0.001 * 9 / 5
  Altro
    GetTol = 0.001
  Fine Se
Fine Funzione

Privato Sub MyMsgBox(ByVal ErrMsg Come Corda)
'
'Emissione del messaggio di errore
' Sostituisci questa funzione con la tua se necessario, o commenta il suo codice se non vuoi vedere i messaggi
'
'Messaggio disabilitato per impostazione predefinita
'MsgBox (ErrMsg)

Fine Sub

Privato Funzione Min(ByVal Num1 Come Variante, ByVal Num2 Come Variante) Come Variante
'
' Funzione Min per restituire un minimo di due numeri
'
  Se (Num1 <= Numero2) Poi
    Min = Num1
  Altro
    Min = Num2
  Fine Se

Fine Funzione

Privato Funzione Max(ByVal Num1 Come Variante, ByVal Num2 Come Variante) Come Variante
'
' Funzione Max per restituire un massimo di due numeri
'
  Se (Num1 >= Numero2) Poi
    Max = Num1
  Altro
    Max = Num2
  Fine Se

Fine Funzione


'**************************************************** ****************************
' Conversioni tra unità di temperatura
'**************************************************** ****************************

Funzione OttieniTRankineFromTFahrenheit(ByVal T_Fahrenheit Come Variante) Come Variante
'
' Funzione di utilità per convertire la temperatura in gradi Rankine (°R)
' temperatura indicata in gradi Fahrenheit (°F).
'
'Argomenti:
' T_Fahrenheit: temperatura in gradi Fahrenheit (°F)
'
'Ritorna:
' Temperatura in gradi Rankine (°R)
'
'Riferimento:
Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
'
'Appunti:
'Conversione esatta.
'
  Su Errore Vai a ErrHandler

  OttieniTRankineFromTFahrenheit = (T_Fahrenheit + ZERO_FAHRENHEIT_AS_RANKINE)
  Uscita Funzione

ErrHandler:
  OttieniTRankineFromTFahrenheit = CVErr(xlErrNA)

Fine Funzione

Funzione Ottieni TFahrenheit da TRankine(ByVal T_Rankine Come Variante) Come Variante
'
' Funzione di utilità per convertire la temperatura in gradi Fahrenheit (°F)
' temperatura data in gradi Rankine (°R).
'
'Argomenti:
' TRankine: Temperatura in gradi Rankine (°R)
'
'Ritorna:
' Temperatura in gradi Fahrenheit (°F)
'
'Riferimento:
Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
'
'Appunti:
'Conversione esatta.
'
  Su Errore Vai a ErrHandler

  Ottieni TFahrenheit da TRankine = (T_Rankine - ZERO_FAHRENHEIT_AS_RANKINE)
  Uscita Funzione

ErrHandler:
  Ottieni TFahrenheit da TRankine = CVErr(xlErrNA)

Fine Funzione

Funzione OttieniTKelvinDaTCelsius(ByVal T_Celsius Come Variante) Come Variante
'
' Funzione di utilità per convertire la temperatura in Kelvin (K)
' temperatura indicata in gradi Celsius (°C).
'
'Argomenti:
' TCelsius: Temperatura in gradi Celsius (°C)
'
'Ritorna:
' Temperatura in Kelvin (K)
'
'Riferimento:
Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
'
'Appunti:
'Conversione esatta.
'
  Su Errore Vai a ErrHandler

  OttieniTKelvinDaTCelsius = (T_Celsius + ZERO_CELSIUS_AS_KELVIN)
  Uscita Funzione

ErrHandler:
  OttieniTKelvinDaTCelsius = CVErr(xlErrNA)

Fine Funzione

Funzione OttieniTCelsiusDaTKelvin(ByVal T_Kelvin Come Variante) Come Variante
'
' Funzione di utilità per convertire la temperatura in gradi Celsius (°C)
' data la temperatura in Kelvin (K).
'
'Argomenti:
' TKelvin: temperatura in Kelvin (K)
'
'Ritorna:
' Temperatura in gradi Celsius (°C)
'
'Riferimento:
Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
'
'Appunti:
'Conversione esatta.
'
  Su Errore Vai a ErrHandler

  OttieniTCelsiusDaTKelvin = (T_Kelvin - ZERO_CELSIUS_AS_KELVIN)
  Uscita Funzione

ErrHandler:
  OttieniTCelsiusDaTKelvin = CVErr(xlErrNA)

Fine Funzione


'**************************************************** ************************************************** ***
' Conversioni tra punto di rugiada, bulbo umido e umidità relativa
'**************************************************** ************************************************** ***

Funzione OttieniTWetBulbFromTDewPoint(ByVal TDryBulb Come Variante, ByVal TDewPoint Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Temperatura di ritorno del bulbo umido data la temperatura del bulbo secco, la temperatura del punto di rugiada e la pressione.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' TDewPoint: temperatura del punto di rugiada in °F [IP] o °C [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Temperatura del bulbo umido in °F [IP] o °C [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1
'
  fioco HumRatio Come Variante

  Su Errore Vai a ErrHandler

  Se TDewPoint > TDryBulb Poi
    MyMsgBox ("La temperatura del punto di rugiada è superiore alla temperatura del bulbo secco")
    Vai a ErrHandler
  Fine Se

  HumRatio = OttieniRapportoRum.DaPuntoDiTew(PuntoDiTew, Pressione)
  OttieniTWetBulbFromTDewPoint = OttieniTWetBulbFromHumRatio(TDryBulb, HumRatio, Pressione)
  Uscita Funzione

ErrHandler:
  OttieniTWetBulbFromTDewPoint = CVErr(xlErrNA)

Fine Funzione

Funzione GetTWetBulbFromRelHum(ByVal TDryBulb Come Variante, ByVal RelHum Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Restituisce la temperatura a bulbo umido data la temperatura a bulbo secco, l'umidità relativa e la pressione.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' RelHum: Umidità relativa nell'intervallo [0, 1]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Temperatura del bulbo umido in °F [IP] o °C [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1
'
  fioco HumRatio Come Variante

  Su Errore Vai a ErrHandler

  Se (RelHum < 0 O RelHum > 1) Poi
    MyMsgBox ("L'umidità relativa è fuori dall'intervallo [0,1]")
    Vai a ErrHandler
  Fine Se

  HumRatio = OttieniRapportoHumFromRelHum(TDryBulb, RelHum, Pressione)
  GetTWetBulbFromRelHum = OttieniTWetBulbFromHumRatio(TDryBulb, HumRatio, Pressione)
  Uscita Funzione

ErrHandler:
  GetTWetBulbFromRelHum = CVErr(xlErrNA)

Fine Funzione

Funzione OttieniRelHumFromTDewPoint(ByVal TDryBulb Come Variante, ByVal TDewPoint Come Variante) Come Variante
'
' Umidità relativa restituita data la temperatura di bulbo secco e la temperatura del punto di rugiada.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' TDewPoint: temperatura del punto di rugiada in °F [IP] o °C [SI]
'
' Ritorna:
' Umidità relativa nell'intervallo [0, 1]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 22
'
  fioco VapPres Come Variante
  fioco SatVapPres Come Variante

  Su Errore Vai a ErrHandler

  Se (TDewPoint > TDryBulb) Poi
    MyMsgBox ("La temperatura del punto di rugiada è superiore alla temperatura del bulbo secco")
    Vai a ErrHandler
  Fine Se

  VapPres = OttieniSatVapPres(TDewPoint)
  SatVapPres = OttieniSatVapPres(TDryBulb)
  OttieniRelHumFromTDewPoint = VapPres / SatVapPres
  Uscita Funzione

ErrHandler:
  OttieniRelHumFromTDewPoint = CVErr(xlErrNA)

Fine Funzione

Funzione GetRelHumFromTWetBulb(ByVal TDryBulb Come Variante, ByVal TWetBulb Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Restituisce l'umidità relativa data la temperatura a bulbo secco, la temperatura a bulbo umido e la pressione.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' TWetBulb: temperatura del bulbo umido in °F [IP] o °C [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Umidità relativa nell'intervallo [0, 1]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1
'
  fioco HumRatio Come Variante

  Su Errore Vai a ErrHandler

  Se TWetBulb > TDryBulb Poi
    MyMsgBox ("La temperatura del bulbo umido è superiore alla temperatura del bulbo secco")
    Vai a ErrHandler
  Fine Se

  HumRatio = Ottieni rapporto humumFromTWetBulb(TDryBulb, TWetLampadina, Pressione)
  GetRelHumFromTWetBulb = OttieniRapportoRelHumFromHum(TDryBulb, HumRatio, Pressione)
  Uscita Funzione

ErrHandler:
  GetRelHumFromTWetBulb = CVErr(xlErrNA)

Fine Funzione

Funzione OttieniTDewPointFromRelHum(ByVal TDryBulb Come Variante, ByVal RelHum Come Variante) Come Variante
'
' Temperatura del punto di rugiada di ritorno data la temperatura a bulbo secco e l'umidità relativa.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' RelHum: Umidità relativa nell'intervallo [0, 1]
'
' Ritorna:
' Temperatura del punto di rugiada in °F [IP] o °C [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1
'

  fioco VapPres Come Variante

  Su Errore Vai a ErrHandler

  Se RelHum < 0 O RelHum > 1 Poi
    MyMsgBox ("L'umidità relativa è fuori dall'intervallo [0, 1]")
    Vai a ErrHandler
  Fine Se

  VapPres = GetVapPresFromRelHum(TDryBulb, RelHum)
  OttieniTDewPointFromRelHum = OttieniTDewPointFromVapPres(TDryBulb, VapPres)
  Uscita Funzione

ErrHandler:
  OttieniTDewPointFromRelHum = CVErr(xlErrNA)

Fine Funzione

Funzione OttieniTDewPointFromTWetBulb(ByVal TDryBulb Come Variante, ByVal TWetBulb Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Temperatura del punto di rugiada di ritorno data la temperatura di bulbo secco, la temperatura di bulbo umido e la pressione.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' TWetBulb: temperatura del bulbo umido in °F [IP] o °C [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Temperatura del punto di rugiada in °F [IP] o °C [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1
'
  fioco HumRatio Come Variante

  Su Errore Vai a ErrHandler

  Se TWetBulb > TDryBulb Poi
    MyMsgBox ("La temperatura del bulbo umido è superiore alla temperatura del bulbo secco")
    Vai a ErrHandler
  Fine Se

  HumRatio = Ottieni rapporto humumFromTWetBulb(TDryBulb, TWetLampadina, Pressione)
  OttieniTDewPointFromTWetBulb = OttieniTDewPointFromHumRatio(TDryBulb, HumRatio, Pressione)
  Uscita Funzione

ErrHandler:
  OttieniTDewPointFromTWetBulb = CVErr(xlErrNA)

Fine Funzione


'**************************************************** ************************************************** ***
' Conversioni tra punto di rugiada o umidità relativa e pressione di vapore
'**************************************************** ************************************************** ***

Funzione GetVapPresFromRelHum(ByVal TDryBulb Come Variante, ByVal RelHum Come Variante) Come Variante
'
' Restituisce la pressione parziale del vapore acqueo in funzione dell'umidità relativa e della temperatura.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' RelHum: Umidità relativa nell'intervallo [0, 1]
'
' Ritorna:
' Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 12, 22
'
  Su Errore Vai a ErrHandler

  Se RelHum < 0 O RelHum > 1 Poi
    MyMsgBox ("L'umidità relativa è fuori dall'intervallo [0, 1]")
    Vai a ErrHandler
  Fine Se

  GetVapPresFromRelHum = RelHum * OttieniSatVapPres(TDryBulb)
  Uscita Funzione

ErrHandler:
  GetVapPresFromRelHum = CVErr(xlErrNA)

Fine Funzione

Funzione GetRelHumFromVapPres(ByVal TDryBulb Come Variante, ByVal VapPres Come Variante) Come Variante
' Restituisce l'umidità relativa data la temperatura a bulbo secco e la pressione del vapore.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' VapPres: pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
'
' Ritorna:
' Umidità relativa nell'intervallo [0, 1]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 12, 22
'
  Su Errore Vai a ErrHandler

  Se (VapPres < 0) Poi
    MyMsgBox ("La pressione parziale del vapore acqueo nell'aria umida è negativa")
    Vai a ErrHandler
  Fine Se

  GetRelHumFromVapPres = VapPres / OttieniSatVapPres(TDryBulb)
  Uscita Funzione

ErrHandler:
  GetRelHumFromVapPres = CVErr(xlErrNA)

Fine Funzione


Privato Funzione dLnPws_(TDryBulb Come Variante) Come Variante
'
' Funzione di supporto che restituisce la derivata del logaritmo naturale della pressione del vapore di saturazione
' in funzione della temperatura a bulbo secco.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
'
' Ritorna:
' Derivata del logaritmo naturale della tensione di vapore dell'aria satura in Psi [IP] o Pa [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 5 e 6
'
  fioco T Come Variante
  Se (èIP()) Poi
    T = OttieniTRankineFromTFahrenheit(TDryBulb)
    Se (TDryBulb <= TRIPLE_POINT_WATER_IP) Poi
      dLnPws_ = 10214.165 / T ^ 2 - 0.0053765794 + 2 * 0.00000019202377 * T _
             + 3 * 3.5575832E-10 * T ^ 2 - 4 * 9.0344688E-14 * T ^ 3 + 4.1635019 / T
    Altro
      dLnPws_ = 10440.397 / T ^ 2 - 0.027022355 + 2 * 0.00001289036 * T _
             - 3 * 2.4780681E-09 * T ^ 2 + 6.5459673 / T
    Fine Se
  Altro
    T = OttieniTKelvinDaTCelsius(TDryBulb)
    Se (TDryBulb <= TRIPLE_POINT_WATER_SI) Poi
      dLnPws_ = 5674.5359 / T ^ 2 - 0.009677843 + 2 * 0.00000062215701 * T _
             + 3 * 2.0747825E-09 * T ^ 2 - 4 * 9.484024E-13 * T ^ 3 + 4.1635019 / T
    Altro
      dLnPws_ = 5800.2206 / T ^ 2 - 0.048640239 + 2 * 0.000041764768 * T _
             - 3 * 0.000000014452093 * T ^ 2 + 6.5459673 / T
    Fine Se
  Fine Se
Fine Funzione

Funzione OttieniTDewPointFromVapPres(ByVal TDryBulb Come Variante, ByVal VapPres Come Variante) Come Variante
'
' Temperatura del punto di rugiada di ritorno data la temperatura a bulbo secco e la pressione del vapore.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' VapPres: pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
'
' Ritorna:
' Temperatura del punto di rugiada in °F [IP] o °C [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 5 e 6
'
' Appunti:
' La temperatura del punto di rugiada viene risolta invertendo l'equazione fornendo la pressione del vapore acqueo
' alla saturazione dalla temperatura anziché utilizzare le regressioni fornite
' di ASHRAE (eqn. 37 e 38) che sono molto meno accurati e hanno un
'intervallo di validità più ristretto.
Il metodo Newton-Raphson (NR) viene utilizzato sul logaritmo del vapore acqueo
pressione in funzione della temperatura, che è una funzione molto regolare
La convergenza viene solitamente raggiunta in 3-5 iterazioni.
' TDryBulb non è realmente necessario qui, viene utilizzato solo per comodità.
'
  fioco LIMITI (2) Come Variante
  fioco PSYCROLIB_TOLERANZA Come Variante

  Se (èIP()) Poi
    LIMITI (1) = -148.
    LIMITI (2) = 392.
  Altro
    LIMITI (1) = -100.
    LIMITI (2) = 200.
  Fine Se

  Su Errore Vai a ErrHandler

  Se ((VapPres < GetSatVapPres(LIMITI(1))) O (VapPres > GetSatVapPres(LIMITI(2)))) Poi
    MyMsgBox ("La pressione parziale del vapore acqueo è fuori dal campo di validità delle equazioni")
    Vai a ErrHandler
  Fine Se

  PSYCROLIB_TOLERANZA = OttieniTol()

  fioco TDewPoint Come Variante
  fioco lnVP Come Variante
  fioco d_lnVP Come Variante
  fioco TDewPoint_iter Come Variante
  fioco lnVP_iter
  fioco indice Come Variante
  indice = 1

  ' Usiamo NR per approssimare la soluzione.
  'Prima ipotesi
  TDewPoint = TDryBulb        ' Valore calcolato delle temperature del punto di rugiada, risolto in modo iterativo
  lnVP = Registro(VapPres)         ' Pressione parziale del vapore acqueo nell'aria umida

  ' Iterazione
  Fare
    TDewPoint_iter = TDewPoint   ' Valore di Tdp utilizzato nel calcolo NR
    lnVP_iter = Registro(GetSatVapPres(TDewPoint_iter))

    ' Derivato della funzione, calcolato analiticamente
    d_lnVP = dLnPws_(TDewPoint_iter)

    ' Nuova stima, delimitata dal dominio di validità dell'eqn. 5 e 6 e dal punto di congelamento
    TDewPoint = TDewPoint_iter - (lnVP_iter - lnVP) / d_lnVP
    TDewPoint = Max(TDewPoint, LIMITI (1))
    TDewPoint = Min(TDPuntoDiNuova, LIMITI (2))

    Se (indice > MAX_ITER_COUNT) Poi
      Vai a ErrHandler
    Fine Se

    indice = indice + 1

  Ciclo continuo Mentre (Ass(TDPuntoDiNuova - TDewPoint_iter) > PSYCHROLIB_TOLERANZA)

  TDewPoint = Min(TDPuntoDiNuova, TDryBulb)
  OttieniTDewPointFromVapPres = TDewPoint
  Uscita Funzione

ErrHandler:
  OttieniTDewPointFromVapPres = CVErr(xlErrNA)

Fine Funzione

Funzione OttieniVapPresFromTDewPoint(ByVal TDewPoint Come Variante) Come Variante
'
' Pressione del vapore di ritorno data la temperatura del punto di rugiada.
'
' Argomenti:
' TDewPoint: temperatura del punto di rugiada in °F [IP] o °C [SI]
'
' Ritorna:
' Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 36
'
  Su Errore Vai a ErrHandler
  OttieniVapPresFromTDewPoint = OttieniSatVapPres(TDewPoint)
  Uscita Funzione

ErrHandler:
  OttieniVapPresFromTDewPoint = CVErr(xlErrNA)

Fine Funzione


'**************************************************** ************************************************** ***
' Conversioni dalla temperatura del bulbo umido, dalla temperatura del punto di rugiada o dal rapporto umidità relativa/umidità
'**************************************************** ************************************************** ***

Funzione Rapporto GetTWetBulbFromHum(ByVal TDryBulb Come Variante, ByVal HumRatio Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Restituisce la temperatura a bulbo umido data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' HumRatio: rapporto di umidità in lb_H2O/lb_Air [IP] o kg_H2O/kg_Air [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Temperatura del bulbo umido in °F [IP] o °C [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 33 e 35 risolti per Tstar
'

  'Dichiarazioni
  fioco Wstar Come Variante
  fioco TDewPoint Come Variante, TWetBulb Come Variante, TWetBulbSup Come Variante, TWetBulbInf Come Variante
  fioco Tol Come Variante, Rapporto Hum limitato Come Variante, indice Come Variante

  Su Errore Vai a ErrHandler

  Se HumRatio < 0 Poi
    MyMsgBox ("Il rapporto di umidità non può essere negativo")
    Vai a ErrHandler
  Fine Se
  Rapporto Hum limitato = max(Rapporto rumore, MIN_HUM_RATIO)

  TDewPoint = OttieniTDewPointFromHumRatio(TDryBulb, Rapporto Hum limitato, Pressione)

  "Ipotesi iniziali
  TWetBulbSup = TDryBulb
  TWetBulbInf = TDewPoint
  TWetBulb = (TWetBulbInf + TWetBulbSup) / 2

  ' Ciclo di bisezione
  Tol = OttieniTol()
  indice = 0
  Mentre ((TWetBulbSup - TWetBulbInf) > Tol)

    ' Calcola il rapporto di umidità alla temperatura Tstar
    Wstar = Ottieni rapporto humumFromTWetBulb(TDryBulb, TWetLampadina, Pressione)

    ' Ottieni nuovi limiti
    Se (Wstar > Rapporto Hum limitato) Poi
      TWetBulbSup = TWetBulb
    Altro
      TWetBulbInf = TWetBulb
    Fine Se

    Nuova ipotesi sulla temperatura del bulbo umido
    TWetBulb = (TWetBulbSup + TWetBulbInf) / 2

    Se (indice > MAX_ITER_COUNT) Poi
      Vai a ErrHandler
    Fine Se

    indice = indice + 1
  Wend

  Rapporto GetTWetBulbFromHum = TWetBulb
  Uscita Funzione

ErrHandler:
  Rapporto GetTWetBulbFromHum = CVErr(xlErrNA)

Fine Funzione

Funzione OttieniHumRatioFromTWetBulb(ByVal TDryBulb Come Variante, ByVal TWetBulb Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Rapporto di umidità di ritorno data la temperatura di bulbo secco, la temperatura di bulbo umido e la pressione.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' TWetBulb: temperatura del bulbo umido in °F [IP] o °C [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Rapporto di umidità in lb_H2O/lb_Air [IP] o kg_H2O/kg_Air [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 33 e 35

  fioco Wsstar Come Variante, HumRatio Come Variante
  Wsstar = Ottieni rapporto humSat(TWetBulb, Pressione)

  Su Errore Vai a ErrHandler

  Se TWetBulb > TDryBulb Poi
    MyMsgBox ("La temperatura del bulbo umido è superiore alla temperatura del bulbo secco")
    Vai a ErrHandler
  Fine Se

  Se isIP() Poi
    Se (TWetBulb >= FREEZING_POINT_WATER_IP) Poi
      HumRatio = ((1093 - 0.556 * TWetBulb) * Wsstar - 0.24 * (TDryBulb - TWetBulb)) / (1093 + 0.444 * TDryBulb - TWetBulb)
    Altro
      HumRatio = ((1220 - 0.04 * TWetBulb) * Wsstar - 0.24 * (TDryBulb - TWetBulb)) / (1220 + 0.444 * TDryBulb - 0.48 * TWetBulb)
    Fine Se
  Altro
    Se (TWetBulb >= FREEZING_POINT_WATER_SI) Poi
      HumRatio = ((2501 - 2.326 * TWetBulb) * Wsstar - 1.006 * (TDryBulb - TWetBulb)) / (2501 + 1.86 * TDryBulb - 4.186 * TWetBulb)
    Altro
      HumRatio = ((2830 - 0.24 * TWetBulb) * Wsstar - 1.006 * (TDryBulb - TWetBulb)) / (2830 + 1.86 * TDryBulb - 2.1 * TWetBulb)
    Fine Se
  Fine Se
  ' Controllo di validità.
  OttieniHumRatioFromTWetBulb = max(Rapporto rumore, MIN_HUM_RATIO)
  Uscita Funzione

ErrHandler:
  OttieniHumRatioFromTWetBulb = CVErr(xlErrNA)

Fine Funzione

Funzione OttieniHumRatioFromRelHum(ByVal TDryBulb Come Variante, ByVal RelHum Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Rapporto di umidità di ritorno data la temperatura a bulbo secco, l'umidità relativa e la pressione.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' RelHum: Umidità relativa nell'intervallo [0, 1]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Rapporto di umidità in lb_H2O/lb_Air [IP] o kg_H2O/kg_Air [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1
'
  fioco VapPres Come Variante

  Su Errore Vai a ErrHandler

  Se RelHum < 0 O RelHum > 1 Poi
    MyMsgBox ("L'umidità relativa è fuori dall'intervallo [0, 1]")
    Vai a ErrHandler
  Fine Se

  VapPres = GetVapPresFromRelHum(TDryBulb, RelHum)
  OttieniHumRatioFromRelHum = Ottieni rapporto humum da VapPres(VapPres, Pressione)
  Uscita Funzione

ErrHandler:
  OttieniHumRatioFromRelHum = CVErr(xlErrNA)

Fine Funzione

Funzione Ottieni rapporto RelHumFromHum(ByVal TDryBulb Come Variante, ByVal HumRatio Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Restituisce l'umidità relativa data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' HumRatio: rapporto di umidità in lb_H2O/lb_Air [IP] o kg_H2O/kg_Air [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Umidità relativa nell'intervallo [0, 1]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1
'
  fioco VapPres Come Variante

  Su Errore Vai a ErrHandler

  Se HumRatio < 0 Poi
    MyMsgBox ("Il rapporto di umidità è negativo")
    Vai a ErrHandler
  Fine Se

  VapPres = GetVapPresFromHumRatio(Rapporto hum, Pressione)
  Ottieni rapporto RelHumFromHum = OttieniRelHumFromVapPres(TDryBulb, VapPres)
  Uscita Funzione

ErrHandler:
  Ottieni rapporto RelHumFromHum = CVErr(xlErrNA)

Fine Funzione


Funzione OttieniHumRatioFromTDewPoint(ByVal TDewPoint Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Rapporto dell'umidità di ritorno data la temperatura e la pressione del punto di rugiada.
'
' Argomenti:
' TDewPoint: temperatura del punto di rugiada in °F [IP] o °C [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Rapporto di umidità in lb_H2O/lb_Air [IP] o kg_H2O/kg_Air [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 13
'
  fioco VapPres Come Variante

  Su Errore Vai a ErrHandler

  VapPres = OttieniSatVapPres(TDewPoint)
  OttieniHumRatioFromTDewPoint = Ottieni rapporto humum da VapPres(VapPres, Pressione)
  Uscita Funzione

ErrHandler:
  OttieniHumRatioFromTDewPoint = CVErr(xlErrNA)

Fine Funzione

Funzione OttieniTDewPointFromHumRatio(ByVal TDryBulb Come Variante, ByVal HumRatio Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Temperatura del punto di rugiada di ritorno data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' HumRatio: rapporto di umidità in lb_H2O/lb_Air [IP] o kg_H2O/kg_Air [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Temperatura del punto di rugiada in °F [IP] o °C [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1
'
  fioco VapPres Come Variante

  Su Errore Vai a ErrHandler

  Se HumRatio < 0 Poi
    MyMsgBox ("Il rapporto di umidità è negativo")
    Vai a ErrHandler
  Fine Se

  VapPres = GetVapPresFromHumRatio(Rapporto hum, Pressione)
  OttieniTDewPointFromHumRatio = OttieniTDewPointFromVapPres(TDryBulb, VapPres)
  Uscita Funzione

ErrHandler:
  OttieniTDewPointFromHumRatio = CVErr(xlErrNA)
Fine Funzione


'**************************************************** ************************************************** ***
' Conversioni tra rapporto di umidità e tensione di vapore
'**************************************************** ************************************************** ***

Funzione OttieniHumRatioFromVapPres(ByVal VapPres Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Rapporto dell'umidità di ritorno data la pressione del vapore acqueo e la pressione atmosferica.
'
' Argomenti:
' VapPres : Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Rapporto di umidità in lb_H2O/lb_Air [IP] o kg_H2O/kg_Air [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 20
'
  fioco HumRatio Come Variante

  Su Errore Vai a ErrHandler

  Se VapPres < 0 Poi
    MyMsgBox ("La pressione parziale del vapore acqueo nell'aria umida è negativa")
    Vai a ErrHandler
  Fine Se

  HumRatio = 0.621945 * VapPres / (Pressione - VapPres)
  ' Controllo di validità.
  OttieniHumRatioFromVapPres = max(Rapporto rumore, MIN_HUM_RATIO)
  Uscita Funzione

ErrHandler:
  OttieniHumRatioFromVapPres = CVErr(xlErrNA)

Fine Funzione

Funzione OttieniVapPresFromHumRatio(ByVal HumRatio Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Pressione di vapore restituita in base al rapporto di umidità e alla pressione.
'
' Argomenti:
' HumRatio: rapporto di umidità in lb_H2O/lb_Air [IP] o kg_H2O/kg_Air [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 20 risolto per pw
'

  fioco VapPres Come Variante, Rapporto Hum limitato Come Variante

  Su Errore Vai a ErrHandler

  Se HumRatio < 0 Poi
    MyMsgBox ("Il rapporto di umidità è negativo")
    Vai a ErrHandler
  Fine Se
  Rapporto Hum limitato = max(Rapporto rumore, MIN_HUM_RATIO)

  VapPres = Pressione * Rapporto Hum limitato / (0.621945 + Rapporto Hum limitato)
  OttieniVapPresFromHumRatio = VapPres
  Uscita Funzione

ErrHandler:
  OttieniVapPresFromHumRatio = CVErr(xlErrNA)

Fine Funzione


'**************************************************** ************************************************** ***
' Conversioni tra rapporto di umidità e umidità specifica
'**************************************************** ************************************************** ***

Funzione Ottieni rapporto HumFromHum specifico(ByVal HumRatio Come Variante) Come Variante
'
' Restituisce l'umidità specifica dal rapporto di umidità (noto anche come rapporto di miscelazione).
'
' Argomenti:
' HumRatio: rapporto di umidità in lb_H₂O lb_Dry_Air⁻¹ [IP] o kg_H₂O kg_Dry_Air⁻¹ [SI]
'
' Ritorna:
' Umidità specifica in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 9b
'
'
  fioco SpecificHum Come Variante

  Su Errore Vai a ErrHandler

  Se (Rapporto ronzio < 0) Poi
    MyMsgBox ("Il rapporto di umidità è negativo")
    Vai a ErrHandler
  Fine Se

  SpecificHum = HumRatio / (1.0 + HumRatio)
  Ottieni rapporto HumFromHum specifico = SpecificHum
  Uscita Funzione

ErrHandler:
  Ottieni rapporto HumFromHum specifico = CVErr(xlErrNA)

Fine Funzione

Funzione Ottieni rapporto humum da hum specifico(ByVal SpecificHum Come Variante) Come Variante
'
' Restituisce il rapporto di umidità (noto anche come rapporto di miscelazione) dall'umidità specifica.
'
' Argomenti:
' SpecificHum: Umidità specifica in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
'
' Ritorna:
' Rapporto di umidità in lb_H₂O lb_Dry_Air⁻¹ [IP] o kg_H₂O kg_Dry_Air⁻¹ [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 9b (risolto per il rapporto di umidità)
'
'
  fioco HumRatio come Variante

  Su Errore Vai a ErrHandler

  Se (SpecificHum < 0 O SpecificHum >= 1) Poi
    MyMsgBox ("L'umidità specifica è fuori dall'intervallo [0, 1[")
    Vai a ErrHandler
  Fine Se

    HumRatio = SpecificHum / (1.0 - SpecificHum)
    Ottieni rapporto humum da hum specifico = max(Rapporto rumore, MIN_HUM_RATIO)
  Uscita Funzione

ErrHandler:
  Ottieni rapporto humum da hum specifico = CVErr(xlErrNA)

Fine Funzione


'**************************************************** ************************************************** ***
' Calcoli dell'aria secca
'**************************************************** ************************************************** ***

Funzione OttieniEntalpiaAriaSecca(ByVal TDryBulb Come Variante) Come Variante
'
' Entalpia dell'aria secca restituita data la temperatura a bulbo secco.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
'
' Ritorna:
' Entalpia dell'aria secca in Btu/lb [IP] o J/kg [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 28
'
  Su Errore Vai a ErrHandler

  Se (èIP()) Poi
    OttieniEntalpiaAriaSecca = 0.24 * TDryBulb
  Altro
    OttieniEntalpiaAriaSecca = 1006 * TDryBulb
  Fine Se
  Uscita Funzione

ErrHandler:
  OttieniEntalpiaAriaSecca = CVErr(xlErrNA)

Fine Funzione

Funzione OttieniDryAirDensity(ByVal TDryBulb Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Restituisce la densità dell'aria secca date la temperatura e la pressione del bulbo secco.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Densità dell'aria secca in lb/ft³ [IP] o kg/m³ [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1
'
' Appunti:
' Eqn 14 per la perfetta relazione tra i gas per l'aria secca.
' Eqn 1 per la costante universale dei gas.
' Il fattore 144 in IP serve per la conversione di Psi = lb/in² in lb/ft².
'
  Su Errore Vai a ErrHandler

  Se (èIP()) Poi
    OttieniDryAirDensity = (144 * Pressione) / R_DA_IP / OttieniTRankineFromTFahrenheit(TDryBulb)
  Altro
    OttieniDryAirDensity = Pressione / R_DA_SI / OttieniTKelvinDaTCelsius(TDryBulb)
  Fine Se
  Uscita Funzione

ErrHandler:
  OttieniDryAirDensity = CVErr(xlErrNA)

Fine Funzione

Funzione OttieniDryAirVolume(ByVal TDryBulb Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Volume di aria secca restituita in base alla temperatura e alla pressione del bulbo secco.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Volume di aria secca in ft³/lb [IP] o in m³/kg [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1
'
' Appunti:
' Eqn 14 per la perfetta relazione tra i gas per l'aria secca.
' Eqn 1 per la costante universale dei gas.
' Il fattore 144 in IP serve per la conversione di Psi = lb/in² in lb/ft².
'
  Su Errore Vai a ErrHandler

  Se (èIP()) Poi
    OttieniDryAirVolume = OttieniTRankineFromTFahrenheit(TDryBulb) * R_DA_IP / (144 * Pressione)
  Altro:
    OttieniDryAirVolume = OttieniTKelvinDaTCelsius(TDryBulb) * R_DA_SI / Pressione
  Fine Se
  Uscita Funzione

ErrHandler:
  OttieniDryAirVolume = CVErr(xlErrNA)

Fine Funzione

Funzione OttieniTDryBulbFromEnthalpyAndHumRatio(ByVal Entalpia dell'aria umida Come Variante, ByVal HumRatio Come Variante) Come Variante
'
' Restituisce la temperatura del bulbo secco dal rapporto entalpia e umidità.
'
'
' Argomenti:
' MoistAirEntalpy: entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹
' HumRatio: rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
'
' Ritorna:
' Temperatura a bulbo secco in °F [IP] o °C [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 30
'
' Appunti:
' Basato sulla funzione "GetMoistAirEnthalpy", riorganizzata per la temperatura.
'

  Su Errore Vai a ErrHandler

  Se HumRatio < 0 Poi
    MyMsgBox ("Il rapporto di umidità è negativo")
    Vai a ErrHandler
  Fine Se

  Se (èIP()) Poi
    OttieniTDryBulbFromEnthalpyAndHumRatio = (Entalpia dell'aria umida - 1061.0 * HumRatio) / (0.24 + 0.444 * HumRatio)
  Altro:
    OttieniTDryBulbFromEnthalpyAndHumRatio = (Entalpia dell'aria umida / 1000.0 - 2501.0 * HumRatio) / (1.006 + 1.86 * HumRatio)
  Fine Se
  Uscita Funzione

ErrHandler:
  OttieniTDryBulbFromEnthalpyAndHumRatio = CVErr(xlErrNA)

Fine Funzione

Funzione Ottieni rapporto hum dall'entalpia e dal bulbo secco(ByVal Entalpia dell'aria umida Come Variante, ByVal TDryBulb Come Variante) Come Variante
'
' Rapporto dell'umidità di ritorno tra entalpia e temperatura di bulbo secco.
'
'
' Argomenti:
' MoistAirEntalpy: entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
'
' Ritorna:
' Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 30
'
' Appunti:
' Basato sulla funzione "GetMoistAirEnthalpy", riorganizzata per il rapporto di umidità.
'

  Su Errore Vai a ErrHandler

  Se (èIP()) Poi
    Ottieni rapporto hum dall'entalpia e dal bulbo secco = (Entalpia dell'aria umida - 0.24 * TDryBulb) / (1061.0 + 0.444 * TDryBulb)
  Altro:
    Ottieni rapporto hum dall'entalpia e dal bulbo secco = (Entalpia dell'aria umida / 1000.0 - 1.006 * TDryBulb) / (2501.0 + 1.86 * TDryBulb)
  Fine Se
  Uscita Funzione

ErrHandler:
  Ottieni rapporto hum dall'entalpia e dal bulbo secco = CVErr(xlErrNA)

Fine Funzione


'**************************************************** ************************************************** ***
' Calcoli dell'aria satura
'**************************************************** ************************************************** ***

Funzione OttieniSatVapPres(ByVal TDryBulb Come Variante) Come Variante
'
' Pressione di ritorno del vapore saturato data la temperatura a bulbo secco.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
'
' Ritorna:
' Pressione di vapore dell'aria satura in Psi [IP] o Pa [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 5 e 6
' Nota importante: le formule ASHRAE sono definite sopra e sotto il punto di congelamento ma hanno
' una discontinuità al punto di congelamento. Questa è una piccola imprecisione da parte di ASHRAE: le formule
' dovrebbe essere definito sopra e sotto il punto triplo dell'acqua (non il punto di contatto), nel qual caso
' la discontinuità svanisce. È essenziale utilizzare il punto triplo dell'acqua altrimenti funzionerà
' GetTDewPointFromVapPres, che inverte la funzione presente, non converge correttamente
'il punto di congelamento.
'
  fioco LnPws Come Variante, T Come Variante

  Su Errore Vai a ErrHandler

  Se (èIP()) Poi
    Se (TDryBulb < -148 O TDryBulb > 392) Poi
      MyMsgBox ("La temperatura del bulbo secco è fuori dall'intervallo [-148, 392] °F")
      Vai a ErrHandler
    Fine Se

    T = OttieniTRankineFromTFahrenheit(TDryBulb)

    Se (TDryBulb <= TRIPLE_POINT_WATER_IP) Poi
      LnPws = (-10214.165 / T - 4.8932428 - 0.0053765794 * T + 0.00000019202377 * T ^ 2 _
            + 3.5575832E-10 * T ^ 3 - 9.0344688E-14 * T ^ 4 + 4.1635019 * Registro(T))
    Altro
      LnPws = -10440.397 / T - 11.29465 - 0.027022355 * T + 0.00001289036 * T ^ 2 _
            - 2.4780681E-09 * T ^ 3 + 6.5459673 * Registro (T)
    Fine Se

  Altro
    Se (TDryBulb < -100 O TDryBulb > 200) Poi
      MyMsgBox ("La temperatura del bulbo secco è fuori dall'intervallo [-100, 200] °C")
      Vai a ErrHandler
    Fine Se

    T = OttieniTKelvinDaTCelsius(TDryBulb)

    Se (TDryBulb <= TRIPLE_POINT_WATER_SI) Poi
        LnPws = -5674.5359 / T + 6.3925247 - 0.009677843 * T + 0.00000062215701 * T ^ 2 _
              + 2.0747825E-09 * T ^ 3 - 9.484024E-13 * T ^ 4 + 4.1635019 * Registro (T)
    Altro
        LnPws = -5800.2206 / T + 1.3914993 - 0.048640239 * T + 0.000041764768 * T ^ 2 _
              - 0.000000014452093 * T ^ 3 + 6.5459673 * Registro (T)
    Fine Se
  Fine Se

  OttieniSatVapPres = Esp(LnPw)
  Uscita Funzione

ErrHandler:
  OttieniSatVapPres = CVErr(xlErrNA)

Fine Funzione

Funzione Ottieni rapporto SatHum(ByVal TDryBulb Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Rapporto di umidità di ritorno dell'aria satura data la temperatura e la pressione a bulbo secco.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Rapporto di umidità dell'aria satura in lb_H2O/lb_Air [IP] o kg_H2O/kg_Air [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 36, risolto per W
'
  fioco SatVaporPres Come Variante, SatHumRatio Come Variante

  Su Errore Vai a ErrHandler

  SatVaporPres = OttieniSatVapPres(TDryBulb)
  SatHumRatio = 0.621945 * SatVaporPres / (Pressione - SatVaporPres)
  Ottieni rapporto SatHum = max(Rapporto hum sat, MIN_HUM_RATIO)
  Uscita Funzione

ErrHandler:
  Ottieni rapporto SatHum = CVErr(xlErrNA)

Fine Funzione

Funzione OttieniSatAirEntalpia(ByVal TDryBulb Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Entalpia di ritorno dell'aria satura data la temperatura e la pressione a bulbo secco.
'
' Argomenti:
' TDryBulb: temperatura a bulbo secco in °F [IP] o °C [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Entalpia dell'aria satura in Btu/lb [IP] o J/kg [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1
'
  Su Errore Vai a ErrHandler

  OttieniSatAirEntalpia = GetMoistAirEntalpia(TDryBulb, Ottieni rapporto humSat(TDryBulb, Pressione))
  Uscita Funzione

ErrHandler:
  OttieniSatAirEntalpia = CVErr(xlErrNA)

Fine Funzione


'**************************************************** ************************************************** ***
' Calcoli dell'aria umida
'**************************************************** ************************************************** ***


Funzione OttieniVaporPressureDeficit(ByVal TDryBulb Come Variante, ByVal HumRatio Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Ritorno Deficit di pressione del vapore data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' HumRatio: rapporto di umidità in lb_H2O/lb_Air [IP] o kg_H2O/kg_Air [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Deficit di pressione del vapore in Psi [IP] o Pa [SI]
'
' Riferimento:
' Oke (1987) eq. 2.13a
'
  fioco RelHum Come Variante

  Su Errore Vai a ErrHandler

  Se HumRatio < 0 Poi
    MyMsgBox ("Il rapporto di umidità è negativo")
    Vai a ErrHandler
  Fine Se

  RelHum = OttieniRapportoRelHumFromHum(TDryBulb, HumRatio, Pressione)
  OttieniVaporPressureDeficit = OttieniSatVapPres(TDryBulb) * (1 - RelHum)
  Uscita Funzione

ErrHandler:
  OttieniVaporPressureDeficit = CVErr(xlErrNA)

Fine Funzione

Funzione Ottieni Grado di Saturazione(ByVal TDryBulb Come Variante, ByVal HumRatio Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Restituisce il grado di saturazione (cioè il rapporto di umidità dell'aria/rapporto di umidità dell'aria alla saturazione
' alla stessa temperatura e pressione) data la temperatura a bulbo secco, il rapporto di umidità e la pressione atmosferica.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' HumRatio: rapporto di umidità in lb_H2O/lb_Air [IP] o kg_H2O/kg_Air [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Grado di saturazione in unità arbitraria
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2009) cap. 1 eq 12
'
' Appunti:
Questa definizione è assente nel Manuale del 2017. Utilizzando invece la versione 2009.
'
  fioco Rapporto Hum limitato Come Variante

  Su Errore Vai a ErrHandler

  Se HumRatio < 0 Poi
    MyMsgBox ("Il rapporto di umidità è negativo")
    Vai a ErrHandler
  Fine Se
  Rapporto Hum limitato = max(Rapporto rumore, MIN_HUM_RATIO)

  Ottieni Grado di Saturazione = Rapporto Hum limitato / Ottieni rapporto humSat(TDryBulb, Pressione)
  Uscita Funzione

ErrHandler:
  Ottieni Grado di Saturazione = CVErr(xlErrNA)

Fine Funzione

Funzione OttieniEntalpiaAriaMostra(ByVal TDryBulb Come Variante, ByVal HumRatio Come Variante) Come Variante
'
' Entalpia dell'aria umida restituita data la temperatura a bulbo secco e il rapporto di umidità.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' HumRatio: rapporto di umidità in lb_H2O/lb_Air [IP] o kg_H2O/kg_Air [SI]
'
' Ritorna:
' Entalpia dell'aria umida in Btu/lb [IP] o J/kg
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 30
'
  fioco Rapporto Hum limitato Come Variante

  Su Errore Vai a ErrHandler

  Se (Rapporto ronzio < 0) Poi
    MyMsgBox ("Il rapporto di umidità è negativo")
    Vai a ErrHandler
  Fine Se
  Rapporto Hum limitato = max(Rapporto rumore, MIN_HUM_RATIO)

  Se (èIP()) Poi
    OttieniEntalpiaAriaMostra = 0.24 * TDryBulb + Rapporto Hum limitato * (1061 + 0.444 * TDryBulb)
  Altro
    OttieniEntalpiaAriaMostra = (1.006 * TDryBulb + Rapporto Hum limitato * (2501 + 1.86 * TDryBulb)) * 1000
  Fine Se
  Uscita Funzione

ErrHandler:
  OttieniEntalpiaAriaMostra = CVErr(xlErrNA)

Fine Funzione

Funzione OttieniMoistAirVolume(ByVal TDryBulb Come Variante, ByVal HumRatio Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Restituisce il volume specifico dell'aria umida in base alla temperatura a bulbo secco, al rapporto di umidità e alla pressione.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' HumRatio: rapporto di umidità in lb_H2O/lb_Air [IP] o kg_H2O/kg_Air [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Volume specifico di aria umida in ft³/lb di aria secca [IP] o in m³/kg di aria secca [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 26
'
' Appunti:
' In unità IP, R_DA_IP / 144 equivale a 0,370486 che è il coefficiente che appare nell'eqn 26
' Il fattore 144 serve per la conversione di Psi = lb/in² in lb/ft².
'
  fioco Rapporto Hum limitato Come Variante

  Su Errore Vai a ErrHandler

  Se (Rapporto ronzio < 0) Poi
    MyMsgBox ("Il rapporto di umidità è negativo")
    Vai a ErrHandler
  Fine Se
  Rapporto Hum limitato = max(Rapporto rumore, MIN_HUM_RATIO)

  Se (èIP()) Poi
    OttieniMoistAirVolume = R_DA_IP * OttieniTRankineFromTFahrenheit(TDryBulb) * (1 + 1.607858 * Rapporto Hum limitato) / (144 * Pressione)
  Altro
    OttieniMoistAirVolume = R_DA_SI * OttieniTKelvinDaTCelsius(TDryBulb) * (1 + 1.607858 * Rapporto Hum limitato) / Pressione
  Fine Se
  Uscita Funzione

ErrHandler:
  OttieniMoistAirVolume = CVErr(xlErrNA)

Fine Funzione

Funzione OttieniTDryBulbFromMoistAirVolumeAndHumRatio(ByVal Volume Aria Umida Come Variante, ByVal HumRatio Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Temperatura di ritorno del bulbo secco in base al volume specifico dell'aria umida, al rapporto di umidità e alla pressione.
'
' Argomenti:
' MoistAirVolume: volume specifico di aria umida in ft³ lb⁻¹ di aria secca [IP] o in m³ kg⁻¹ di aria secca [SI]
' HumRatio: rapporto di umidità in lb_H2O/lb_Air [IP] o kg_H2O/kg_Air [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Volume specifico di aria umida in ft³/lb di aria secca [IP] o in m³/kg di aria secca [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 26
'
' Appunti:
' In unità IP, R_DA_IP / 144 equivale a 0,370486 che è il coefficiente che appare nell'eqn 26
' Il fattore 144 serve per la conversione di Psi = lb/in² in lb/ft².
' Basato sulla funzione "GetMoistAirVolume", riorganizzato per la temperatura a bulbo secco.
'
  fioco Rapporto Hum limitato Come Variante

  Su Errore Vai a ErrHandler

  Se (Rapporto ronzio < 0) Poi
    MyMsgBox ("Il rapporto di umidità è negativo")
    Vai a ErrHandler
  Fine Se
  Rapporto Hum limitato = max(Rapporto rumore, MIN_HUM_RATIO)

  Se (èIP()) Poi
    OttieniTDryBulbFromMoistAirVolumeAndHumRatio = OttieniTFahrenheitFromTRankine(MoistAirVolume * (144 * Pressione) / (R_DA_IP * (1 + 1.607858 * Rapporto Hum limitato)))
  Altro
    OttieniTDryBulbFromMoistAirVolumeAndHumRatio = OttieniTCelsiusFromTKelvin(MoistAirVolume * Pressione / (R_DA_SI * (1 + 1.607858 * Rapporto Hum limitato)))
  Fine Se
  Uscita Funzione

ErrHandler:
  OttieniTDryBulbFromMoistAirVolumeAndHumRatio = CVErr(xlErrNA)

Fine Funzione

Funzione GetMoistAirDensity(ByVal TDryBulb Come Variante, ByVal HumRatio Come Variante, ByVal Pressione Come Variante) Come Variante
'
' Restituisce la densità dell'aria umida in base al rapporto di umidità, alla temperatura del bulbo secco e alla pressione.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' HumRatio: rapporto di umidità in lb_H2O/lb_Air [IP] o kg_H2O/kg_Air [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' MoistAirDensity: densità dell'aria umida in lb/ft³ [IP] o kg/m³ [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 11
'
  fioco Volume Aria Umida Come Variante, Rapporto Hum limitato Come Variante

  Su Errore Vai a ErrHandler

  Se (Rapporto ronzio < 0) Poi
    MyMsgBox ("Il rapporto di umidità è negativo")
    Vai a ErrHandler
  Fine Se
  Rapporto Hum limitato = max(Rapporto rumore, MIN_HUM_RATIO)

  Volume Aria Umida = GetMoistAirVolume(TDryBulb, Rapporto Hum limitato, Pressione)
  GetMoistAirDensity = (1 + Rapporto Hum limitato) / Volume Aria Umida
  Uscita Funzione

ErrHandler:
  GetMoistAirDensity = CVErr(xlErrNA)

Fine Funzione


'**************************************************** ************************************************** ***
'Atmosfera standard
'**************************************************** ************************************************** ***

Funzione OttieniPressioneAtmStandard(ByVal Altitudine Come Variante) Come Variante
'
' Restituisce la pressione barometrica atmosferica standard, data l'elevazione (altitudine).
'
' Argomenti:
' Altitudine: altitudine in piedi [IP] o m [SI]
'
' Ritorna:
' Pressione barometrica atmosferica standard in Psi [IP] o Pa [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 3
'
  Su Errore Vai a ErrHandler

  Se (èIP()) Poi
    OttieniPressioneAtmStandard = 14.696 * (1 - 0.0000068754 * Altitudine) ^ 5.2559
  Altro
    OttieniPressioneAtmStandard = 101325 * (1 - 0.0000225577 * Altitudine) ^ 5.2559
  Fine Se
  Uscita Funzione

ErrHandler:
  OttieniPressioneAtmStandard = CVErr(xlErrNA)

Fine Funzione

Funzione OttieniTemperaturaAtmStandard(ByVal Altitudine Come Variante) Come Variante
'
' Restituisce la temperatura atmosferica standard, data l'elevazione (altitudine).
'
' Argomenti:
' Altitudine: altitudine in piedi
'
' Ritorna:
' Temperatura atmosfera standard a bulbo secco in °F [IP] o °C [SI]
'
' Riferimento:
Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 4
'
  Su Errore Vai a ErrHandler

  Se (èIP()) Poi
    OttieniTemperaturaAtmStandard = 59 - 0.0035662 * Altitudine
  Altro
    OttieniTemperaturaAtmStandard = 15 - 0.0065 * Altitudine
  Fine Se
  Uscita Funzione

ErrHandler:
  OttieniTemperaturaAtmStandard = CVErr(xlErrNA)

Fine Funzione

Funzione Ottieni la pressione del livello del mare(ByVal StazionePressione Come Variante, ByVal Altitudine Come Variante, ByVal TDryBulb Come Variante) Come Variante
'
' Pressione di ritorno al livello del mare data la temperatura a bulbo secco, l'altitudine sul livello del mare e la pressione.
'
' Argomenti:
' StationPressure: pressione della stazione osservata in Psi [IP] o Pa [SI]
' Altitudine: altitudine in piedi [IP] o m [SI]
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
'
' Ritorna:
' Pressione barometrica al livello del mare in Psi [IP] o Pa [SI]
'
' Riferimento:
' Hess SL, Introduzione alla meteorologia teorica, Holt Rinehart e Winston, NY 1959,
' cap. 6,5; Stull RB, Meteorologia per scienziati e ingegneri, 2a edizione,
' Brooks/Cole 2000, cap. 1.
'
' Appunti:
La procedura standard per gli Stati Uniti consiste nell'utilizzare la media per TDryBulb
' della temperatura attuale della stazione e della temperatura della stazione di 12 ore fa.
'

  ' Calcola la temperatura media nella colonna d'aria, assumendo un intervallo di tempo
  ' di 6,5 °C/km
  fioco TColonna Come Variante
  fioco H Come Variante

  Su Errore Vai a ErrHandler

  Se (èIP()) Poi
    ' Calcola la temperatura media nella colonna d'aria, assumendo un intervallo di tempo
    ' di 3,6 °F/1000 piedi
    TColonna = TDryBulb + 0.0036 * Altitudine / 2

    ' Determinare l'altezza della scala
    H = 53.351 * OttieniTRankineFromTFahrenheit(TConmina)
  Altro
    ' Calcola la temperatura media nella colonna d'aria, assumendo un intervallo di tempo
    ' di 6,5 °C/km
    TColonna = TDryBulb + 0.0065 * Altitudine / 2

    ' Determinare l'altezza della scala
    H = 287.055 * OttieniTKelvinDaTCelsius(TColonna) / 9.807
  Fine Se

  ' Calcolare la pressione a livello del mare
  Ottieni la pressione del livello del mare = StazionePressione * Esp(Altitudine / H)
  Uscita Funzione

ErrHandler:
  Ottieni la pressione del livello del mare = CVErr(xlErrNA)

Fine Funzione

Funzione Ottieni pressione stazione(ByVal Pressione al livello del mare Come Variante, ByVal Altitudine Come Variante, ByVal TDryBulb Come Variante) Come Variante
'
' Argomenti:
' SeaLevelPressure: pressione barometrica al livello del mare in Psi [IP] o Pa [SI]
' Altitudine: altitudine in piedi [IP] o m [SI]
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
'
' Ritorna:
' Pressione della stazione in Psi [IP] o Pa [SI]
'
' Riferimento:
' Vedi 'Ottieni pressione livello mare'
'
' Appunti:
Questa funzione è esattamente l'inverso di "GetSeaLevelPressure".
'
  Su Errore Vai a ErrHandler

  Ottieni pressione stazione = Pressione al livello del mare / Ottieni pressione livello mare (1, Altitudine, TDryBulb)
  Uscita Funzione

ErrHandler:
  Ottieni pressione stazione = CVErr(xlErrNA)

Fine Funzione

'**************************************************** ************************************************** ***
' Funzioni per impostare tutti i valori psicrometrici
'**************************************************** ************************************************** ***

Sub CalcPsychrometricsFromTWetBulb(ByVal TDryBulb Come Variante, ByVal TWetBulb Come Variante, ByVal Pressione Come Variante, _
    ByRef HumRatio Come Variante, ByRef TDewPoint Come Variante, ByRef RelHum Come Variante, ByRef VapPres Come Variante, _
    ByRef Entalpia dell'aria umida Come Variante, ByRef Volume Aria Umida Come Variante, ByRef Grado Di Saturazione Come Variante)
'
' Funzione di utilità per calcolare il rapporto di umidità, la temperatura del punto di rugiada, l'umidità relativa,
' pressione del vapore, entalpia dell'aria umida, volume dell'aria umida e grado di saturazione dell'aria fornita
' temperatura di bulbo secco, temperatura di bulbo umido e pressione.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' TWetBulb: temperatura del bulbo umido in °F [IP] o °C [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Rapporto di umidità in lb_H2O/lb_Air [IP] o kg_H2O/kg_Air [SI]
' Temperatura del punto di rugiada in °F [IP] o °C [SI]
' Umidità relativa nell'intervallo [0, 1]
' Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
' Entalpia dell'aria umida in Btu/lb [IP] o J/kg [SI]
' Volume specifico di aria umida in ft³/lb [IP] o in m³/kg [SI]
' Grado di saturazione [senza unità]
'
  HumRatio = Ottieni rapporto humumFromTWetBulb(TDryBulb, TWetLampadina, Pressione)
  TDewPoint = OttieniTDewPointFromHumRatio(TDryBulb, HumRatio, Pressione)
  RelHum = OttieniRapportoRelHumFromHum(TDryBulb, HumRatio, Pressione)
  VapPres = GetVapPresFromHumRatio(Rapporto hum, Pressione)
  Entalpia dell'aria umida = GetMoistAirEntalpia(TDryBulb, HumRatio)
  Volume Aria Umida = GetMoistAirVolume(TDryBulb, HumRatio, Pressione)
  Grado Di Saturazione = Ottieni Grado di saturazione (TDryBulb, HumRatio, Pressione)

Fine Sub

Sub CalcPsychrometricsFromTDewPoint(ByVal TDryBulb Come Variante, ByVal TDewPoint Come Variante, ByVal Pressione Come Variante, _
    ByRef HumRatio Come Variante, ByRef TWetBulb Come Variante, ByRef RelHum Come Variante, ByRef VapPres Come Variante, _
    ByRef Entalpia dell'aria umida Come Variante, ByRef Volume Aria Umida Come Variante, ByRef Grado Di Saturazione Come Variante)
'
' Funzione di utilità per calcolare il rapporto di umidità, la temperatura del bulbo umido, l'umidità relativa,
' pressione del vapore, entalpia dell'aria umida, volume dell'aria umida e grado di saturazione dell'aria fornita
' temperatura del bulbo secco, temperatura del punto di rugiada e pressione.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' TDewPoint: temperatura del punto di rugiada in °F [IP] o °C [SI]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Rapporto di umidità in lb_H2O/lb_Air [IP] o kg_H2O/kg_Air [SI]
' Temperatura del bulbo umido in °F [IP] o °C [SI]
' Umidità relativa nell'intervallo [0, 1]
' Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
' Entalpia dell'aria umida in Btu/lb [IP] o J/kg [SI]
' Volume specifico di aria umida in ft³/lb [IP] o in m³/kg [SI]
' Grado di saturazione [senza unità]
'
  HumRatio = OttieniRapportoRum.DaPuntoDiTew(PuntoDiTew, Pressione)
  TWetBulb = OttieniTWetBulbFromHumRatio(TDryBulb, HumRatio, Pressione)
  RelHum = OttieniRapportoRelHumFromHum(TDryBulb, HumRatio, Pressione)
  VapPres = GetVapPresFromHumRatio(Rapporto hum, Pressione)
  Entalpia dell'aria umida = GetMoistAirEntalpia(TDryBulb, HumRatio)
  Volume Aria Umida = GetMoistAirVolume(TDryBulb, HumRatio, Pressione)
  Grado Di Saturazione = Ottieni Grado di saturazione (TDryBulb, HumRatio, Pressione)

Fine Sub

Sub CalcPsychrometricsFromRelHum(ByVal TDryBulb Come Variante, ByVal RelHum Come Variante, ByVal Pressione Come Variante, _
    ByRef HumRatio Come Variante, ByRef TWetBulb Come Variante, ByRef TDewPoint Come Variante, ByRef VapPres Come Variante, _
    ByRef Entalpia dell'aria umida Come Variante, ByRef Volume Aria Umida Come Variante, ByRef Grado Di Saturazione Come Variante)
'
' Funzione di utilità per calcolare il rapporto di umidità, la temperatura del bulbo umido, la temperatura del punto di rugiada,
' pressione del vapore, entalpia dell'aria umida, volume dell'aria umida e grado di saturazione dell'aria fornita
' temperatura a bulbo secco, umidità relativa e pressione.
'
' Argomenti:
' TDryBulb: temperatura del bulbo secco in °F [IP] o °C [SI]
' RelHum: Umidità relativa nell'intervallo [0, 1]
' Pressione: pressione atmosferica in Psi [IP] o Pa [SI]
'
' Ritorna:
' Rapporto di umidità in lb_H2O/lb_Air [IP] o kg_H2O/kg_Air [SI]
' Temperatura del bulbo umido in °F [IP] o °C [SI]
' Temperatura del punto di rugiada in °F [IP] o °C [SI].
' Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
' Entalpia dell'aria umida in Btu/lb [IP] o J/kg [SI]
' Volume specifico di aria umida in ft³/lb [IP] o in m³/kg [SI]
' Grado di saturazione [senza unità]
'
  HumRatio = OttieniRapportoHumFromRelHum(TDryBulb, RelHum, Pressione)
  TWetBulb = OttieniTWetBulbFromHumRatio(TDryBulb, HumRatio, Pressione)
  TDewPoint = OttieniTDewPointFromHumRatio(TDryBulb, HumRatio, Pressione)
  VapPres = GetVapPresFromHumRatio(Rapporto hum, Pressione)
  Entalpia dell'aria umida = GetMoistAirEntalpia(TDryBulb, HumRatio)
  Volume Aria Umida = GetMoistAirVolume(TDryBulb, HumRatio, Pressione)
  Grado Di Saturazione = Ottieni Grado di saturazione (TDryBulb, HumRatio, Pressione)

Fine Sub

Javascript

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
/ **
 * PsychroLib (versione 2.3.0) (https://github.com/psychrometrics/psychrolib)
 * Copyright (c) 2018 D. Thevenard e D. Meyer per l'attuale implementazione della libreria
 * Copyright (c) Manuale ASHRAE 2017 — Fondamenti per equazioni e coefficienti ASHRAE
 * Concesso in licenza con la licenza MIT.
  * /

funzione Psicrometria() {
  / **
   * Panoramica del modulo
   * Contiene funzioni per il calcolo delle proprietà termodinamiche delle miscele gas-vapore
   * e atmosfera standard adatta alla maggior parte delle applicazioni ingegneristiche, fisiche e meteorologiche
   *applicazioni.
      *
   * La maggior parte delle funzioni sono un'implementazione delle formule presenti nel file
   * Manuale ASHRAE 2017 - Fondamenti, in entrambi i sistemi internazionali (SI),
   * e unità imperiali (IP). Si prega di fare riferimento alle informazioni incluse nel
   * ciascuna funzione per il rispettivo riferimento.
      *
   * Esempio (es. Node.JS)
   * // Importa il file PsychroLib
   * var psychrolib = require('psychrolib.js')
   * // Imposta il sistema di unità
   * psychrolib.SetUnitSystem(psychrolib.SI)
   * // Calcola la temperatura del punto di rugiada per una temperatura a bulbo secco di 25 C e un'umidità relativa dell'80%
   * var TDewPoint = psychrolib.GetTDewPointFromRelHum(25.0, 0.80);
   * console.log('TDewPoint: %d', TDewPoint);
   *21.3094
      *
   * Diritto d'autore
   * - Per l'attuale implementazione della libreria
   * Copyright (c) 2018 D. Thevenard e D. Meyer.
   * - Per equazioni e coefficienti pubblicati ASHRAE Handbook — Fundamentals, capitolo 1
   * Copyright (c) Manuale ASHRAE 2017 – Fondamenti (https://www.ashrae.org)
      *
   * Licenza
   *MIT (https://github.com/psychrometrics/psychrolib/LICENSE.txt)
      *
   * Nota degli autori
   *Abbiamo fatto ogni sforzo per garantire che il codice sia adeguato, tuttavia, facciamo no
   * Rappresentazione rispetto alla sua accuratezza. Utilizzare a proprio rischio. Dovresti notarlo
   * un errore o se hai un suggerimento, segnalacelo tramite GitHub all'indirizzo
   * https://github.com/psychromometrics/psychrolib/issues.
      */


  // Funzioni standard
  var ceppo = Matematica.tronco d'albero;
  var esp = Matematica.exp;
  var pow = Matematica.potenza;
  var min = Matematica.min;
  var max = Matematica.max;
  var addominali = Matematica.addominali;


  /**************************************************** ************************************************** ***
   * Costanti globali
   ************************************************** ************************************************** */

  var ZERO_FAHRENHEIT_AS_RANKINE = 459.67;  // Zero gradi Fahrenheit (°F) espressi in gradi Rankine (°R).
                                            // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 39.

  var ZERO_CELSIUS_AS_KELVIN = 273.15;      // Zero gradi Celsius (°C) espressi in Kelvin (K).
                                            // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 39.

  var R_DA_IP = 53.350;               // Costante universale del gas per aria secca (versione IP) in ft lb_Force lb_DryAir⁻¹ R⁻¹.
                                      // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1.

  var R_DA_SI = 287.042;              // Costante universale dei gas per aria secca (versione SI) in J kg_DryAir⁻¹ K⁻¹.
                                      // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1.

  var NON VALIDO = -99999;               // Valore non valido (adimensionale).

  var MAX_ITER_COUNT = 100            // Numero massimo di iterazioni prima di uscire dai cicli while.

  var MIN_HUM_RATIO = 1e-7            // Rapporto di umidità minimo accettabile utilizzato/restituito da qualsiasi funzione.
                                      // Qualsiasi valore superiore a 0 o inferiore a MIN_HUM_RATIO verrà reimpostato su questo valore.

  var FREEZING_POINT_WATER_IP = 32.0  // Punto di congelamento dell'acqua in Fahrenheit.

  var FREEZING_POINT_WATER_SI = 0.0   // Punto di congelamento dell'acqua in gradi Celsius.

  var TRIPLO_POINT_ACQUA_IP = 32.018  // Punto triplo dell'acqua in Fahrenheit.

  var TRIPLO_POINT_ACQUA_SI = 0.01    // Punto triplo dell'acqua in gradi Celsius.



  /**************************************************** ************************************************** ***
   * Funzioni di supporto
   ************************************************** ************************************************** */

  // Sistemi di unità (IP o SI)
  var PSYCHROLIB_UNITÀ = indefinito;

  questo.IP = 1;
  questo.SI = 2;

  // Funzione per impostare il sistema di unità
  // Nota: questa funzione *DEVE ESSERE CHIAMATA* prima che la libreria possa essere utilizzata
  questo.SetUnitSystem = funzione(Sistema di unità) {
    se (SistemaUnità ! = questo.IP && UnitSystem ! = questo.SI) {
      gettare nuovo Errore('UnitSystem deve essere IP o SI');
    }
    PSYCHROLIB_UNITÀ = UnitàSistema;
    // Definisce la tolleranza dei calcoli della temperatura
    // La tolleranza è la stessa in IP e SI
    se (PSYCHROLIB_UNITS == questo.IP)
      PSYCROLIB_TOLERANZA = 0.001 * 9. / 5.;
    altro
      PSYCROLIB_TOLERANZA = 0.001;
  }

  // Sistema di restituzione delle unità in uso.
  questo.GetUnitSystem = funzione() {
    ritorno PSYCROLIB_UNITÀ;
  }

  // Funzione per verificare se l'attuale sistema di unità è SI o IP
  // La funzione termina per errore se il sistema di unità non è definito
  questo.isIP = funzione() {
    se (PSYCHROLIB_UNITS == questo.IP)
      ritorno vero;
    altro se (PSYCHROLIB_UNITS == questo.SI)
      ritorno falso;
    altro
      gettare nuovo Errore("Il sistema di unità non è definito");
  }


  /**************************************************** ************************************************** ***
   * Conversione tra unità di temperatura
   ************************************************** ************************************************** */

  // Funzione di utilità per convertire la temperatura in gradi Rankine (°R)
  // temperatura indicata in gradi Fahrenheit (°F).
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
  questo.GetTRankineFromTFahrenheit = funzione (T_F) { ritorno T_F + ZERO_FAHRENHEIT_AS_RANKINE; }       /* esatto */

  // Funzione di utilità per convertire la temperatura in gradi Fahrenheit (°F)
  // temperatura indicata in gradi Rankine (°R).
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
  questo.GetTFahrenheitFromTRankine = funzione (T_R) { ritorno T_R - ZERO_FAHRENHEIT_AS_RANKINE; }       /* esatto */

  // Funzione di utilità per convertire la temperatura in Kelvin (K)
  // temperatura indicata in gradi Celsius (°C).
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
  questo.GetTKelvinFromTCelsius = funzione (T_C) { ritorno T_C + ZERO_CELSIUS_AS_KELVIN; }               /* esatto */

  // Funzione di utilità per convertire la temperatura in gradi Celsius (°C)
  // data la temperatura in Kelvin (K).
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
  questo.GetTCelsiusFromTKelvin = funzione (T_K) { ritorno T_K - ZERO_CELSIUS_AS_KELVIN; }                /* esatto */

  /**************************************************** ************************************************** ***
   * Conversioni tra punto di rugiada, bulbo umido e umidità relativa
   ************************************************** ************************************************** */

  // Temperatura di ritorno del bulbo umido data la temperatura del bulbo secco, la temperatura del punto di rugiada e la pressione.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
  questo.GetTWetBulbFromTDewPoint = funzione  // (o) Temperatura del bulbo umido in °F [IP] o °C [SI]
    ( TDryBulb                              // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , TDewPoint                             // (i) Temperatura del punto di rugiada in °F [IP] o °C [SI]
    , Pressione                              // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var Rapporto Hum;

    se (!(TDPuntoDiNuova <= TDryBulb))
      gettare nuovo Errore("La temperatura del punto di rugiada è superiore alla temperatura del bulbo secco");

    HumRatio = questo.GetHumRatioFromTDewPoint(TDewPoint, Pressione);
    ritorno questo.GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pressione);
  }

  // Restituisce la temperatura a bulbo umido data la temperatura a bulbo secco, l'umidità relativa e la pressione.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
  questo.GetTWetBulbFromRelHum = funzione // (o) Temperatura del bulbo umido in °F [IP] o °C [SI]
    ( TDryBulb                          // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , RelHum                            // (i) Umidità relativa [0-1]
    , Pressione                          // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var Rapporto Hum;

    se (!(RelHum >= 0. && RelHum <= 1.))
      gettare nuovo Errore("L'umidità relativa è fuori dall'intervallo [0,1]");

    HumRatio = questo.GetHumRatioFromRelHum(TDryBulb, RelHum, Pressione);
    ritorno questo.GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pressione);
  }

  // Umidità relativa restituita data la temperatura di bulbo secco e la temperatura del punto di rugiada.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 22
  questo.GetRelHumFromTDewPoint = funzione  // (o) Umidità relativa [0-1]
    ( TDryBulb                            // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , TDewPoint                           // (i) Temperatura del punto di rugiada in °F [IP] o °C [SI]
    ) {
    var VapPres, SatVapPres;

    se (!(TDPuntoDiNuova <= TDryBulb))
      gettare nuovo Errore("La temperatura del punto di rugiada è superiore alla temperatura del bulbo secco");

    VapPres = questo.GetSatVapPres(TDewPoint);
    SatVapPres = questo.GetSatVapPres(TDryBulb);
    ritorno VapPres / SatVapPres;
  }

  // Umidità relativa restituita data la temperatura a bulbo secco, la temperatura a bulbo umido e la pressione.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
  questo.GetRelHumFromTWetBulb = funzione // (o) Umidità relativa [0-1]
    ( TDryBulb                          // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , TWetBulb                          // (i) Temperatura del bulbo umido in °F [IP] o °C [SI]
    , Pressione                          // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var Rapporto Hum;

    se (!(TWetBulb <= TDryBulb))
      gettare nuovo Errore("La temperatura del bulbo umido è superiore alla temperatura del bulbo secco");

    HumRatio = questo.GetHumRatioFromTWetBulb(TDryBulb, TWetLampadina, Pressione);
    ritorno questo.GetRelHumFromHumRatio(TDryBulb, HumRatio, Pressione);
  }

  // Temperatura del punto di rugiada di ritorno data la temperatura a bulbo secco e l'umidità relativa.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
  questo.GetTDewPointFromRelHum = funzione  // (o) Temperatura del punto di rugiada in °F [IP] o °C [SI]
    ( TDryBulb                            // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , RelHum                              // (i) Umidità relativa [0-1]
    ) {
    var VapPres;

    se (!(RelHum >= 0. && RelHum <= 1.))
      gettare nuovo Errore("L'umidità relativa è fuori dall'intervallo [0,1]");

    VapPres = questo.GetVapPresFromRelHum(TDryBulb, RelHum);
    ritorno questo.GetTDewPointFromVapPres(TDryBulb, VapPres);
  }

  // Temperatura del punto di rugiada di ritorno data la temperatura di bulbo secco, la temperatura di bulbo umido e la pressione.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
  questo.GetTDewPointFromTWetBulb = funzione  // (o) Temperatura del punto di rugiada in °F [IP] o °C [SI]
    ( TDryBulb                              // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , TWetBulb                              // (i) Temperatura del bulbo umido in °F [IP] o °C [SI]
    , Pressione                              // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var Rapporto Hum;

    se (!(TWetBulb <= TDryBulb))
      gettare nuovo Errore("La temperatura del bulbo umido è superiore alla temperatura del bulbo secco");

    HumRatio = questo.GetHumRatioFromTWetBulb(TDryBulb, TWetLampadina, Pressione);
    ritorno questo.GetTDewPointFromHumRatio(TDryBulb, HumRatio, Pressione);
  }


  /**************************************************** ************************************************** ***
   * Conversioni tra punto di rugiada o umidità relativa e pressione di vapore
   ************************************************** ************************************************** */

  // Restituisce la pressione parziale del vapore acqueo in funzione dell'umidità relativa e della temperatura.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 12, 22
  questo.GetVapPresFromRelHum = funzione  // (o) Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
    ( TDryBulb                          // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , RelHum                            // (i) Umidità relativa [0-1]
    ) {

    se (!(RelHum >= 0. && RelHum <= 1.))
      gettare nuovo Errore("L'umidità relativa è fuori dall'intervallo [0,1]");

    ritorno RelHum * questo.GetSatVapPres(TDryBulb);
  }

  // Umidità relativa restituita data la temperatura a bulbo secco e la pressione del vapore.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 12, 22
  questo.GetRelHumFromVapPres = funzione  // (o) Umidità relativa [0-1]
    ( TDryBulb                          // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , VapPres                           // (i) Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
    ) {

    se (!(VapPres >= 0.))
      gettare nuovo Errore("La pressione parziale del vapore acqueo nell'aria umida è negativa");

    ritorno VapPres / questo.GetSatVapPres(TDryBulb);
  }

  // Funzione di supporto che restituisce la derivata del logaritmo naturale della pressione del vapore di saturazione
  // in funzione della temperatura a bulbo secco.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 5 e 6
  questo.dLnPws_ = funzione       // (o) Derivata del logaritmo naturale della tensione di vapore dell'aria satura in Psi [IP] o Pa [SI]
    ( TDryBulb                  // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    ) {
    var dLnPw, T;

    se (questo.isIP())
    {
      T = questo.GetTRankineFromTFahrenheit(TDryBulb);

      se (TDryBulb <= TRIPLE_POINT_WATER_IP)
        dLnPws = 1.0214165E+04 / pow(T, 2) - 5.3765794E-03 + 2 * 1.9202377E-07 * T
                 + 3 * 3.5575832E-10 * pow(T, 2) - 4 * 9.0344688E-14 * pow(T, 3) + 4.1635019 / T;
      altro
        dLnPws = 1.0440397E+04 / pow(T, 2) - 2.7022355E-02 + 2 * 1.2890360E-05 * T
                 - 3 * 2.4780681E-09 * pow(T, 2) + 6.5459673 / T;
    }
    altro
    {
      T = questo.GetTKelvinFromTCelsius(TDryBulb);

      se (TDryBulb <= TRIPLE_POINT_WATER_SI)
        dLnPws = 5.6745359E+03 / pow(T, 2) - 9.677843E-03 + 2 * 6.2215701E-07 * T
                 + 3 * 2.0747825E-09 * pow(T, 2) - 4 * 9.484024E-13 * pow(T, 3) + 4.1635019 / T;
      altro
        dLnPws = 5.8002206E+03 / pow(T, 2) - 4.8640239E-02 + 2 * 4.1764768E-05 * T
                 - 3 * 1.4452093E-08 * pow(T, 2) + 6.5459673 / T;
    }

    ritorno dLnPw;
  }

  // Temperatura del punto di rugiada di ritorno data la temperatura a bulbo secco e la pressione del vapore.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 5 e 6
  // Note: la temperatura del punto di rugiada si risolve invertendo l'equazione dando la pressione del vapore acqueo
  // alla saturazione dalla temperatura anziché utilizzare le regressioni fornite
  // da ASHRAE (eqn. 37 e 38) che sono molto meno accurati e hanno un
  // intervallo di validità più ristretto.
  // Il metodo Newton-Raphson (NR) viene utilizzato sul logaritmo del vapore acqueo
  // pressione in funzione della temperatura, che è una funzione molto fluida
  // La convergenza viene solitamente raggiunta in 3-5 iterazioni.
  // TDryBulb non è realmente necessario in questo caso, viene utilizzato solo per comodità.
  questo.GetTDewPointFromVapPres = funzione // (o) Temperatura del punto di rugiada in °F [IP] o °C [SI]
    ( TDryBulb                            // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , VapPres                             // (i) Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
    ) {
   // Funzione dei limiti del sistema di unità
  var CONFINI              // Dominio di validità delle equazioni

  se (questo.isIP())
  {
    CONFINI = [-148., 392.];   // Dominio di validità delle equazioni
  }
  altro
  {
    CONFINI = [-100., 200.];   // Dominio di validità delle equazioni
  }

  // Limiti oltre i quali non è possibile trovare una soluzione
  se (VapPres < questo.GetSatVapPres(BOUNDS[0]) || VapPres > questo.GetSatVapPres(BOUNDS[1]))
    gettare nuovo Errore("La pressione parziale del vapore acqueo è fuori dal campo di validità delle equazioni");

  // Usiamo NR per approssimare la soluzione.
  // Prima ipotesi
  var TDewPoint = TDryBulb;      // Valore calcolato delle temperature del punto di rugiada, risolto iterativamente in °F [IP] o °C [SI]
  var lnVP = log(VapPres);       // Logaritmo naturale della pressione parziale della pressione del vapore acqueo nell'aria umida

  var TDewPoint_iter;            // Valore di TDewPoint utilizzato nel calcolo NR
  var lnVP_iter;                 // Valore del logaritmo della pressione del vapore acqueo utilizzato nel calcolo NR
  var indice = 1;
  fare
  {
    // Punto corrente
    TDewPoint_iter = TDewPoint;
    lnVP_iter = tronco d'albero(questo.GetSatVapPres(TDewPoint_iter));

    // Derivato della funzione, calcolato analiticamente
    var d_lnVP = questo.dLnPws_(TDewPoint_iter);

    // Nuova stima, delimitata dal dominio di validità dell'eqn. 5 e 6
    TDewPoint = TDewPoint_iter - (lnVP_iter - lnVP) / d_lnVP;
    TDewPoint = max(TDewPoint, CONFINI[0]);
    TDewPoint = min(TDPuntoDew, CONFINI[1]);

    se (indice > MAX_ITER_COUNT)
      gettare nuovo Errore("Convergenza non raggiunta in GetTDewPointFromVapPres. Arresto.");

    indice++;
  }
  mentre (abs(TDPuntoDiNuova - TDewPoint_iter) > PSYCHROLIB_TOLERANZA);
  ritorno min(TDPuntoDew, TDryBulb);
  }

  // Pressione del vapore di ritorno data la temperatura del punto di rugiada.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 36
  questo.GetVapPresFromTDewPoint = funzione // (o) Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
    ( TDewPoint                           // (i) Temperatura del punto di rugiada in °F [IP] o °C [SI]
    ) {
    ritorno questo.GetSatVapPres(TDewPoint);
  }


  /**************************************************** ************************************************** ***
   * Conversioni dalla temperatura del bulbo umido, dalla temperatura del punto di rugiada o dal rapporto umidità relativa/umidità
   ************************************************** ************************************************** */

  // Restituisce la temperatura a bulbo umido data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 33 e 35 risolti per Tstar
  questo.GetTWetBulbFromHumRatio = funzione // (o) Temperatura del bulbo umido in °F [IP] o °C [SI]
    ( TDryBulb                            // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , HumRatio                            // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    , Pressione                            // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    // Dichiarazioni
    var stella;
    var punto di rugiada, TWetLampadina, TWetBulbSup, TWetBulbInf, Rapporto Hum limitato;
    var indice = 1;

    se (!(Rapporto ronzio >= 0.))
      gettare nuovo Errore("Il rapporto di umidità è negativo");
    Rapporto Hum limitato = max(Rapporto rumore, MIN_UM_RATIO);

    TDewPoint = questo.GetTDewPointFromHumRatio(TDryBulb, Rapporto Hum limitato, Pressione);

    // Ipotesi iniziali
    TWetBulbSup = TDryBulb;
    TWetBulbInf = TDewPoint;
    TWetBulb = (TWetBulbInf + TWetBulbSup) / 2.;

    // Ciclo di bisezione
    mentre ((TWetBulbSup - TWetBulbInf) > PSYCHROLIB_TOLERANZA) {
      // Calcola il rapporto di umidità alla temperatura Tstar
      Wstar = questo.GetHumRatioFromTWetBulb(TDryBulb, TWetLampadina, Pressione);

      // Ottieni nuovi limiti
      se (Wstar > Rapporto Hum limitato)
        TWetBulbSup = TWetLampadina;
      altro
        TWetBulbInf = TWetLampadina;

      // Nuova ipotesi sulla temperatura del bulbo umido
      TWetBulb = (TWetBulbSup + TWetBulbInf) / 2.;

      se (indice > MAX_ITER_COUNT)
        gettare nuovo Errore("Convergenza non raggiunta in GetTWetBulbFromHumRatio. Arresto.");

      indice++;
    }

    ritorno TWetLampadina;
  }

  // Rapporto di umidità di ritorno data la temperatura di bulbo secco, la temperatura di bulbo umido e la pressione.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 33 e 35
  questo.GetHumRatioFromTWetBulb = funzione // (o) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    ( TDryBulb                            // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , TWetBulb                            // (i) Temperatura del bulbo umido in °F [IP] o °C [SI]
    , Pressione                            // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var Wsstar;
    HumRatio = NON VALIDO

    se (!(TWetBulb <= TDryBulb))
      gettare nuovo Errore("La temperatura del bulbo umido è superiore alla temperatura del bulbo secco");

      Wsstar = questo.GetSatHumRatio(TWetBulb, Pressione);

      se (questo.isIP())
      {
        se (TWetBulb >= FREEZING_POINT_WATER_IP)
          HumRatio = ((1093. - 0.556 * TWetBulb) * Wsstar - 0.240 * (TDryBulb - TWetBulb))
          / (1093. + 0.444 * TDryBulb - TWetBulb);
        altro
          HumRatio = ((1220. - 0.04 * TWetBulb) * Wsstar - 0.240 * (TDryBulb - TWetBulb))
          / (1220. + 0.444 * TDryBulb - 0.48 * TWetBulb);
      }
      altro
      {
        se (TWetBulb >= FREEZING_POINT_WATER_SI)
          HumRatio = ((2501. - 2.326 * TWetBulb) * Wsstar - 1.006 * (TDryBulb - TWetBulb))
             / (2501. + 1.86 * TDryBulb - 4.186 * TWetBulb);
        altro
          HumRatio = ((2830. - 0.24 * TWetBulb) * Wsstar - 1.006 * (TDryBulb - TWetBulb))
             / (2830. + 1.86 * TDryBulb - 2.1 * TWetBulb);
      }
      // Controllo di validità.
      ritorno max(Rapporto rumore, MIN_UM_RATIO);
    }

  // Rapporto di umidità di ritorno data la temperatura a bulbo secco, l'umidità relativa e la pressione.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
  questo.GetHumRatioFromRelHum = funzione // (o) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    ( TDryBulb                          // (i) Temperatura a bulbo secco [F]
    , RelHum                            // (i) Umidità relativa [0-1]
    , Pressione                          // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var VapPres;

    se (!(RelHum >= 0. && RelHum <= 1.))
      gettare nuovo Errore("L'umidità relativa è fuori dall'intervallo [0,1]");

    VapPres = questo.GetVapPresFromRelHum(TDryBulb, RelHum);
    ritorno questo.GetHumRatioFromVapPres(VapPres, Pressione);
  }

  // Restituisce l'umidità relativa data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
  questo.GetRelHumFromHumRatio = funzione // (o) Umidità relativa [0-1]
    ( TDryBulb                          // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , HumRatio                          // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    , Pressione                          // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var VapPres;

    se (!(Rapporto ronzio >= 0.))
      gettare nuovo Errore("Il rapporto di umidità è negativo");

    VapPres = questo.GetVapPresFromHumRatio(Rapporto Hum, Pressione);
    ritorno questo.GetRelHumFromVapPres(TDryBulb, VapPres);
  }

  // Rapporto di umidità di ritorno data la temperatura e la pressione del punto di rugiada.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
  questo.GetHumRatioFromTDewPoint = funzione  // (o) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    ( TDewPoint                             // (i) Temperatura del punto di rugiada in °F [IP] o °C [SI]
    , Pressione                              // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var VapPres;

    VapPres = questo.GetSatVapPres(TDewPoint);
    ritorno questo.GetHumRatioFromVapPres(VapPres, Pressione);
  }

  // Temperatura del punto di rugiada di ritorno data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
  questo.GetTDewPointFromHumRatio = funzione  // (o) Temperatura del punto di rugiada in °F [IP] o °C [SI]
    ( TDryBulb                              // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , HumRatio                              // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    , Pressione                              // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var VapPres;

    se (!(Rapporto ronzio >= 0.))
      gettare nuovo Errore("Il rapporto di umidità è negativo");

    VapPres = questo.GetVapPresFromHumRatio(Rapporto Hum, Pressione);
    ritorno questo.GetTDewPointFromVapPres(TDryBulb, VapPres);
  }


  /**************************************************** ************************************************** ***
   * Conversioni tra rapporto di umidità e pressione di vapore
   ************************************************** ************************************************** */

  // Rapporto dell'umidità di ritorno data la pressione del vapore acqueo e la pressione atmosferica.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 20
  questo.GetHumRatioFromVapPres = funzione  // (o) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    ( VapPres                             // (i) Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
    , Pressione                            // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var Rapporto Hum;

    se (!(VapPres >= 0.))
      gettare nuovo Errore("La pressione parziale del vapore acqueo nell'aria umida è negativa");

    HumRatio = 0.621945 * VapPres / (Pressione - VapPres);

    // Controllo di validità.
    ritorno max(Rapporto rumore, MIN_UM_RATIO);
  }

  // Pressione del vapore di ritorno dati il ​​rapporto di umidità e la pressione.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 20 risolto per pw
  questo.GetVapPresFromHumRatio = funzione  // (o) Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
    ( HumRatio                            // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    , Pressione                            // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var VapPres, Rapporto Hum limitato;

    se (!(Rapporto ronzio >= 0.))
      gettare nuovo Errore("Il rapporto di umidità è negativo");
    Rapporto Hum limitato = max(Rapporto rumore, MIN_UM_RATIO);

    VapPres = Pressione * Rapporto Hum limitato / (0.621945 + Rapporto Hum Limitato);
    ritorno VapPres;
  }


  /**************************************************** ************************************************** ***
   *Conversioni tra rapporto di umidità e umidità specifica
   ************************************************** ************************************************** */

  // Restituisce l'umidità specifica dal rapporto di umidità (noto anche come rapporto di miscelazione)
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 9b
  questo.GetSpecificHumFromHumRatio = funzione  // (o) Rapporto di umidità specifica in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    ( HumRatio                                // (i) Rapporto di umidità in lb_H₂O lb_Dry_Air⁻¹ [IP] o kg_H₂O kg_Dry_Air⁻¹ [SI]
    ) {
    var Rapporto Hum limitato;
    se (!(Rapporto ronzio >= 0.))
      gettare nuovo Errore("Il rapporto di umidità è negativo");
    Rapporto Hum limitato = max(Rapporto rumore, MIN_UM_RATIO);

    ritorno Rapporto Hum limitato / (1.0 + Rapporto Hum Limitato);
  }

  // Restituisce il rapporto di umidità (noto anche come rapporto di miscelazione) dall'umidità specifica
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 9b (risolto per il rapporto di umidità)
  questo.GetHumRatioFromSpecificHum = funzione  // (o) Rapporto di umidità in lb_H₂O lb_Dry_Air⁻¹ [IP] o kg_H₂O kg_Dry_Air⁻¹ [SI]
    ( SpecificHum                             // (i) Rapporto di umidità specifica in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    ) {
    var Rapporto Hum;

    se (!(SpecificHum >= 0.0 && SpecificHum < 1.0))
      gettare nuovo Errore("L'umidità specifica è fuori dall'intervallo [0, 1[");

    HumRatio = SpecificHum / (1.0 - SpecificHum);

    // Controllo di validità
    ritorno max(Rapporto rumore, MIN_UM_RATIO);
  }


  /**************************************************** ************************************************** ***
   * Calcoli dell'aria secca
   ************************************************** ************************************************** */

  // Entalpia dell'aria secca restituita data la temperatura a bulbo secco.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 28
  questo.GetDryAirEntalpia = funzione // (o) Entalpia dell'aria secca in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
    ( TDryBulb                      // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    ) {
    se (questo.isIP())
      ritorno 0.240 * TDryBulb;
    altro
      ritorno 1006. * TDryBulb;
  }

  // Densità di ritorno dell'aria secca date la temperatura e la pressione del bulbo secco.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
  // Note: eqn 14 per la perfetta relazione tra i gas per l'aria secca.
  // Eqn 1 per la costante universale dei gas.
  // Il fattore 144 in IP serve per la conversione di Psi = lb in⁻² in lb ft⁻².
  questo.GetDryAirDensity = funzione  // (o) Densità dell'aria secca in lb ft⁻³ [IP] o kg m⁻³ [SI]
    ( TDryBulb                      // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , Pressione                      // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    se (questo.isIP())
      ritorno (144. * Pressione) / R_DA_IP / questo.GetTRankineFromTFahrenheit(TDryBulb);
    altro
      ritorno Pressione / R_DA_SI / questo.GetTKelvinFromTCelsius(TDryBulb);
  }

  // Volume di aria secca restituito in base alla temperatura e alla pressione del bulbo secco.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1.
  // Note: eqn 14 per la perfetta relazione tra i gas per l'aria secca.
  // Eqn 1 per la costante universale dei gas.
  // Il fattore 144 in IP serve per la conversione di Psi = lb in⁻² in lb ft⁻².
  questo.GetDryAirVolume = funzione // (o) Volume di aria secca ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
    ( TDryBulb                    // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , Pressione                    // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    se (questo.isIP())
      ritorno R_DA_IP * questo.GetTRankineFromTFahrenheit(TDryBulb) / (144. * Pressione);
    altro
      ritorno R_DA_SI * questo.GetTKelvinFromTCelsius(TDryBulb) / Pressione;
  }

  // Restituisce la temperatura del bulbo secco dal rapporto entalpia e umidità.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 30.
  // Note: basato sulla funzione `GetMoistAirEnthalpy`, riorganizzato per la temperatura.
  questo.GetTDryBulbFromEnthalpyAndHumRatio = funzione   // (o) Temperatura a bulbo secco in °F [IP] o °C [SI]
    ( Entalpia dell'aria umida                                 // (i) Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹
    , HumRatio                                         // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    ) {
    var Rapporto Hum limitato;
    se (!(Rapporto ronzio >= 0.))
      gettare nuovo Errore("Il rapporto di umidità è negativo");
    Rapporto Hum limitato = max(Rapporto rumore, MIN_UM_RATIO);

    se (questo.isIP())
      ritorno (Entalpia dell'aria umida - 1061.0 * Rapporto Hum limitato) / (0.240 + 0.444 * Rapporto Hum Limitato);
    altro
      ritorno (Entalpia dell'aria umida / 1000.0 - 2501.0 * Rapporto Hum limitato) / (1.006 + 1.86 * Rapporto Hum Limitato);
    }

  // Rapporto dell'umidità di ritorno tra entalpia e temperatura a bulbo secco.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 30.
  // Note: basato sulla funzione `GetMoistAirEnthalpy`, riorganizzato per il rapporto di umidità.
  questo.GetHumRatioFromEnthalpyAndTDryBulb = funzione   // (o) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻
    ( Entalpia dell'aria umida                                 // (i) Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹
    , TDryBulb                                         // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    ) {
    var Rapporto Hum;
    se (questo.isIP())
      HumRatio = (Entalpia dell'aria umida - 0.240 * TDryBulb) / (1061.0 + 0.444 * TDryBulb);
    altro
      HumRatio = (Entalpia dell'aria umida / 1000.0 - 1.006 * TDryBulb) / (2501.0 + 1.86 * TDryBulb);

    // Controllo di validità.
    ritorno max(Rapporto rumore, MIN_UM_RATIO);
    }


  /**************************************************** ************************************************** ***
   * Calcoli dell'aria satura
   ************************************************** ************************************************** */

  // Pressione del vapore di saturazione di ritorno data la temperatura a bulbo secco.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 5 e 6
  // Nota importante: le formule ASHRAE sono definite sopra e sotto il punto di congelamento ma hanno
  // una discontinuità al punto di congelamento. Questa è una piccola imprecisione da parte di ASHRAE: le formule
  // dovrebbe essere definito sopra e sotto il punto triplo dell'acqua (non il punto di contatto), nel qual caso
  // la discontinuità svanisce. È essenziale utilizzare il punto triplo dell'acqua altrimenti funzionerà
  // GetTDewPointFromVapPres, che inverte la funzione presente, non converge correttamente
  // il punto di congelamento.
  questo.GetSatVapPres = funzione // (o) Pressione del vapore dell'aria satura in Psi [IP] o Pa [SI]
    ( TDryBulb                  // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    ) {
    var LnPw, T;

    se (questo.isIP())
    {
      se (!(TDryBulb >= -148. && TDryBulb <= 392.))
        gettare nuovo Errore("La temperatura del bulbo secco è fuori dall'intervallo [-148, 392]");

      T = questo.GetTRankineFromTFahrenheit(TDryBulb);
      se (TDryBulb <= TRIPLE_POINT_WATER_IP)
        LnPws = (-1.0214165E+04 / T - 4.8932428 - 5.3765794E-03 * T + 1.9202377E-07 * T * T
                + 3.5575832E-10 * pow(T, 3) - 9.0344688E-14 * pow(T, 4) + 4.1635019 * registro(T));
      altro
        LnPws = -1.0440397E+04 / T - 1.1294650E+01 - 2.7022355E-02 * T + 1.2890360E-05 * T * T
                - 2.4780681E-09 * pow(T, 3) + 6.5459673 * registro(T);
    }
    altro
    {
      se (!(TDryBulb >= -100. && TDryBulb <= 200.))
        gettare nuovo Errore("La temperatura del bulbo secco è fuori dall'intervallo [-100, 200]");

      T = questo.GetTKelvinFromTCelsius(TDryBulb);
      se (TDryBulb <= TRIPLE_POINT_WATER_SI)
        LnPws = -5.6745359E+03 / T + 6.3925247 - 9.677843E-03 * T + 6.2215701E-07 * T * T
                + 2.0747825E-09 * pow(T, 3) - 9.484024E-13 * pow(T, 4) + 4.1635019 * registro(T);
      altro
        LnPws = -5.8002206E+03 / T + 1.3914993 - 4.8640239E-02 * T + 4.1764768E-05 * T * T
                - 1.4452093E-08 * pow(T, 3) + 6.5459673 * registro(T);
    }

    ritorno exp(LnPws);
  }

  // Rapporto di umidità di ritorno dell'aria satura data la temperatura e la pressione a bulbo secco.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 36, risolto per W
  questo.GetSatHumRatio = funzione  // (o) Rapporto di umidità dell'aria satura in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    ( TDryBulb                    // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , Pressione                    // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var SatVaporPres, Rapporto SatHum;

    SatVaporPres = questo.GetSatVapPres(TDryBulb);
    SatHumRatio = 0.621945 * SatVaporPres / (Pressione - SatVaporPres);

    // Controllo di validità.
    ritorno max(Rapporto hum sat, MIN_UM_RATIO);
  }

  // Restituisce l'entalpia dell'aria satura data la temperatura e la pressione a bulbo secco.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
  questo.GetSatAirEntalpia = funzione // (o) Entalpia dell'aria satura in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
    ( TDryBulb                      // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , Pressione                      // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    ritorno questo.GetMoistAirEntalpia(TDryBulb, questo.GetSatHumRatio(TDryBulb, Pressione));
  }


  /**************************************************** ************************************************** ***
   * Calcoli dell'aria umida
   ************************************************** ************************************************** */

  // Ritorno Deficit di pressione del vapore data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
  // Riferimento: vedere Oke (1987) eqn. 2.13a
  questo.GetVaporPressureDeficit = funzione  // (o) Deficit di pressione del vapore in Psi [IP] o Pa [SI]
    ( TDryBulb            // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , HumRatio            // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    , Pressione            // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var RelHum;

    se (!(Rapporto ronzio >= 0.))
      gettare nuovo Errore("Il rapporto di umidità è negativo");

    RelHum = questo.GetRelHumFromHumRatio(TDryBulb, HumRatio, Pressione);
    ritorno questo.GetSatVapPres(TDryBulb) * (1. - RelHum);
  }

  // Restituisce il grado di saturazione (ovvero il rapporto di umidità dell'aria/rapporto di umidità dell'aria alla saturazione
  // alla stessa temperatura e pressione) data la temperatura a bulbo secco, il rapporto di umidità e la pressione atmosferica.
  // Riferimento: Manuale ASHRAE - Fondamenti (2009) cap. 1 eq. 12
  // Note: la definizione è assente nel Manuale 2017
  questo.GetDegreeOfSaturation = funzione // (o) Grado di saturazione (senza unità)
    ( TDryBulb                          // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , HumRatio                          // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    , Pressione                          // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var Rapporto Hum limitato;

    se (!(Rapporto ronzio >= 0.))
      gettare nuovo Errore("Il rapporto di umidità è negativo");
    Rapporto Hum limitato = max(Rapporto rumore, MIN_UM_RATIO);

    ritorno Rapporto Hum limitato / questo.GetSatHumRatio(TDryBulb, Pressione);
  }

  // L'entalpia dell'aria umida restituita data la temperatura a bulbo secco e il rapporto di umidità.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 30
  questo.GetMoistAirEntalpia = funzione // (o) Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
    ( TDryBulb                        // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , HumRatio                        // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    ) {
    var Rapporto Hum limitato;

    se (!(Rapporto ronzio >= 0.))
      gettare nuovo Errore("Il rapporto di umidità è negativo");
    Rapporto Hum limitato = max(Rapporto rumore, MIN_UM_RATIO);

    se (questo.isIP())
      ritorno 0.240 * TDryBulb + Rapporto Hum limitato * (1061. + 0.444 * TDryBulb);
    altro
      ritorno (1.006 * TDryBulb + Rapporto Hum limitato * (2501. + 1.86 * TDryBulb)) * 1000.;
  }

  // Restituisce il volume specifico dell'aria umida in base alla temperatura a bulbo secco, al rapporto di umidità e alla pressione.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 26
  // Note: in unità IP, R_DA_IP / 144 equivale a 0,370486 che è il coefficiente che appare nell'eqn 26.
  // Il fattore 144 serve per la conversione di Psi = lb in⁻² in lb ft⁻².
  questo.GetMoistAirVolume = funzione // (o) Volume specifico ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
    ( TDryBulb                      // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , HumRatio                      // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    , Pressione                      // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var Rapporto Hum limitato;

    se (!(Rapporto ronzio >= 0.))
      gettare nuovo Errore("Il rapporto di umidità è negativo");
    Rapporto Hum limitato = max(Rapporto rumore, MIN_UM_RATIO);

    se (questo.isIP())
      ritorno R_DA_IP * questo.GetTRankineFromTFahrenheit(TDryBulb) * (1. + 1.607858 * Rapporto Hum limitato) / (144. * Pressione);
    altro
      ritorno R_DA_SI * questo.GetTKelvinFromTCelsius(TDryBulb) * (1. + 1.607858 * Rapporto Hum limitato) / Pressione;
  }

  // Temperatura di ritorno a bulbo secco dato il volume specifico dell'aria umida, il rapporto di umidità e la pressione.
  // Riferimento:
  // Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 26
  // Appunti:
  // In unità IP, R_DA_IP / 144 equivale a 0,370486 che è il coefficiente che appare nell'eqn 26
  // Il fattore 144 serve per la conversione di Psi = lb in⁻² in lb ft⁻².
  // Basato sulla funzione "GetMoistAirVolume", riorganizzato per la temperatura a bulbo secco.
  questo.GetTDryBulbFromMoistAirVolumeAndHumRatio = funzione  // (o) Temperatura a bulbo secco in °F [IP] o °C [SI]
    ( Volume Aria Umida                                        // (i) Volume specifico di aria umida in ft³ lb⁻¹ di aria secca [IP] o in m³ kg⁻¹ di aria secca [SI]
    , HumRatio                                              // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    , Pressione                                              // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var Rapporto Hum limitato;

    se (!(Rapporto ronzio >= 0.))
      gettare nuovo Errore("Il rapporto di umidità è negativo");
    Rapporto Hum limitato = max(Rapporto rumore, MIN_UM_RATIO);

    se (questo.isIP())
      ritorno questo.GetTFahrenheitFromTRankine(MoistAirVolume * (144 * Pressione) / (R_DA_IP * (1 + 1.607858 * Rapporto Hum limitato)));
    altro
      ritorno  questo.GetTCelsiusFromTKelvin(MoistAirVolume * Pressione / (R_DA_SI * (1 + 1.607858 * Rapporto Hum limitato)));
  }

  // Restituisce la densità dell'aria umida in base al rapporto di umidità, alla temperatura del bulbo secco e alla pressione.
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 11
  questo.GetMoistAirDensity = funzione  // (o) Densità dell'aria umida in lb ft⁻³ [IP] o kg m⁻³ [SI]
    ( TDryBulb                        // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , HumRatio                        // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
    , Pressione                        // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var Rapporto Hum limitato;

    se (!(Rapporto ronzio >= 0.))
      gettare nuovo Errore("Il rapporto di umidità è negativo");
    Rapporto Hum limitato = max(Rapporto rumore, MIN_UM_RATIO);

    ritorno (1. + Rapporto Hum limitato) / questo.GetMoistAirVolume(TDryBulb, Rapporto Hum limitato, Pressione);
  }


  /**************************************************** ************************************************** ***
   *Atmosfera standard
   ************************************************** ************************************************** */

  // Restituisce la pressione barometrica atmosferica standard, data l'elevazione (altitudine).
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 3
  questo.GetStandardAtmPressure = funzione  // (o) Pressione barometrica atmosferica standard in Psi [IP] o Pa [SI]
    ( Altitudine                            // (i) Altitudine in piedi [IP] o m [SI]
    ) {
    var Pressione;

    se (questo.isIP())
      Pressione = 14.696 * pow(1. - 6.8754e-06 * Altitudine, 5.2559);
    altro
      Pressione = 101325. * pow(1. - 2.25577e-05 * Altitudine, 5.2559);
    ritorno Pressione;
  }

  // Restituisce la temperatura atmosferica standard, data l'elevazione (altitudine).
  // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 4
  questo.GetStandardAtmTemperatura = funzione // (o) Temperatura a bulbo secco dell'atmosfera standard in °F [IP] o °C [SI]
    ( Altitudine                              // (i) Altitudine in piedi [IP] o m [SI]
    ) {
    var Temperatura;
    se (questo.isIP())
      Temperatura = 59. - 0.00356620 * Altitudine;
    altro
      Temperatura = 15. - 0.0065 * Altitudine;
    ritorno Temperatura;
  }

  // Pressione di ritorno al livello del mare data la temperatura a bulbo secco, l'altitudine sul livello del mare e la pressione.
  // Riferimento: Hess SL, Introduzione alla meteorologia teorica, Holt Rinehart e Winston, NY 1959,
  // cap. 6,5; Stull RB, Meteorologia per scienziati e ingegneri, 2a edizione,
  // Brooks/Cole 2000, cap. 1.
  // Note: la procedura standard per gli Stati Uniti prevede l'utilizzo della media per TDryBulb
  // della temperatura attuale della stazione e della temperatura della stazione di 12 ore fa.
  questo.GetSeaLevelPressure = funzione // (o) Pressione barometrica al livello del mare in Psi [IP] o Pa [SI]
    ( StnPressione                     // (i) Pressione osservata nella stazione in Psi [IP] o Pa [SI]
    , Altitudine                        // (i) Altitudine sopra il livello del mare in piedi [IP] o m [SI]
    , TDryBulb                        // (i) Temperatura a bulbo secco ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
    ) {
      var Colonna, H;
      se (questo.isIP())
      {
        // Calcola la temperatura media nella colonna d'aria, assumendo un intervallo di tempo
        // di 3,6 °F/1000 piedi
        TColonna = TDryBulb + 0.0036 * Altitudine / 2.;

        // Determina l'altezza della scala
        H = 53.351 * questo.GetTRankineFromTFahrenheit(TColumn);
      }
      altro
      {
        // Calcola la temperatura media nella colonna d'aria, assumendo un intervallo di tempo
        // di 6,5 °C/km
        TColonna = TDryBulb + 0.0065 * Altitudine / 2.;

        // Determina l'altezza della scala
        H = 287.055 * questo.GetTKelvinFromTCelsius(TColumna) / 9.807;
      }

      // Calcola la pressione a livello del mare
      var Pressione al livello del mare = StnPressione * exp(Altitudine / H);
      ritorno Pressione al livello del mare;
  }

  // Pressione della stazione di ritorno dalla pressione a livello del mare
  // Riferimento: vedere 'GetSeaLevelPressure'
  // Note: questa funzione è esattamente l'inverso di 'GetSeaLevelPressure'.
  questo.GetStationPressure = funzione  // (o) Pressione della stazione in Psi [IP] o Pa [SI]
    ( Pressione al livello del mare                // (i) Pressione barometrica al livello del mare in Psi [IP] o Pa [SI]
    , Altitudine                        // (i) Altitudine sopra il livello del mare in piedi [IP] o m [SI]
    , TDryBulb                        // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    ) {
    ritorno Pressione al livello del mare / questo.GetSeaLevelPressure(1., Altitudine, TDryBulb);
  }


  /**************************************************** ************************************************** ***
   * Funzioni per impostare tutti i valori psicrometrici
   ************************************************** ************************************************** */

  // Funzione di utilità per calcolare il rapporto di umidità, la temperatura del punto di rugiada, l'umidità relativa,
  // pressione del vapore, entalpia dell'aria umida, volume dell'aria umida e grado di saturazione dell'aria fornita
  // temperatura a bulbo secco, temperatura a bulbo umido e pressione.
  questo.CalcPsychrometricsFromTWetBulb = funzione
    / **
     * HumRatio // (o) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
     * TDewPoint // (o) Temperatura del punto di rugiada in °F [IP] o °C [SI]
     * RelHum // (o) Umidità relativa [0-1]
     * VapPres // (o) Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
     * MoistAirEntalpia // (o) Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
     * MoistAirVolume // (o) Volume specifico ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
     * DegreeOfSaturation // (o) Grado di saturazione [senza unità]
     */
    ( TDryBulb            // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , TWetBulb            // (i) Temperatura del bulbo umido in °F [IP] o °C [SI]
    , Pressione            // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var HumRatio = questo.GetHumRatioFromTWetBulb(TDryBulb, TWetLampadina, Pressione);
    var TDewPoint = questo.GetTDewPointFromHumRatio(TDryBulb, HumRatio, Pressione);
    var RelHum = questo.GetRelHumFromHumRatio(TDryBulb, HumRatio, Pressione);
    var VapPres = questo.GetVapPresFromHumRatio(Rapporto Hum, Pressione);
    var Entalpia dell'aria umida = questo.GetMoistAirEntalpia(TDryBulb, HumRatio);
    var Volume Aria Umida = questo.GetMoistAirVolume(TDryBulb, HumRatio, Pressione);
    var Grado Di Saturazione = questo.GetDegreeOfSaturation(TDryBulb, HumRatio, Pressione);
    ritorno [Rapporto di ronzio, punto di rugiada, RelHum, VapPres, Entalpia dell'aria umida, Volumeariaumida, Grado Di Saturazione];
  }

  // Funzione di utilità per calcolare il rapporto di umidità, la temperatura del bulbo umido, l'umidità relativa,
  // pressione del vapore, entalpia dell'aria umida, volume dell'aria umida e grado di saturazione dell'aria fornita
  // temperatura del bulbo secco, temperatura del punto di rugiada e pressione.
  questo.CalcPsychrometricsFromTDewPoint = funzione
    / **
     * HumRatio // (o) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
     * TWetBulb // (o) Temperatura del bulbo umido in °F [IP] o °C [SI]
     * RelHum // (o) Umidità relativa [0-1]
     * VapPres // (o) Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
     * MoistAirEntalpia // (o) Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
     * MoistAirVolume // (o) Volume specifico ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
     * DegreeOfSaturation // (o) Grado di saturazione [senza unità]
     */
    ( TDryBulb            // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , TDewPoint           // (i) Temperatura del punto di rugiada in °F [IP] o °C [SI]
    , Pressione            // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var HumRatio = questo.GetHumRatioFromTDewPoint(TDewPoint, Pressione);
    var TWetBulb = questo.GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pressione);
    var RelHum = questo.GetRelHumFromHumRatio(TDryBulb, HumRatio, Pressione);
    var VapPres = questo.GetVapPresFromHumRatio(Rapporto Hum, Pressione);
    var Entalpia dell'aria umida = questo.GetMoistAirEntalpia(TDryBulb, HumRatio);
    var Volume Aria Umida = questo.GetMoistAirVolume(TDryBulb, HumRatio, Pressione);
    var Grado Di Saturazione = questo.GetDegreeOfSaturation(TDryBulb, HumRatio, Pressione);
    ritorno [Rapporto di ronzio, TWetLampadina, RelHum, VapPres, Entalpia dell'aria umida, Volumeariaumida, Grado Di Saturazione];
  }

  // Funzione di utilità per calcolare il rapporto di umidità, la temperatura del bulbo umido, la temperatura del punto di rugiada,
  // pressione del vapore, entalpia dell'aria umida, volume dell'aria umida e grado di saturazione dell'aria fornita
  // temperatura a bulbo secco, umidità relativa e pressione.
  questo.CalcPsychrometricsFromRelHum = funzione
    / **
     * HumRatio // (o) Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
     * TWetBulb // (o) Temperatura del bulbo umido in °F [IP] o °C [SI]
     * TDewPoint // (o) Temperatura del punto di rugiada in °F [IP] o °C [SI]
     *VapPres // (o) Pressione parziale del vapore acqueo nell'aria umida [Psi]
     * MoistAirEntalpia // (o) Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
     * MoistAirVolume // (o) Volume specifico ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
     * DegreeOfSaturation // (o) Grado di saturazione [senza unità]
    */
    ( TDryBulb            // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
    , RelHum              // (i) Umidità relativa [0-1]
    , Pressione            // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
    ) {
    var HumRatio = questo.GetHumRatioFromRelHum(TDryBulb, RelHum, Pressione);
    var TWetBulb = questo.GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pressione);
    var TDewPoint = questo.GetTDewPointFromHumRatio(TDryBulb, HumRatio, Pressione);
    var VapPres = questo.GetVapPresFromHumRatio(Rapporto Hum, Pressione);
    var Entalpia dell'aria umida = questo.GetMoistAirEntalpia(TDryBulb, HumRatio);
    var Volume Aria Umida = questo.GetMoistAirVolume(TDryBulb, HumRatio, Pressione);
    var Grado Di Saturazione = questo.GetDegreeOfSaturation(TDryBulb, HumRatio, Pressione);
    ritorno [Rapporto di ronzio, TWetLampadina, punto di rugiada, VapPres, Entalpia dell'aria umida, Volumeariaumida, Grado Di Saturazione];
  }
}

// https://github.com/umdjs/umd
(funzione (radice, fabbrica) {
  se (tipo di definire === 'funzione' && definire.amd) {
      // AMD. Registrati come modulo anonimo.
      definire([], fabbrica);
  } altro se (tipo di modulo === 'oggetto' && modulo.export) {
      // Nodo. Non funziona con CommonJS rigoroso, ma
      // solo ambienti simili a CommonJS che supportano module.exports,
      // come Node.
      module.exports = fabbrica();
  } altro {
      // Globali del browser (la root è la finestra)
      root.psychrolib = fabbrica();
}
}(tipo di se stesso !== 'non definito' ? se stesso : questo, funzione () {
  ritorno nuovo Psicrometria();
}));

C

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
/ **
 * PsychroLib (versione 2.3.0) (https://github.com/psychrometrics/psychrolib)
 * Copyright (c) 2018 D. Thevenard e D. Meyer per l'attuale implementazione della libreria
 * Copyright (c) Manuale ASHRAE 2017 — Fondamenti per equazioni e coefficienti ASHRAE
 * Concesso in licenza con la licenza MIT.
  *
 * Panoramica del modulo
 * Contiene funzioni per il calcolo delle proprietà termodinamiche delle miscele gas-vapore
 * e atmosfera standard adatta alla maggior parte delle applicazioni ingegneristiche, fisiche e meteorologiche
 *applicazioni.
  *
 * La maggior parte delle funzioni sono un'implementazione delle formule presenti nel file
 * Manuale ASHRAE 2017 - Fondamenti, in entrambi i sistemi internazionali (SI),
 * e unità imperiali (IP). Si prega di fare riferimento alle informazioni incluse nel
 * ciascuna funzione per il rispettivo riferimento.
  *
 * Esempio
 * #include "psychrolib.h"
 * // Imposta il sistema di unità, ad esempio su SI (può essere 'SI' o 'IP')
 * ImpostaSistemaUnità(SI);
 * // Calcola la temperatura del punto di rugiada per una temperatura a bulbo secco di 25 C e un'umidità relativa dell'80%
 * double TDewPoint = GetTDewPointFromRelHum(25.0, 0.80);
 * printf("%lg", TDewPoint);
 * 21.3094
  *
 * Diritto d'autore
 * - Per l'attuale implementazione della libreria
 * Copyright (c) 2018 D. Thevenard e D. Meyer.
 * - Per equazioni e coefficienti pubblicati ASHRAE Handbook — Fundamentals, capitolo 1
 * Copyright (c) Manuale ASHRAE 2017 – Fondamenti (https://www.ashrae.org)
  *
 * Licenza
 *MIT (https://github.com/psychrometrics/psychrolib/LICENSE.txt)
  *
 * Nota degli autori
 *Abbiamo fatto ogni sforzo per garantire che il codice sia adeguato, tuttavia, facciamo no
 * Rappresentazione rispetto alla sua accuratezza. Utilizzare a proprio rischio. Dovresti notarlo
 * un errore o se hai un suggerimento, segnalacelo tramite GitHub all'indirizzo
 * https://github.com/psychromometrics/psychrolib/issues.
  * /

// File di intestazione C standard
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

// Intestazione specifica per questo file
#include "psychrolib.h"


/**************************************************** ************************************************** ***
 * Costanti globali
 ************************************************** ************************************************** */

# definisce ZERO_FAHRENHEIT_AS_RANKINE 459.67  // Zero gradi Fahrenheit (°F) espressi in gradi Rankine (°R).
                                            // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 39.

# definisce ZERO_CELSIUS_AS_KELVIN 273.15      // Zero gradi Celsius (°C) espressi in Kelvin (K).
                                            // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 39.

#define R_DA_IP 53.350                  // Costante universale del gas per aria secca (versione IP) in ft∙lbf/lb_da/R.
                                        // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1.

#define R_DA_SI 287.042                 // Costante universale dei gas per aria secca (versione SI) in J/kg_da/K.
                                        // Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1.

#define NON VALIDO -99999                  // Valore non valido.

#define MAX_ITER_COUNT 100              // Numero massimo di iterazioni prima di uscire dai cicli while.

#define MIN_HUM_RATIO 1e-7              // Rapporto di umidità minimo accettabile utilizzato/restituito da qualsiasi funzione.
                                        // Qualsiasi valore superiore a 0 o inferiore a MIN_HUM_RATIO verrà reimpostato su questo valore.

#define FREEZING_POINT_WATER_IP 32.0    // Punto di congelamento dell'acqua in Fahrenheit.

#define FREEZING_POINT_WATER_SI 0.0     // Punto di congelamento dell'acqua in gradi Celsius.

#define TRIPLE_POINT_WATER_IP 32.018    // Punto triplo dell'acqua in Fahrenheit.

#define TRIPLO_POINT_ACQUA_SI 0.01      // Punto triplo dell'acqua in gradi Celsius.


/**************************************************** ************************************************** ***
 * Funzioni di supporto
 ************************************************** ************************************************** */

#define ASSERT(condizione, messaggio) \
  se (! (condizione)) \
  { \
    Asserzione(messaggio, __FILE__, __LINE__); \
    }

// Funzione chiamata se un'asserzione fallisce
// Sostituisci questa funzione con la tua funzione per una migliore elaborazione degli errori
vuoto Affermare
    ( car *Msg                 // (i) messaggio da stampare sullo schermo
    , car *Nome del file            // (i) nome del file in cui si è verificato l'errore
    , int Linea n                // (i) numero di riga in cui si è verificato l'errore
    )
{
  printf("Dichiarazione non riuscita nel file %s alla riga %d:", Nome del file, linea n.);
  printf("%s", Msg);
  printf("Interruzione del programma...");
  printf("\un");
  Uscita(1);
}

// Macro min e max (nel caso non siano definite)
#ifndefmin
#define min(a,b) (((a) < (b)) ? (a) : (b))
#finisci se

#ifndefmax
#define max(a,b) (((a) > (b)) ? (a) : (b))
#finisci se

// Sistemi di unità (IP o SI)
statico enum UnitSystem PSYCHROLIB_UNITÀ = NON DEFINITO;

// Tolleranza dei calcoli della temperatura
statico doppio PSYCROLIB_TOLERANZA = 1.;

// Imposta il sistema di unità da utilizzare (SI o IP).
// Nota: questa funzione *DEVE ESSERE CHIAMATA* prima che la libreria possa essere utilizzata
vuoto Impostasistemaunità
  ( enum UnitSystem Unità       // (i) Sistema di unità (IP o SI)
  )
{
  PSYCHROLIB_UNITÀ = unità;

  // Definisce la tolleranza sui calcoli della temperatura
  // La tolleranza è la stessa in IP e SI
  se (PSYCHROLIB_UNITS == IP)
    PSYCROLIB_TOLERANZA = 0.001 * 9. / 5.;
  altro
    PSYCROLIB_TOLERANZA = 0.001;
}

// Sistema di restituzione delle unità in uso.
enum UnitSystem GetUnitSystem  // (o) Sistema di unità (SI o IP)
  (
  )
{
  ritorno PSYCROLIB_UNITÀ;
}

// Controlla se il sistema in uso è IP o SI.
// La funzione termina per errore se il sistema di unità non è definito
int isIP                    // (o) 1 se IP, 0 se SI, errore altrimenti
(
)
{
  se (PSYCHROLIB_UNITS == IP)
    ritorno 1;
  altro se (PSYCHROLIB_UNITS == SI)
    ritorno 0;
  altro
  {
    printf("Il sistema di unità non è stato definito");
    Uscita(1);
  }
}


/**************************************************** ************************************************** ***
 * Conversione tra unità di temperatura
 ************************************************** ************************************************** */

// Funzione di utilità per convertire la temperatura in gradi Rankine (°R)
// temperatura indicata in gradi Fahrenheit (°F).
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
doppio OttieniTRankineFromTFahrenheit(doppio T_F) { ritorno T_F + ZERO_FAHRENHEIT_AS_RANKINE; }         /* esatto */

// Funzione di utilità per convertire la temperatura in gradi Fahrenheit (°F)
// temperatura indicata in gradi Rankine (°R).
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
doppio Ottieni TFahrenheit da TRankine (doppio T_R) { ritorno T_R - ZERO_FAHRENHEIT_AS_RANKINE; }        /* esatto */

// Funzione di utilità per convertire la temperatura in Kelvin (K)
// temperatura indicata in gradi Celsius (°C).
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
doppio OttieniTKelvinDaTCelsius(doppio T_C) { ritorno T_C + ZERO_CELSIUS_AS_KELVIN; }                /* esatto */

// Funzione di utilità per convertire la temperatura in gradi Celsius (°C)
// data la temperatura in Kelvin (K).
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 sezione 3
doppio OttieniTCelsiusDaTKelvin(doppio T_K) { ritorno T_K - ZERO_CELSIUS_AS_KELVIN; }                /* esatto */


/**************************************************** ************************************************** ***
 * Conversioni tra punto di rugiada, bulbo umido e umidità relativa
 ************************************************** ************************************************** */

// Temperatura di ritorno del bulbo umido data la temperatura del bulbo secco, la temperatura del punto di rugiada e la pressione.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
doppio OttieniTWetBulbFromTDewPoint // (o) Temperatura del bulbo umido in °F [IP] o °C [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio TDewPoint            // (i) Temperatura del punto di rugiada in °F [IP] o °C [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  doppio Rapporto Hum;

  ASSERIRE (TDewPoint <= TDryBulb, "La temperatura del punto di rugiada è superiore alla temperatura del bulbo secco")

  HumRatio = OttieniRapportoRum.DaPuntoDiTew(PuntoDiTew, Pressione);
  ritorno Rapporto GetTWetBulbFromHum(Tlampadina, HumRatio, Pressione);
}

// Restituisce la temperatura a bulbo umido data la temperatura a bulbo secco, l'umidità relativa e la pressione.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
doppio GetTWetBulbFromRelHum    // (o) Temperatura del bulbo umido in °F [IP] o °C [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio RelHum               // (i) Umidità relativa [0-1]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  doppio Rapporto Hum;

  ASSERIRE (RelHum >= 0 && RelHum <= 1, "L'umidità relativa è fuori dall'intervallo [0,1]")

  HumRatio = OttieniRapportoHumFromRelHum(TDryBulb, RelHum, Pressione);
  ritorno Rapporto GetTWetBulbFromHum(Tlampadina, HumRatio, Pressione);
}

// Umidità relativa restituita data la temperatura di bulbo secco e la temperatura del punto di rugiada.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 22
doppio OttieniRelHumFromTDewPoint   // (o) Umidità relativa [0-1]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio TDewPoint            // (i) Temperatura del punto di rugiada in °F [IP] o °C [SI]
  )
{
  doppio VapPres, SatVapPres;

  ASSERIRE (TDewPoint <= TDryBulb, "La temperatura del punto di rugiada è superiore alla temperatura del bulbo secco")

  VapPres = GetSatVapPres(TDewPoint);
  SatVapPres = GetSatVapPres(TDryBulb);
  ritorno VapPres/SatVapPres;
}

// Umidità relativa restituita data la temperatura a bulbo secco, la temperatura a bulbo umido e la pressione.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
doppio GetRelHumFromTWetBulb    // (o) Umidità relativa [0-1]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio TWetBulb             // (i) Temperatura del bulbo umido in °F [IP] o °C [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  doppio Rapporto Hum;

  ASSERIRE (TWetBulb <= TDryBulb, "La temperatura del bulbo umido è superiore alla temperatura del bulbo secco")

  HumRatio = Ottieni rapporto humumFromTWetBulb(TDryBulb, TWetLampadina, Pressione);
  ritorno Ottieni rapporto RelHumFromHum(Tlampadina, HumRatio, Pressione);
}

// Temperatura del punto di rugiada di ritorno data la temperatura a bulbo secco e l'umidità relativa.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
doppio OttieniTDewPointFromRelHum   // (o) Temperatura del punto di rugiada in °F [IP] o °C [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio RelHum               // (i) Umidità relativa [0-1]
  )
{
  doppio VapPres;

  ASSERIRE (RelHum >= 0 && RelHum <= 1, "L'umidità relativa è fuori dall'intervallo [0,1]")

  VapPres = GetVapPresFromRelHum(TDryBulb, RelHum);
  ritorno OttieniTDewPointFromVapPres(Tlampadina, VapPres);
}

// Temperatura del punto di rugiada di ritorno data la temperatura di bulbo secco, la temperatura di bulbo umido e la pressione.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
doppio OttieniTDewPointFromTWetBulb // (o) Temperatura del punto di rugiada in °F [IP] o °C [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio TWetBulb             // (i) Temperatura del bulbo umido in °F [IP] o °C [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  doppio Rapporto Hum;

  ASSERIRE (TWetBulb <= TDryBulb, "La temperatura del bulbo umido è superiore alla temperatura del bulbo secco")

  HumRatio = Ottieni rapporto humumFromTWetBulb(TDryBulb, TWetLampadina, Pressione);
  ritorno OttieniTDewPointFromHumRatio(Tlampadina, HumRatio, Pressione);
}


/**************************************************** ************************************************** ***
 * Conversioni tra punto di rugiada o umidità relativa e pressione di vapore
 ************************************************** ************************************************** */

// Restituisce la pressione parziale del vapore acqueo in funzione dell'umidità relativa e della temperatura.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 12, 22
doppio GetVapPresFromRelHum     // (o) Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio RelHum               // (i) Umidità relativa [0-1]
  )
{
  ASSERIRE (RelHum >= 0. && RelHum <= 1., "L'umidità relativa è fuori dall'intervallo [0,1]")

  ritorno RelHum*GetSatVapPres(TDryBulb);
}

// Umidità relativa restituita data la temperatura a bulbo secco e la pressione del vapore.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 12, 22
doppio GetRelHumFromVapPres     // (o) Umidità relativa [0-1]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio VapPres              // (i) Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
  )
{
  ASSERIRE (VapPres >= 0., "La pressione parziale del vapore acqueo nell'aria umida è negativa")

  ritorno VapPres/GetSatVapPres(TDryBulb);
}

// Funzione di supporto che restituisce la derivata del logaritmo naturale della pressione del vapore di saturazione
// in funzione della temperatura a bulbo secco.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 5 e 6
doppio dLnPws_        // (o) Derivata del logaritmo naturale della tensione di vapore dell'aria satura in Psi [IP] o Pa [SI]
  ( doppio TDryBulb   // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  )
{
  doppio dLnPw, T;

  se (èIP())
  {
    T = OttieniTRankineFromTFahrenheit(TDryBulb);

    se (TDryBulb <= TRIPLE_POINT_WATER_IP)
      dLnPws = 1.0214165E+04 / pow(T, 2) - 5.3765794E-03 + 2 * 1.9202377E-07 * T
               + 3 * 3.5575832E-10 * pow(T, 2) - 4 * 9.0344688E-14 * pow(T, 3) + 4.1635019 / T;
    altro
      dLnPws = 1.0440397E+04 / pow(T, 2) - 2.7022355E-02 + 2 * 1.2890360E-05 * T
               - 3 * 2.4780681E-09 * pow(T, 2) + 6.5459673 / T;
  }
  altro
  {
    T = OttieniTKelvinDaTCelsius(TDryBulb);

    se (TDryBulb <= TRIPLE_POINT_WATER_SI)
      dLnPws = 5.6745359E+03 / pow(T, 2) - 9.677843E-03 + 2 * 6.2215701E-07 * T
               + 3 * 2.0747825E-09 * pow(T, 2) - 4 * 9.484024E-13 * pow(T, 3) + 4.1635019 / T;
    altro
      dLnPws = 5.8002206E+03 / pow(T, 2) - 4.8640239E-02 + 2 * 4.1764768E-05 * T
               - 3 * 1.4452093E-08 * pow(T, 2) + 6.5459673 / T;
  }

  ritorno dLnPw;
}

// Temperatura del punto di rugiada di ritorno data la temperatura a bulbo secco e la pressione del vapore.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 5 e 6
// Note: la temperatura del punto di rugiada si risolve invertendo l'equazione dando la pressione del vapore acqueo
// alla saturazione dalla temperatura anziché utilizzare le regressioni fornite
// da ASHRAE (eqn. 37 e 38) che sono molto meno accurati e hanno un
// intervallo di validità più ristretto.
// Il metodo Newton-Raphson (NR) viene utilizzato sul logaritmo del vapore acqueo
// pressione in funzione della temperatura, che è una funzione molto fluida
// La convergenza viene solitamente raggiunta in 3-5 iterazioni.
// TDryBulb non è realmente necessario in questo caso, viene utilizzato solo per comodità.
doppio OttieniTDewPointFromVapPres  // (o) Temperatura del punto di rugiada in °F [IP] o °C [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio VapPres              // (i) Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
  )
{
  // Funzione dei limiti del sistema di unità
  doppio CONFINI[2];              // Dominio di validità delle equazioni

  se (èIP())
  {
    CONFINI[0] = -148.;
    CONFINI[1] = 392.;
  }
  altro
  {
    CONFINI[0] = -100.;
    CONFINI[1] = 200.;
  }

  // Limiti oltre i quali non è possibile trovare una soluzione
  ASSERIRE (VapPres >= GetSatVapPres(LIMITI[0]) && VapPres <= GetSatVapPres(LIMITI[1]),
          "La pressione parziale del vapore acqueo è fuori dal campo di validità delle equazioni")

  // Usiamo NR per approssimare la soluzione.
  // Prima ipotesi
  doppio TDewPoint = TDryBulb;      // Valore calcolato delle temperature del punto di rugiada, risolto iterativamente in °F [IP] o °C [SI]
  doppio lnVP = log(VapPres);       // Logaritmo naturale della pressione parziale della pressione del vapore acqueo nell'aria umida

  doppio TDewPoint_iter;            // Valore di TDewPoint utilizzato nel calcolo NR
  doppio lnVP_iter;                 // Valore del logaritmo della pressione del vapore acqueo utilizzato nel calcolo NR
  int indice = 1;

  fare
  {
    TDewPoint_iter = TDewPoint; // TDewPoint utilizzato nel calcolo NR
    lnVP_iter = log(GetSatVapPres(TDewPoint_iter));

    // Derivato della funzione, calcolato analiticamente
    doppio d_lnVP = dLnPws_(TDewPoint_iter);

    // Nuova stima, delimitata dal dominio di validità dell'eqn. 5 e 6
    TDewPoint = TDewPoint_iter - (lnVP_iter - lnVP) / d_lnVP;
    TDewPoint = max(TDewPoint, CONFINI[0]);
    TDewPoint = min(TDPuntoDew, CONFINI[1]);

    ASSERIRE (indice <= MAX_ITER_COUNT, "Convergenza non raggiunta in GetTDewPointFromVapPres. Arresto.")

    indice++;
  }
  mentre (fabs(TDewPoint - TDewPoint_iter) > PSYCHROLIB_TOLERANZA);
  ritorno min(TDewPoint, TDryBulb);
}

// Pressione del vapore di ritorno data la temperatura del punto di rugiada.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 36
doppio OttieniVapPresFromTDewPoint  // (o) Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
  ( doppio TDewPoint            // (i) Temperatura del punto di rugiada in °F [IP] o °C [SI]
  )
{
  ritorno GetSatVapPres(TDewPoint);
}


/**************************************************** ************************************************** ***
 * Conversioni dalla temperatura del bulbo umido, dalla temperatura del punto di rugiada o dal rapporto umidità relativa/umidità
 ************************************************** ************************************************** */

// Restituisce la temperatura a bulbo umido data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 33 e 35 risolti per Tstar
doppio Rapporto GetTWetBulbFromHum  // (o) Temperatura del bulbo umido in °F [IP] o °C [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio HumRatio             // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  // Dichiarazioni
  doppio stella;
  doppio punto di rugiada, TWetLampadina, TWetBulbSup, TWetBulbInf, Rapporto Hum limitato;
  int indice = 1;

  ASSERIRE (Rapporto ronzio >= 0., "Il rapporto di umidità è negativo")
  Rapporto Hum limitato = max(Rapporto rumore, MIN_UM_RATIO);

  TDewPoint = OttieniTDewPointFromHumRatio(TDryBulb, Rapporto Hum limitato, Pressione);

  // Ipotesi iniziali
  TWetBulbSup = TDryBulb;
  TWetBulbInf = TDewPoint;
  TWetBulb = (TWetBulbInf + TWetBulbSup) / 2.;

  // Ciclo di bisezione
  mentre ((TWetBulbSup - TWetBulbInf) > PSYCHROLIB_TOLERANZA)
  {
   // Calcola il rapporto di umidità alla temperatura Tstar
   Wstar = Ottieni rapporto humumFromTWetBulb(TDryBulb, TWetLampadina, Pressione);

   // Ottieni nuovi limiti
   se (Wstar > Rapporto Hum limitato)
    TWetBulbSup = TWetLampadina;
   altro
    TWetBulbInf = TWetLampadina;

   // Nuova ipotesi sulla temperatura del bulbo umido
   TWetBulb = (TWetBulbSup+TWetBulbInf) / 2.;

   ASSERIRE (indice <= MAX_ITER_COUNT, "Convergenza non raggiunta in GetTWetBulbFromHumRatio. Arresto.")

   indice++;
  }

  ritorno TWetLampadina;
}

// Rapporto di umidità di ritorno data la temperatura di bulbo secco, la temperatura di bulbo umido e la pressione.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 33 e 35
doppio OttieniHumRatioFromTWetBulb  // (o) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio TWetBulb             // (i) Temperatura del bulbo umido in °F [IP] o °C [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  doppio Wsstar;
  doppio HumRatio = NON VALIDO;

  ASSERIRE (TWetBulb <= TDryBulb, "La temperatura del bulbo umido è superiore alla temperatura del bulbo secco")

  Wsstar = Ottieni rapporto humSat(TWetBulb, Pressione);

  se (èIP())
  {
    se (TWetBulb >= FREEZING_POINT_WATER_IP)
      HumRatio = ((1093. - 0.556 * TWetBulb) * Wsstar - 0.240 * (TDryBulb - TWetBulb))
      / (1093. + 0.444 * TDryBulb - TWetBulb);
    altro
      HumRatio = ((1220. - 0.04 * TWetBulb) * Wsstar - 0.240 * (TDryBulb - TWetBulb))
      / (1220. + 0.444 * TDryBulb - 0.48 * TWetBulb);
  }
  altro
  {
    se (TWetBulb >= FREEZING_POINT_WATER_SI)
      HumRatio = ((2501. - 2.326 * TWetBulb) * Wsstar - 1.006 * (TDryBulb - TWetBulb))
         / (2501. + 1.86 * TDryBulb - 4.186 * TWetBulb);
    altro
      HumRatio = ((2830. - 0.24 * TWetBulb) * Wsstar - 1.006 * (TDryBulb - TWetBulb))
         / (2830. + 1.86 * TDryBulb - 2.1 * TWetBulb);
  }
  // Controllo di validità.
  ritorno max(Rapporto rumore, MIN_UM_RATIO);
}

// Rapporto di umidità di ritorno data la temperatura a bulbo secco, l'umidità relativa e la pressione.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
doppio OttieniHumRatioFromRelHum    // (o) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio RelHum               // (i) Umidità relativa [0-1]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  doppio VapPres;

  ASSERIRE (RelHum >= 0. && RelHum <= 1., "L'umidità relativa è fuori dall'intervallo [0,1]")

  VapPres = GetVapPresFromRelHum(TDryBulb, RelHum);
  ritorno OttieniHumRatioFromVapPres(VapPres, Pressione);
}

// Restituisce l'umidità relativa data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
doppio Ottieni rapporto RelHumFromHum    // (o) Umidità relativa [0-1]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio HumRatio             // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  doppio VapPres;

  ASSERIRE (Rapporto ronzio >= 0., "Il rapporto di umidità è negativo")

  VapPres = GetVapPresFromHumRatio(Rapporto hum, Pressione);
  ritorno GetRelHumFromVapPres(Tlampadina, VapPres);
}

// Rapporto di umidità di ritorno data la temperatura e la pressione del punto di rugiada.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
doppio OttieniHumRatioFromTDewPoint // (o) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  ( doppio TDewPoint            // (i) Temperatura del punto di rugiada in °F [IP] o °C [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  doppio VapPres;

  VapPres = GetSatVapPres(TDewPoint);
  ritorno OttieniHumRatioFromVapPres(VapPres, Pressione);
}

// Temperatura del punto di rugiada di ritorno data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
doppio OttieniTDewPointFromHumRatio // (o) Temperatura del punto di rugiada in °F [IP] o °C [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio HumRatio             // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  doppio VapPres;

  ASSERIRE (Rapporto ronzio >= 0., "Il rapporto di umidità è negativo")

  VapPres = GetVapPresFromHumRatio(Rapporto hum, Pressione);
  ritorno OttieniTDewPointFromVapPres(Tlampadina, VapPres);
}


/**************************************************** ************************************************** ***
 * Conversioni tra rapporto di umidità e pressione di vapore
 ************************************************** ************************************************** */

// Rapporto dell'umidità di ritorno data la pressione del vapore acqueo e la pressione atmosferica.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 20
doppio OttieniHumRatioFromVapPres   // (o) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  ( doppio VapPres              // (i) Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  doppio Rapporto Hum;

  ASSERIRE (VapPres >= 0., "La pressione parziale del vapore acqueo nell'aria umida è negativa")

  HumRatio = 0.621945 * VapPres / (Pressione - VapPres);

  // Controllo di validità.
  ritorno max(Rapporto ronzio, MIN_UM_RATIO);
}

// Pressione del vapore di ritorno dati il ​​rapporto di umidità e la pressione.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 20 risolto per pw
doppio OttieniVapPresFromHumRatio   // (o) Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
  ( doppio HumRatio             // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  doppio VapPres, Rapporto Hum limitato;

  ASSERIRE (Rapporto ronzio >= 0., "Il rapporto di umidità è negativo")
  Rapporto Hum limitato = max(Rapporto rumore, MIN_UM_RATIO);

  VapPres = Pressione * Rapporto Hum limitato / (0.621945 + Rapporto Hum Limitato);
  ritorno VapPres;
}


/**************************************************** ************************************************** ***
 *Conversioni tra rapporto di umidità e umidità specifica
 ************************************************** ************************************************** */

// Restituisce l'umidità specifica dal rapporto di umidità (noto anche come rapporto di miscelazione)
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 9b
doppio Ottieni rapporto HumFromHum specifico // (o) Rapporto di umidità specifica in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  ( doppio HumRatio               // (i) Rapporto di umidità in lb_H₂O lb_Dry_Air⁻¹ [IP] o kg_H₂O kg_Dry_Air⁻¹ [SI]
  )
{
  doppio Rapporto Hum limitato;

  ASSERIRE (Rapporto ronzio >= 0., "Il rapporto di umidità è negativo")
  Rapporto Hum limitato = max(Rapporto rumore, MIN_UM_RATIO);

  ritorno Rapporto Hum limitato / (1.0 + Rapporto Hum Limitato);
}

// Restituisce il rapporto di umidità (noto anche come rapporto di miscelazione) dall'umidità specifica
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 9b (risolto per il rapporto di umidità)
doppio Ottieni rapporto humum da hum specifico // (o) Rapporto di umidità in lb_H₂O lb_Dry_Air⁻¹ [IP] o kg_H₂O kg_Dry_Air⁻¹ [SI]
  ( doppio SpecificHum            // (i) Rapporto di umidità specifica in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  )
{
  doppio Rapporto Hum;

  ASSERIRE (SpecificHum >= 0.0 && SpecificHum < 1.0, "L'umidità specifica è fuori dall'intervallo [0,1[")

  HumRatio = SpecificHum / (1.0 - SpecificHum);

  // Controllo di validità
  ritorno max(Rapporto ronzio, MIN_UM_RATIO);
}


/**************************************************** ************************************************** ***
 * Calcoli dell'aria secca
 ************************************************** ************************************************** */

// Entalpia dell'aria secca restituita data la temperatura a bulbo secco.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 28
doppio OttieniEntalpiaAriaSecca        // (o) Entalpia dell'aria secca in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  )
{
  se (èIP())
    ritorno 0.240 * TDryBulb;
  altro
    ritorno 1006 * TDryBulb;
}

// Densità di ritorno dell'aria secca date la temperatura e la pressione del bulbo secco.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
// Note: eqn 14 per la perfetta relazione tra i gas per l'aria secca.
// Eqn 1 per la costante universale dei gas.
// Il fattore 144 in IP serve per la conversione di Psi = lb in⁻² in lb ft⁻².
doppio OttieniDryAirDensity         // (o) Densità dell'aria secca in lb ft⁻³ [IP] o kg m⁻³ [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  se (èIP())
    ritorno (144. * Pressione) / R_DA_IP / OttieniTRankineFromTFahrenheit(TDryBulb);
  altro
    ritorno Pressione / R_DA_SI / OttieniTKelvinDaTCelsius(TDryBulb);
}

// Volume di aria secca restituito in base alla temperatura e alla pressione del bulbo secco.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
// Note: eqn 14 per la perfetta relazione tra i gas per l'aria secca.
// Eqn 1 per la costante universale dei gas.
// Il fattore 144 in IP serve per la conversione di Psi = lb in⁻² in lb ft⁻².
doppio OttieniDryAirVolume          // (o) Volume di aria secca ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  se (èIP())
    ritorno R_DA_IP * OttieniTRankineFromTFahrenheit(TDryBulb) / (144. * Pressione);
  altro
    ritorno R_DA_SI * OttieniTKelvinDaTCelsius(TDryBulb) / Pressione;
}

// Restituisce la temperatura del bulbo secco dal rapporto entalpia e umidità.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 30.
// Note: basato sulla funzione `GetMoistAirEnthalpy`, riorganizzato per la temperatura.
doppio OttieniTDryBulbFromEnthalpyAndHumRatio  // (o) Temperatura a bulbo secco in °F [IP] o °C [SI]
  ( doppio Entalpia dell'aria umida                // (i) Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹
  , doppio HumRatio                        // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  )
{
  doppio Rapporto Hum limitato;

  ASSERIRE (Rapporto ronzio >= 0., "Il rapporto di umidità è negativo")
  Rapporto Hum limitato = max(Rapporto rumore, MIN_UM_RATIO);

  se (èIP())
    ritorno (Entalpia dell'aria umida - 1061.0 * Rapporto Hum limitato) / (0.240 + 0.444 * Rapporto Hum Limitato);
  altro
    ritorno (Entalpia dell'aria umida / 1000.0 - 2501.0 * Rapporto Hum limitato) / (1.006 + 1.86 * Rapporto Hum Limitato);
}

// Rapporto dell'umidità di ritorno tra entalpia e temperatura a bulbo secco.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 30.
// Note: basato sulla funzione `GetMoistAirEnthalpy`, riorganizzato per il rapporto di umidità.
doppio Ottieni rapporto hum dall'entalpia e dal bulbo secco  // (o) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  ( doppio Entalpia dell'aria umida                // (i) Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹
  , doppio TDryBulb                        // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  )
{
  doppio Rapporto Hum;
  se (èIP())
    HumRatio = (Entalpia dell'aria umida - 0.240 * TDryBulb) / (1061.0 + 0.444 * TDryBulb);
  altro
    HumRatio = (Entalpia dell'aria umida / 1000.0 - 1.006 * TDryBulb) / (2501.0 + 1.86 * TDryBulb);

  // Controllo di validità.
  ritorno max(Rapporto ronzio, MIN_UM_RATIO);
}


/**************************************************** ************************************************** ***
 * Calcoli dell'aria satura
 ************************************************** ************************************************** */

// Pressione del vapore di saturazione di ritorno data la temperatura a bulbo secco.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 5 e 6
// Nota importante: le formule ASHRAE sono definite sopra e sotto il punto di congelamento ma hanno
// una discontinuità al punto di congelamento. Questa è una piccola imprecisione da parte di ASHRAE: le formule
// dovrebbe essere definito sopra e sotto il punto triplo dell'acqua (non il punto di contatto), nel qual caso
// la discontinuità svanisce. È essenziale utilizzare il punto triplo dell'acqua altrimenti funzionerà
// GetTDewPointFromVapPres, che inverte la funzione presente, non converge correttamente
// il punto di congelamento.
doppio OttieniSatVapPres            // (o) Pressione del vapore dell'aria satura in Psi [IP] o Pa [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  )
{
  doppio LnPw, T;

  se (èIP())
  {
    ASSERT(TDryBulb >= -148. && TDryBulb <= 392., "La temperatura del bulbo secco è fuori dall'intervallo [-148, 392]")

    T = OttieniTRankineFromTFahrenheit(TDryBulb);

    se (TDryBulb <= TRIPLE_POINT_WATER_IP)
      LnPws = (-1.0214165E+04 / T - 4.8932428 - 5.3765794E-03 * T + 1.9202377E-07 * T * T
        + 3.5575832E-10 * pow(T, 3) - 9.0344688E-14 * pow(T, 4) + 4.1635019 * registro(T));
    altro
      LnPws = -1.0440397E+04 / T - 1.1294650E+01 - 2.7022355E-02 * T + 1.2890360E-05 * T * T
      - 2.4780681E-09 * pow(T, 3) + 6.5459673 * registro(T);
  }
  altro
  {
    ASSERT(TDryBulb >= -100. && TDryBulb <= 200., "La temperatura del bulbo secco è fuori dall'intervallo [-100, 200]")

    T = OttieniTKelvinDaTCelsius(TDryBulb);

    se (TDryBulb <= TRIPLE_POINT_WATER_SI)
      LnPws = -5.6745359E+03 / T + 6.3925247 - 9.677843E-03 * T + 6.2215701E-07 * T * T
          + 2.0747825E-09 * pow(T, 3) - 9.484024E-13 * pow(T, 4) + 4.1635019 * registro(T);
    altro
      LnPws = -5.8002206E+03 / T + 1.3914993 - 4.8640239E-02 * T + 4.1764768E-05 * T * T
        - 1.4452093E-08 * pow(T, 3) + 6.5459673 * registro(T);
  }

  ritorno exp(LnPws);
}

// Rapporto di umidità di ritorno dell'aria satura data la temperatura e la pressione a bulbo secco.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eqn 36, risolto per W
doppio Ottieni rapporto SatHum           // (o) Rapporto di umidità dell'aria satura in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  doppio SatVaporPres, Rapporto SatHum;

  SatVaporPres = GetSatVapPres(TDryBulb);
  SatHumRatio = 0.621945 * SatVaporPres / (Pressione - SatVaporPres);

  // Controllo di validità.
  ritorno max(Rapporto SatHum, MIN_UM_RATIO);
}

// Restituisce l'entalpia dell'aria satura data la temperatura e la pressione a bulbo secco.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1
doppio OttieniSatAirEntalpia        // (o) Entalpia dell'aria satura in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  ritorno GetMoistAirEntalpia(TDryBulb, Ottieni rapporto humSat(TDryBulb, Pressione));
}

/**************************************************** ************************************************** ***
 * Calcoli dell'aria umida
 ************************************************** ************************************************** */

// Ritorno Deficit di pressione del vapore data la temperatura a bulbo secco, il rapporto di umidità e la pressione.
// Riferimento: vedere Oke (1987) eqn. 2.13a
doppio OttieniVaporPressureDeficit  // (o) Deficit di pressione del vapore in Psi [IP] o Pa [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio HumRatio             // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  doppio RelHum;

  ASSERIRE (Rapporto ronzio >= 0., "Il rapporto di umidità è negativo")

  RelHum = OttieniRapportoRelHumFromHum(TDryBulb, HumRatio, Pressione);
  ritorno OttieniSatVapPres(Tlampadina) * (1. - RelHum);
}

// Restituisce il grado di saturazione (ovvero il rapporto di umidità dell'aria/rapporto di umidità dell'aria alla saturazione
// alla stessa temperatura e pressione) data la temperatura a bulbo secco, il rapporto di umidità e la pressione atmosferica.
// Riferimento: Manuale ASHRAE - Fondamenti (2009) cap. 1 eq. 12
// Note: la definizione è assente nel Manuale 2017
doppio Ottieni Grado di Saturazione    // (o) Grado di saturazione []
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio HumRatio             // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  doppio Rapporto Hum limitato;

  ASSERIRE (Rapporto ronzio >= 0., "Il rapporto di umidità è negativo")
  Rapporto Hum limitato = max(Rapporto rumore, MIN_UM_RATIO);

  ritorno Rapporto Hum limitato / Ottieni rapporto humSat(TDryBulb, Pressione);
}

// L'entalpia dell'aria umida restituita data la temperatura a bulbo secco e il rapporto di umidità.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 30
doppio OttieniEntalpiaAriaMostra      // (o) Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio HumRatio             // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  )
{
  doppio Rapporto Hum limitato;

  ASSERIRE (Rapporto ronzio >= 0., "Il rapporto di umidità è negativo")
  Rapporto Hum limitato = max(Rapporto rumore, MIN_UM_RATIO);

  se (èIP())
    ritorno 0.240 * TDryBulb + Rapporto hum limitato*(1061. + 0.444 * TDryBulb);
  altro
    ritorno (1.006 * TDryBulb + Rapporto hum limitato*(2501. + 1.86 * TDryBulb)) * 1000.;
}

// Restituisce il volume specifico dell'aria umida in base alla temperatura a bulbo secco, al rapporto di umidità e alla pressione.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 26
// Note: in unità IP, R_DA_IP / 144 equivale a 0,370486 che è il coefficiente che appare nell'eqn 26.
// Il fattore 144 serve per la conversione di Psi = lb in⁻² in lb ft⁻².
doppio OttieniMoistAirVolume        // (o) Volume specifico ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio HumRatio             // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  doppio Rapporto Hum limitato;

  ASSERIRE (Rapporto ronzio >= 0., "Il rapporto di umidità è negativo")
  Rapporto Hum limitato = max(Rapporto rumore, MIN_UM_RATIO);

  se (èIP())
    ritorno R_DA_IP * OttieniTRankineFromTFahrenheit(TDryBulb) * (1. + 1.607858 * Rapporto Hum limitato) / (144. * Pressione);
  altro
    ritorno R_DA_SI * OttieniTKelvinDaTCelsius(TDryBulb) * (1. + 1.607858 * Rapporto Hum limitato) / Pressione;
}

// Temperatura di ritorno a bulbo secco dato il volume specifico dell'aria umida, il rapporto di umidità e la pressione.
// Riferimento:
// Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 26
// Appunti:
// In unità IP, R_DA_IP / 144 equivale a 0,370486 che è il coefficiente che appare nell'eqn 26
// Il fattore 144 serve per la conversione di Psi = lb in⁻² in lb ft⁻².
// Basato sulla funzione "GetMoistAirVolume", riorganizzato per la temperatura a bulbo secco.
doppio OttieniTDryBulbFromMoistAirVolumeAndHumRatio   // (o) Temperatura a bulbo secco in °F [IP] o °C [SI]
  ( doppio Volume Aria Umida                         // (i) Volume specifico di aria umida in ft³ lb⁻¹ di aria secca [IP] o in m³ kg⁻¹ di aria secca [SI]
  , doppio HumRatio                               // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  , doppio Pressione                               // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  doppio Rapporto Hum limitato;

  ASSERIRE (Rapporto ronzio >= 0., "Il rapporto di umidità è negativo")
  Rapporto Hum limitato = max(Rapporto rumore, MIN_UM_RATIO);

  se (èIP())
    ritorno OttieniTFahrenheitFromTRankine(MoistAirVolume * (144 * Pressione) / (R_DA_IP * (1 + 1.607858 * Rapporto Hum limitato)));
  altro
    ritorno  OttieniTCelsiusDaTKelvin(Volume Aria Umida * Pressione / (R_DA_SI * (1 + 1.607858 * Rapporto Hum limitato)));
}

// Restituisce la densità dell'aria umida in base al rapporto di umidità, alla temperatura del bulbo secco e alla pressione.
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq. 11
doppio GetMoistAirDensity       // (o) Densità dell'aria umida in lb ft⁻³ [IP] o kg m⁻³ [SI]
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio HumRatio             // (i) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  )
{
  doppio Rapporto Hum limitato;

  ASSERIRE (Rapporto ronzio >= 0., "Il rapporto di umidità è negativo")
  Rapporto Hum limitato = max(Rapporto rumore, MIN_UM_RATIO);

  ritorno (1. + Rapporto Hum limitato) / GetMoistAirVolume(TDryBulb, Rapporto Hum limitato, Pressione);
}


/**************************************************** ************************************************** ***
 *Atmosfera standard
 ************************************************** ************************************************** */

// Restituisce la pressione barometrica atmosferica standard, data l'elevazione (altitudine).
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 3
doppio OttieniPressioneAtmStandard   // (o) Pressione barometrica atmosferica standard in Psi [IP] o Pa [SI]
  ( doppio Altitudine             // (i) Altitudine in piedi [IP] o m [SI]
  )
{
  doppio Pressione;
  se (èIP())
    Pressione = 14.696 * pow(1. - 6.8754e-06 * Altitudine, 5.2559);
  altro
    Pressione = 101325. * pow(1. - 2.25577e-05 * Altitudine, 5.2559);
  ritorno Pressione;
}

// Restituisce la temperatura atmosferica standard, data l'elevazione (altitudine).
// Riferimento: Manuale ASHRAE - Fondamenti (2017) cap. 1 eq 4
doppio OttieniTemperaturaAtmStandard // (o) Temperatura a bulbo secco dell'atmosfera standard in °F [IP] o °C [SI]
  ( doppio Altitudine              // (i) Altitudine in piedi [IP] o m [SI]
  )
 {
  doppio Temperatura;
  se (èIP())
    Temperatura = 59. - 0.00356620 * Altitudine;
  altro
    Temperatura = 15. - 0.0065 * Altitudine;
  ritorno Temperatura;
}

// Pressione di ritorno al livello del mare data la temperatura a bulbo secco, l'altitudine sul livello del mare e la pressione.
// Riferimento: Hess SL, Introduzione alla meteorologia teorica, Holt Rinehart e Winston, NY 1959,
// cap. 6,5; Stull RB, Meteorologia per scienziati e ingegneri, 2a edizione,
// Brooks/Cole 2000, cap. 1.
// Note: la procedura standard per gli Stati Uniti prevede l'utilizzo della media per TDryBulb
// della temperatura attuale della stazione e della temperatura della stazione di 12 ore fa.
doppio Ottieni la pressione del livello del mare   // (o) Pressione barometrica al livello del mare in Psi [IP] o Pa [SI]
  ( doppio StnPressione       // (i) Pressione osservata nella stazione in Psi [IP] o Pa [SI]
  , doppio Altitudine          // (i) Altitudine sopra il livello del mare in piedi [IP] o m [SI]
  , doppio TDryBulb          // (i) Temperatura a bulbo secco ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
  )
{
  doppio Colonna, H;
  se (èIP())
  {
    // Calcola la temperatura media nella colonna d'aria, assumendo un intervallo di tempo
    // di 3,6 °F/1000 piedi
    TColonna = TDryBulb + 0.0036 * Altitudine / 2.;

    // Determina l'altezza della scala
    H = 53.351 * GetTRankineFromTFahrenheit(TConmina);
  }
  altro
  {
    // Calcola la temperatura media nella colonna d'aria, assumendo un intervallo di tempo
    // di 6,5 °C/km
    TColonna = TDryBulb + 0.0065 * Altitudine / 2.;

    // Determina l'altezza della scala
    H = 287.055 * OttieniTKelvinDaTCelsius(TColonna) / 9.807;
  }

  // Calcola la pressione a livello del mare
  doppio Pressione al livello del mare = StnPressione * exp(Altitudine / H);
  ritorno Pressione al livello del mare;
}

// Pressione della stazione di ritorno dalla pressione a livello del mare
// Riferimento: vedere 'GetSeaLevelPressure'
// Note: questa funzione è esattamente l'inverso di 'GetSeaLevelPressure'.
doppio Ottieni pressione stazione    // (o) Pressione della stazione in Psi [IP] o Pa [SI]
  ( doppio Pressione al livello del mare  // (i) Pressione barometrica al livello del mare in Psi [IP] o Pa [SI]
  , doppio Altitudine          // (i) Altitudine sopra il livello del mare in piedi [IP] o m [SI]
  , doppio TDryBulb          // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  )
{
  ritorno Pressione al livello del mare / Ottieni pressione livello mare (1., Altitudine, TDryBulb);
}


/**************************************************** ************************************************** ***
 * Funzioni per impostare tutti i valori psicrometrici
 ************************************************** ************************************************** */

// Funzione di utilità per calcolare il rapporto di umidità, la temperatura del punto di rugiada, l'umidità relativa,
// pressione del vapore, entalpia dell'aria umida, volume dell'aria umida e grado di saturazione dell'aria fornita
// temperatura a bulbo secco, temperatura a bulbo umido e pressione.
vuoto CalcPsychrometricsFromTWetBulb
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio TWetBulb             // (i) Temperatura del bulbo umido in °F [IP] o °C [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  , doppio *Rapporto Hum            // (o) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  , doppio *TDewPoint           // (o) Temperatura del punto di rugiada in °F [IP] o °C [SI]
  , doppio *RelHum              // (o) Umidità relativa [0-1]
  , doppio *VapPres             // (o) Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
  , doppio *Entalpia dell'aria umida    // (o) Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
  , doppio *Volume Aria Umida      // (o) Volume specifico ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
  , doppio *Grado di saturazione  // (o) Grado di saturazione [senza unità]
)
{
  ASSERT(TBulb <= TDryBulb, "La temperatura del bulbo umido è superiore alla temperatura del bulbo secco")

  *Rapporto Hum = Ottieni rapporto humumFromTWetBulb(TDryBulb, TWetLampadina, Pressione);
  *TDewPoint = OttieniTDewPointFromHumRatio(TDryBulb, *Rapporto Hum, Pressione);
  *RelHum = OttieniRapportoRelHumFromHum(TDryBulb, *Rapporto Hum, Pressione);
  *VapPres = GetVapPresFromHumRatio(*Rapporto Hum, Pressione);
  *Entalpia dell'aria umida = GetMoistAirEntalpia(TDryBulb, *Rapporto ronzio);
  *Volume Aria Umida = GetMoistAirVolume(TDryBulb, *Rapporto Hum, Pressione);
  *Grado di saturazione = Ottieni Grado di saturazione (TDryBulb, *Rapporto Hum, Pressione);
}

// Funzione di utilità per calcolare il rapporto di umidità, la temperatura del bulbo umido, l'umidità relativa,
// pressione del vapore, entalpia dell'aria umida, volume dell'aria umida e grado di saturazione dell'aria fornita
// temperatura del bulbo secco, temperatura del punto di rugiada e pressione.
vuoto CalcPsychrometricsFromTDewPoint
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio TDewPoint            // (i) Temperatura del punto di rugiada in °F [IP] o °C [SI]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  , doppio *Rapporto Hum            // (o) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  , doppio *TWetBulb            // (o) Temperatura del bulbo umido in °F [IP] o °C [SI]
  , doppio *RelHum              // (o) Umidità relativa [0-1]
  , doppio *VapPres             // (o) Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
  , doppio *Entalpia dell'aria umida    // (o) Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
  , doppio *Volume Aria Umida      // (o) Volume specifico ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
  , doppio *Grado di saturazione  // (o) Grado di saturazione [senza unità]
)
{
  ASSERT(TDewPoint <= TDryBulb, "La temperatura del punto di rugiada è superiore alla temperatura del bulbo secco")

  *Rapporto Hum = OttieniRapportoRum.DaPuntoDiTew(PuntoDiTew, Pressione);
  *TWetBulb = OttieniTWetBulbFromHumRatio(TDryBulb, *Rapporto Hum, Pressione);
  *RelHum = OttieniRapportoRelHumFromHum(TDryBulb, *Rapporto Hum, Pressione);
  *VapPres = GetVapPresFromHumRatio(*Rapporto Hum, Pressione);
  *Entalpia dell'aria umida = GetMoistAirEntalpia(TDryBulb, *Rapporto ronzio);
  *Volume Aria Umida = GetMoistAirVolume(TDryBulb, *Rapporto Hum, Pressione);
  *Grado di saturazione = Ottieni Grado di saturazione (TDryBulb, *Rapporto Hum, Pressione);
}

// Funzione di utilità per calcolare il rapporto di umidità, la temperatura del bulbo umido, la temperatura del punto di rugiada,
// pressione del vapore, entalpia dell'aria umida, volume dell'aria umida e grado di saturazione dell'aria fornita
// temperatura a bulbo secco, umidità relativa e pressione.
vuoto CalcPsychrometricsFromRelHum
  ( doppio TDryBulb             // (i) Temperatura a bulbo secco in °F [IP] o °C [SI]
  , doppio RelHum               // (i) Umidità relativa [0-1]
  , doppio Pressione             // (i) Pressione atmosferica in Psi [IP] o Pa [SI]
  , doppio *Rapporto Hum            // (o) Rapporto di umidità in lb_H₂O lb_Air⁻¹ [IP] o kg_H₂O kg_Air⁻¹ [SI]
  , doppio *TWetBulb            // (o) Temperatura del bulbo umido in °F [IP] o °C [SI]
  , doppio *TDewPoint           // (o) Temperatura del punto di rugiada in °F [IP] o °C [SI]
  , doppio *VapPres             // (o) Pressione parziale del vapore acqueo nell'aria umida in Psi [IP] o Pa [SI]
  , doppio *Entalpia dell'aria umida    // (o) Entalpia dell'aria umida in Btu lb⁻¹ [IP] o J kg⁻¹ [SI]
  , doppio *Volume Aria Umida      // (o) Volume specifico ft³ lb⁻¹ [IP] o in m³ kg⁻¹ [SI]
  , doppio *Grado di saturazione  // (o) Grado di saturazione [senza unità]
)
{
  ASSERT(RelHum >= 0 && RelHum <= 1, "L'umidità relativa è fuori dall'intervallo [0,1]")

  *Rapporto Hum = OttieniRapportoHumFromRelHum(TDryBulb, RelHum, Pressione);
  *TWetBulb = OttieniTWetBulbFromHumRatio(TDryBulb, *Rapporto Hum, Pressione);
  *TDewPoint = OttieniTDewPointFromHumRatio(TDryBulb, *Rapporto Hum, Pressione);
  *VapPres = GetVapPresFromHumRatio(*Rapporto Hum, Pressione);
  *Entalpia dell'aria umida = GetMoistAirEntalpia(TDryBulb, *Rapporto ronzio);
  *Volume Aria Umida = GetMoistAirVolume(TDryBulb, *Rapporto Hum, Pressione);
  *Grado di saturazione = Ottieni Grado di saturazione (TDryBulb, *Rapporto Hum, Pressione);
}