Fonctions de programmation psychrométrique

Bibliothèque de fonctions psychrométriques pour calculer les propriétés thermodynamiques de l'air pour Python, C, C#, Fortran, JavaScript et VBA/Excel

Aperçu

La psychrométrie est l'étude des propriétés physiques et thermodynamiques de l'air humide. Ces propriétés incluent, par exemple, la température du point de rosée de l'air, sa température de bulbe humide, l'humidité relative, le taux d'humidité et l'enthalpie.

L'estimation de ces propriétés est essentielle dans plusieurs applications techniques et scientifiques telles que le chauffage, la ventilation et la climatisation (CVC) et la météorologie. Bien que les formules permettant de calculer les propriétés psychrométriques de l'air soient largement disponibles dans la littérature (@Stull2011;@Wexler1983;@Stoecker1982;@Dilley1968;@Humphreys1920), leur mise en œuvre dans des programmes informatiques ou des feuilles de calcul peut être difficile et prendre du temps.

PsychroLib est une bibliothèque de fonctions permettant de calculer les propriétés psychrométriques de l'air humide et sec. La bibliothèque est disponible pour Python, C, C#, Fortran, JavaScript, Microsoft Excel Visual Basic pour Applications (VBA). Il fonctionne dans les systèmes d'unités métriques (SI) et impériaux (IP). Les fonctions sont basées sur des formules du manuel ASHRAE 2017 — Fondamentaux, chapitre 1, éditions SI et IP. Les fonctions peuvent être regroupées en deux catégories :

  1. Fonctions pour le calcul de la température du point de rosée, de la température du bulbe humide, de la pression partielle de vapeur de l'eau, du taux d'humidité ou de l'humidité relative, en connaissant les autres éléments, la température du bulbe sec et la pression atmosphérique.
  2. Fonctions pour le calcul d'autres propriétés de l'air humide. Tous ces éléments utilisent le taux d’humidité comme entrée.

Python

   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 (version 2.3.0) (https://github.com/psychrometrics/psychrolib)
# Copyright (c) 2018 D. Thevenard et D. Meyer pour l'implémentation actuelle de la bibliothèque
# Copyright (c) 2017 Manuel ASHRAE — Principes fondamentaux des équations et coefficients ASHRAE
# Sous licence MIT.

""" psychrolib.py
Contient des fonctions de calcul des propriétés thermodynamiques des mélanges gaz-vapeur
et atmosphère standard adaptée à la plupart des applications techniques, physiques et météorologiques
applications.
La plupart des fonctions sont une implémentation des formules trouvées dans le
Manuel ASHRAE 2017 - Fondamentaux, dans les deux systèmes internationaux (SI),
et unités impériales (IP). Veuillez vous référer aux informations incluses dans
chaque fonction pour leur référence respective.
Exemple
    >>> importer du psychrolib
    >>> # Définissez le système d'unités, par exemple sur SI (peut être psychrolib.SI ou psychrolib.IP)
    >>> psychrolib.SetUnitSystem(psychrolib.SI)
    >>> # Calculer la température du point de rosée pour une température sèche de 25 C et une humidité relative de 80%
    >>> TDewPoint = psychrolib.GetTDewPointFromRelHum(25.0, 0.80)
    >>> imprimer (TDewPoint)
    21.309397163661785
droits d'auteur
    - Pour l'implémentation actuelle de la bibliothèque
        Copyright (c) 2018 D. Thévenard et D. Meyer.
    - Pour les équations et les coefficients publiés ASHRAE Handbook — Fundamentals, Chapitre 1
        Copyright (c) Manuel ASHRAE 2017 — Fondamentaux (https://www.ashrae.org)
Licence
    MIT (https://github.com/psychrometrics/psychrolib/LICENSE.txt)
Note des auteurs
    Nous avons fait tous les efforts possibles pour garantir que le code soit adéquat, mais nous ne faisons aucun
    représentation quant à son exactitude. À utiliser à vos risques et périls. Si vous remarquez
    une erreur, ou si vous avez une suggestion, veuillez nous en informer via GitHub à l'adresse
    https://github.com/psychrometrics/psychrolib/issues.
"""


importer mathématiques
de énumération importer Énumération, auto
de dactylographie importer Facultatif


################################################# ################################################# ###
# Constantes globales
################################################# ################################################# ###

ZERO_FAHRENHEIT_AS_RANKINE = 459.67
"""flotteur : zéro degré Fahrenheit (°F) exprimé en degré Rankine (°R)
    Unités:
        °R
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 39
"""

ZERO_CELSIUS_AS_KELVIN = 273.15
"""flotteur : zéro degré Celsius (°C) exprimé en Kelvin (K)
    Unités:
        K
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 39
"""

R_DA_IP = 53.350
"""flotteur : Constante de gaz universelle pour air sec (version IP)
    Unités:
        pi lb_Force lb_DryAir⁻¹ R⁻¹
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1
"""

R_DA_SI = 287.042
"""flotteur : Constante de gaz universelle pour air sec (version SI)
    Unités:
        J kg_DryAir⁻¹ K⁻¹
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1
"""

MAX_ITER_COUNT = 100
"""int : nombre maximum d'itérations avant de quitter les boucles while.
"""

MIN_HUM_RATIO = 1e-7
"""flotteur : taux d'humidité minimum acceptable utilisé/restitué par toutes les fonctions.
          Toute valeur supérieure à 0 ou inférieure au MIN_HUM_RATIO sera réinitialisée à cette valeur.
"""

FREEZING_POINT_WATER_IP = 32.0
"""flotteur : Point de congélation de l'eau en Fahrenheit.
"""

FREEZING_POINT_WATER_SI = 0.0
"""flotteur : Point de congélation de l'eau en Celsius.
"""

TRIPLE_POINT_WATER_IP = 32.018
"""flotteur : Triple point d'eau en Fahrenheit.
"""

TRIPLE_POINT_WATER_SI = 0.01
"""flotteur : Triple point de l'eau en Celsius.
"""

################################################# ################################################# ###
# Fonctions d'assistance
################################################# ################################################# ###

# Système d'unités à utiliser.
classe Système d'unité(énumération):
    """
    Classe privée non exposée utilisée pour définir des valeurs d'énumération automatique.
    """
    IP = auto()
    SI = auto()

IP = UnitSystem.IP
SI = UnitSystem.SI

PSYCHROLIB_UNITS = Aucun

PSYCHROLIB_TOLERANCE = 1.0
# Tolérance des calculs de température

définitivement DéfinirSystèmeUnité(Unités: Système d'unité) -> Aucun:
    """
    Définissez le système d’unités à utiliser (SI ou IP).
    Arguments :
        Unités : chaîne indiquant le système d'unités choisi (SI ou IP)
    Remarques:
        Cette fonction *DOIT ÊTRE APPELÉE* avant que la bibliothèque puisse être utilisée
    """
    global PSYCHROLIB_UNITS
    global PSYCHROLIB_TOLERANCE

    si ne pas estinstance(Unités, Système d'unité):
        augmenter Erreur de valeur("Le système d'unités doit être soit SI, soit IP.")

    PSYCHROLIB_UNITS = Unités

    # Définir la tolérance sur les calculs de température
    # La tolérance est la même en IP et SI
    si Unités == IP :
        PSYCHROLIB_TOLERANCE = 0.001 * 9. / 5.
    autre:
        PSYCHROLIB_TOLERANCE = 0.001

définitivement ObtenirUnitSystem() -> Facultatif[UnitSystem] :
    """
    Système de retour des unités en cours d'utilisation.
    """
    retour PSYCHROLIB_UNITS

définitivement estIP() -> bourdonner:
    """
    Vérifiez si le système utilisé est IP ou SI.
    """
    si PSYCHROLIB_UNITS == IP :
        retour Vrai
    elif PSYCHROLIB_UNITS == SI:
        retour Faux
    autre:
        augmenter Erreur de valeur("Le système d'unités n'a pas été défini.")


################################################# ################################################# ###
# Conversion entre unités de température
################################################# ################################################# ###

définitivement ObtenirTRankineFromTFahrenheit(TFahrenheit : flotteur) -> flotteur:
    """
    Fonction utilitaire pour convertir la température en degré Rankine (°R)
    température donnée en degrés Fahrenheit (°F).
    Arguments :
        Trankine : Température en degrés Fahrenheit (°F)
    Retour:
        Température en degré Rankine (°R)
    Référence:
        Référence : Manuel ASHRAE - Fondamentaux (2017) ch. 1 chapitre 3
    Remarques:
        Conversion exacte.
    """
    TRankine = TFahrenheit + ZERO_FAHRENHEIT_AS_RANKINE
    retour TRankine

définitivement ObtenirTFahrenheitDeTRankine(TRangine : flotteur) -> flotteur:
    """
    Fonction utilitaire pour convertir la température en degrés Fahrenheit (°F)
    température donnée en degré Rankine (°R).
    Arguments :
        TRankine : Température en degré Rankine (°R)
    Retour:
        Température en degrés Fahrenheit (°F)
    Référence:
        Référence : Manuel ASHRAE - Fondamentaux (2017) ch. 1 chapitre 3
    Remarques:
        Conversion exacte.
    """
    retour TRankine - ZERO_FAHRENHEIT_AS_RANKINE

définitivement ObtenirTKelvinFromTCelsius(TCelsius : flotteur) -> flotteur:
    """
    Fonction utilitaire pour convertir la température en Kelvin (K)
    température donnée en degrés Celsius (°C).
    Arguments :
        TCelsius : Température en degrés Celsius (°C)
    Retour:
        Température en Kelvin (K)
    Référence:
        Référence : Manuel ASHRAE - Fondamentaux (2017) ch. 1 chapitre 3
    Remarques:
        Conversion exacte.
    """
    TKelvin = TCelsius + ZERO_CELSIUS_AS_KELVIN
    retour TKelvin

définitivement ObtenirTCelsiusFromTKelvin(TKelvin : flotteur) -> flotteur:
    """
    Fonction utilitaire pour convertir la température en degrés Celsius (°C)
    température donnée en Kelvin (K).
    Arguments :
        TKelvin : Température en Kelvin (K)
    Retour:
        Température en degrés Celsius (°C)
    Référence:
        Référence : Manuel ASHRAE - Fondamentaux (2017) ch. 1 chapitre 3
    Remarques:
        Conversion exacte.
    """
    retour TKelvin - ZERO_CELSIUS_AS_KELVIN


################################################# ################################################# ###
# Conversions entre point de rosée, bulbe humide et humidité relative
################################################# ################################################# ###

définitivement GetTWetBulbFromTDewPoint(TDDryBulb : flotteur, TDewPoint : flotteur, Pression: flotteur) -> flotteur:
    """
    Renvoie la température du bulbe humide en fonction de la température du bulbe sec, de la température du point de rosée et de la pression.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        TDewPoint : Température du point de rosée en °F [IP] ou °C [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Température du bulbe humide en °F [IP] ou °C [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1
    """
    si TDewPoint > TDryBulb :
        augmenter Erreur de valeur("La température du point de rosée est supérieure à la température du bulbe sec")

    HumRatio = GetHumRatioFromTDewPoint(TDewPoint, Pression)
    TWetBulbComment = GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pression)
    retour TWetBulbComment

définitivement GetTWetBulbFromRelHum(TDDryBulb : flotteur, RelHum : flotteur, Pression: flotteur) -> flotteur:
    """
    Renvoie la température du bulbe humide en fonction de la température du bulbe sec, de l'humidité relative et de la pression.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        RelHum : Humidité relative dans la plage [0, 1]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Température du bulbe humide en °F [IP] ou °C [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1
    """
    si RelHum < 0 ou RelHum > 1:
        augmenter Erreur de valeur("L'humidité relative est en dehors de la plage [0, 1]")

    HumRatio = GetHumRatioFromRelHum(TDryBulb, RelHum, Pression)
    TWetBulbComment = GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pression)
    retour TWetBulbComment

définitivement GetRelHumFromTDewPoint(TDDryBulb : flotteur, TDewPoint : flotteur) -> flotteur:
    """
    Renvoie l'humidité relative en fonction de la température du bulbe sec et de la température du point de rosée.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        TDewPoint : Température du point de rosée en °F [IP] ou °C [SI]
    Retour:
        Humidité relative dans la plage [0, 1]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 22
    """
    si TDewPoint > TDryBulb :
        augmenter Erreur de valeur("La température du point de rosée est supérieure à la température du bulbe sec")

    VapPres = ObtenirSatVapPres(TDewPoint)
    SatVapPres = ObtenirSatVapPres(TDryBulb)
    RelHum = VapPres / SatVapPres
    retour RelHum

définitivement GetRelHumFromTWetBulb(TDDryBulb : flotteur, TWetBulb : flotteur, Pression: flotteur) -> flotteur:
    """
    Renvoie l'humidité relative en fonction de la température du bulbe sec, de la température du bulbe humide et de la pression.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        TWetBulb : Température du bulbe humide en °F [IP] ou °C [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Humidité relative dans la plage [0, 1]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1
    """
    si TWetBulbComment > TDryBulb :
        augmenter Erreur de valeur("La température du bulbe humide est supérieure à la température du bulbe sec")

    HumRatio = GetHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pression)
    RelHum =  GetRelHumFromHumRatio(TDryBulb, HumRatio, Pression)
    retour RelHum

définitivement ObtenirTDewPointFromRelHum(TDDryBulb : flotteur, RelHum : flotteur) -> flotteur:
    """
    Température de retour du point de rosée en fonction de la température du bulbe sec et de l'humidité relative.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        RelHum : humidité relative dans la plage [0, 1]
    Retour:
        Température du point de rosée en °F [IP] ou °C [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1
    """
    si RelHum < 0 ou RelHum > 1:
        augmenter Erreur de valeur("L'humidité relative est en dehors de la plage [0, 1]")

    VapPres = GetVapPresFromRelHum(TDryBulb, RelHum)
    TDewPoint = GetTDewPointFromVapPres(TDryBulb, VapPres)
    retour TDewPoint

définitivement GetTDewPointFromTWetBulb(TDDryBulb : flotteur, TWetBulb : flotteur, Pression: flotteur) -> flotteur:
    """
    Température de retour du point de rosée en fonction de la température du bulbe sec, de la température du bulbe humide et de la pression.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        TWetBulb : Température du bulbe humide en °F [IP] ou °C [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Température du point de rosée en °F [IP] ou °C [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1
    """
    si TWetBulbComment > TDryBulb :
        augmenter Erreur de valeur("La température du bulbe humide est supérieure à la température du bulbe sec")

    HumRatio = GetHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pression)
    TDewPoint = GetTDewPointFromHumRatio(TDryBulb, HumRatio, Pression)
    retour TDewPoint


################################################# ################################################# ###
# Conversions entre point de rosée ou humidité relative et pression de vapeur
################################################# ################################################# ###

définitivement GetVapPresFromRelHum(TDDryBulb : flotteur, RelHum : flotteur) -> flotteur:
    """
    Renvoie la pression partielle de vapeur d'eau en fonction de l'humidité relative et de la température.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        RelHum : Humidité relative dans la plage [0, 1]
    Retour:
        Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 12, 22
    """
    si RelHum < 0 ou RelHum > 1:
        augmenter Erreur de valeur("L'humidité relative est en dehors de la plage [0, 1]")

    VapPres = RelHum * ObtenirSatVapPres(TDryBulb)
    retour VapPres

définitivement GetRelHumFromVapPres(TDDryBulb : flotteur, VapPres : flotteur) -> flotteur:
    """
    Renvoie l'humidité relative en fonction de la température du bulbe sec et de la pression de vapeur.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        VapPres : Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
    Retour:
        Humidité relative dans la plage [0, 1]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 12, 22
    """
    si VapPres < 0:
        augmenter Erreur de valeur("La pression partielle de la vapeur d'eau dans l'air humide ne peut pas être négative")

    RelHum = VapPres / ObtenirSatVapPres(TDryBulb)
    retour RelHum

définitivement dLnPws_(TDDryBulb : flotteur) -> flotteur:
    """
    Fonction d'assistance renvoyant la dérivée du logarithme népérien de la pression de vapeur saturante 
    en fonction de la température du bulbe sec.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
    Retour:
        Dérivée du logarithme naturel de la pression de vapeur de l'air saturé en Psi [IP] ou Pa [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équations 5 et 6
    """
    si estIP() :
        J = ObtenirTRankineFromTFahrenheit(TDryBulb)
        si TDryBulb <= TRIPLE_POINT_WATER_IP :
            dLnPws = 1.0214165E+04 / math.pow(T, 2) - 5.3765794E-03 + 2 * 1.9202377E-07 * J \
                  + 3 * 3.5575832E-10 * math.pow(T, 2) - 4 * 9.0344688E-14 * math.pow(T, 3) + 4.1635019 / J
        autre:
            dLnPws = 1.0440397E+04 / math.pow(T, 2) - 2.7022355E-02 + 2 * 1.2890360E-05 * J \
                  - 3 * 2.4780681E-09 * math.pow(T, 2) + 6.5459673 / J
    autre:
        J = ObtenirTKelvinFromTCelsius(TDryBulb)
        si TDryBulb <= TRIPLE_POINT_WATER_SI :
            dLnPws = 5.6745359E+03 / math.pow(T, 2) - 9.677843E-03 + 2 * 6.2215701E-07 * J \
                  + 3 * 2.0747825E-09 * math.pow(T, 2) - 4 * 9.484024E-13 * math.pow(T, 3) + 4.1635019 / J
        autre:
            dLnPws = 5.8002206E+03 / math.pow(T, 2) - 4.8640239E-02 + 2 * 4.1764768E-05 * J \
                  - 3 * 1.4452093E-08 * math.pow(T, 2) + 6.5459673 / J

    retour dLnPws

définitivement GetTDewPointFromVapPres(TDDryBulb : flotteur, VapPres : flotteur) -> flotteur:
    """
    Température du point de rosée de retour compte tenu de la température du bulbe sec et de la pression de vapeur.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        VapPres : Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
    Retour:
        Température du point de rosée en °F [IP] ou °C [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 éq. 5 et 6
    Remarques:
        La température du point de rosée est résolue en inversant l'équation donnant la pression de vapeur d'eau
        à saturation à partir de la température plutôt que d'utiliser les régressions fournies
        par ASHRAE (équations 37 et 38) qui sont beaucoup moins précises et ont un
        plage de validité plus étroite.
        La méthode Newton-Raphson (NR) est utilisée sur le logarithme de la vapeur d'eau
        pression en fonction de la température, ce qui est une fonction très fluide
        La convergence est généralement obtenue en 3 à 5 itérations. 
        TDryBulb n'est pas vraiment nécessaire ici, juste utilisé pour plus de commodité.
    """
    si estIP() :
        BORNES = [-148, 392]
    autre:
        BORNES = [-100, 200]

    # Contrôle de validité -- limites en dehors desquelles une solution ne peut pas être trouvée
    si VapPres < GetSatVapPres(LIMES[0]) ou VapPres > GetSatVapPres(LIMES[1]):
        augmenter Erreur de valeur("La pression partielle de la vapeur d'eau se situe en dehors du domaine de validité des équations")

    # Nous utilisons NR pour approximer la solution.
    # Première supposition
    TDewPoint = TDryBulb        # Valeur calculée des températures du point de rosée, résolue de manière itérative
    lnVP = math.log(VapPres)    # Pression partielle de vapeur d'eau dans l'air humide

    indice = 1

    tandis que Vrai:
        TDewPoint_iter = TDewPoint   # TDewPoint utilisé dans le calcul NR
        lnVP_iter = math.log(GetSatVapPres(TDewPoint_iter))

        # Dérivée de fonction, calculée analytiquement
        d_lnVP = dLnPws_(TDewPoint_iter)

        # Nouvelle estimation, délimitée par le domaine de recherche défini ci-dessus
        TDewPoint = TDewPoint_iter - (lnVP_iter - lnVP) / d_lnVP
        TDewPoint = maximum(TDewPoint, BORNES[0])
        TDewPoint = min(TDewPoint, BORNES[1])

        si ((math.fabs(TDewPoint - TDewPoint_iter) <= PSYCHROLIB_TOLERANCE) :
            Pause

        si (indice > MAX_ITER_COUNT) :
            augmenter Erreur de valeur("Convergence non atteinte dans GetTDewPointFromVapPres. Arrêt.")

        indice = indice + 1

    TDewPoint = min(TDewPoint, TDryBulb)
    retour TDewPoint

définitivement GetVapPresFromTDewPoint(TDewPoint : flotteur) -> flotteur:
    """
    Pression de vapeur de retour en fonction de la température du point de rosée.
    Arguments :
        TDewPoint : Température du point de rosée en °F [IP] ou °C [SI]
    Retour:
        Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 36
    """
    VapPres = ObtenirSatVapPres(TDewPoint)
    retour VapPres


################################################# ################################################# ###
# Conversions de la température du bulbe humide, de la température du point de rosée ou du rapport humidité relative/humidité
################################################# ################################################# ###

définitivement GetTWetBulbFromHumRatio(TDDryBulb : flotteur, HumRatio : flotteur, Pression: flotteur) -> flotteur:
    """
    Renvoie la température du bulbe humide en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        HumRatio : Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Température du bulbe humide en °F [IP] ou °C [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équations 33 et 35 résolues pour Tstar
    """
    si HumRatio < 0:
        augmenter Erreur de valeur("Le taux d'humidité ne peut pas être négatif")
    BoundedHumRatio = maximum(HumRapport, MIN_HUM_RATIO)

    TDewPoint = GetTDewPointFromHumRatio(TDryBulb, Rapport HumBounded, Pression)

    # Suppositions initiales
    TWetBulbSup = TDryBulb
    TWetBulbInf = TDewPoint
    TWetBulbComment = (TWetBulbInf + TWetBulbSup) / 2

    indice = 1
    # Boucle de bissection
    tandis que ((TWetBulbSup - TWetBulbInf) > PSYCHROLIB_TOLERANCE :

        # Calculer le taux d'humidité à la température Tstar
        Wstar = GetHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pression)

        # Obtenez de nouvelles limites
        si Wstar > Rapport HumBounded :
            TWetBulbSup = TWetBulbComment
        autre:
            TWetBulbInf = TWetBulbComment

        # Nouvelle estimation de la température du bulbe humide
        TWetBulbComment = (TWetBulbSup + TWetBulbInf) / 2

        si (indice >= MAX_ITER_COUNT) :
            augmenter Erreur de valeur("Convergence non atteinte dans GetTWetBulbFromHumRatio. Arrêt.")

        indice = indice + 1
    retour TWetBulbComment

définitivement GetHumRatioFromTWetBulb(TDDryBulb : flotteur, TWetBulb : flotteur, Pression: flotteur) -> flotteur:
    """
    Rapport d'humidité de retour en fonction de la température du bulbe sec, de la température du bulbe humide et de la pression.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        TWetBulb : Température du bulbe humide en °F [IP] ou °C [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équations 33 et 35
    """
    si TWetBulbComment > TDryBulb :
        augmenter Erreur de valeur("La température du bulbe humide est supérieure à la température du bulbe sec")

    Wsstar = GetSatHumRatio(TWetBulb, Pression)

    si estIP() :
       si TWetBulbComment >= FREEZING_POINT_WATER_IP :
           HumRatio = ((1093 - 0.556 * TWetBulb) * Wsstar - 0.240 * (TDDryBulb - TWetBulb)) \
                    / (1093 + 0.444 * TDryBulb - TWetBulb)
       autre:
           HumRatio = ((1220 - 0.04 * TWetBulb) * Wsstar - 0.240 * (TDDryBulb - TWetBulb)) \
                    / (1220 + 0.444 * TDryBulb - 0.48* TWetBulb)
    autre:
       si TWetBulbComment >= FREEZING_POINT_WATER_SI :
           HumRatio = ((2501. - 2.326 * TWetBulb) * Wsstar - 1.006 * (TDDryBulb - TWetBulb)) \
                    / (2501. + 1.86 * TDryBulb - 4.186 * TWetBulb)
       autre:
           HumRatio = ((2830. - 0.24 * TWetBulb) * Wsstar - 1.006 * (TDDryBulb - TWetBulb)) \
                    / (2830. + 1.86 * TDryBulb - 2.1 * TWetBulb)
    # Contrôle de validité.
    retour maximum(HumRapport, MIN_HUM_RATIO)

définitivement GetHumRatioFromRelHum(TDDryBulb : flotteur, RelHum : flotteur, Pression: flotteur) -> flotteur:
    """
    Taux d'humidité de retour en fonction de la température du bulbe sec, de l'humidité relative et de la pression.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        RelHum : Humidité relative dans la plage [0, 1]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1
    """
    si RelHum < 0 ou RelHum > 1:
        augmenter Erreur de valeur("L'humidité relative est en dehors de la plage [0, 1]")

    VapPres = GetVapPresFromRelHum(TDryBulb, RelHum)
    HumRatio = GetHumRatioFromVapPres(VapPres, Pression)
    retour HumRatio

définitivement GetRelHumFromHumRatio(TDDryBulb : flotteur, HumRatio : flotteur, Pression: flotteur) -> flotteur:
    """
    Renvoie l'humidité relative en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        HumRatio : Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Humidité relative dans la plage [0, 1]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1
    """
    si HumRatio < 0:
        augmenter Erreur de valeur("Le taux d'humidité ne peut pas être négatif")

    VapPres = GetVapPresFromHumRatio(HumRatio, Pression)
    RelHum = GetRelHumFromVapPres(TDDryBulb, VapPres)
    retour RelHum

définitivement GetHumRatioFromTDewPoint(TDewPoint : flotteur, Pression: flotteur) -> flotteur:
    """
    Taux d'humidité de retour en fonction de la température et de la pression du point de rosée.
    Arguments :
        TDewPoint : Température du point de rosée en °F [IP] ou °C [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 13
    """
    VapPres = ObtenirSatVapPres(TDewPoint)
    HumRatio = GetHumRatioFromVapPres(VapPres, Pression)
    retour HumRatio

définitivement GetTDewPointFromHumRatio(TDDryBulb : flotteur, HumRatio : flotteur, Pression: flotteur) -> flotteur:
    """
    Température de retour du point de rosée en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        HumRatio : Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Température du point de rosée en °F [IP] ou °C [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1
    """
    si HumRatio < 0:
        augmenter Erreur de valeur("Le taux d'humidité ne peut pas être négatif")

    VapPres = GetVapPresFromHumRatio(HumRatio, Pression)
    TDewPoint = GetTDewPointFromVapPres(TDryBulb, VapPres)
    retour TDewPoint


################################################# ################################################# ###
# Conversions entre taux d'humidité et pression de vapeur
################################################# ################################################# ###

définitivement GetHumRatioFromVapPres(VapPres : flotteur, Pression: flotteur) -> flotteur:
    """
    Taux d'humidité de retour étant donné la pression de vapeur d'eau et la pression atmosphérique.
    Arguments :
        VapPres : Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 20
    """
    si VapPres < 0:
        augmenter Erreur de valeur("La pression partielle de la vapeur d'eau dans l'air humide ne peut pas être négative")

    HumRatio = 0.621945 * VapPres / (Pression - VapPres)

    # Contrôle de validité.
    retour maximum(HumRapport, MIN_HUM_RATIO)

définitivement GetVapPresFromHumRatio(HumRatio : flotteur, Pression: flotteur) -> flotteur:
    """
    Pression de vapeur de retour en fonction du taux d'humidité et de la pression.
    Arguments :
        HumRatio : Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 20 résolue pour pw
    """
    si HumRatio < 0:
        augmenter Erreur de valeur("Le taux d'humidité est négatif")
    BoundedHumRatio = maximum(HumRapport, MIN_HUM_RATIO)

    VapPres = Pression * BoundedHumRatio / (0.621945 + BoundedHumRatio)
    retour VapPres


################################################# ################################################# ###
# Conversions entre taux d'humidité et humidité spécifique
################################################# ################################################# ###

définitivement GetSpecificHumFromHumRatio(HumRatio : flotteur) -> flotteur:
    """
    Renvoie l'humidité spécifique à partir du rapport d'humidité (c'est-à-dire le rapport de mélange).
    Arguments :
        HumRatio : Taux d'humidité en lb_H₂O lb_Dry_Air⁻¹ [IP] ou kg_H₂O kg_Dry_Air⁻¹ [SI]
    Retour:
        Humidité spécifique en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 9b
    """
    si HumRatio < 0:
        augmenter Erreur de valeur("Le taux d'humidité ne peut pas être négatif")
    BoundedHumRatio = maximum(HumRapport, MIN_HUM_RATIO)

    SpécifiqueHum = BoundedHumRatio / (1.0 + BoundedHumRatio)
    retour SpécifiqueHum

définitivement GetHumRatioFromSpecificHum(Hum spécifique : flotteur) -> flotteur:
    """
    Renvoie le taux d'humidité (c'est-à-dire le taux de mélange) à partir d'une humidité spécifique.
    Arguments :
        SpecificHum : Humidité spécifique en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    Retour:
        Taux d'humidité en lb_H₂O lb_Dry_Air⁻¹ [IP] ou kg_H₂O kg_Dry_Air⁻¹ [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 9b (résolu pour le taux d'humidité)
    """
    si SpécifiqueHum < 0.0 ou SpécifiqueHum >= 1.0:
        augmenter Erreur de valeur("L'humidité spécifique est en dehors de la plage [0, 1[")

    HumRatio = SpécifiqueHum / (1.0 - SpécifiqueHum)

    # Contrôle de validité.
    retour maximum(HumRapport, MIN_HUM_RATIO)


################################################# ################################################# ###
# Calculs d'air sec
################################################# ################################################# ###

définitivement GetDryAirEnthalpy(TDDryBulb : flotteur) -> flotteur:
    """
    Renvoie l'enthalpie de l'air sec en fonction de la température du bulbe sec.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
    Retour:
        Enthalpie de l'air sec en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 28
    """
    si estIP() :
        Enthalpie de l'air sec = 0.240 * TDryBulb
    autre:
        Enthalpie de l'air sec = 1006 * TDryBulb
    retour Enthalpie de l'air sec

définitivement GetDryAirDensity(TDDryBulb : flotteur, Pression: flotteur) -> flotteur:
    """
    Renvoyez la densité de l'air sec en fonction de la température et de la pression du bulbe sec.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Densité de l'air sec en lb ft⁻³ [IP] ou kg m⁻³ [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1
    Remarques:
        Éqn 14 pour la relation gazeuse parfaite pour l'air sec.
        Eqn 1 pour la constante universelle des gaz.
        Le facteur 144 en IP est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².
    """
    si estIP() :
        DryAirDensity = (144 * Pression) / R_DA_IP / ObtenirTRankineFromTFahrenheit(TDryBulb)
    autre:
        DryAirDensity = Pression / R_DA_SI / ObtenirTKelvinFromTCelsius(TDryBulb)
    retour DryAirDensity

définitivement GetDryAirVolume(TDDryBulb : flotteur, Pression: flotteur) -> flotteur:
    """
    Restituez le volume d’air sec en fonction de la température et de la pression du bulbe sec.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Volume d'air sec en pi³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1
    Remarques:
        Éqn 14 pour la relation gazeuse parfaite pour l'air sec.
        Eqn 1 pour la constante universelle des gaz.
        Le facteur 144 en IP est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².
    """
    si estIP() :
        Volume d'air sec = R_DA_IP * ObtenirTRankineFromTFahrenheit(TDryBulb) / (144 * Pression)
    autre:
        Volume d'air sec = R_DA_SI * ObtenirTKelvinFromTCelsius(TDryBulb) / Pression
    retour Volume d'air sec


définitivement GetTDryBulbFromEnthalpyAndHumRatio(Enthalpie de l'air humide : flotteur, HumRatio : flotteur) -> flotteur:
    """
    Renvoie la température du bulbe sec à partir du rapport d’enthalpie et d’humidité.
    Arguments :
        MoistAirEnthalpy : Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹
        HumRatio : Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    Retour:
        Température du bulbe sec en °F [IP] ou °C [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 30
    Remarques:
        Basé sur la fonction « GetMoistAirEnthalpy », réorganisée en fonction de la température.
    """
    si HumRatio < 0:
        augmenter Erreur de valeur("Le taux d'humidité est négatif")
    BoundedHumRatio = maximum(HumRapport, MIN_HUM_RATIO)

    si estIP() :
        TDryBulb  = (Enthalpie de l'air humide - 1061.0 * BoundedHumRatio) / (0.240 + 0.444 * BoundedHumRatio)
    autre:
        TDryBulb  = (Enthalpie de l'air humide / 1000.0 - 2501.0 * BoundedHumRatio) / (1.006 + 1.86 * BoundedHumRatio)
    retour TDryBulb

définitivement GetHumRatioFromEnthalpyAndTDryBulb(Enthalpie de l'air humide : flotteur, TDryBulb : flotteur) -> flotteur:
    """
    Renvoie le rapport d’humidité à partir de l’enthalpie et de la température du bulbe sec.
    Arguments :
        MoistAirEnthalpy : Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
    Retour:
        Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 30.
    Remarques:
        Basé sur la fonction « GetMoistAirEnthalpy », réorganisée en fonction du taux d'humidité.
    """
    si estIP() :
        HumRatio  = (Enthalpie de l'air humide - 0.240 * TDryBulb) / (1061.0 + 0.444 * TDryBulb)
    autre:
        HumRatio  = (Enthalpie de l'air humide / 1000.0 - 1.006 * TDryBulb) / (2501.0 + 1.86 * TDryBulb)

    # Contrôle de validité.
    retour maximum(HumRapport, MIN_HUM_RATIO)


################################################# ################################################# ###
# Calculs d'air saturé
################################################# ################################################# ###

définitivement GetSatVapPres(TDDryBulb : flotteur) -> flotteur:
    """
    Pression de vapeur saturante de retour étant donné la température du bulbe sec.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
    Retour:
        Pression de vapeur de l'air saturé en Psi [IP] ou Pa [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équations 5 et 6
        Remarque importante : les formules ASHRAE sont définies au dessus et en dessous du point de congélation mais ont
        une discontinuité au point de congélation. Il s'agit d'une petite inexactitude de la part d'ASHRAE : les formules
        doit être défini au-dessus et au-dessous du point triple de l'eau (et non du point de congélation), auquel cas
        la discontinuité disparaît. Il est indispensable d'utiliser le point triple d'eau sinon fonctionne
        GetTDewPointFromVapPres, qui inverse la fonction actuelle, ne converge pas correctement autour de
        le point de congélation.
    """
    si estIP() :
        si (TDDryBulb < -148 ou TDryBulb > 392):
            augmenter Erreur de valeur("La température du bulbe sec doit être comprise dans la plage [-148, 392]°F")

        J = ObtenirTRankineFromTFahrenheit(TDryBulb)

        si (TDDryBulb <= TRIPLE_POINT_WATER_IP :
            LnPws = (-1.0214165E+04 / J - 4.8932428 - 5.3765794E-03 * J + 1.9202377E-07 * T**2 \
                  + 3.5575832E-10 * math.pow(T, 3) - 9.0344688E-14 * math.pow(T, 4) + 4.1635019 * math.log(T))
        autre:
            LnPws = -1.0440397E+04 / J - 1.1294650E+01 - 2.7022355E-02* J + 1.2890360E-05 * T**2 \
                  - 2.4780681E-09 * math.pow(T, 3) + 6.5459673 * math.log(T)
    autre:
        si (TDDryBulb < -100 ou TDryBulb > 200):
            augmenter Erreur de valeur("La température du bulbe sec doit être comprise dans la plage [-100, 200]°C")

        J = ObtenirTKelvinFromTCelsius(TDryBulb)

        si (TDDryBulb <= TRIPLE_POINT_EAU_SI) :
            LnPws = -5.6745359E+03 / J + 6.3925247 - 9.677843E-03 * J + 6.2215701E-07 * T**2 \
                  + 2.0747825E-09 * math.pow(T, 3) - 9.484024E-13 * math.pow(T, 4) + 4.1635019 * math.log(T)
        autre:
            LnPws = -5.8002206E+03 / J + 1.3914993 - 4.8640239E-02 * J + 4.1764768E-05 * T**2 \
                  - 1.4452093E-08 * math.pow(T, 3) + 6.5459673 * math.log(T)

    SatVapPres = math.exp(LnPws)
    retour SatVapPres

définitivement GetSatHumRatio(TDDryBulb : flotteur, Pression: flotteur) -> flotteur:
    """
    Taux d'humidité de retour de l'air saturé en fonction de la température et de la pression du bulbe sec.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Taux d'humidité de l'air saturé en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 36, résolue pour W
    """
    SatVaporPres = ObtenirSatVapPres(TDryBulb)
    SatHumRatio = 0.621945 * SatVaporPres / (Pression - SatVaporPres)

    # Contrôle de validité.
    retour maximum(SatHumRatio, MIN_HUM_RATIO)

définitivement GetSatAirEnthalpy(TDDryBulb : flotteur, Pression: flotteur) -> flotteur:
    """
    Renvoyez l’enthalpie de l’air saturé en fonction de la température et de la pression du bulbe sec.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Enthalpie de l'air saturé en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1
    """
    SatHumRatio = GetSatHumRatio(TDDryBulb, Pression)
    SatAirEnthalpie = GetMoistAirEnthalpy(TDDryBulb, SatHumRatio)
    retour SatAirEnthalpie


################################################# ################################################# ###
# Calculs d'air humide
################################################# ################################################# ###

définitivement GetVaporPressureDeficit(TDDryBulb : flotteur, HumRatio : flotteur, Pression: flotteur) -> flotteur:
    """
    Retour Déficit de pression de vapeur en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        HumRatio : Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Déficit de pression de vapeur en Psi [IP] ou Pa [SI]
    Référence:
        Oke (1987) équation 2.13a
    """
    si HumRatio < 0:
        augmenter Erreur de valeur("Le taux d'humidité est négatif")

    RelHum = GetRelHumFromHumRatio(TDryBulb, HumRatio, Pression)
    Déficit de pression de vapeur = ObtenirSatVapPres(TDryBulb) * (1 - RelHum)
    retour Déficit de pression de vapeur

définitivement GetDegreeOfSaturation(TDDryBulb : flotteur, HumRatio : flotteur, Pression: flotteur) -> flotteur:
    """
    Renvoie le degré de saturation (c'est à dire le rapport humidité de l'air/humidité de l'air à saturation
    à la même température et pression) étant donné la température du bulbe sec, le taux d'humidité et la pression atmosphérique.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        HumRatio : Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Degré de saturation en unité arbitraire
    Référence:
        Manuel ASHRAE - Fondamentaux (2009) ch. 1 équation 12
    Remarques:
        Cette définition est absente du Manuel 2017. Utiliser plutôt la version 2009.
    """
    si HumRatio < 0:
        augmenter Erreur de valeur("Le taux d'humidité est négatif")
    BoundedHumRatio = maximum(HumRapport, MIN_HUM_RATIO)

    SatHumRatio = GetSatHumRatio(TDDryBulb, Pression)
    DegréDeSaturation = BoundedHumRatio / SatHumRatio
    retour DegréDeSaturation

définitivement GetMoistAirEnthalpy(TDDryBulb : flotteur, HumRatio : flotteur) -> flotteur:
    """
    Renvoie l'enthalpie de l'air humide en fonction de la température du bulbe sec et du rapport d'humidité.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        HumRatio : Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    Retour:
        Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 30
    """
    si HumRatio < 0:
        augmenter Erreur de valeur("Le taux d'humidité est négatif")
    BoundedHumRatio = maximum(HumRapport, MIN_HUM_RATIO)

    si estIP() :
        Enthalpie de l'air humide = 0.240 * TDryBulb + BoundedHumRatio * (1061 + 0.444 * TDryBulb)
    autre:
        Enthalpie de l'air humide = (1.006 * TDryBulb + BoundedHumRatio * (2501. + 1.86 * TDryBulb)) * 1000
    retour Enthalpie de l'air humide

définitivement GetMoistAirVolume(TDDryBulb : flotteur, HumRatio : flotteur, Pression: flotteur) -> flotteur:
    """
    Renvoyez le volume spécifique d’air humide en fonction de la température du bulbe sec, du taux d’humidité et de la pression.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        HumRatio : Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Volume spécifique d'air humide en pi³ lb⁻¹ d'air sec [IP] ou en m³ kg⁻¹ d'air sec [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 26
    Remarques:
        En unités IP, R_DA_IP/144 est égal à 0,370486 qui est le coefficient apparaissant dans l'équation 26
        Le facteur 144 est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².
    """
    si HumRatio < 0:
        augmenter Erreur de valeur("Le taux d'humidité est négatif")
    BoundedHumRatio = maximum(HumRapport, MIN_HUM_RATIO)

    si estIP() :
        Volume d'air humide = R_DA_IP * ObtenirTRankineFromTFahrenheit(TDryBulb) * (1 + 1.607858 * BoundedHumRatio) / (144 * Pression)
    autre:
        Volume d'air humide = R_DA_SI * ObtenirTKelvinFromTCelsius(TDryBulb) * (1 + 1.607858 * BoundedHumRatio) / Pression
    retour Volume d'air humide

définitivement GetTDryBulbFromMoistAirVolumeAndHumRatio(Volume d'air humide : flotteur, HumRatio : flotteur, Pression: flotteur) -> flotteur:
    """
    Renvoyez la température du bulbe sec en fonction du volume spécifique de l'air humide, du taux d'humidité et de la pression.
    Arguments :
        MoistAirVolume : Volume spécifique d'air humide en ft³ lb⁻¹ d'air sec [IP] ou en m³ kg⁻¹ d'air sec [SI]
        HumRatio : Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 26
    Remarques:
        En unités IP, R_DA_IP/144 est égal à 0,370486 qui est le coefficient apparaissant dans l'équation 26
        Le facteur 144 est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².
        Basé sur la fonction « GetMoistAirVolume », réorganisée pour la température sèche.
    """
    si HumRatio < 0:
        augmenter Erreur de valeur("Le taux d'humidité est négatif")
    BoundedHumRatio = maximum(HumRapport, MIN_HUM_RATIO)

    si estIP() :
        TDryBulb = GetTFahrenheitFromTRankine(MoistAirVolume * (144 * Pression)
                        / (R_DA_IP * (1 + 1.607858 * BoundedHumRatio)))
    autre:
        TDryBulb = GetTCelsiusFromTKelvin(MoistAirVolume * Pression
                        / (R_DA_SI * (1 + 1.607858 * BoundedHumRatio)))
    retour TDryBulb

définitivement GetMoistAirDensity(TDDryBulb : flotteur, HumRatio : flotteur, Pression:flotteur) -> flotteur:
    """
    Renvoyez la densité de l’air humide en fonction du taux d’humidité, de la température du bulbe sec et de la pression.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        HumRatio : Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        MoistAirDensity : densité de l'air humide en lb ft⁻³ [IP] ou kg m⁻³ [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 11
    """
    si HumRatio < 0:
        augmenter Erreur de valeur("Le taux d'humidité est négatif")
    BoundedHumRatio = maximum(HumRapport, MIN_HUM_RATIO)

    Volume d'air humide = GetMoistAirVolume(TDDryBulb, Rapport HumBounded, Pression)
    Densité de l'air humide = (1 + BoundedHumRatio) / Volume d'air humide
    retour Densité de l'air humide


################################################# ################################################# ###
# Atmosphère normale
################################################# ################################################# ###

définitivement GetStandardAtmPressure(Altitude: flotteur) -> flotteur:
    """
    Renvoie la pression barométrique de l'atmosphère standard, compte tenu de l'élévation (altitude).
    Arguments :
        Altitude : altitude en pieds [IP] ou en m [SI]
    Retour:
        Pression barométrique de l'atmosphère standard en Psi [IP] ou Pa [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 3
    """

    si estIP() :
        Pression atmosphérique standard = 14.696 * math.pow(1 - 6.8754e-06 * Altitude, 5.2559)
    autre:
        Pression atmosphérique standard = 101325 * math.pow(1 - 2.25577e-05 * Altitude, 5.2559)
    retour Pression atmosphérique standard

définitivement GetStandardAtmTemperature(Altitude: flotteur) -> flotteur:
    """
    Renvoie la température atmosphérique standard, compte tenu de l'élévation (altitude).
    Arguments :
        Altitude : altitude en pieds [IP] ou en m [SI]
    Retour:
        Température du bulbe sec de l'atmosphère standard en °F [IP] ou °C [SI]
    Référence:
        Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 4
    """
    si estIP() :
        Température atmosphérique standard = 59 - 0.00356620 * Altitude
    autre:
        Température atmosphérique standard = 15 - 0.0065 * Altitude
    retour Température atmosphérique standard

définitivement GetSeaLevelPressure(StationPressure : flotteur, Altitude: flotteur, TDryBulb : flotteur) -> flotteur:

    """
    Pression de retour au niveau de la mer en fonction de la température du bulbe sec, de l'altitude au-dessus du niveau de la mer et de la pression.
    Arguments :
        StationPressure : Pression de la station observée en Psi [IP] ou Pa [SI]
        Altitude : altitude en pieds [IP] ou en m [SI]
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
    Retour:
        Pression barométrique au niveau de la mer en Psi [IP] ou Pa [SI]
    Référence:
        Hess SL, Introduction à la météorologie théorique, Holt Rinehart et Winston, NY 1959,
        ch. 6,5 ; Stull RB, Météorologie pour les scientifiques et les ingénieurs, 2e édition,
        Brooks/Cole 2000, chap. 1.
    Remarques:
        La procédure standard aux États-Unis consiste à utiliser pour TDryBulb la moyenne
        de la température actuelle de la station et de la température de la station d'il y a 12 heures.
    """
    si estIP() :
        # Calculer la température moyenne dans la colonne d'air, en supposant un taux de déchéance
        # de 3,6 °F/1000 pi
        TColonne = TDryBulb + 0.0036 * Altitude / 2

        # Déterminer la hauteur de l'échelle
        H = 53.351 * GetTRankineFromTFahrenheit(TColumn)
    autre:
        # Calculer la température moyenne dans la colonne d'air, en supposant un taux de déchéance
        # de 6,5 °C/km
        TColonne = TDryBulb + 0.0065 * Altitude / 2

        # Déterminer la hauteur de l'échelle
        H = 287.055 * GetTKelvinFromTCelsius(TColonne) / 9.807

    # Calculer la pression au niveau de la mer
    PressionNiveau De La Mer = StationPression * math.exp(Altitude / H)
    retour PressionNiveau De La Mer

définitivement GetStationPressure(Pression au niveau de la mer : flotteur, Altitude: flotteur, TDryBulb : flotteur) -> flotteur:
    """
    Pression de la station de retour à partir de la pression au niveau de la mer.
    Arguments :
        SeaLevelPressure : Pression barométrique au niveau de la mer en Psi [IP] ou Pa [SI]
        Altitude : altitude en pieds [IP] ou en m [SI]
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
    Retour:
        Pression de la station en Psi [IP] ou Pa [SI]
    Référence:
        Voir « Obtenir la pression du niveau de la mer »
    Remarques:
        Cette fonction est juste l'inverse de « GetSeaLevelPressure ».
    """
    StationPression = PressionNiveau De La Mer / GetSeaLevelPressure(1, Altitude, TDryBulb)
    retour StationPression


################################################# ################################################# ##
# Fonctions pour définir toutes les valeurs psychrométriques
################################################# ################################################# ###

définitivement CalcPsychrometricsFromTWetBulb(TDDryBulb : flotteur, TWetBulb : flotteur, Pression: flotteur) -> tuple:
    """
    Fonction utilitaire pour calculer le taux d'humidité, la température du point de rosée, l'humidité relative,
    pression de vapeur, enthalpie de l'air humide, volume d'air humide et degré de saturation de l'air donnés
    température du bulbe sec, température du bulbe humide et pression.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        TWetBulb : Température du bulbe humide en °F [IP] ou °C [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
        Température du point de rosée en °F [IP] ou °C [SI]
        Humidité relative dans la plage [0, 1]
        Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
        Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
        Volume spécifique d'air humide en ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
        Degré de saturation [sans unité]
    """
    HumRatio = GetHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pression)
    TDewPoint = GetTDewPointFromHumRatio(TDryBulb, HumRatio, Pression)
    RelHum = GetRelHumFromHumRatio(TDryBulb, HumRatio, Pression)
    VapPres = GetVapPresFromHumRatio(HumRatio, Pression)
    Enthalpie de l'air humide = GetMoistAirEnthalpy(TDDryBulb, HumRatio)
    Volume d'air humide = GetMoistAirVolume(TDDryBulb, HumRatio, Pression)
    DegréDeSaturation = ObtenirDegréDeSaturation(TDryBulb, HumRatio, Pression)
    retour HumRatio, TDewPoint, RelHum, VapPres, Enthalpie de l'air humide, Volume d'air humide, DegréDeSaturation

définitivement CalcPsychrometricsFromTDewPoint(TDDryBulb : flotteur, TDewPoint : flotteur, Pression: flotteur) -> tuple:
    """
    Fonction utilitaire pour calculer le taux d'humidité, la température du bulbe humide, l'humidité relative,
    pression de vapeur, enthalpie de l'air humide, volume d'air humide et degré de saturation de l'air donnés
    température du bulbe sec, température du point de rosée et pression.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        TDewPoint : Température du point de rosée en °F [IP] ou °C [SI]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
        Température du bulbe humide en °F [IP] ou °C [SI]
        Humidité relative dans la plage [0, 1]
        Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
        Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
        Volume spécifique d'air humide en ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
        Degré de saturation [sans unité]
    """
    HumRatio = GetHumRatioFromTDewPoint(TDewPoint, Pression)
    TWetBulbComment = GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pression)
    RelHum = GetRelHumFromHumRatio(TDryBulb, HumRatio, Pression)
    VapPres = GetVapPresFromHumRatio(HumRatio, Pression)
    Enthalpie de l'air humide = GetMoistAirEnthalpy(TDDryBulb, HumRatio)
    Volume d'air humide = GetMoistAirVolume(TDDryBulb, HumRatio, Pression)
    DegréDeSaturation = ObtenirDegréDeSaturation(TDryBulb, HumRatio, Pression)
    retour HumRatio, TWetBulb, RelHum, VapPres, Enthalpie de l'air humide, Volume d'air humide, DegréDeSaturation

définitivement CalcPsychrometricsFromRelHum(TDDryBulb : flotteur, RelHum : flotteur, Pression: flotteur) -> tuple:
    """
    Fonction utilitaire pour calculer le taux d'humidité, la température du bulbe humide, la température du point de rosée,
    pression de vapeur, enthalpie de l'air humide, volume d'air humide et degré de saturation de l'air donnés
    température du bulbe sec, humidité relative et pression.
    Arguments :
        TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
        RelHum : Humidité relative dans la plage [0, 1]
        Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
    Retour:
        Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
        Température du bulbe humide en °F [IP] ou °C [SI]
        Température du point de rosée en °F [IP] ou °C [SI].
        Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
        Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
        Volume spécifique d'air humide en ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
        Degré de saturation [sans unité]
    """
    HumRatio = GetHumRatioFromRelHum(TDryBulb, RelHum, Pression)
    TWetBulbComment = GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pression)
    TDewPoint = GetTDewPointFromHumRatio(TDryBulb, HumRatio, Pression)
    VapPres = GetVapPresFromHumRatio(HumRatio, Pression)
    Enthalpie de l'air humide = GetMoistAirEnthalpy(TDDryBulb, HumRatio)
    Volume d'air humide = GetMoistAirVolume(TDDryBulb, HumRatio, Pression)
    DegréDeSaturation = ObtenirDegréDeSaturation(TDryBulb, HumRatio, Pression)
    retour HumRatio, TWetBulb, TDewPoint, VapPres, Enthalpie de l'air humide, Volume d'air humide, DegréDeSaturation

Do dièse

   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 (version 2.3.0) (https://github.com/psychrometrics/psychrolib)
 * Copyright (c) 2018 D. Thevenard et D. Meyer, D. Gosnell pour l'implémentation actuelle de la bibliothèque
 * Copyright (c) Manuel ASHRAE 2017 — Principes fondamentaux des équations et coefficients ASHRAE
 * Porté en C# par https://github.com/DJGosnell
 * Sous licence MIT.
 */

en utilisant Système;

espace de noms PsychoLib
{
    /// <résumé>
    /// Classe de fonctions permettant le calcul des propriétés psychrométriques de l'air humide et sec.
    /// </résumé>
    Publique classe Psychrométrie
    {
        /*************************************************** ************************************************** ***
         * Constantes globales
         ************************************************** ************************************************** */

        /// <résumé>
        /// Zéro degré Fahrenheit (°F) exprimé en degré Rankine (°R).
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 39.
        /// </résumé>
        privé constante double ZERO_FAHRENHEIT_AS_RANKINE = 459.67;

        /// <résumé>
        /// Zéro degré Celsius (°C) exprimé en Kelvin (K).
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 39.
        /// </résumé>
        privé constante double ZERO_CELSIUS_AS_KELVIN = 273.15;

        /// <résumé>
        /// Constante de gaz universelle pour air sec (version IP) en ft lb_Force lb_DryAir⁻¹ R⁻¹.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1.
        /// </résumé>
        privé constante double R_DA_IP = 53.350;

        /// <résumé>
        /// Constante de gaz universelle pour air sec (version SI) en J kg_DryAir⁻¹ K⁻¹.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1.
        /// </résumé>
        privé constante double R_DA_SI = 287.042;

        /// <résumé>
        /// Valeur invalide (sans dimension).
        /// </résumé>
        privé constante double INVALIDE = -99999;

        /// <résumé>
        /// Nombre maximum d'itérations avant de quitter les boucles while.
        /// </résumé>
        privé constante double MAX_ITER_COUNT = 100;

        /// <résumé>
        /// Rapport d'humidité minimum acceptable utilisé/renvoyé par toutes les fonctions.
        /// Toute valeur supérieure à 0 ou inférieure au MIN_HUM_RATIO sera réinitialisée à cette valeur.
        /// </résumé>
        privé constante double MIN_HUM_RATIO = 1e-7;

        /// <résumé>
        /// Point de congélation de l'eau en Fahrenheit.
        /// </résumé>
        privé constante double FREEZING_POINT_WATER_IP = 32.0;

        /// <résumé>
        /// Point de congélation de l'eau en Celsius.
        /// </résumé>
        privé constante double FREEZING_POINT_WATER_SI = 0.0;

        /// <résumé>
        /// Triple point d'eau en Fahrenheit.
        /// </résumé>
        privé constante double TRIPLE_POINT_WATER_IP = 32.018;

        /// <résumé>
        /// Triple point d'eau en Celsius.
        /// </résumé>
        privé constante double TRIPLE_POINT_WATER_SI = 0.01;

        /// <résumé>
        /// Obtient ou définit le système d'unités actuel pour les calculs.
        /// </résumé>
        Publique Système d'unité Système d'unité
        {
            obtenir => _Système d'unité;
            Positionner
            {
                _Système d'unité = évaluer;
                si (évaluer == UnitSystem.IP)
                    PSYCHROLIB_TOLERANCE = 0.001 * 9.0 / 5.0;
                autre
                    PSYCHROLIB_TOLERANCE = 0.001;
            }
        }

        privé double PSYCHROLIB_TOLERANCE ;
        privé Système d'unité _Système d'unité;

        /// <résumé>
        /// Constructeur pour créer une instance avec le système d'unités spécifié.
        /// </résumé>
        /// <param name="unitSystem">Système d'unités à utiliser pour les calculs.</param>
        Publique Psychrométrie(Système d'unité Système d'unité)
        {
            Système d'unité = Système d'unité;
        }


        /*************************************************** ************************************************** ***
         * Conversion entre unités de température
         ************************************************** ************************************************** */

        /// <résumé>
        /// Fonction utilitaire pour convertir la température en degré Rankine (°R)
        /// température donnée en degrés Fahrenheit (°F).
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 chapitre 3
        /// </résumé>
        /// <param name="tF">Température en Fahrenheit (°F)</param>
        /// <retour>Rankine (°R)</retour>
        Publique double ObtenirTRankineFromTFahrenheit(double tF)
        {
            retour tF + ZERO_FAHRENHEIT_AS_RANKINE ; /* exact */
        }

        /// <résumé>
        /// Fonction utilitaire pour convertir la température en degrés Fahrenheit (°F)
        /// température donnée en degré Rankine (°R).
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 chapitre 3
        /// </résumé>
        /// <param name="tR">Température en Rankine (°R)</param>
        /// <retourne>Fahrenheit (°F)</retourne>
        Publique double ObtenirTFahrenheitDeTRankine(double tR)
        {
            retour tR - ZERO_FAHRENHEIT_AS_RANKINE ; /* exact */
        }

        /// <résumé>
        /// Fonction utilitaire pour convertir la température en Kelvin (K)
        /// température donnée en degrés Celsius (°C).
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 chapitre 3
        /// </résumé>
        /// <param name="tC">Température en Celsius (°C)</param>
        /// <retour>Rankine (°R)</retour>
        Publique double ObtenirTKelvinFromTCelsius(double tC)
        {
            retour tC + ZERO_CELSIUS_AS_KELVIN ; /* exact */
        }

        /// <résumé>
        /// Fonction utilitaire pour convertir la température en degrés Celsius (°C)
        /// température donnée en Kelvin (K).
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 chapitre 3
        /// </résumé>
        /// <param name="tK">Température en Rankine (°R)</param>
        /// <retourne>Celsius (°C)</retourne>
        Publique double ObtenirTCelsiusFromTKelvin(double tK)
        {
            retour tK - ZERO_CELSIUS_AS_KELVIN ; /* exact */
        }


        /*************************************************** ************************************************** ***
         * Conversions entre point de rosée, bulbe humide et humidité relative
         ************************************************** ************************************************** */

        /// <résumé>
        /// Renvoie la température du bulbe humide en fonction de la température du bulbe sec, de la température du point de rosée et de la pression.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="tDewPoint">Température du point de rosée en °F [IP] ou °C [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Température du bulbe humide en °F [IP] ou °C [SI]</returns>
        Publique double GetTWetBulbFromTDewPoint(double tDryBulb, double tPoint de rosée, double pression)
        {
            si (!(tPoint de rosée <= tDryBulb))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("La température du point de rosée est supérieure à la température du bulbe sec");

            var humRatio = GetHumRatioFromTDewPoint(tDewPoint, pression);
            retour GetTWetBulbFromHumRatio(tDryBulb, humRatio, pression);
        }


        /// <résumé>
        /// Renvoie la température du bulbe humide en fonction de la température du bulbe sec, de l'humidité relative et de la pression.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="relHum">Humidité relative [0-1]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Température du bulbe humide en °F [IP] ou °C [SI]</returns>
        Publique double GetTWetBulbFromRelHum(double tDryBulb, double relHum, double pression)
        {
            si (!(relHum >= 0.0 && relHum <= 1.0))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("L'humidité relative est en dehors de la plage [0,1]");

            var humRatio = GetHumRatioFromRelHum(tDryBulb, relHum, pression);
            retour GetTWetBulbFromHumRatio(tDryBulb, humRatio, pression);
        }


        /// <résumé>
        /// Renvoie l'humidité relative en fonction de la température du bulbe sec et de la température du point de rosée.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 22
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="tDewPoint">Température du point de rosée en °F [IP] ou °C [SI]</param>
        /// <returns>Humidité relative [0-1]</returns>
        Publique double GetRelHumFromTDewPoint(double tDryBulb, double tPoint de rosée)
        {
            si (!(tPoint de rosée <= tDryBulb))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("La température du point de rosée est supérieure à la température du bulbe sec");

            var vapPres = GetSatVapPres(tDewPoint);
            var SatVapPres = GetSatVapPres(tDryBulb);
            retour vapPres / SatVapPres ;
        }

        /// <résumé>
        /// Renvoie l'humidité relative en fonction de la température du bulbe sec, de la température du bulbe humide et de la pression.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="tWetBulb">Température du bulbe humide en °F [IP] ou °C [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Humidité relative [0-1]</returns>
        Publique double GetRelHumFromTWetBulb(double tDryBulb, double tWetBulb, double pression)
        {
            si (!(tWetBulb <= tDryBulb))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("La température du bulbe humide est supérieure à la température du bulbe sec");

            var humRatio = GetHumRatioFromTWetBulb(tDryBulb, tWetBulb, pression);
            retour GetRelHumFromHumRatio(tDryBulb, humRatio, pression);
        }

        /// <résumé>
        /// Renvoie la température du point de rosée en fonction de la température du bulbe sec et de l'humidité relative.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="relHum">Humidité relative [0-1]</param>
        /// <returns>Température du point de rosée en °F [IP] ou °C [SI]</returns>
        Publique double ObtenirTDewPointFromRelHum(double tDryBulb, double relHum)
        {
            si (!(relHum >= 0.0 && relHum <= 1.0))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("L'humidité relative est en dehors de la plage [0,1]");

            var vapPres = GetVapPresFromRelHum(tDryBulb, relHum);
            retour GetTDewPointFromVapPres(tDryBulb, vapPres);
        }

        /// <résumé>
        /// Renvoie la température du point de rosée en fonction de la température du bulbe sec, de la température du bulbe humide et de la pression.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="tWetBulb">Température du bulbe humide en °F [IP] ou °C [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Température du point de rosée en °F [IP] ou °C [SI]</returns>
        Publique double GetTDewPointFromTWetBulb(double tDryBulb, double tWetBulb, double pression)
        {
            si (!(tWetBulb <= tDryBulb))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("La température du bulbe humide est supérieure à la température du bulbe sec");

            var humRatio = GetHumRatioFromTWetBulb(tDryBulb, tWetBulb, pression);
            retour GetTDewPointFromHumRatio(tDryBulb, humRatio, pression);
        }


        /*************************************************** ************************************************** ***
         * Conversions entre point de rosée ou humidité relative et pression de vapeur
         ************************************************** ************************************************** */

        /// <résumé>
        /// Renvoie la pression partielle de vapeur d'eau en fonction de l'humidité relative et de la température.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 12, 22
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="relHum">Humidité relative [0-1]</param>
        /// <returns>Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]</returns>
        Publique double GetVapPresFromRelHum(double tDryBulb, double relHum)
        {
            si (!(relHum >= 0.0 && relHum <= 1.0))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("L'humidité relative est en dehors de la plage [0,1]");

            retour relHum * GetSatVapPres(tDryBulb);
        }

        /// <résumé>
        /// Renvoie l'humidité relative en fonction de la température du bulbe sec et de la pression de vapeur.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 12, 22
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="vapPres">Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]</param>
        /// <returns>Humidité relative [0-1]</returns>
        Publique double GetRelHumFromVapPres(double tDryBulb, double vapPres)
        {
            si (!(vapPres >= 0.0))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("La pression partielle de la vapeur d'eau dans l'air humide est négative");

            retour vapPres / GetSatVapPres(tDryBulb);
        }

        /// <résumé>
        /// Fonction d'assistance renvoyant la dérivée du logarithme népérien de la pression de vapeur saturante
        /// en fonction de la température du bulbe sec.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 5 &amp; 6
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <returns>Dérivée du log naturel de la pression de vapeur de l'air saturé en Psi [IP] ou Pa [SI]</returns>
        privé double dLnPws_(double tDryBulb)
        {
            double dLnPws, T;

            si (Système d'unité == UnitSystem.IP)
            {
                J = GetTRankineFromTFahrenheit(tDryBulb);

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

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

            retour dLnPws ;
        }

        /// <résumé>
        /// Température de retour du point de rosée en fonction de la température du bulbe sec et de la pression de vapeur.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 5 et 6
        /// Notes : la température du point de rosée est résolue en inversant l'équation donnant la pression de vapeur d'eau
        /// à saturation à partir de la température plutôt que d'utiliser les régressions fournies
        /// par ASHRAE (équations 37 et 38) qui sont beaucoup moins précises et ont un
        /// plage de validité plus étroite.
        /// La méthode Newton-Raphson (NR) est utilisée sur le logarithme de la vapeur d'eau
        /// pression en fonction de la température, qui est une fonction très fluide
        /// La convergence est généralement obtenue en 3 à 5 itérations.
        /// tDryBulb n'est pas vraiment nécessaire ici, juste utilisé pour plus de commodité.
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="vapPres">Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]</param>
        /// <returns>(o) Température du point de rosée en °F [IP] ou °C [SI]</returns>
        Publique double GetTDewPointFromVapPres(double tDryBulb, double vapPres)
        {
            // Fonction limites du système d'unités

            var bornes = Système d'unité == UnitSystem.IP
                ? Nouveau[] {-148.0, 392.0}
                : Nouveau[] {-100.0, 200.0} ;

            // Limites en dehors desquelles aucune solution ne peut être trouvée
            si (vapPres < GetSatVapPres(bornes[0]) || vapPres > GetSatVapPres(bornes[1]))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException(
                    "La pression partielle de la vapeur d'eau se situe en dehors du domaine de validité des équations");

            // Nous utilisons NR pour approximer la solution.
            // Première estimation
            var tPoint de rosée =
                tDryBulb ; // Valeur calculée des températures du point de rosée, résolue de manière itérative en °F [IP] ou °C [SI]
            var lnVP = Math.Log(vapPres); // Logarithme naturel de la pression partielle de la vapeur d'eau dans l'air humide

            double tDewPoint_iter ; // Valeur du tDewPoint utilisée dans le calcul NR
            double lnVP_iter ; // Valeur du log de pression de vapeur d'eau utilisée dans le calcul du NR
            var indice = 1;
            faire
            {
                // Point courant
                tDewPoint_iter = tPoint de rosée ;
                lnVP_iter = Math.Log(GetSatVapPres(tDewPoint_iter));

                // Dérivée de fonction, calculée analytiquement
                var d_lnVP = dLnPws_(tDewPoint_iter);

                // Nouvelle estimation, délimitée par le domaine de validité de l'équation. 5 et 6
                tPoint de rosée = tDewPoint_iter - (lnVP_iter - lnVP) / d_lnVP ;
                tPoint de rosée = Math.Max(tDewPoint, bornes[0]);
                tPoint de rosée = Math.Min(tDewPoint, bornes[1]);

                si (indice > MAX_ITER_COUNT)
                    jeter Nouveau InvalidOperationExceptionInvalidOperationException(
                        "Convergence non atteinte dans GetTDewPointFromVapPres. Arrêt.");

                indice++ ;
            } tandis que (Math.Abs(tPointDew - tDewPoint_iter) > PSYCHROLIB_TOLERANCE );

            retour Math.Min(tDewPoint, tDryBulb);
        }

        /// <résumé>
        /// Pression de vapeur de retour en fonction de la température du point de rosée.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 36
        /// </résumé>
        /// <param name="tDewPoint">Température du point de rosée en °F [IP] ou °C [SI]</param>
        /// <returns>Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]</returns>
        Publique double GetVapPresFromTDewPoint(double tPoint de rosée)
        {
            retour GetSatVapPres(tPointDew);
        }


        /*************************************************** ************************************************** ***
         * Conversions de la température du bulbe humide, de la température du point de rosée ou du rapport humidité relative/humidité
         ************************************************** ************************************************** */

        /// <résumé>
        /// Renvoie la température du bulbe humide en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équations 33 et 35 résolues pour Tstar
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="humRatio">Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Température du bulbe humide en °F [IP] ou °C [SI]</returns>
        Publique double GetTWetBulbFromHumRatio(double tDryBulb, double humRatio, double pression)
        {
            // Déclarations
            double Wstar ;
            double tPoint de rosée, tWetBulb, tWetBulbSup, tWetBulbInf, bornedHumRatio ;
            var indice = 1;

            si (!(humRapport >= 0.0))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("Le taux d'humidité est négatif");
            boundedHumRatio = Math.Max(humRatio, MIN_HUM_RATIO);

            tPoint de rosée = GetTDewPointFromHumRatio(tDryBulb, rapport de hum délimité, pression);

            // Premières suppositions
            tWetBulbSup = tDryBulb ;
            tWetBulbInf = tPoint de rosée ;
            tWetBulb = (tWetBulbInf + tWetBulbSup) / 2.0;

            // Boucle de bissection
            tandis que ((tWetBulbSup - tWetBulbInf) > PSYCHROLIB_TOLERANCE)
            {
                // Calculer le taux d'humidité à la température Tstar
                Wstar = GetHumRatioFromTWetBulb(tDryBulb, tWetBulb, pression);

                // Obtenir de nouvelles limites
                si (Wstar > rapport hum délimité)
                    tWetBulbSup = tWetBulb ;
                autre
                    tWetBulbInf = tWetBulb ;

                // Nouvelle estimation de la température du bulbe humide
                tWetBulb = (tWetBulbSup + tWetBulbInf) / 2.0;

                si (indice > MAX_ITER_COUNT)
                    jeter Nouveau InvalidOperationExceptionInvalidOperationException(
                        "Convergence non atteinte dans GetTWetBulbFromHumRatio. Arrêt.");

                indice++ ;
            }

            retour tWetBulb ;
        }

        /// <résumé>
        /// Rapport d'humidité de retour en fonction de la température du bulbe sec, de la température du bulbe humide et de la pression.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équations 33 et 35
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="tWetBulb">Température du bulbe humide en °F [IP] ou °C [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]</returns>
        Publique double GetHumRatioFromTWetBulb(double tDryBulb, double tWetBulb, double pression)
        {
            double wsstar ;
            double humRatio = INVALIDE;

            si (!(tWetBulb <= tDryBulb))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("La température du bulbe humide est supérieure à la température du bulbe sec");

            wsstar = GetSatHumRatio(tWetBulb, pression);

            si (Système d'unité == UnitSystem.IP)
            {
                si (tWetBulb >= FREEZING_POINT_WATER_IP)
                    humRatio = ((1093.0 - 0.556 * tWetBulb) * wsstar - 0.240 * (tDryBulb - tWetBulb))
                               / (1093.0 + 0.444 * tDryBulb - tWetBulb);
                autre
                    humRatio = ((1220.0 - 0.04 * tWetBulb) * wsstar - 0.240 * (tDryBulb - tWetBulb))
                               / (1220.0 + 0.444 * tDryBulb - 0.48 * tWetBulb);
            }
            autre
            {
                si (tWetBulb >= FREEZING_POINT_WATER_SI)
                    humRatio = ((2501.0 - 2.326 * tWetBulb) * wsstar - 1.006 * (tDryBulb - tWetBulb))
                               / (2501.0 + 1.86 * tDryBulb - 4.186 * tWetBulb);
                autre
                    humRatio = ((2830.0 - 0.24 * tWetBulb) * wsstar - 1.006 * (tDryBulb - tWetBulb))
                               / (2830.0 + 1.86 * tDryBulb - 2.1 * tWetBulb);
            }

            // Contrôle de validité.
            retour Math.Max(humRatio, MIN_HUM_RATIO);
        }


        /// <résumé>
        /// Renvoie le taux d'humidité en fonction de la température du bulbe sec, de l'humidité relative et de la pression.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="relHum">Humidité relative [0-1]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]</returns>
        Publique double GetHumRatioFromRelHum(double tDryBulb, double relHum, double pression)
        {
            si (!(relHum >= 0.0 && relHum <= 1.0))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("L'humidité relative est en dehors de la plage [0,1]");

            var vapPres = GetVapPresFromRelHum(tDryBulb, relHum);
            retour GetHumRatioFromVapPres(vapPres, pression);
        }


        /// <résumé>
        /// Renvoie l'humidité relative en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="humRatio">Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Humidité relative [0-1]</returns>
        Publique double GetRelHumFromHumRatio(double tDryBulb, double humRatio, double pression)
        {
            si (!(humRapport >= 0.0))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("Le taux d'humidité est négatif");

            var vapPres = GetVapPresFromHumRatio(humRatio, pression);
            retour GetRelHumFromVapPres(tDryBulb, vapPres);
        }

        /// <résumé>
        /// Taux d'humidité de retour en fonction de la température et de la pression du point de rosée.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
        /// </résumé>
        /// <param name="tDewPoint">Température du point de rosée en °F [IP] ou °C [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]</returns>
        Publique double GetHumRatioFromTDewPoint(double tPoint de rosée, double pression)
        {
            var vapPres = GetSatVapPres(tDewPoint);
            retour GetHumRatioFromVapPres(vapPres, pression);
        }

        /// <résumé>
        /// Retourne la température du point de rosée en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="humRatio">Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Température du point de rosée en °F [IP] ou °C [SI]</returns>
        Publique double GetTDewPointFromHumRatio(double tDryBulb, double humRatio, double pression)
        {
            si (!(humRapport >= 0.0))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("Le taux d'humidité est négatif");

            var vapPres = GetVapPresFromHumRatio(humRatio, pression);
            retour GetTDewPointFromVapPres(tDryBulb, vapPres);
        }


        /*************************************************** ************************************************** ***
         * Conversions entre taux d'humidité et pression de vapeur
         ************************************************** ************************************************** */

        /// <résumé>
        /// Taux d'humidité de retour étant donné la pression de vapeur d'eau et la pression atmosphérique.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 20
        /// </résumé>
        /// <param name="vapPres">Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]</returns>
        Publique double GetHumRatioFromVapPres(double vapPres, double pression)
        {
            si (!(vapPres >= 0.0))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("La pression partielle de la vapeur d'eau dans l'air humide est négative");

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

            // Contrôle de validité.
            retour Math.Max(humRatio, MIN_HUM_RATIO);
        }


        /// <résumé>
        /// Pression de vapeur de retour en fonction du taux d'humidité et de la pression.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 20 résolue pour pw
        /// </résumé>
        /// <param name="humRatio">Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]</returns>
        Publique double GetVapPresFromHumRatio(double humRatio, double pression)
        {
            si (!(humRapport >= 0.0))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("Le taux d'humidité est négatif");
            var boundedHumRatio = Math.Max(humRatio, MIN_HUM_RATIO);

            var vapPres = pression * boundedHumRatio / (0.621945 + boundedHumRatio);
            retour vapPres;
        }


        /*************************************************** ************************************************** ***
         * Conversions entre taux d'humidité et humidité spécifique
         ************************************************** ************************************************** */

        /// <résumé>
        /// Renvoie l'humidité spécifique à partir du rapport d'humidité (alias rapport de mélange)
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 9b
        /// </résumé>
        /// <param name="humRatio">Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <returns>Taux d'humidité spécifique en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]</returns>
        Publique double GetSpecificHumFromHumRatio(double humRatio)
        {
            si (!(humRapport >= 0.0))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("Le taux d'humidité est négatif");
            var boundedHumRatio = Math.Max(humRatio, MIN_HUM_RATIO);

            retour boundedHumRatio / (1.0 + boundedHumRatio);
        }


        /// <résumé>
        /// Renvoie le taux d'humidité (c'est-à-dire le taux de mélange) à partir d'une humidité spécifique
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 9b (résolu pour le taux d'humidité)
        /// </résumé>
        /// <param name="specificHum"></param>
        /// <returns>Taux d'humidité en lb_H₂O lb_Dry_Air⁻¹ [IP] ou kg_H₂O kg_Dry_Air⁻¹ [SI]</returns>
        Publique double GetHumRatioFromSpecificHum(double hum spécifique)
        {
            si (!(specificHum >= 0.0 && spécifiqueHum < 1.0))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("L'humidité spécifique est en dehors de la plage [0, 1]");

            var humRatio = spécifiqueHum / (1.0 - hum spécifique);

            // Contrôle de validité
            retour Math.Max(humRatio, MIN_HUM_RATIO);
        }


        /*************************************************** ************************************************** ***
         * Calculs d'air sec
         ************************************************** ************************************************** */

        /// <résumé>
        /// Renvoie l'enthalpie de l'air sec en fonction de la température du bulbe sec.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 28
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <returns>Enthalpie de l'air sec en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]</returns>
        Publique double GetDryAirEnthalpy(double tDryBulb)
        {
            si (Système d'unité == UnitSystem.IP)
                retour 0.240 * tDryBulb ;

            retour 1006.0 * tDryBulb ;
        }


        /// <résumé>
        /// Renvoie la densité de l'air sec en fonction de la température et de la pression du bulbe sec.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
        /// Notes : équation 14 pour la relation gazeuse parfaite pour l'air sec.
        /// Eqn 1 pour la constante universelle des gaz.
        /// Le facteur 144 en IP est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Densité de l'air sec en lb ft⁻³ [IP] ou kg m⁻³ [SI]</returns>
        Publique double GetDryAirDensity(double tDryBulb, double pression)
        {
            si (Système d'unité == UnitSystem.IP)
                retour (144.0 * pression) / R_DA_IP / GetTRankineFromTFahrenheit(tDryBulb);

            retour pression / R_DA_SI / GetTKelvinFromTCelsius(tDryBulb);
        }


        /// <résumé>
        /// Retourner le volume d'air sec en fonction de la température et de la pression du bulbe sec.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1.
        /// Notes : équation 14 pour la relation gazeuse parfaite pour l'air sec.
        /// Eqn 1 pour la constante universelle des gaz.
        /// Le facteur 144 en IP est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Volume d'air sec ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]</returns>
        Publique double GetDryAirVolume(double tDryBulb, double pression)
        {
            si (Système d'unité == UnitSystem.IP)
                retour R_DA_IP * GetTRankineFromTFahrenheit(tDryBulb) / (144.0 * pression);

            retour R_DA_SI * GetTKelvinFromTCelsius(tDryBulb) / pression;
        }


        /// <résumé>
        /// Renvoie la température du bulbe sec à partir du rapport d'enthalpie et d'humidité.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 30.
        /// Notes : basé sur la fonction `GetMoistAirEnthalpy`, réorganisé pour la température.
        /// </résumé>
        /// <param name="moistAirEnthalpy">Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹</param>
        /// <param name="humRatio">Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <returns>Température du bulbe sec en °F [IP] ou °C [SI]</returns>
        Publique double GetTDryBulbFromEnthalpyAndHumRatio(double Enthalpie de l'air humide, double humRatio)
        {
            si (!(humRapport >= 0.0))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("Le taux d'humidité est négatif");
            var boundedHumRatio = Math.Max(humRatio, MIN_HUM_RATIO);

            si (Système d'unité == UnitSystem.IP)
                retour (humideAirEnthalpie - 1061.0 * rapport hum délimité) / (0.240 + 0.444 * boundedHumRatio);

            retour (humideAirEnthalpie / 1000.0 - 2501.0 * rapport hum délimité) / (1.006 + 1.86 * boundedHumRatio);
        }


        /// <résumé>
        /// Renvoie le rapport d'humidité à partir de l'enthalpie et de la température du bulbe sec.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 30.
        /// Notes : basé sur la fonction `GetMoistAirEnthalpy`, réorganisé pour le taux d'humidité.
        /// </résumé>
        /// <param name="moistAirEnthalpy">Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹</param>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <returns>Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻</returns>
        Publique double GetHumRatioFromEnthalpyAndTDryBulb(double Enthalpie de l'air humide, double tDryBulb)
        {
            {
                double humRatio ;
                si (Système d'unité == UnitSystem.IP)
                    humRatio = (humideAirEnthalpie - 0.240 * tDryBulb) / (1061.0 + 0.444 * tDryBulb);
                autre
                    humRatio = (humideAirEnthalpie / 1000.0 - 1.006 * tDryBulb) / (2501.0 + 1.86 * tDryBulb);

                // Contrôle de validité.
                retour Math.Max(humRatio, MIN_HUM_RATIO);
            }
        }


        /*************************************************** ************************************************** ***
         * Calculs d'air saturé
         ************************************************** ************************************************** */

        /// <résumé>
        /// Renvoie la pression de vapeur saturante en fonction de la température du bulbe sec.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 5 &amp; 6
        /// Remarque importante : les formules ASHRAE sont définies au dessus et en dessous du point de congélation mais ont
        /// une discontinuité au point de congélation. Il s'agit d'une petite inexactitude de la part d'ASHRAE : les formules
        /// doit être défini au-dessus et en dessous du point triple de l'eau (et non du point de congélation), auquel cas
        /// la discontinuité disparaît. Il est indispensable d'utiliser le point triple d'eau sinon fonctionne
        /// GetTDewPointFromVapPres, qui inverse la fonction actuelle, ne converge pas correctement autour
        /// le point de congélation.
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <returns>Pression de vapeur de l'air saturé en Psi [IP] ou Pa [SI]</returns>
        Publique double GetSatVapPres(double tDryBulb)
        {
            double lnPws ;

            si (Système d'unité == UnitSystem.IP)
            {
                si (!(tDryBulb >= -148.0 && tDryBulb <= 392.0))
                    jeter Nouveau InvalidOperationExceptionInvalidOperationException("La température du bulbe sec est en dehors de la plage [-148, 392]");

                var J = GetTRankineFromTFahrenheit(tDryBulb);
                si (tDryBulb <= TRIPLE_POINT_WATER_IP)
                    lnPws = (-1.0214165E+04 / J - 4.8932428 - 5.3765794E-03 * J + 1.9202377E-07 * J * J
                                                                                + 3.5575832E-10 * Math.Pow(T, 3) -
                             9.0344688E-14 * Math.Pow(T, 4) + 4.1635019 * Math.Log(T));
                autre
                    lnPws = -1.0440397E+04 / J - 1.1294650E+01 - 2.7022355E-02 * J + 1.2890360E-05 * J * J
                            - 2.4780681E-09 * Math.Pow(T, 3) + 6.5459673 * Math.Log(T);
            }
            autre
            {
                si (!(tDryBulb >= -100.0 && tDryBulb <= 200.0))
                    jeter Nouveau InvalidOperationExceptionInvalidOperationException("La température du bulbe sec est en dehors de la plage [-100, 200]");

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

            retour Math.Exp(lnPws);
        }


        /// <résumé>
        /// Taux d'humidité de retour de l'air saturé en fonction de la température et de la pression du bulbe sec.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 36, résolue pour W
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Taux d'humidité de l'air saturé en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]</returns>
        Publique double GetSatHumRatio(double tDryBulb, double pression)
        {
            var satVaporPres = GetSatVapPres(tDryBulb);
            var SatHumRatio = 0.621945 * satVaporPres / (pression - satVaporPres);

            // Contrôle de validité.
            retour Math.Max(satHumRatio, MIN_HUM_RATIO);
        }

        /// <résumé>
        /// Renvoie l'enthalpie de l'air saturé en fonction de la température et de la pression du bulbe sec.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Enthalpie de l'air saturé en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]</returns>
        Publique double GetSatAirEnthalpy(double tDryBulb, double pression)
        {
            retour GetMoistAirEnthalpy(tDryBulb, GetSatHumRatio(tDryBulb, pression));
        }


        /*************************************************** ************************************************** ***
         * Calculs d'air humide
         ************************************************** ************************************************** */

        /// <résumé>
        /// Retour Déficit de pression de vapeur en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
        /// Référence : voir Oke (1987), équation. 2.13a
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="humRatio">Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Déficit de pression de vapeur en Psi [IP] ou Pa [SI]</returns>
        Publique double GetVaporPressureDeficit(double tDryBulb, double humRatio, double pression)
        {
            si (!(humRapport >= 0.0))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("Le taux d'humidité est négatif");

            var relHum = GetRelHumFromHumRatio(tDryBulb, humRatio, pression);
            retour GetSatVapPres(tDryBulb) * (1.0 - relHum);
        }


        /// <résumé>
        /// Renvoie le degré de saturation (c'est à dire le rapport humidité de l'air / rapport humidité de l'air à saturation
        /// à la même température et pression) étant donné la température du bulbe sec, le taux d'humidité et la pression atmosphérique.
        /// Référence : ASHRAE Handbook - Fundamentals (2009) ch. 1 éq. 12
        /// Notes : la définition est absente du Manuel 2017
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="humRatio">Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Degré de saturation (sans unité)</returns>
        Publique double GetDegreeOfSaturation(double tDryBulb, double humRatio, double pression)
        {
            si (!(humRapport >= 0.0))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("Le taux d'humidité est négatif");
            var boundedHumRatio = Math.Max(humRatio, MIN_HUM_RATIO);

            retour boundedHumRatio / GetSatHumRatio(tDryBulb, pression);
        }

        /// <résumé>
        /// Renvoie l'enthalpie de l'air humide en fonction de la température du bulbe sec et du rapport d'humidité.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 30
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="humRatio">Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <returns>Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]</returns>
        Publique double GetMoistAirEnthalpy(double tDryBulb, double humRatio)
        {
            si (!(humRapport >= 0.0))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("Le taux d'humidité est négatif");

            var boundedHumRatio = Math.Max(humRatio, MIN_HUM_RATIO);

            si (Système d'unité == UnitSystem.IP)
                retour 0.240 * tDryBulb + boundedHumRatio * (1061.0 + 0.444 * tDryBulb);

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


        /// <résumé>
        /// Restitue le volume spécifique d'air humide en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 26
        /// Notes : en unités IP, R_DA_IP / 144 est égal à 0,370486 qui est le coefficient apparaissant dans l'équation 26.
        /// Le facteur 144 est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="humRatio">Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Volume spécifique ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]</returns>
        Publique double GetMoistAirVolume(double tDryBulb, double humRatio, double pression)
        {
            si (!(humRapport >= 0.0))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("Le taux d'humidité est négatif");
            var boundedHumRatio = Math.Max(humRatio, MIN_HUM_RATIO);

            si (Système d'unité == UnitSystem.IP)
                retour R_DA_IP * GetTRankineFromTFahrenheit(tDryBulb) * (1.0 + 1.607858 * rapport hum délimité) /
                       (144.0 * pression);

            retour R_DA_SI * GetTKelvinFromTCelsius(tDryBulb) * (1.0 + 1.607858 * rapport hum délimité) / pression;
        }


        /// <résumé>
        /// Renvoie la température du bulbe sec en fonction du volume spécifique de l'air humide, du taux d'humidité et de la pression.
        /// Référence:
        /// Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 26
        /// Remarques:
        /// En unités IP, R_DA_IP / 144 est égal à 0,370486 qui est le coefficient apparaissant dans l'équation 26
        /// Le facteur 144 est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².
        /// Basé sur la fonction `GetMoistAirVolume`, réorganisée pour la température sèche.
        /// </résumé>
        /// <param name="MoistAirVolume">Volume spécifique d'air humide en pi³ lb⁻¹ d'air sec [IP] ou en m³ kg⁻¹ d'air sec [SI]</param>
        /// <param name="humRatio">Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Température du bulbe sec en °F [IP] ou °C [SI]</returns>
        Publique double GetTDryBulbFromMoistAirVolumeAndHumRatio(double Volume d'air humide, double humRatio, double pression)
        {
            si (!(humRapport >= 0.0))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("Le taux d'humidité est négatif");
            var boundedHumRatio = Math.Max(humRatio, MIN_HUM_RATIO);

            si (Système d'unité == UnitSystem.IP)
                retour  ObtenirTFahrenheitDeTRankine(Volume d'air humide * (144 * pression) / (R_DA_IP * (1 + 1.607858 * boundedHumRatio)));

            retour ObtenirTCelsiusFromTKelvin(Volume d'air humide * pression / (R_DA_SI * (1 + 1.607858 * boundedHumRatio)));
        }


        /// <résumé>
        /// Renvoie la densité de l'air humide en fonction du taux d'humidité, de la température du bulbe sec et de la pression.
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 11
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="humRatio">Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Densité de l'air humide en lb ft⁻³ [IP] ou kg m⁻³ [SI]</returns>
        Publique double GetMoistAirDensity(double tDryBulb, double humRatio, double pression)
        {
            si (!(humRapport >= 0.0))
                jeter Nouveau InvalidOperationExceptionInvalidOperationException("Le taux d'humidité est négatif");

            var boundedHumRatio = Math.Max(humRatio, MIN_HUM_RATIO);

            retour (1.0 + rapport hum délimité) / GetMoistAirVolume(tDryBulb, rapport de hum délimité, pression);
        }


        /*************************************************** ************************************************** ***
         * Atmosphère normale
         ************************************************** ************************************************** */

        /// <résumé>
        /// Renvoie la pression barométrique de l'atmosphère standard, compte tenu de l'élévation (altitude).
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 3
        /// </résumé>
        /// <param name="altitude">altitude en ft [IP] ou m [SI]</param>
        /// <returns>Pression barométrique d'atmosphère standard en Psi [IP] ou Pa [SI]</returns>
        Publique double GetStandardAtmPressure(double altitude)
        {
            si (Système d'unité == UnitSystem.IP)
                retour 14.696 * Math.Pow(1.0 - 6.8754e-06 * altitude, 5.2559);

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


        /// <résumé>
        /// Renvoie la température atmosphérique standard, compte tenu de l'élévation (altitude).
        /// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 4
        /// </résumé>
        /// <param name="altitude">altitude en ft [IP] ou m [SI]</param>
        /// <returns> Température du bulbe sec dans l'atmosphère standard en °F [IP] ou °C [SI]</returns>
        Publique double GetStandardAtmTemperature(double altitude)
        {
            si (Système d'unité == UnitSystem.IP)
                retour 59.0 - 0.00356620 * altitude;

            retour 15.0 - 0.0065 * altitude;
        }

        /// <résumé>
        /// Renvoie la pression au niveau de la mer en fonction de la température du bulbe sec, de l'altitude au-dessus du niveau de la mer et de la pression.
        /// Référence : Hess SL, Introduction à la météorologie théorique, Holt Rinehart et Winston, NY 1959,
        /// ch. 6,5 ; Stull RB, Météorologie pour les scientifiques et les ingénieurs, 2e édition,
        /// Brooks/Cole 2000, ch. 1.
        /// Notes : la procédure standard pour les États-Unis consiste à utiliser pour le tDryBulb la moyenne
        /// de la température actuelle de la station et de la température de la station d'il y a 12 heures.
        /// </résumé>
        /// <param name="stnPressure">Pression de station observée en Psi [IP] ou Pa [SI]</param>
        /// <param name="altitude">Altitude au-dessus du niveau de la mer en ft [IP] ou m [SI]</param>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <returns>Pression barométrique au niveau de la mer en Psi [IP] ou Pa [SI]</returns>
        Publique double GetSeaLevelPressure(double stnPression, double altitude, double tDryBulb)
        {
            double h;
            si (Système d'unité == UnitSystem.IP)
            {
                // Calculer la température moyenne dans la colonne d'air, en supposant un taux de déchéance
                // de 3,6 °F/1000 pieds
                var tColonne = tDryBulb + 0.0036 * altitude / 2.0;

                // Déterminer la hauteur de l'échelle
                h = 53.351 * GetTRankineFromTFahrenheit(tColumn);
            }
            autre
            {
                // Calculer la température moyenne dans la colonne d'air, en supposant un taux de déchéance
                // de 6,5 °C/km
                var tColonne = tDryBulb + 0.0065 * altitude / 2.0;

                // Déterminer la hauteur de l'échelle
                h = 287.055 * GetTKelvinFromTCelsius(tColonne) / 9.807;
            }

            // Calculer la pression au niveau de la mer
            var Niveau de la merPression = stnPression * Math.Exp(altitude / h);
            retour pression au niveau de la mer ;
        }


        /// <résumé>
        /// Pression de retour de la station à partir de la pression au niveau de la mer
        /// Référence : voir 'GetSeaLevelPressure'
        /// Notes : cette fonction est juste l'inverse de 'GetSeaLevelPressure'.
        /// </résumé>
        /// <param name="seaLevelPressure">Pression barométrique au niveau de la mer en Psi [IP] ou Pa [SI]</param>
        /// <param name="altitude">Altitude au-dessus du niveau de la mer en ft [IP] ou m [SI]</param>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <returns>Pression de la station en Psi [IP] ou Pa [SI]</returns>
        Publique double GetStationPressure(double pression au niveau de la mer, double altitude, double tDryBulb)
        {
            retour Niveau de la merPression / GetSeaLevelPressure(1.0, altitude, tDryBulb);
        }


        /*************************************************** ************************************************** ***
         * Fonctions pour définir toutes les valeurs psychrométriques
         ************************************************** ************************************************** */

        /// <résumé>
        /// Fonction utilitaire pour calculer le taux d'humidité, la température du point de rosée, l'humidité relative,
        /// pression de vapeur, enthalpie de l'air humide, volume d'air humide et degré de saturation de l'air donnés
        /// température du bulbe sec, température du bulbe humide et pression.
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="tWetBulb">Température du bulbe humide en °F [IP] ou °C [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Valeurs calculées.</returns>
        Publique Valeur psychrométrique CalcPsychrometricsFromTWetBulb(double tDryBulb, double tWetBulb, double pression)
        {
            var évaluer = Nouveau Valeur psychrométrique
            {
                TDryBulb = tDryBulb,
                TWetBulbComment = tWetBulb,
                Pression = pression
            } ;

            évaluer.HumRatio = GetHumRatioFromTWetBulb(tDryBulb, tWetBulb, pression);
            évaluer.TDewPoint = GetTDewPointFromHumRatio(tDryBulb, évaluer.HumRatio, pression);
            évaluer.RelHum = GetRelHumFromHumRatio(tDryBulb, évaluer.HumRatio, pression);
            évaluer.VapPres = GetVapPresFromHumRatio(évaluer.HumRatio, pression);
            évaluer.MoistAirEnthalpy = GetMoistAirEnthalpy(tDryBulb, évaluer.HumRatio);
            évaluer.MoistAirVolume = GetMoistAirVolume(tDryBulb, évaluer.HumRatio, pression);
            évaluer.DegreeOfSaturation = GetDegreeOfSaturation(tDryBulb, évaluer.HumRatio, pression);

            retour évaluer;
        }


        /// <résumé>
        /// Fonction utilitaire pour calculer le taux d'humidité, la température du bulbe humide, l'humidité relative,
        /// pression de vapeur, enthalpie de l'air humide, volume d'air humide et degré de saturation de l'air donnés
        /// température du bulbe sec, température du point de rosée et pression.
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="tDewPoint">Température du point de rosée en °F [IP] ou °C [SI]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Valeurs calculées.</returns>
        Publique Valeur psychrométrique CalcPsychrometricsFromTDewPoint(double tDryBulb, double tPoint de rosée, double pression)
        {
            var évaluer = Nouveau Valeur psychrométrique
            {
                TDryBulb = tDryBulb,
                TDewPoint = tPoint de rosée,
                Pression = pression
            } ;

            évaluer.HumRatio = GetHumRatioFromTDewPoint(tDewPoint, pression);
            évaluer.TWetBulb = GetTWetBulbFromHumRatio(tDryBulb, évaluer.HumRatio, pression);
            évaluer.RelHum = GetRelHumFromHumRatio(tDryBulb, évaluer.HumRatio, pression);
            évaluer.VapPres = GetVapPresFromHumRatio(évaluer.HumRatio, pression);
            évaluer.MoistAirEnthalpy = GetMoistAirEnthalpy(tDryBulb, évaluer.HumRatio);
            évaluer.MoistAirVolume = GetMoistAirVolume(tDryBulb, évaluer.HumRatio, pression);
            évaluer.DegreeOfSaturation = GetDegreeOfSaturation(tDryBulb, évaluer.HumRatio, pression);

            retour évaluer;
        }


        /// <résumé>
        /// Fonction utilitaire pour calculer le taux d'humidité, la température du bulbe humide, la température du point de rosée,
        /// pression de vapeur, enthalpie de l'air humide, volume d'air humide et degré de saturation de l'air donnés
        /// température sèche, humidité relative et pression.
        /// </résumé>
        /// <param name="tDryBulb">Température du bulbe sec en °F [IP] ou °C [SI]</param>
        /// <param name="relHum">Humidité relative [0-1]</param>
        /// <param name="pression">Pression atmosphérique en Psi [IP] ou Pa [SI]</param>
        /// <returns>Valeurs calculées.</returns>
        Publique Valeur psychrométrique CalcPsychrometricsFromRelHum(double tDryBulb, double relHum, double pression)
        {
            var évaluer = Nouveau Valeur psychrométrique
            {
                TDryBulb = tDryBulb,
                RelHum = relHum,
                Pression = pression
            } ;

            évaluer.HumRatio = GetHumRatioFromRelHum(tDryBulb, relHum, pression);
            évaluer.TWetBulb = GetTWetBulbFromHumRatio(tDryBulb, évaluer.HumRatio, pression);
            évaluer.TDewPoint = GetTDewPointFromHumRatio(tDryBulb, évaluer.HumRatio, pression);
            évaluer.VapPres = GetVapPresFromHumRatio(évaluer.HumRatio, pression);
            évaluer.MoistAirEnthalpy = GetMoistAirEnthalpy(tDryBulb, évaluer.HumRatio);
            évaluer.MoistAirVolume = GetMoistAirVolume(tDryBulb, évaluer.HumRatio, pression);
            évaluer.DegreeOfSaturation = GetDegreeOfSaturation(tDryBulb, évaluer.HumRatio, pression);

            retour évaluer;
        }
    }

    /// <résumé>
    /// Contient les résultats de sortie d'un calcul psychrométrique.
    /// </résumé>
    Publique classe Valeur psychrométrique
    {
        /// <résumé>
        /// Température du bulbe sec en °F [IP] ou °C [SI]
        /// </résumé>
        Publique double TDryBulb { obtenir; Positionner; }

        /// <résumé>
        /// Température du bulbe humide en °F [IP] ou °C [SI]
        /// </résumé>
        Publique double TWetBulbComment { obtenir; Positionner; }

        /// <résumé>
        /// Pression atmosphérique en Psi [IP] ou Pa [SI]
        /// </résumé>
        Publique double Pression { obtenir; Positionner; }

        /// <résumé>
        /// Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
        /// </résumé>
        Publique double HumRatio { obtenir; Positionner; }

        /// <résumé>
        /// Température du point de rosée en °F [IP] ou °C [SI]
        /// </résumé>
        Publique double TDewPoint { obtenir; Positionner; }

        /// <résumé>
        /// Humidité relative [0-1]
        /// </résumé>
        Publique double RelHum { obtenir; Positionner; }

        /// <résumé>
        /// Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
        /// </résumé>
        Publique double VapPres { obtenir; Positionner; }

        /// <résumé>
        /// Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
        /// </résumé>
        Publique double Enthalpie de l'air humide { obtenir; Positionner; }

        /// <résumé>
        /// Volume spécifique ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
        /// </résumé>
        Publique double Volume d'air humide { obtenir; Positionner; }

        /// <résumé>
        /// Degré de saturation [sans unité]
        /// </résumé>
        Publique double DegréDeSaturation { obtenir; Positionner; }
    }

    /// <résumé>
    /// Systèmes d'unités standard
    /// </résumé>
    Publique énumération Système d'unité
    {
        /// <résumé>
        /// Unités impériales
        /// </résumé>
        IP = 1,

        /// <résumé>
        /// Unités du système métrique
        /// </résumé>
        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 (version 2.3.0) (https://github.com/psychrometrics/psychrolib)
! Copyright (c) 2018 D. Thevenard et D. Meyer pour l'implémentation actuelle de la bibliothèque
! Copyright (c) Manuel ASHRAE 2017 — Principes fondamentaux des équations et coefficients ASHRAE
! Sous licence MIT.

module psychrolib
  !+ Présentation des modules
  !+ Contient des fonctions pour calculer les propriétés thermodynamiques des mélanges gaz-vapeur
  !+ et atmosphère standard adaptée à la plupart des applications techniques, physiques et météorologiques
  !+ applications.
  !+
  !+ La plupart des fonctions sont une implémentation des formules trouvées dans le
  !+ 2017 ASHRAE Handbook - Fondamentaux, dans les deux systèmes internationaux (SI),
  Unités !+ et impériales (IP). Veuillez vous référer aux informations incluses dans
  !+ chaque fonction pour leur référence respective.
  !+
  !+ Exemple
  !+ utiliser psychrolib, uniquement : GetTDewPointFromRelHum, SetUnitSystem, SI
  !+ ! Réglez le système d'unités, par exemple sur SI (peut être « SI » ou « IP »)
  !+ appeler SetUnitSystem(SI)
  !+ ! Calculer la température du point de rosée pour une température de bulbe sec de 25 C et une humidité relative de 80 %
  !+ imprimer *, GetTDewPointFromRelHum(25.0, 0.80)
  !+ 21.3094
  !+
  !+ Droit d'auteur
  !+ - Pour l'implémentation actuelle de la bibliothèque
  !+ Copyright (c) 2018 D. Thevenard et D. Meyer.
  !+ - Pour les équations et les coefficients publiés ASHRAE Handbook — Fundamentals, Chapitre 1
  !+ Copyright (c) Manuel ASHRAE 2017 — Fondamentaux (https://www.ashrae.org)
  !+
  !+ Licence
  !+ MIT (https://github.com/psychrometrics/psychrolib/LICENSE.txt)
  !+
  !+ Note des auteurs
  !+ Nous avons fait tous les efforts possibles pour garantir que le code soit adéquat, mais nous ne faisons aucun
  !+ représentation par rapport à son exactitude. À utiliser à vos risques et périls. Si vous remarquez
  !+ une erreur, ou si vous avez une suggestion, veuillez nous en informer via GitHub à l'adresse
  !+ https://github.com/psychrometrics/psychrolib/issues.


  implicite aucun

  privé
  public :: IP
  Publique :: SI
  Publique :: DéfinirSystèmeUnité
  Publique :: ObtenirUnitSystem
  Publique :: estIP
  Publique :: ObtenirTRankineFromTFahrenheit
  Publique :: ObtenirTFahrenheitDeTRankine
  Publique :: ObtenirTKelvinFromTCelsius
  Publique :: ObtenirTCelsiusFromTKelvin
  Publique :: GetTWetBulbFromTDewPoint
  Publique :: GetTWetBulbFromRelHum
  Publique :: GetRelHumFromTDewPoint
  Publique :: GetRelHumFromTWetBulb
  Publique :: ObtenirTDewPointFromRelHum
  Publique :: GetTDewPointFromTWetBulb
  Publique :: GetVapPresFromRelHum
  Publique :: GetRelHumFromVapPres
  Publique :: GetTDewPointFromVapPres
  Publique :: GetVapPresFromTDewPoint
  Publique :: GetTWetBulbFromHumRatio
  Publique :: GetHumRatioFromTWetBulb
  Publique :: GetHumRatioFromRelHum
  Publique :: GetRelHumFromHumRatio
  Publique :: GetHumRatioFromTDewPoint
  Publique :: GetTDewPointFromHumRatio
  Publique :: GetHumRatioFromVapPres
  Publique :: GetVapPresFromHumRatio
  Publique :: GetDryAirEnthalpy
  Publique :: GetDryAirDensity
  Publique :: GetDryAirVolume
  Publique :: GetTDryBulbFromEnthalpyAndHumRatio
  Publique :: GetHumRatioFromEnthalpyAndTDryBulb
  Publique :: GetSatVapPres
  Publique :: GetSatHumRatio
  Publique :: GetSatAirEnthalpy
  Publique :: GetVaporPressureDeficit
  Publique :: GetDegreeOfSaturation
  Publique :: GetMoistAirEnthalpy
  Publique :: GetMoistAirVolume
  Publique :: GetTDryBulbFromMoistAirVolumeAndHumRatio
  Publique :: GetMoistAirDensity
  Publique :: GetStandardAtmPressure
  Publique :: GetStandardAtmTemperature
  Publique :: GetSeaLevelPressure
  Publique :: GetStationPressure
  Publique :: GetSpecificHumFromHumRatio
  Publique :: GetHumRatioFromSpecificHum
  Publique :: CalcPsychrometricsFromTWetBulb
  Publique :: CalcPsychrometricsFromTDewPoint
  Publique :: CalcPsychrometricsFromRelHum
  Publique :: dLnPws_


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Constantes globales
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  réel, paramètre ::  ZERO_FAHRENHEIT_AS_RANKINE = 459.67
    !+ Zéro degré Fahrenheit (°F) exprimé en degré Rankine (°R).
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 39.

  réel, paramètre ::  ZERO_CELSIUS_AS_KELVIN = 273.15
    !+ Zéro degré Celsius (°C) exprimé en Kelvin (K).
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 39.

  réel, paramètre ::  R_DA_IP = 53.350
    !+ Constante de gaz universelle pour air sec (version IP) en ft lb_Force lb_DryAir⁻¹ R⁻¹.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1.

  réel, paramètre ::  R_DA_SI = 287.042
    !+ Constante de gaz universelle pour air sec (version SI) en J kg_DryAir⁻¹ K⁻¹.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1.

  entier, paramètre :: IP = 1
  entier, paramètre :: SI = 2

  entier  :: PSYCHROLIB_UNITS = 0 ! 0 = indéfini.
    !+ Système d'unités à utiliser.

  réel ::  PSYCHROLIB_TOLERANCE = 1.0
    !+ Tolérance des calculs de température.

  entier, paramètre  :: MAX_ITER_COUNT = 100
    !+ Nombre maximum d'itérations avant de quitter les boucles while.

  réel, paramètre  :: MIN_HUM_RATIO = 1e-7
    !+ Taux d'humidité minimum acceptable utilisé/restitué par toutes les fonctions.
    !+ Toute valeur supérieure à 0 ou inférieure au MIN_HUM_RATIO sera réinitialisée à cette valeur.

  réel, paramètre  :: FREEZING_POINT_WATER_IP = 32.0
    !+ float : Point de congélation de l'eau en Fahrenheit.

  réel, paramètre  :: FREEZING_POINT_WATER_SI = 0.0
    !+ float : Point de congélation de l’eau en Celsius.

  réel, paramètre  :: TRIPLE_POINT_WATER_IP = 32.018
    !+ flotteur : Triple point d'eau en Fahrenheit.

  réel, paramètre  :: TRIPLE_POINT_WATER_SI = 0.01
    !+ float : Triple point de l'eau en Celsius.


  contient


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Fonctions d'assistance
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  sous-programme DéfinirSystèmeUnité(Système d'unité)
  !+ Définissez le système d'unités à utiliser (SI ou IP).
  !+ Notes : cette fonction *DOIT ÊTRE APPELÉE* avant que la bibliothèque puisse être utilisée

    entier, intention(dans)    :: Système d'unité
    !+ Unités : chaîne indiquant le système d'unités choisi (SI ou IP)

    si (.pas. (Système d'unité == SI .ou. Système d'unité == IP)) ensuite
      erreur arrêt "Le système d'unités doit être soit SI, soit IP."
    fin si

    PSYCHROLIB_UNITS = Système d'unité

    ! Définir la tolérance sur les calculs de température
    ! La tolérance est la même en IP et SI
    si (Système d'unité == IP) ensuite
      PSYCHROLIB_TOLERANCE = 0.001 * 9.0 / 5.0
    autre
      PSYCHROLIB_TOLERANCE = 0.001
    fin si
  sous-programme de fin DéfinirSystèmeUnité

  fonction ObtenirUnitSystem() résultat(Système d'unité)
    !+ Renvoie le système d'unités utilisé.
    entier :: Système d'unité
    Système d'unité = PSYCHROLIB_UNITS
  fonction de fin ObtenirUnitSystem

  fonction estIP()
    !+ Vérifiez si le système utilisé est IP ou SI
    logique :: estIP
    si (PSYCHROLIB_UNITS == IP) ensuite
      estIP = .vrai.
    sinon si (PSYCHROLIB_UNITS == SI) ensuite
      estIP = .FAUX.
    autre
      erreur arrêt "Le système d'unités n'a pas été défini."
    fin si
  fonction de fin estIP


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Conversion entre unités de température
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  fonction ObtenirTRankineFromTFahrenheit(TFahrenheit) résultat(TRankine)
    !+ Fonction utilitaire pour convertir la température en degré Rankine (°R)
    !+ température donnée en degrés Fahrenheit (°F).
    !+ Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 chapitre 3

    réel, intention(dans)  :: TFahrenheit
      !+ Température en degrés Fahrenheit
    réel              :: TRankine
      !+ Température en degré Rankine

    TRankine = TFahrenheit + ZERO_FAHRENHEIT_AS_RANKINE
  fonction de fin ObtenirTRankineFromTFahrenheit

  fonction ObtenirTFahrenheitDeTRankine(TRankine) résultat(TFahrenheit)
    !+ Fonction utilitaire pour convertir la température en degrés Fahrenheit (°F)
    !+ température donnée en degré Rankine (°R).
    !+ Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 chapitre 3

    réel, intention(dans)  :: TRankine
      !+ Température en degré Rankine
    réel              :: TFahrenheit
      !+ Température en degrés Fahrenheit

    TFahrenheit = TRankine - ZERO_FAHRENHEIT_AS_RANKINE
  fonction de fin ObtenirTFahrenheitDeTRankine

  fonction ObtenirTKelvinFromTCelsius(TCelsius) résultat(TKelvin)
    !+ Fonction utilitaire pour convertir la température en Kelvin (K)
    !+ température donnée en degrés Celsius (°C).
    !+ Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 chapitre 3

    réel, intention(dans)  :: TCelsius
      !+ Température en degrés Celsius
    réel              :: TKelvin
      !+ Tempearatyre en Kelvin

    TKelvin = TCelsius + ZERO_CELSIUS_AS_KELVIN
  fonction de fin ObtenirTKelvinFromTCelsius

  fonction ObtenirTCelsiusFromTKelvin(TKelvin) résultat(TCelsius)
    !+ Fonction utilitaire pour convertir la température en degrés Celsius (°C)
    !+ température donnée en Kelvin (K).
    !+ Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 chapitre 3

    réel, intention(dans)  :: TKelvin
      !+ Tempearatyre en Kelvin
    réel              :: TCelsius
      !+ Température en degrés Celsius

    TCelsius = TKelvin - ZERO_CELSIUS_AS_KELVIN
  fonction de fin ObtenirTCelsiusFromTKelvin


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Conversions entre point de rosée, bulbe humide et humidité relative
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  fonction GetTWetBulbFromTDewPoint(TDryBulb, TDewPoint, Pression) résultat(TWetBulbComment)
    !+ Renvoie la température du bulbe humide en fonction de la température du bulbe sec, de la température du point de rosée et de la pression.
    !+ Références :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1

    réel, intention(dans)  :: TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  :: TDewPoint
      !+ Température du point de rosée en °F [IP] ou °C [SI]
    réel, intention(dans)  :: Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              :: TWetBulbComment
      !+ Température du thermomètre mouillé en °F [IP] ou °C [SI]
    réel              :: HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]

    si (TDewPoint > TDryBulb) ensuite
      erreur arrêt "Erreur : la température du point de rosée est supérieure à la température du bulbe sec"
    fin si

    HumRatio = GetHumRatioFromTDewPoint(TDewPoint, Pression)
    TWetBulbComment = GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pression)
  fonction de fin GetTWetBulbFromTDewPoint

  fonction GetTWetBulbFromRelHum(TDryBulb, RelHum, Pression) résultat(TWetBulbComment)
    !+ Renvoie la température du bulbe humide en fonction de la température du bulbe sec, de l'humidité relative et de la pression.
    !+ Références :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  RelHum
      !+ Humidité relative dans la plage [0, 1]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  TWetBulbComment
      !+ Température du thermomètre mouillé en °F [IP] ou °C [SI]
    réel              ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]

    si (RelHum < 0.0 .ou. RelHum > 1.0) ensuite
      erreur arrêt "Erreur : l'humidité relative est en dehors de la plage [0,1]"
    fin si

    HumRatio = GetHumRatioFromRelHum(TDryBulb, RelHum, Pression)
    TWetBulbComment = GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pression)
  fonction de fin GetTWetBulbFromRelHum

  fonction GetRelHumFromTDewPoint(TDryBulb, TDewPoint) résultat(RelHum)
    !+ Renvoie l'humidité relative en fonction de la température du bulbe sec et de la température du point de rosée.
    !+ Références :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 22

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  TDewPoint
      !+ Température du point de rosée en °F [IP] ou °C [SI]
    réel              ::  RelHum
      !+ Humidité relative dans la plage [0, 1]
    réel              ::  VapPres
      !+ Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
    réel              ::  SatVapPres
      !+ Pression de vapeur de l'air saturé en Psi [IP] ou Pa [SI]

    si (TDewPoint > TDryBulb) ensuite
      erreur arrêt "Erreur : la température du point de rosée est supérieure à la température du bulbe sec"
    fin si

    VapPres     = GetSatVapPres(TDewPoint)
    SatVapPres  = GetSatVapPres(TDryBulb)
    RelHum      = VapPres / SatVapPres
  fonction de fin GetRelHumFromTDewPoint

  fonction GetRelHumFromTWetBulb(TDryBulb, TWetBulbComment, Pression) résultat(RelHum)
    !+ Renvoie l'humidité relative en fonction de la température du bulbe sec, de la température du bulbe humide et de la pression.
    !+ Références :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  TWetBulbComment
      !+ Température du thermomètre mouillé en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  RelHum
      !+ Humidité relative dans la plage [0, 1]
    réel              ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]

    si (TWetBulbComment > TDryBulb) ensuite
      erreur arrêt "Erreur : la température du bulbe humide est supérieure à la température du bulbe sec"
    fin si

    HumRatio = GetHumRatioFromTWetBulb(TDryBulb, TWetBulbComment, Pression)
    RelHum   = GetRelHumFromHumRatio(TDryBulb, HumRatio, Pression)
  fonction de fin GetRelHumFromTWetBulb

  fonction ObtenirTDewPointFromRelHum(TDryBulb, RelHum) résultat(TDewPoint)
    !+ Température de retour du point de rosée en fonction de la température du bulbe sec et de l'humidité relative.
    !+ Références :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  RelHum
      !+ Humidité relative dans la plage [0, 1]
    réel              ::  TDewPoint
      !+ Température du point de rosée en °F [IP] ou °C [SI]
    réel              ::  VapPres
      !+ Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]

    si (RelHum < 0.0 .ou. RelHum > 1.0) ensuite
      erreur arrêt "Erreur : l'humidité relative est en dehors de la plage [0,1]"
    fin si

    VapPres   = GetVapPresFromRelHum(TDryBulb, RelHum)
    TDewPoint = GetTDewPointFromVapPres(TDryBulb, VapPres)
  fonction de fin ObtenirTDewPointFromRelHum

  fonction GetTDewPointFromTWetBulb(TDryBulb, TWetBulbComment, Pression) résultat(TDewPoint)
    !+ Température de retour du point de rosée en fonction de la température du bulbe sec, de la température du bulbe humide et de la pression.
    !+ Références :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  TWetBulbComment
      !+ Température du thermomètre mouillé en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  TDewPoint
      !+ Température du point de rosée en °F [IP] ou °C [SI]
    réel              ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]

    si (TWetBulbComment > TDryBulb) ensuite
      erreur arrêt "Erreur : la température du bulbe humide est supérieure à la température du bulbe sec"
    fin si

    HumRatio  = GetHumRatioFromTWetBulb(TDryBulb, TWetBulbComment, Pression)
    TDewPoint = GetTDewPointFromHumRatio(TDryBulb, HumRatio, Pression)
  fonction de fin GetTDewPointFromTWetBulb


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Conversions entre le point de rosée ou l'humidité relative et la pression de vapeur
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  fonction GetVapPresFromRelHum(TDryBulb, RelHum) résultat(VapPres)
    !+ Renvoie la pression partielle de vapeur d'eau en fonction de l'humidité relative et de la température.
    !+ Références :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 12, 22

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  RelHum
      !+ Humidité relative dans la plage [0, 1]
    réel              ::  VapPres
      !+ Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]

    si (RelHum < 0.0 .ou. RelHum > 1.0) ensuite
      erreur arrêt "Erreur : l'humidité relative est en dehors de la plage [0,1]"
    fin si

    VapPres = RelHum * GetSatVapPres(TDryBulb)
  fonction de fin GetVapPresFromRelHum

  fonction GetRelHumFromVapPres(TDryBulb, VapPres) résultat(RelHum)
    !+ Renvoie l'humidité relative en fonction de la température du bulbe sec et de la pression de vapeur.
    !+ Références :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 12, 22

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  VapPres
      !+ Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
    réel              ::  RelHum
      !+ Humidité relative dans la plage [0, 1]

    si (VapPres < 0.0) ensuite
      erreur arrêt "Erreur : la pression partielle de la vapeur d'eau dans l'air humide ne peut pas être négative"
    fin si

    RelHum = VapPres / GetSatVapPres(TDryBulb)
  fonction de fin GetRelHumFromVapPres

  fonction dLnPws_(TDryBulb) résultat(dLnPws)
    !+ Fonction d'assistance renvoyant la dérivée du logarithme naturel de la pression de vapeur saturante
    !+ en fonction de la température du bulbe sec.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 5

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel              ::  dLnPws
      !+ Dérivée du logarithme naturel de la pression de vapeur de l'air saturé en Psi [IP] ou Pa [SI]
    réel              ::  J
      !+ Température sèche en R [IP] ou K [SI]

    si (estIP()) ensuite

      J = ObtenirTRankineFromTFahrenheit(TDryBulb)

      si (TDryBulb <= TRIPLE_POINT_WATER_IP) ensuite
        dLnPws = 1.0214165E+04 / J**2 - 5.3765794E-03 + 2 * 1.9202377E-07 * J &
                 + 3 * 3.5575832E-10 * J**2 - 4 * 9.0344688E-14 * J**3 + 4.1635019 / J
      autre
        dLnPws = 1.0440397E+04 / J**2 - 2.7022355E-02 + 2 * 1.2890360E-05 * J &
                 - 3 * 2.4780681E-09 * J**2 + 6.5459673 / J
      fin si

    autre

      J = ObtenirTKelvinFromTCelsius(TDryBulb)

      si (TDryBulb <= TRIPLE_POINT_WATER_SI) ensuite
        dLnPws = 5.6745359E+03 / J**2 - 9.677843E-03 + 2 * 6.2215701E-07 * J &
                 + 3 * 2.0747825E-09 * J**2 - 4 * 9.484024E-13 * J**3 + 4.1635019 / J
      autre
        dLnPws = 5.8002206E+03 / J**2 - 4.8640239E-02 + 2 * 4.1764768E-05 * J &
                 - 3 * 1.4452093E-08 * J**2 + 6.5459673 / J
      fin si
    fin si
  fonction de fin dLnPws_

  fonction GetTDewPointFromVapPres(TDryBulb, VapPres) résultat(TDewPoint)
    !+ Température de retour du point de rosée compte tenu de la température du bulbe sec et de la pression de vapeur.
    !+ Références :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 éq. 5 et 6
    !+ Remarques :
    !+ La température du point de rosée est résolue en inversant l'équation donnant la pression de vapeur d'eau
    !+ à saturation à partir de la température plutôt que d'utiliser les régressions fournies
    !+ par ASHRAE (équations 37 et 38) qui sont beaucoup moins précis et ont un
    !+ plage de validité plus étroite.
    !+ La méthode Newton-Raphson (NR) est utilisée sur le logarithme de la vapeur d'eau
    !+ pression en fonction de la température, ce qui est une fonction très douce
    !+ La convergence est généralement obtenue en 3 à 5 itérations.
    !+ TDryBulb n'est pas vraiment nécessaire ici, juste utilisé pour plus de commodité.

    réel, intention(dans)    ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)    ::  VapPres
      !+ Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
    réel                ::  TDewPoint
      !+ Température du point de rosée en °F [IP] ou °C [SI]
    réel                ::  lnVP
      !+ Logarithme naturel de la pression partielle de la vapeur d'eau dans l'air humide
    réel                ::  d_lnVP
      !+ Dérivée de la fonction, calculée numériquement
    réel                ::  lnVP_iter
      !+ Valeur du log de pression de vapeur d'eau utilisée dans le calcul du NR
    réel                ::  TDewPoint_iter
      !+ Valeur de TDewPoint utilisée dans le calcul NR
    réel, dimension(2)  ::  BORNES
      !+ Plage de température valide en °F [IP] ou °C [SI]
    entier             :: indice
      !+ Indice utilisé dans le calcul

    ! Bornes et taille de pas en fonction du système d'unités
    si (estIP()) ensuite
        BORNES(1) = -148.0
        BORNES(2) =  392.0
    autre
        BORNES(1) = -100.0
        BORNES(2) =  200.0
    fin si

    ! Contrôle de validité – limites en dehors desquelles une solution ne peut être trouvée
    si (VapPres < GetSatVapPres(BORNES(1)) .ou. VapPres > GetSatVapPres(BORNES(2))) ensuite
      erreur arrêt "Erreur : la pression partielle de la vapeur d'eau est en dehors de la plage de validité des équations"
    fin si

    ! Nous utilisons NR pour approximer la solution.
    TDewPoint = TDryBulb
    lnVP = enregistrer(VapPres)
    indice = 1

    faire pendant (.vrai.)
      TDewPoint_iter = TDewPoint ! TDewPoint_iter utilisé dans le calcul NR
      lnVP_iter = enregistrer(GetSatVapPres(TDewPoint_iter))

      ! Dérivée de fonction, calculée analytiquement
      d_lnVP = dLnPws_(TDewPoint_iter)

      ! Nouvelle estimation, délimitée par le domaine de recherche défini ci-dessus
      TDewPoint = TDewPoint_iter - (lnVP_iter - lnVP) / d_lnVP
      TDewPoint = maximum(TDewPoint, BORNES(1))
      TDewPoint = min(TDewPoint, BORNES(2))

      si (abdos(TDewPoint - TDewPoint_iter) <= PSYCHROLIB_TOLERANCE) ensuite
        sortie
      fin si

      si (indice > MAX_ITER_COUNT) ensuite
        erreur arrêt "Convergence non atteinte dans GetTDewPointFromVapPres. Arrêt."
      fin si

      indice = indice + 1
    fin faire

  TDewPoint = min(TDewPoint, TDryBulb)
  fonction de fin GetTDewPointFromVapPres

  fonction GetVapPresFromTDewPoint(TDewPoint) résultat(VapPres)
    !+ Pression de vapeur de retour en fonction de la température du point de rosée.
    !+ Références :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 36

    réel, intention(dans)  ::  TDewPoint
      !+ Température du point de rosée en °F [IP] ou °C [SI]
    réel              ::  VapPres
      !+ Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]

    VapPres = GetSatVapPres(TDewPoint)
  fonction de fin GetVapPresFromTDewPoint


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Conversions de la température du bulbe humide, de la température du point de rosée ou du rapport humidité relative/humidité
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  fonction GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pression) résultat(TWetBulbComment)
    !+ Renvoie la température du bulbe humide en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
    !+ Références :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équations 33 et 35 résolues pour Tstar

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  TWetBulbComment
      !+ Température du thermomètre mouillé en °F [IP] ou °C [SI]
    réel              ::  TDewPoint
      !+ TDewPoint : Température du point de rosée en °F [IP] ou °C [SI]
    réel              ::  TWetBulbSup
      !+ Valeur supérieure de la température du bulbe humide dans la méthode de bissection (la supposition initiale est basée sur la température du bulbe sec) en °F [IP] ou °C [SI]
    réel              ::  TWetBulbInf
      !+ Valeur inférieure de la température du bulbe humide dans la méthode de bissection (la supposition initiale est basée sur la température du point de rosée) en °F [IP] ou °C [SI]
    réel              ::  Wstar
      !+ Taux d'humidité à la température Tstar en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel              ::  BoundedHumRatio
      !+ Taux d'humidité borné à MIN_HUM_RATIO
    entier           ::  indice
      !+ index utilisé dans l'itération

    si (HumRatio < 0.0) ensuite
      erreur arrêt "Erreur : le taux d'humidité ne peut pas être négatif"
    fin si
    BoundedHumRatio = maximum(HumRatio, MIN_HUM_RATIO)

    TDewPoint = GetTDewPointFromHumRatio(TDryBulb, BoundedHumRatio, Pression)

    ! Premières suppositions
    TWetBulbSup = TDryBulb
    TWetBulbInf = TDewPoint
    TWetBulbComment = (TWetBulbInf + TWetBulbSup) / 2.0

    indice = 1
    ! Boucle de bissection
    faire pendant ((TWetBulbSup - TWetBulbInf) > PSYCHROLIB_TOLERANCE)

    ! Calculer le taux d'humidité à la température Tstar
    Wstar = GetHumRatioFromTWetBulb(TDryBulb, TWetBulbComment, Pression)

    ! Obtenez de nouvelles limites
    si (Wstar > BoundedHumRatio) ensuite
      TWetBulbSup = TWetBulbComment
    autre
      TWetBulbInf = TWetBulbComment
    fin si

    ! Nouvelle estimation de la température du bulbe humide
    TWetBulbComment = (TWetBulbSup + TWetBulbInf) / 2.0

      si (indice > MAX_ITER_COUNT) ensuite
        erreur arrêt "Convergence non atteinte dans GetTWetBulbFromHumRatio. Arrêt."
      fin si

    indice = indice + 1
    fin faire
  fonction de fin GetTWetBulbFromHumRatio

  fonction GetHumRatioFromTWetBulb(TDryBulb, TWetBulbComment, Pression) résultat(HumRatio)
    !+ Taux d'humidité de retour en fonction de la température du bulbe sec, de la température du bulbe humide et de la pression.
    !+ Références :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équations 33 et 35

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  TWetBulbComment
      !+ Température du thermomètre mouillé en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel              ::  Wsstar
      !+ Taux d'humidité à la température Tstar en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]

    si (TWetBulbComment > TDryBulb) ensuite
      erreur arrêt "Erreur : la température du bulbe humide est supérieure à la température du bulbe sec"
    fin si

    Wsstar = GetSatHumRatio(TWetBulbComment, Pression)

    si (estIP()) ensuite
      si (TWetBulbComment >= FREEZING_POINT_WATER_IP) ensuite
        HumRatio = ((1093.0 - 0.556 * TWetBulbComment) * Wsstar - 0.240 * (TDryBulb - TWetBulbComment))   &
                   / (1093.0 + 0.444 * TDryBulb - TWetBulbComment)
      autre
        HumRatio = ((1220.0 - 0.04 * TWetBulbComment) * Wsstar - 0.240 * (TDryBulb - TWetBulbComment))    &
                   / (1220.0 + 0.444 * TDryBulb - 0.48 * TWetBulbComment)
      fin si
    autre
      si (TWetBulbComment >= FREEZING_POINT_WATER_SI) ensuite
        HumRatio = ((2501.0 - 2.326 * TWetBulbComment) * Wsstar - 1.006 * (TDryBulb - TWetBulbComment))   &
                   / (2501.0 + 1.86 * TDryBulb - 4.186 * TWetBulbComment)
      autre
           HumRatio = ((2830.0 - 0.24 * TWetBulbComment) * Wsstar - 1.006 * (TDryBulb - TWetBulbComment)) &
                      / (2830.0 + 1.86 * TDryBulb - 2.1 * TWetBulbComment)
      fin si
    fin si

    ! Contrôle de validité.
    HumRatio = maximum(HumRatio, MIN_HUM_RATIO)
  fonction de fin GetHumRatioFromTWetBulb

  fonction GetHumRatioFromRelHum(TDryBulb, RelHum, Pression) résultat(HumRatio)
    !+ Taux d'humidité de retour en fonction de la température du bulbe sec, de l'humidité relative et de la pression.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  RelHum
      !+ Humidité relative dans la plage [0, 1]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel              ::  VapPres
      !+ Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]

    si (RelHum < 0.0 .ou. RelHum > 1.0) ensuite
      erreur arrêt "Erreur : l'humidité relative est en dehors de la plage [0,1]"
    fin si

    VapPres   = GetVapPresFromRelHum(TDryBulb, RelHum)
    HumRatio  = GetHumRatioFromVapPres(VapPres, Pression)
  fonction de fin GetHumRatioFromRelHum

  fonction GetRelHumFromHumRatio(TDryBulb, HumRatio, Pression) résultat(RelHum)
  !+ Renvoie l'humidité relative en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
  !+ Référence :
  !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  RelHum
      !+ Humidité relative dans la plage [0, 1]
    réel              ::  VapPres
      !+ Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]

    si (HumRatio < 0.0) ensuite
      erreur arrêt "Erreur : le taux d'humidité ne peut pas être négatif"
    fin si

    VapPres = GetVapPresFromHumRatio(HumRatio, Pression)
    RelHum  = GetRelHumFromVapPres(TDryBulb, VapPres)
  fonction de fin GetRelHumFromHumRatio

  fonction GetHumRatioFromTDewPoint(TDewPoint, Pression) résultat(HumRatio)
    !+ Taux d'humidité de retour en fonction de la température et de la pression du point de rosée.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1

    réel, intention(dans)  ::  TDewPoint
      !+ Température du point de rosée en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel              ::  VapPres
      !+ Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]

    VapPres   = GetSatVapPres(TDewPoint)
    HumRatio  = GetHumRatioFromVapPres(VapPres, Pression)
  fonction de fin GetHumRatioFromTDewPoint

  fonction GetTDewPointFromHumRatio(TDryBulb, HumRatio, Pression) résultat(TDewPoint)
    !+ Température de retour du point de rosée en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  TDewPoint
      !+ Température du point de rosée en °F [IP] ou °C [SI]
    réel              ::  VapPres
      !+ Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]

    si (HumRatio < 0.0) ensuite
      erreur arrêt "Erreur : le taux d'humidité ne peut pas être négatif"
    fin si

    VapPres   = GetVapPresFromHumRatio(HumRatio, Pression)
    TDewPoint = GetTDewPointFromVapPres(TDryBulb, VapPres)
  fonction de fin GetTDewPointFromHumRatio


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Conversions entre taux d'humidité et pression de vapeur
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  fonction GetHumRatioFromVapPres(VapPres, Pression) résultat(HumRatio)
    !+ Taux d'humidité de retour en fonction de la pression de vapeur d'eau et de la pression atmosphérique.
    !+ Référence :
    !+ Fondamentaux d'ASHRAE (2005) ch. 6 éq. 22 ;
    !+ Fondamentaux d'ASHRAE (2009) ch. 1 éq. 22.

    réel, intention(dans)  ::  VapPres
      !+ Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]

    si (VapPres < 0.0) ensuite
      erreur arrêt "Erreur : la pression partielle de la vapeur d'eau dans l'air humide ne peut pas être négative"
    fin si

    HumRatio = 0.621945 * VapPres / (Pression-VapPres)

    ! Contrôle de validité.
    HumRatio = maximum(HumRatio, MIN_HUM_RATIO)
  fonction de fin GetHumRatioFromVapPres

  fonction GetVapPresFromHumRatio(HumRatio, Pression) résultat(VapPres)
    !+ Pression de vapeur de retour en fonction du taux d'humidité et de la pression.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 20 résolue pour pw

    réel, intention(dans)  ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  VapPres
      !+ Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
    réel              ::  BoundedHumRatio
      !+ Taux d'humidité borné à MIN_HUM_RATIO

    si (HumRatio < 0.0) ensuite
      erreur arrêt "Erreur : le taux d'humidité est négatif"
    fin si
    BoundedHumRatio = maximum(HumRatio, MIN_HUM_RATIO)

    VapPres = Pression * BoundedHumRatio / (0.621945 + BoundedHumRatio)
  fonction de fin GetVapPresFromHumRatio


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Conversions entre taux d'humidité et humidité spécifique
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  fonction GetSpecificHumFromHumRatio(HumRatio) résultat(SpécifiqueHum)
    !+ Renvoie l'humidité spécifique à partir du rapport d'humidité (c'est-à-dire le rapport de mélange).
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 9b

    réel, intention(dans) :: HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Dry_Air⁻¹ [IP] ou kg_H₂O kg_Dry_Air⁻¹ [SI]
    réel             :: SpécifiqueHum
      !+ Humidité spécifique en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel              ::  BoundedHumRatio
      !+ Taux d'humidité borné à MIN_HUM_RATIO

    si (HumRatio < 0.0) ensuite
      erreur arrêt "Erreur : le taux d'humidité ne peut pas être négatif"
    fin si
    BoundedHumRatio = maximum(HumRatio, MIN_HUM_RATIO)

    SpécifiqueHum = BoundedHumRatio / (1.0 + BoundedHumRatio)
  fonction de fin GetSpecificHumFromHumRatio

  fonction GetHumRatioFromSpecificHum(SpécifiqueHum) résultat(HumRatio)
    !+ Renvoie le taux d'humidité (alias taux de mélange) à partir de l'humidité spécifique.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 9b (résolu pour le taux d'humidité)

    réel, intention(dans)  :: SpécifiqueHum
      !+ Humidité spécifique en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel              :: HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Dry_Air⁻¹ [IP] ou kg_H₂O kg_Dry_Air⁻¹ [SI]

    si (SpécifiqueHum < 0.0 .ou. SpécifiqueHum >= 1.0) ensuite
      erreur arrêt "Erreur : l'humidité spécifique est en dehors de la plage [0, 1["
    fin si

    HumRatio = SpécifiqueHum / (1.0 - SpécifiqueHum)

    ! Contrôle de validité.
    HumRatio = maximum(HumRatio, MIN_HUM_RATIO)
  fonction de fin GetHumRatioFromSpecificHum


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Calculs d'air sec
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  fonction GetDryAirEnthalpy(TDryBulb) résultat(Enthalpie de l'air sec)
    !+ Renvoie l'enthalpie de l'air sec en fonction de la température du bulbe sec.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 28

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel              ::  Enthalpie de l'air sec
      !+ Enthalpie de l'air sec en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]

    si (estIP()) ensuite
      Enthalpie de l'air sec = 0.240 * TDryBulb
    autre
      Enthalpie de l'air sec = 1006 * TDryBulb
    fin si
  fonction de fin GetDryAirEnthalpy

  fonction GetDryAirDensity(TDryBulb, Pression) résultat(DryAirDensity)
    !+ Renvoyez la densité de l'air sec en fonction de la température et de la pression du bulbe sec.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1
    !+ Remarques :
    !+ Éqn 14 pour la relation gazeuse parfaite pour l'air sec.
    !+ Eqn 1 pour la constante universelle des gaz.
    !+ Le facteur 144 en IP est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  DryAirDensity
      !+ Densité de l'air sec en lb ft⁻³ [IP] ou kg m⁻³ [SI]

    si (estIP()) ensuite
      DryAirDensity = (144 * Pression) / R_DA_IP / ObtenirTRankineFromTFahrenheit(TDryBulb)
    autre
      DryAirDensity = Pression / R_DA_SI / ObtenirTKelvinFromTCelsius(TDryBulb)
    fin si
  fonction de fin GetDryAirDensity

  fonction GetDryAirVolume(TDryBulb, Pression) résultat(Volume d'air sec)
    !+ Restituer le volume d'air sec en fonction de la température et de la pression du bulbe sec.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1
    !+ Remarques :
    !+ Éqn 14 pour la relation gazeuse parfaite pour l'air sec.
    !+ Eqn 1 pour la constante universelle des gaz.
    !+ Le facteur 144 en IP est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  Volume d'air sec
      !+ Volume d'air sec en ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]

    si (estIP()) ensuite
      Volume d'air sec = ObtenirTRankineFromTFahrenheit(TDryBulb) * R_DA_IP / (144 * Pression)
    autre
      Volume d'air sec = ObtenirTKelvinFromTCelsius(TDryBulb) * R_DA_SI / Pression
    fin si
  fonction de fin GetDryAirVolume

  fonction GetTDryBulbFromEnthalpyAndHumRatio(Enthalpie de l'air humide, HumRatio) résultat(TDryBulb)
    !+ Renvoie la température du bulbe sec à partir de l'enthalpie et du rapport d'humidité.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 30
    !+ Remarques :
    !+ Basé sur la fonction `GetMoistAirEnthalpy`, réorganisée en fonction de la température.

    réel, intention(dans)  ::  Enthalpie de l'air humide
      !+ Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹
    réel, intention(dans)  ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel              ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel              ::  BoundedHumRatio
      !+ Taux d'humidité borné à MIN_HUM_RATIO

    si (HumRatio < 0.0) ensuite
      erreur arrêt "Erreur : le taux d'humidité est négatif"
    fin si
    BoundedHumRatio = maximum(HumRatio, MIN_HUM_RATIO)

    si (estIP()) ensuite
      TDryBulb  = (Enthalpie de l'air humide - 1061.0 * BoundedHumRatio) / (0.240 + 0.444 * BoundedHumRatio)
    autre
      TDryBulb  = (Enthalpie de l'air humide / 1000.0 - 2501.0 * BoundedHumRatio) / (1.006 + 1.86 * BoundedHumRatio)
    fin si
  fonction de fin GetTDryBulbFromEnthalpyAndHumRatio

  fonction GetHumRatioFromEnthalpyAndTDryBulb(Enthalpie de l'air humide, TDryBulb) résultat(HumRatio)
    !+ Renvoie le rapport d'humidité à partir de l'enthalpie et de la température du bulbe sec.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 30
    !+ Remarques :
    !+ Basé sur la fonction `GetMoistAirEnthalpy`, réorganisé pour le taux d'humidité.

    réel, intention(dans)  ::  Enthalpie de l'air humide
      !+ Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹
    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel              ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]

    si (estIP()) ensuite
      HumRatio  = (Enthalpie de l'air humide - 0.240 * TDryBulb) / (1061.0 + 0.444 * TDryBulb)
    autre
      HumRatio  = (Enthalpie de l'air humide / 1000.0 - 1.006 * TDryBulb) / (2501.0 + 1.86 * TDryBulb)
    fin si

    ! Contrôle de validité.
    HumRatio = maximum(HumRatio, MIN_HUM_RATIO)
  fonction de fin GetHumRatioFromEnthalpyAndTDryBulb


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Calculs d'air saturé
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  fonction GetSatVapPres(TDryBulb) résultat(SatVapPres)
    !+ Pression de vapeur saturante de retour en fonction de la température du bulbe sec.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 5
    !+ Remarque importante : les formules ASHRAE sont définies au dessus et en dessous du point de congélation mais ont
    !+ une discontinuité au point de congélation. Il s'agit d'une petite inexactitude de la part d'ASHRAE : les formules
    !+ doit être défini au-dessus et en dessous du point triple de l'eau (et non du point de congélation), auquel cas 
    !+ la discontinuité disparaît. Il est indispensable d'utiliser le point triple d'eau sinon fonctionne
    !+ GetTDewPointFromVapPres, qui inverse la fonction actuelle, ne converge pas correctement autour
    !+ le point de congélation.

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel              ::  SatVapPres
      !+ Pression de vapeur de l'air saturé en Psi [IP] ou Pa [SI]
    réel              ::  LnPws
      !+ Log de pression de vapeur de l'air saturé (sans dimension)
    réel              ::  J
      !+ Température sèche en R [IP] ou K [SI]

    si (estIP()) ensuite
      si (TDryBulb < -148.0 .ou. TDryBulb > 392.0) ensuite
        erreur arrêt "Erreur : la température du bulbe sec doit être comprise dans la plage [-148, 392]°F"
      fin si

      J = ObtenirTRankineFromTFahrenheit(TDryBulb)

      si (TDryBulb <= TRIPLE_POINT_WATER_IP) ensuite
        LnPws = (-1.0214165E+04 / J - 4.8932428 - 5.3765794E-03 * J + 1.9202377E-07 * J**2    &
                + 3.5575832E-10 * J**3 - 9.0344688E-14 * J**4 + 4.1635019 * enregistrer(J))
      autre
        LnPws = -1.0440397E+04 / J - 1.1294650E+01 - 2.7022355E-02* J + 1.2890360E-05 * J**2  &
                - 2.4780681E-09 * J**3 + 6.5459673 * enregistrer(J)
      fin si

      autre
        si (TDryBulb < -100.0 .ou. TDryBulb > 200.0) ensuite
          erreur arrêt "Erreur : la température du bulbe sec doit être comprise dans la plage [-100, 200]°C"
        fin si

        J = ObtenirTKelvinFromTCelsius(TDryBulb)

        si (TDryBulb <= TRIPLE_POINT_WATER_SI) ensuite
          LnPws = -5.6745359E+03 / J + 6.3925247 - 9.677843E-03 * J + 6.2215701E-07 * J**2    &
                  + 2.0747825E-09 * J**3 - 9.484024E-13 * J**4 + 4.1635019 * enregistrer(J)
        autre
          LnPws = -5.8002206E+03 / J + 1.3914993 - 4.8640239E-02 * J + 4.1764768E-05 * J**2   &
                  - 1.4452093E-08 * J**3 + 6.5459673 * enregistrer(J)
        fin si
      fin si

    SatVapPres = exp(LnPws)
  fonction de fin GetSatVapPres

  fonction GetSatHumRatio(TDryBulb, Pression) résultat(SatHumRatio)
    !+ Taux d'humidité de retour de l'air saturé en fonction de la température et de la pression du bulbe sec.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 36, résolue pour W

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  SatHumRatio
      !+ Taux d'humidité de l'air saturé en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel              ::  SatVaporPres
      !+ Pression de vapeur de l'air saturé po en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]

    SatVaporPres  = GetSatVapPres(TDryBulb)
    SatHumRatio   = 0.621945 * SatVaporPres / (Pression-SatVaporPres)

    ! Contrôle de validité.
    SatHumRatio = maximum(SatHumRatio, MIN_HUM_RATIO)
  fonction de fin GetSatHumRatio

  fonction GetSatAirEnthalpy(TDryBulb, Pression) résultat(SatAirEnthalpie)
    !+ Renvoyez l'enthalpie de l'air saturé en fonction de la température et de la pression du bulbe sec.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  SatAirEnthalpie
      !+ Enthalpie de l'air saturé en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]

    SatAirEnthalpie = GetMoistAirEnthalpy(TDryBulb, GetSatHumRatio(TDryBulb, Pression))
  fonction de fin GetSatAirEnthalpy


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Calculs d'air humide
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  fonction GetVaporPressureDeficit(TDryBulb, HumRatio, Pression) résultat(Déficit de pression de vapeur)
    !+ Retour Déficit de pression de vapeur en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
    !+ Référence :
    !+ Oke (1987) eqn 2.13a

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  Déficit de pression de vapeur
      !+ Déficit de pression de vapeur en Psi [IP] ou Pa [SI]
    réel              ::  RelHum
      !+ Humidité relative dans la plage [0, 1]

    si (HumRatio < 0.0) ensuite
      erreur arrêt "Erreur : le taux d'humidité est négatif"
    fin si

    RelHum = GetRelHumFromHumRatio(TDryBulb, HumRatio, Pression)
    Déficit de pression de vapeur = GetSatVapPres(TDryBulb) * (1.0 - RelHum)
  fonction de fin GetVaporPressureDeficit

  fonction GetDegreeOfSaturation(TDryBulb, HumRatio, Pression) résultat(DegréDeSaturation)
    !+ Renvoie le degré de saturation (c'est à dire le rapport humidité de l'air / rapport humidité de l'air à saturation
    !+ à la même température et pression) étant donné la température du bulbe sec, le taux d'humidité et la pression atmosphérique.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2009) ch. 1 équation 12
    !+ Remarques :
    !+ Cette définition est absente du Manuel 2017. Utiliser plutôt la version 2009.

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  DegréDeSaturation
      !+ Degré de saturation en unité arbitraire
    réel              ::  BoundedHumRatio
      !+ Taux d'humidité borné à MIN_HUM_RATIO

    si (HumRatio < 0.0) ensuite
      erreur arrêt "Erreur : le taux d'humidité est négatif"
    fin si
    BoundedHumRatio = maximum(HumRatio, MIN_HUM_RATIO)

    DegréDeSaturation = BoundedHumRatio / GetSatHumRatio(TDryBulb, Pression)
  fonction de fin GetDegreeOfSaturation

  fonction GetMoistAirEnthalpy(TDryBulb, HumRatio) résultat(Enthalpie de l'air humide)
    !+ Renvoie l'enthalpie de l'air humide en fonction de la température du bulbe sec et du rapport d'humidité.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 30

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel              ::  Enthalpie de l'air humide
      !+ Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹
    réel              ::  BoundedHumRatio
      !+ Taux d'humidité borné à MIN_HUM_RATIO

    si (HumRatio < 0.0) ensuite
      erreur arrêt "Erreur : le taux d'humidité est négatif"
    fin si
    BoundedHumRatio = maximum(HumRatio, MIN_HUM_RATIO)

    si (estIP()) ensuite
        Enthalpie de l'air humide = 0.240 * TDryBulb + BoundedHumRatio * (1061.0 + 0.444 * TDryBulb)
    autre
        Enthalpie de l'air humide = (1.006 * TDryBulb + BoundedHumRatio * (2501.0 + 1.86 * TDryBulb)) * 1000.0
    fin si
  fonction de fin GetMoistAirEnthalpy

  fonction GetMoistAirVolume(TDryBulb, HumRatio, Pression) résultat(Volume d'air humide)
    !+ Restituez le volume spécifique d'air humide en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 26
    !+ Remarques :
    !+ En unités IP, R_DA_IP / 144 est égal à 0,370486 qui est le coefficient apparaissant dans l'équation 26
    !+ Le facteur 144 est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  Volume d'air humide
      !+ Volume spécifique d'air humide en ft³ lb⁻¹ d'air sec [IP] ou en m³ kg⁻¹ d'air sec [SI]
    réel              ::  BoundedHumRatio
      !+ Taux d'humidité borné à MIN_HUM_RATIO

    si (HumRatio < 0.0) ensuite
      erreur arrêt "Erreur : le taux d'humidité est négatif"
    fin si
    BoundedHumRatio = maximum(HumRatio, MIN_HUM_RATIO)

    si (estIP()) ensuite
        Volume d'air humide = R_DA_IP * ObtenirTRankineFromTFahrenheit(TDryBulb) * (1.0 + 1.607858 * BoundedHumRatio) / (144.0 * Pression)
    autre
        Volume d'air humide = R_DA_SI * ObtenirTKelvinFromTCelsius(TDryBulb) * (1.0 + 1.607858 * BoundedHumRatio) / Pression
    fin si
  fonction de fin GetMoistAirVolume

  fonction GetTDryBulbFromMoistAirVolumeAndHumRatio(Volume d'air humide, HumRatio, Pression) résultat(TDryBulb)
    !+ Renvoie la température du bulbe sec en fonction du volume spécifique de l'air humide, du taux d'humidité et de la pression.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 26
    !+ Remarques :
    !+ En unités IP, R_DA_IP / 144 est égal à 0,370486 qui est le coefficient apparaissant dans l'équation 26
    !+ Le facteur 144 est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².
    !+ Basé sur la fonction `GetMoistAirVolume`, réorganisé pour la température du bulbe sec.

    réel, intention(dans)  ::  Volume d'air humide
      !+ Volume spécifique d'air humide en ft³ lb⁻¹ d'air sec [IP] ou en m³ kg⁻¹ d'air sec [SI]
    réel, intention(dans)  ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel              ::  BoundedHumRatio
      !+ Taux d'humidité borné à MIN_HUM_RATIO

    si (HumRatio < 0.0) ensuite
      erreur arrêt "Erreur : le taux d'humidité est négatif"
    fin si
    BoundedHumRatio = maximum(HumRatio, MIN_HUM_RATIO)

    si (estIP()) ensuite
      TDryBulb = ObtenirTFahrenheitDeTRankine(Volume d'air humide * (144 * Pression) &
                                / (R_DA_IP * (1 + 1.607858 * BoundedHumRatio)))
    autre
      TDryBulb = ObtenirTCelsiusFromTKelvin(Volume d'air humide * Pression &
                                / (R_DA_SI * (1 + 1.607858 * BoundedHumRatio)))
    fin si
  fonction de fin GetTDryBulbFromMoistAirVolumeAndHumRatio

  fonction GetMoistAirDensity(TDryBulb, HumRatio, Pression) résultat(Densité de l'air humide)
    !+ Renvoyez la densité de l'air humide en fonction du taux d'humidité, de la température du bulbe sec et de la pression.
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 11

    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)  ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel, intention(dans)  ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel              ::  Densité de l'air humide
      !+ Densité de l'air humide en lb ft⁻³ [IP] ou kg m⁻³ [SI]
    réel              ::  BoundedHumRatio
      !+ Taux d'humidité borné à MIN_HUM_RATIO

    si (HumRatio < 0.0) ensuite
      erreur arrêt "Erreur : le taux d'humidité est négatif"
    fin si
    BoundedHumRatio = maximum(HumRatio, MIN_HUM_RATIO)

    Densité de l'air humide = (1.0 + BoundedHumRatio) / GetMoistAirVolume(TDryBulb, BoundedHumRatio, Pression)
  fonction de fin GetMoistAirDensity


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Atmosphère normale
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  fonction GetStandardAtmPressure(Altitude) résultat(Pression atmosphérique standard)
    !+ Renvoie la pression barométrique de l'atmosphère standard, compte tenu de l'élévation (altitude).
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 3

    réel, intention(dans)  ::  Altitude
      !+ Altitude en ft [IP] ou m [SI]
    réel              ::  Pression atmosphérique standard
      !+ Pression barométrique de l'atmosphère standard en Psi [IP] ou Pa [SI]

    si (estIP()) ensuite
        Pression atmosphérique standard = 14.696 * (1.0 - 6.8754e-06 * Altitude)**5.2559
    autre
        Pression atmosphérique standard = 101325 * (1 - 2.25577e-05 * Altitude)**5.2559
    fin si
  fonction de fin GetStandardAtmPressure

  fonction GetStandardAtmTemperature(Altitude) résultat(Température atmosphérique standard)
    !+ Renvoie la température atmosphérique standard, compte tenu de l'élévation (altitude).
    !+ Référence :
    !+ Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 4

    réel, intention(dans)  ::  Altitude
      !+ Altitude en ft [IP] ou m [SI]
    réel              ::  Température atmosphérique standard
      !+ Température du bulbe sec de l'atmosphère standard en °F [IP] ou °C [SI]

    si (estIP()) ensuite
        Température atmosphérique standard = 59.0 - 0.00356620 * Altitude
    autre
        Température atmosphérique standard = 15.0 - 0.0065 * Altitude
    fin si
  fonction de fin GetStandardAtmTemperature

  fonction GetSeaLevelPressure(StnPression, Altitude, TDryBulb) résultat(PressionNiveau De La Mer)
    !+ Pression de retour au niveau de la mer en fonction de la température du bulbe sec, de l'altitude au-dessus du niveau de la mer et de la pression.
    !+ Référence :
    !+ Hess SL, Introduction à la météorologie théorique, Holt Rinehart et Winston, NY 1959,
    !+ ch. 6,5 ; Stull RB, Météorologie pour les scientifiques et les ingénieurs, 2e édition,
    !+ Brooks/Cole 2000, chap. 1.
    !+ Remarques :
    !+ La procédure standard pour les États-Unis consiste à utiliser pour TDryBulb la moyenne
    !+ de la température actuelle de la station et de la température de la station d'il y a 12 heures.

    réel, intention(dans)  ::  StnPression
      !+ Pression de station observée en Psi [IP] ou Pa [SI]
    réel, intention(dans)  ::  Altitude
      !+ Altitude en ft [IP] ou m [SI]
    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel              ::  PressionNiveau De La Mer
      !+ Pression barométrique au niveau de la mer en Psi [IP] ou Pa [SI]
    réel              ::  TColonne
      !+ Température moyenne dans la colonne d'air en R [IP] ou K [SI]
    réel              ::  H
      !+ hauteur de l'échelle (sans dimension)

    si (estIP()) ensuite
      ! Calculer la température moyenne dans la colonne d'air, en supposant un taux de déchéance
      ! de 3,6 °F/1000 pieds
      TColonne = TDryBulb + 0.0036 * Altitude / 2.0

      ! Déterminer la hauteur de l'échelle
      H = 53.351 * ObtenirTRankineFromTFahrenheit(TColonne)
    autre
      ! Calculer la température moyenne dans la colonne d'air, en supposant un taux de déchéance
      ! de 6,5 °C/km
      TColonne = TDryBulb + 0.0065 * Altitude / 2.0

      ! Déterminer la hauteur de l'échelle
      H = 287.055 * ObtenirTKelvinFromTCelsius(TColonne) / 9.807
    fin si

    ! Calculer la pression au niveau de la mer
    PressionNiveau De La Mer = StnPression * exp(Altitude / H)
  fonction de fin GetSeaLevelPressure

  fonction GetStationPressure(PressionNiveau De La Mer, Altitude, TDryBulb) résultat(StationPression)
    !+ Pression de retour de la station à partir de la pression au niveau de la mer.
    !+ Référence :
    !+ Voir 'GetSeaLevelPressure'
    !+ Remarques :
    !+ Cette fonction est juste l'inverse de 'GetSeaLevelPressure'.

    réel, intention(dans)  ::  PressionNiveau De La Mer
      !+ Pression barométrique au niveau de la mer en Psi [IP] ou Pa [SI]
    réel, intention(dans)  ::  Altitude
      !+ Altitude en ft [IP] ou m [SI]
    réel, intention(dans)  ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel              ::  StationPression
      !+ Pression de la station en Psi [IP] ou Pa [SI]

    StationPression = PressionNiveau De La Mer / GetSeaLevelPressure(1.0, Altitude, TDryBulb)
  fonction de fin GetStationPressure


  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
  ! Fonctions pour définir toutes les valeurs psychrométriques
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!

  sous-programme CalcPsychrometricsFromTWetBulb(TDryBulb,           &
                                            TWetBulbComment,           &
                                            Pression,           &
                                            HumRatio,           &
                                            TDewPoint,          &
                                            RelHum,             &
                                            VapPres,            &
                                            Enthalpie de l'air humide,   &
                                            Volume d'air humide,     &
                                            DegréDeSaturation)

    !+ Fonction utilitaire pour calculer le taux d'humidité, la température du point de rosée, l'humidité relative,
    !+ Pression de vapeur, enthalpie de l'air humide, volume d'air humide et degré de saturation de l'air donnés
    !+ Température du bulbe sec, température du bulbe humide et pression.

    réel, intention(dans)    ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)    ::  TWetBulbComment
      !+ Température du thermomètre mouillé en °F [IP] ou °C [SI]
    réel, intention(dans)    ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel, intention(dehors)   ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel, intention(dehors)   ::  TDewPoint
      !+ Température du point de rosée en °F [IP] ou °C [SI]
    réel, intention(dehors)   ::  RelHum
      !+ Humidité relative dans la plage [0, 1]
    réel, intention(dehors)   ::  VapPres
      !+ Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
    réel, intention(dehors)   ::  Enthalpie de l'air humide
      !+ Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
    réel, intention(dehors)   ::  Volume d'air humide
      !+ Volume spécifique d'air humide en ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
    réel, intention(dehors)   ::  DegréDeSaturation
      !+ Degré de saturation [sans unité]

    HumRatio            = GetHumRatioFromTWetBulb(TDryBulb, TWetBulbComment, Pression)
    TDewPoint           = GetTDewPointFromHumRatio(TDryBulb, HumRatio, Pression)
    RelHum              = GetRelHumFromHumRatio(TDryBulb, HumRatio, Pression)
    VapPres             = GetVapPresFromHumRatio(HumRatio, Pression)
    Enthalpie de l'air humide    = GetMoistAirEnthalpy(TDryBulb, HumRatio)
    Volume d'air humide      = GetMoistAirVolume(TDryBulb, HumRatio, Pression)
    DegréDeSaturation  = GetDegreeOfSaturation(TDryBulb, HumRatio, Pression)
  sous-programme de fin CalcPsychrometricsFromTWetBulb

  sous-programme CalcPsychrometricsFromTDewPoint(TDryBulb,           &
                                             TDewPoint,          &
                                             Pression,           &
                                             HumRatio,           &
                                             TWetBulbComment,           &
                                             RelHum,             &
                                             VapPres,            &
                                             Enthalpie de l'air humide,   &
                                             Volume d'air humide,     &
                                             DegréDeSaturation)

    !+ Fonction utilitaire pour calculer le taux d'humidité, la température du bulbe humide, l'humidité relative,
    !+ Pression de vapeur, enthalpie de l'air humide, volume d'air humide et degré de saturation de l'air donnés
    !+ Température du bulbe sec, température du point de rosée et pression.

    réel, intention(dans)    ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)    ::  TDewPoint
      !+ Température du point de rosée en °F [IP] ou °C [SI]
    réel, intention(dans)    ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel, intention(dehors)   ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel, intention(dehors)   ::  TWetBulbComment
      !+ Température du thermomètre mouillé en °F [IP] ou °C [SI]
    réel, intention(dehors)   ::  RelHum
      !+ Humidité relative dans la plage [0, 1]
    réel, intention(dehors)   ::  VapPres
      !+ Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
    réel, intention(dehors)   ::  Enthalpie de l'air humide
      !+ Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
    réel, intention(dehors)   ::  Volume d'air humide
      !+ Volume spécifique d'air humide en ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
    réel, intention(dehors)   ::  DegréDeSaturation
      !+ Degré de saturation [sans unité]

    HumRatio            = GetHumRatioFromTDewPoint(TDewPoint, Pression)
    TWetBulbComment            = GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pression)
    RelHum              = GetRelHumFromHumRatio(TDryBulb, HumRatio, Pression)
    VapPres             = GetVapPresFromHumRatio(HumRatio, Pression)
    Enthalpie de l'air humide    = GetMoistAirEnthalpy(TDryBulb, HumRatio)
    Volume d'air humide      = GetMoistAirVolume(TDryBulb, HumRatio, Pression)
    DegréDeSaturation  = GetDegreeOfSaturation(TDryBulb, HumRatio, Pression)
  sous-programme de fin CalcPsychrometricsFromTDewPoint

  sous-programme CalcPsychrometricsFromRelHum(TDryBulb,           &
                                          RelHum,             &
                                          Pression,           &
                                          HumRatio,           &
                                          TWetBulbComment,           &
                                          TDewPoint,          &
                                          VapPres,            &
                                          Enthalpie de l'air humide,   &
                                          Volume d'air humide,     &
                                          DegréDeSaturation)

    !+ Fonction utilitaire pour calculer le taux d'humidité, la température du bulbe humide, la température du point de rosée,
    !+ Pression de vapeur, enthalpie de l'air humide, volume d'air humide et degré de saturation de l'air donnés
    !+ Température sèche, humidité relative et pression.

    réel, intention(dans)    ::  TDryBulb
      !+ Température du bulbe sec en °F [IP] ou °C [SI]
    réel, intention(dans)    ::  RelHum
      !+ Humidité relative dans la plage [0, 1]
    réel, intention(dans)    ::  Pression
      !+ Pression atmosphérique en Psi [IP] ou Pa [SI]
    réel, intention(dehors)   ::  HumRatio
      !+ Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    réel, intention(dehors)   ::  TWetBulbComment
      !+ Température du thermomètre mouillé en °F [IP] ou °C [SI]
    réel, intention(dehors)   ::  TDewPoint
      !+ Température du point de rosée en °F [IP] ou °C [SI]
    réel, intention(dehors)   ::  VapPres
      !+ Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
    réel, intention(dehors)   ::  Enthalpie de l'air humide
      !+ Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
    réel, intention(dehors)   ::  Volume d'air humide
      !+ Volume spécifique d'air humide en ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
    réel, intention(dehors)   ::  DegréDeSaturation
      !+ Degré de saturation [sans unité]

    HumRatio            = GetHumRatioFromRelHum(TDryBulb, RelHum, Pression)
    TWetBulbComment            = GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pression)
    TDewPoint           = GetTDewPointFromHumRatio(TDryBulb, HumRatio, Pression)
    VapPres             = GetVapPresFromHumRatio(HumRatio, Pression)
    Enthalpie de l'air humide    = GetMoistAirEnthalpy(TDryBulb, HumRatio)
    Volume d'air humide      = GetMoistAirVolume(TDryBulb, HumRatio, Pression)
    DegréDeSaturation  = GetDegreeOfSaturation(TDryBulb, HumRatio, Pression)
  sous-programme de fin CalcPsychrometricsFromRelHum


module de fin psychrolib

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 (version 2.3.0) (https://github.com/psychrometrics/psychrolib)
' Copyright (c) 2018 D. Thevenard et D. Meyer pour l'implémentation actuelle de la bibliothèque
' Copyright (c) 2017 Manuel ASHRAE — Principes fondamentaux des équations et coefficients ASHRAE
' Sous licence MIT.
'
' psychrolib.vba
'
' Contient des fonctions pour calculer les propriétés thermodynamiques des mélanges gaz-vapeur
' et atmosphère standard adaptée à la plupart des applications techniques, physiques et météorologiques
' applications.
'
' La plupart des fonctions sont une implémentation des formules trouvées dans le
' Manuel ASHRAE 2017 - Fondamentaux, dans les deux systèmes internationaux (SI),
' et unités impériales (IP). Veuillez vous référer aux informations incluses dans
'chaque fonction pour leur référence respective.
'
' Exemple
' ' Définissez le système d'unités, par exemple sur SI (peut être ' SI' ou ' IP' )
' ' en décommentant la ligne suivante dans le module psychrolib
' Const PSYCHROLIB_UNITS = UnitSystem.SI
'
' ' Calculer la température du point de rosée pour une température sèche de 25 C et une humidité relative de 80 %
' TDewPoint = GetTDewPointFromRelHum (25,0, 0,80)
' Debug.Print(TDewPoint)
' 21.309397163661785
'
' Droits d'auteur
' - Pour l'implémentation actuelle de la bibliothèque
' Copyright (c) 2018 D. Thévenard et D. Meyer.
' - Pour les équations et les coefficients publiés ASHRAE Handbook — Fundamentals, Chapitre 1
' Copyright (c) Manuel ASHRAE 2017 — Fondamentaux (https://www.ashrae.org)
'
' Licence
' MIT (https://github.com/psychrometrics/psychrolib/LICENSE.txt)
'
' Note des auteurs
" Nous avons fait tous les efforts possibles pour garantir que le code soit adéquat, mais nous ne faisons aucun
' représentation en ce qui concerne son exactitude. À utiliser à vos risques et périls. Si vous remarquez
' une erreur, ou si vous avez une suggestion, veuillez nous en informer via GitHub à l'adresse
' https://github.com/psychrometrics/psychrolib/issues.
'

Option Explicite


'*************************************************** ************************************************** ***
' IMPORTANT : Décommentez manuellement le système d'unités à utiliser
'*************************************************** ************************************************** ***

'Énumération pour définir des systèmes d'unités
Énumération Système d'unité
  IP = 1
  SI = 2
Fin Énumération

' Décommentez l'une de ces deux lignes pour définir le système d'unités ("IP" ou "SI")
'Const PSYCHROLIB_UNITS = UnitSystem.IP
'Const PSYCHROLIB_UNITS = UnitSystem.SI


'*************************************************** ************************************************** ***
' Constantes globales
'*************************************************** ************************************************** ***

Privé Const. ZERO_FAHRENHEIT_AS_RANKINE = 459.67   ' Zéro degré Fahrenheit (°F) exprimé en degré Rankine (°R).
                                                    'Référence : Manuel ASHRAE - Fondamentaux (2017) ch. 39.

Privé Const. ZERO_CELSIUS_AS_KELVIN = 273.15       ' Zéro degré Celsius (°C) exprimé en Kelvin (K).
                                                    ' Référence : Manuel ASHRAE - Fondamentaux (2017) ch. 39.

Privé Const. R_DA_IP = 53.35                 ' Constante de gaz universelle pour air sec (version IP) en ft lbf/lb_DryAir/R.

Privé Const. R_DA_SI = 287.042               ' Constante de gaz universelle pour air sec (version SI) en J/kg_DryAir/K.

Privé Const. MAX_ITER_COUNT = 100            ' Nombre maximum d'itérations avant de quitter les boucles while.

Privé Const. MIN_HUM_RATIO = 1e-7            ' Rapport d'humidité minimum acceptable utilisé/restitué par toutes les fonctions.
                                              'Toute valeur supérieure à 0 ou inférieure au MIN_HUM_RATIO sera réinitialisée à cette valeur.

Privé Const. FREEZING_POINT_WATER_IP = 32.0  ' Point de congélation de l'eau, en °F

Privé Const. FREEZING_POINT_WATER_SI = 0.0   ' Point de congélation de l'eau, en °C

Privé Const. TRIPLE_POINT_WATER_IP = 32.018  ' Point triple de l'eau, en °F

Privé Const. TRIPLE_POINT_WATER_SI = 0.01    ' Point triple de l'eau, en °C

'*************************************************** ************************************************** ***
' Fonctions d'assistance
'*************************************************** ************************************************** ***

Une fonction ObtenirUnitSystem() Comme Système d'unité
'
' Cette fonction renvoie le système d'unités actuellement utilisé (SI ou IP).
'
' Arguments :
' aucun
'
' Retour:
' Le système d'unités actuellement utilisé (« SI » ou « IP »)
'
' Note:
'
' Si vous obtenez une erreur ici, c'est que vous n'avez pas décommenté l'une des deux lignes
' définissant PSYCHROLIB_UNITS (voir la section Constantes globales)
'
    ObtenirUnitSystem = PSYCHROLIB_UNITS

Fin Une fonction

Privé Une fonction estIP() Comme Une variante
'
' Cette fonction vérifie si le système d'unités actuellement utilisé est IP ou SI.
'
' Arguments :
' aucun
'
' Retour:
' Vrai si IP, Faux si SI et génère une erreur si non défini
'
  Si (PSYCHROLIB_UNITS = UnitSystem.IP) Alors
    estIP = Vrai
  SinonSi (PSYCHROLIB_UNITS = UnitSystem.SI) Alors
    estIP = Faux
  Autre
    MsgBox ("Le système d'unités n'a pas été défini.")
    estIP = CVErr(xlErrNA)
  Fin Si

Fin Une fonction

Privé Une fonction GetTol() Comme Une variante
'
' Cette fonction renvoie la tolérance sur les températures utilisées pour la résolution itérative.
' La valeur est physiquement la même en IP ou SI.
'
' Arguments :
' aucun
'
' Retour:
' Tolérance sur les températures
'
  Si (PSYCHROLIB_UNITS = UnitSystem.IP) Alors
    GetTol = 0.001 * 9 / 5
  Autre
    GetTol = 0.001
  Fin Si
Fin Une fonction

Privé Sous MaBoîteMsg(ParVal ErrMsg Comme Chaîne)
'
' Affichage du message d'erreur
' Remplacez cette fonction par la vôtre si nécessaire, ou commentez son code si vous ne souhaitez pas voir les messages.
'
'Message désactivé par défaut
' MsgBox (ErrMsg)

Fin Sous

Privé Une fonction Min(ParVal Num1 Comme Une variante, ParVal Num2 Comme Une variante) Comme Une variante
'
'Fonction Min pour renvoyer au moins deux nombres
'
  Si (Num1 <= Num2) Alors
    Min = Num1
  Autre
    Min = Num2
  Fin Si

Fin Une fonction

Privé Une fonction Max(ParVal Num1 Comme Une variante, ParVal Num2 Comme Une variante) Comme Une variante
'
' Fonction Max pour renvoyer un maximum de deux nombres
'
  Si (Num1 >= Num2) Alors
    Max = Num1
  Autre
    Max = Num2
  Fin Si

Fin Une fonction


'************************************************ ****************************
' Conversions entre unités de température
'************************************************ ****************************

Une fonction ObtenirTRankineFromTFahrenheit(ParVal T_Fahrenheit Comme Une variante) Comme Une variante
'
' Fonction utilitaire pour convertir la température en degré Rankine (°R)
' température donnée en degrés Fahrenheit (°F).
'
'Args :
' T_Fahrenheit : Température en degrés Fahrenheit (°F)
'
'Retour:
' Température en degré Rankine (°R)
'
'Référence:
' Référence : Manuel ASHRAE - Fondamentaux (2017) ch. 1 chapitre 3
'
'Remarques:
' Conversion exacte.
'
  Sur Erreur Aller à ErrHandler

  ObtenirTRankineFromTFahrenheit = (T_Fahrenheit + ZERO_FAHRENHEIT_AS_RANKINE)
  Sortie Une fonction

ErrHandler:
  ObtenirTRankineFromTFahrenheit = CVErr(xlErrNA)

Fin Une fonction

Une fonction ObtenirTFahrenheitDeTRankine(ParVal T_Rankine Comme Une variante) Comme Une variante
'
' Fonction utilitaire pour convertir la température en degrés Fahrenheit (°F)
' température donnée en degré Rankine (°R).
'
'Args :
' TRankine : Température en degré Rankine (°R)
'
'Retour:
' Température en degrés Fahrenheit (°F)
'
'Référence:
' Référence : Manuel ASHRAE - Fondamentaux (2017) ch. 1 chapitre 3
'
'Remarques:
' Conversion exacte.
'
  Sur Erreur Aller à ErrHandler

  ObtenirTFahrenheitDeTRankine = (T_Rankine - ZERO_FAHRENHEIT_AS_RANKINE)
  Sortie Une fonction

ErrHandler:
  ObtenirTFahrenheitDeTRankine = CVErr(xlErrNA)

Fin Une fonction

Une fonction ObtenirTKelvinFromTCelsius(ParVal T_Celsius Comme Une variante) Comme Une variante
'
' Fonction utilitaire pour convertir la température en Kelvin (K)
' température donnée en degrés Celsius (°C).
'
'Args :
' TCelsius : Température en degrés Celsius (°C)
'
'Retour:
' Température en Kelvin (K)
'
'Référence:
' Référence : Manuel ASHRAE - Fondamentaux (2017) ch. 1 chapitre 3
'
'Remarques:
' Conversion exacte.
'
  Sur Erreur Aller à ErrHandler

  ObtenirTKelvinFromTCelsius = (T_Celsius + ZERO_CELSIUS_AS_KELVIN)
  Sortie Une fonction

ErrHandler:
  ObtenirTKelvinFromTCelsius = CVErr(xlErrNA)

Fin Une fonction

Une fonction ObtenirTCelsiusFromTKelvin(ParVal T_Kelvin Comme Une variante) Comme Une variante
'
' Fonction utilitaire pour convertir la température en degrés Celsius (°C)
' température donnée en Kelvin (K).
'
'Args :
' TKelvin : Température en Kelvin (K)
'
'Retour:
' Température en degrés Celsius (°C)
'
'Référence:
' Référence : Manuel ASHRAE - Fondamentaux (2017) ch. 1 chapitre 3
'
'Remarques:
' Conversion exacte.
'
  Sur Erreur Aller à ErrHandler

  ObtenirTCelsiusFromTKelvin = (T_Kelvin - ZERO_CELSIUS_AS_KELVIN)
  Sortie Une fonction

ErrHandler:
  ObtenirTCelsiusFromTKelvin = CVErr(xlErrNA)

Fin Une fonction


'*************************************************** ************************************************** ***
' Conversions entre le point de rosée, le bulbe humide et l'humidité relative
'*************************************************** ************************************************** ***

Une fonction GetTWetBulbFromTDewPoint(ParVal TDryBulb Comme Une variante, ParVal TDewPoint Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Renvoie la température du bulbe humide en fonction de la température du bulbe sec, de la température du point de rosée et de la pression.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' TDewPoint : Température du point de rosée en °F [IP] ou °C [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Température du thermomètre mouillé en °F [IP] ou °C [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1
'
  Faible HumRatio Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si TDewPoint > TDryBulb Alors
    MaBoîteMsg ("La température du point de rosée est supérieure à la température du bulbe sec")
    Aller à ErrHandler
  Fin Si

  HumRatio = GetHumRatioFromTDewPoint(TDewPoint, Pression)
  GetTWetBulbFromTDewPoint = GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pression)
  Sortie Une fonction

ErrHandler:
  GetTWetBulbFromTDewPoint = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetTWetBulbFromRelHum(ParVal TDryBulb Comme Une variante, ParVal RelHum Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Renvoie la température du bulbe humide en fonction de la température du bulbe sec, de l'humidité relative et de la pression.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' RelHum : Humidité relative dans la plage [0, 1]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Température du thermomètre mouillé en °F [IP] ou °C [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1
'
  Faible HumRatio Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si (RelHum < 0 Ou alors RelHum > 1) Alors
    MaBoîteMsg ("L'humidité relative est en dehors de la plage [0,1]")
    Aller à ErrHandler
  Fin Si

  HumRatio = GetHumRatioFromRelHum(TDryBulb, RelHum, Pression)
  GetTWetBulbFromRelHum = GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pression)
  Sortie Une fonction

ErrHandler:
  GetTWetBulbFromRelHum = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetRelHumFromTDewPoint(ParVal TDryBulb Comme Une variante, ParVal TDewPoint Comme Une variante) Comme Une variante
'
' Renvoie l'humidité relative en fonction de la température du bulbe sec et de la température du point de rosée.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' TDewPoint : Température du point de rosée en °F [IP] ou °C [SI]
'
' Retour:
' Humidité relative dans la plage [0, 1]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 22
'
  Faible VapPres Comme Une variante
  Faible SatVapPres Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si (TDewPoint > TDryBulb) Alors
    MaBoîteMsg ("La température du point de rosée est supérieure à la température du bulbe sec")
    Aller à ErrHandler
  Fin Si

  VapPres = ObtenirSatVapPres(TDewPoint)
  SatVapPres = ObtenirSatVapPres(TDryBulb)
  GetRelHumFromTDewPoint = VapPres / SatVapPres
  Sortie Une fonction

ErrHandler:
  GetRelHumFromTDewPoint = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetRelHumFromTWetBulb(ParVal TDryBulb Comme Une variante, ParVal TWetBulbComment Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Renvoie l'humidité relative en fonction de la température du bulbe sec, de la température du bulbe humide et de la pression.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' TWetBulb : Température du bulbe humide en °F [IP] ou °C [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Humidité relative dans la plage [0, 1]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1
'
  Faible HumRatio Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si TWetBulbComment > TDryBulb Alors
    MaBoîteMsg ("La température du bulbe humide est supérieure à la température du bulbe sec")
    Aller à ErrHandler
  Fin Si

  HumRatio = GetHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pression)
  GetRelHumFromTWetBulb = GetRelHumFromHumRatio(TDryBulb, HumRatio, Pression)
  Sortie Une fonction

ErrHandler:
  GetRelHumFromTWetBulb = CVErr(xlErrNA)

Fin Une fonction

Une fonction ObtenirTDewPointFromRelHum(ParVal TDryBulb Comme Une variante, ParVal RelHum Comme Une variante) Comme Une variante
'
' Température de retour du point de rosée en fonction de la température du bulbe sec et de l'humidité relative.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' RelHum : humidité relative dans la plage [0, 1]
'
' Retour:
' Température du point de rosée en °F [IP] ou °C [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1
'

  Faible VapPres Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si RelHum < 0 Ou alors RelHum > 1 Alors
    MaBoîteMsg ("L'humidité relative est en dehors de la plage [0, 1]")
    Aller à ErrHandler
  Fin Si

  VapPres = GetVapPresFromRelHum(TDryBulb, RelHum)
  ObtenirTDewPointFromRelHum = GetTDewPointFromVapPres(TDryBulb, VapPres)
  Sortie Une fonction

ErrHandler:
  ObtenirTDewPointFromRelHum = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetTDewPointFromTWetBulb(ParVal TDryBulb Comme Une variante, ParVal TWetBulbComment Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Température de retour du point de rosée en fonction de la température du bulbe sec, de la température du bulbe humide et de la pression.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' TWetBulb : Température du bulbe humide en °F [IP] ou °C [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Température du point de rosée en °F [IP] ou °C [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1
'
  Faible HumRatio Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si TWetBulbComment > TDryBulb Alors
    MaBoîteMsg ("La température du bulbe humide est supérieure à la température du bulbe sec")
    Aller à ErrHandler
  Fin Si

  HumRatio = GetHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pression)
  GetTDewPointFromTWetBulb = GetTDewPointFromHumRatio(TDryBulb, HumRatio, Pression)
  Sortie Une fonction

ErrHandler:
  GetTDewPointFromTWetBulb = CVErr(xlErrNA)

Fin Une fonction


'*************************************************** ************************************************** ***
' Conversions entre le point de rosée ou l'humidité relative et la pression de vapeur
'*************************************************** ************************************************** ***

Une fonction GetVapPresFromRelHum(ParVal TDryBulb Comme Une variante, ParVal RelHum Comme Une variante) Comme Une variante
'
' Renvoie la pression partielle de la vapeur d'eau en fonction de l'humidité relative et de la température.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' RelHum : Humidité relative dans la plage [0, 1]
'
' Retour:
' Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 12, 22
'
  Sur Erreur Aller à ErrHandler

  Si RelHum < 0 Ou alors RelHum > 1 Alors
    MaBoîteMsg ("L'humidité relative est en dehors de la plage [0, 1]")
    Aller à ErrHandler
  Fin Si

  GetVapPresFromRelHum = RelHum * ObtenirSatVapPres(TDryBulb)
  Sortie Une fonction

ErrHandler:
  GetVapPresFromRelHum = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetRelHumFromVapPres(ParVal TDryBulb Comme Une variante, ParVal VapPres Comme Une variante) Comme Une variante
' Renvoie l'humidité relative en fonction de la température du bulbe sec et de la pression de vapeur.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' VapPres : Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
'
' Retour:
' Humidité relative dans la plage [0, 1]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 12, 22
'
  Sur Erreur Aller à ErrHandler

  Si (VapPres < 0) Alors
    MaBoîteMsg ("La pression partielle de la vapeur d'eau dans l'air humide est négative")
    Aller à ErrHandler
  Fin Si

  GetRelHumFromVapPres = VapPres / ObtenirSatVapPres(TDryBulb)
  Sortie Une fonction

ErrHandler:
  GetRelHumFromVapPres = CVErr(xlErrNA)

Fin Une fonction


Privé Une fonction dLnPws_(TDDryBulb Comme Une variante) Comme Une variante
'
' Fonction d'assistance renvoyant la dérivée du logarithme népérien de la pression de vapeur saturante
' en fonction de la température du bulbe sec.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
'
' Retour:
' Dérivée du logarithme naturel de la pression de vapeur de l'air saturé en Psi [IP] ou Pa [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équations 5 et 6
'
  Faible J Comme Une variante
  Si (estIP()) Alors
    J = ObtenirTRankineFromTFahrenheit(TDryBulb)
    Si (TDDryBulb <= TRIPLE_POINT_WATER_IP) Alors
      dLnPws_ = 10214.165 / J ^ 2 - 0.0053765794 + 2 * 0.00000019202377 * J _
             + 3 * 3.5575832E-10 * J ^ 2 - 4 * 9.0344688E-14 * J ^ 3 + 4.1635019 / J
    Autre
      dLnPws_ = 10440.397 / J ^ 2 - 0.027022355 + 2 * 0.00001289036 * J _
             - 3 * 2.4780681E-09 * J ^ 2 + 6.5459673 / J
    Fin Si
  Autre
    J = ObtenirTKelvinFromTCelsius(TDryBulb)
    Si (TDDryBulb <= TRIPLE_POINT_WATER_SI) Alors
      dLnPws_ = 5674.5359 / J ^ 2 - 0.009677843 + 2 * 0.00000062215701 * J _
             + 3 * 2.0747825E-09 * J ^ 2 - 4 * 9.484024E-13 * J ^ 3 + 4.1635019 / J
    Autre
      dLnPws_ = 5800.2206 / J ^ 2 - 0.048640239 + 2 * 0.000041764768 * J _
             - 3 * 0.000000014452093 * J ^ 2 + 6.5459673 / J
    Fin Si
  Fin Si
Fin Une fonction

Une fonction GetTDewPointFromVapPres(ParVal TDryBulb Comme Une variante, ParVal VapPres Comme Une variante) Comme Une variante
'
' Température du point de rosée de retour compte tenu de la température du bulbe sec et de la pression de vapeur.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' VapPres : Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
'
' Retour:
' Température du point de rosée en °F [IP] ou °C [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 éq. 5 et 6
'
' Remarques:
' La température du point de rosée est résolue en inversant l'équation donnant la pression de vapeur d'eau
' à saturation à partir de la température plutôt que d'utiliser les régressions fournies
' par ASHRAE (équations 37 et 38) qui sont beaucoup moins précises et ont un
' plage de validité plus étroite.
' La méthode Newton-Raphson (NR) est utilisée sur le logarithme de la vapeur d'eau
' pression en fonction de la température, ce qui est une fonction très douce
« La convergence est généralement obtenue en 3 à 5 itérations.
' TDryBulb n'est pas vraiment nécessaire ici, juste utilisé pour plus de commodité.
'
  Faible BORNES(2) Comme Une variante
  Faible PSYCHROLIB_TOLERANCE Comme Une variante

  Si (estIP()) Alors
    BORNES(1) = -148.
    BORNES(2) = 392.
  Autre
    BORNES(1) = -100.
    BORNES(2) = 200.
  Fin Si

  Sur Erreur Aller à ErrHandler

  Si ((VapPres < GetSatVapPres(LIMITES(1))) Ou alors (VapPres > GetSatVapPres(LIMITES(2)))) Alors
    MaBoîteMsg ("La pression partielle de la vapeur d'eau se situe en dehors du domaine de validité des équations")
    Aller à ErrHandler
  Fin Si

  PSYCHROLIB_TOLERANCE = GetTol()

  Faible TDewPoint Comme Une variante
  Faible lnVP Comme Une variante
  Faible d_lnVP Comme Une variante
  Faible TDewPoint_iter Comme Une variante
  Faible lnVP_iter
  Faible indice Comme Une variante
  indice = 1

  ' Nous utilisons NR pour approximer la solution.
  ' Première supposition
  TDewPoint = TDryBulb        ' Valeur calculée des températures du point de rosée, résolue de manière itérative
  lnVP = Journal(VapPres)         ' Pression partielle de vapeur d'eau dans l'air humide

  ' Itération
  Fais
    TDewPoint_iter = TDewPoint   ' Valeur de Tdp utilisée dans le calcul du NR
    lnVP_iter = Journal (GetSatVapPres (TDewPoint_iter))

    ' Dérivée de fonction, calculée analytiquement
    d_lnVP = dLnPws_(TDewPoint_iter)

    ' Nouvelle estimation, délimitée par le domaine de validité de l'équation. 5 et 6 et par le point de congélation
    TDewPoint = TDewPoint_iter - (lnVP_iter - lnVP) / d_lnVP
    TDewPoint = Max(TDewPoint, BORNES(1))
    TDewPoint = Min(TDewPoint, BORNES(2))

    Si (indice > MAX_ITER_COUNT) Alors
      Aller à ErrHandler
    Fin Si

    indice = indice + 1

  Boucle Alors que (Abs(TDewPoint - TDewPoint_iter) > PSYCHROLIB_TOLERANCE)

  TDewPoint = Min(TDewPoint, TDryBulb)
  GetTDewPointFromVapPres = TDewPoint
  Sortie Une fonction

ErrHandler:
  GetTDewPointFromVapPres = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetVapPresFromTDewPoint(ParVal TDewPoint Comme Une variante) Comme Une variante
'
' Pression de vapeur de retour en fonction de la température du point de rosée.
'
' Arguments :
' TDewPoint : Température du point de rosée en °F [IP] ou °C [SI]
'
' Retour:
' Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 36
'
  Sur Erreur Aller à ErrHandler
  GetVapPresFromTDewPoint = ObtenirSatVapPres(TDewPoint)
  Sortie Une fonction

ErrHandler:
  GetVapPresFromTDewPoint = CVErr(xlErrNA)

Fin Une fonction


'*************************************************** ************************************************** ***
' Conversions de la température du bulbe humide, de la température du point de rosée ou du rapport humidité relative/humidité
'*************************************************** ************************************************** ***

Une fonction GetTWetBulbFromHumRatio(ParVal TDryBulb Comme Une variante, ParVal HumRatio Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Renvoie la température du bulbe humide en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' HumRatio : Rapport d'humidité en lb_H2O/lb_Air [IP] ou kg_H2O/kg_Air [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Température du thermomètre mouillé en °F [IP] ou °C [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équations 33 et 35 résolues pour Tstar
'

  ' Déclarations
  Faible Wstar Comme Une variante
  Faible TDewPoint Comme Une variante, TWetBulbComment Comme Une variante, TWetBulbSup Comme Une variante, TWetBulbInf Comme Une variante
  Faible tol Comme Une variante, BoundedHumRatio Comme Une variante, indice Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si HumRatio < 0 Alors
    MaBoîteMsg ("Le taux d'humidité ne peut pas être négatif")
    Aller à ErrHandler
  Fin Si
  BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO)

  TDewPoint = GetTDewPointFromHumRatio(TDryBulb, Rapport HumBounded, Pression)

  ' Premières suppositions
  TWetBulbSup = TDryBulb
  TWetBulbInf = TDewPoint
  TWetBulbComment = (TWetBulbInf + TWetBulbSup) / 2

  ' Boucle de bissection
  tol = GetTol()
  indice = 0
  Alors que ((TWetBulbSup - TWetBulbInf) > Tol)

    ' Calculer le taux d'humidité à la température Tstar
    Wstar = GetHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pression)

    ' Obtenez de nouvelles limites
    Si (Wstar > BoundedHumRatio) Alors
      TWetBulbSup = TWetBulbComment
    Autre
      TWetBulbInf = TWetBulbComment
    Fin Si

    " Nouvelle estimation de la température du bulbe humide
    TWetBulbComment = (TWetBulbSup + TWetBulbInf) / 2

    Si (indice > MAX_ITER_COUNT) Alors
      Aller à ErrHandler
    Fin Si

    indice = indice + 1
  Wend

  GetTWetBulbFromHumRatio = TWetBulbComment
  Sortie Une fonction

ErrHandler:
  GetTWetBulbFromHumRatio = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetHumRatioFromTWetBulb(ParVal TDryBulb Comme Une variante, ParVal TWetBulbComment Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Rapport d'humidité de retour en fonction de la température du bulbe sec, de la température du bulbe humide et de la pression.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' TWetBulb : Température du bulbe humide en °F [IP] ou °C [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Rapport d'humidité en lb_H2O/lb_Air [IP] ou kg_H2O/kg_Air [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équations 33 et 35

  Faible Wsstar Comme Une variante, HumRatio Comme Une variante
  Wsstar = GetSatHumRatio(TWetBulb, Pression)

  Sur Erreur Aller à ErrHandler

  Si TWetBulbComment > TDryBulb Alors
    MaBoîteMsg ("La température du bulbe humide est supérieure à la température du bulbe sec")
    Aller à ErrHandler
  Fin Si

  Si estIP() Alors
    Si (TWetBulb >= FREEZING_POINT_WATER_IP) Alors
      HumRatio = ((1093 - 0.556 * TWetBulb) * Wsstar - 0.24 * (TDDryBulb - TWetBulb)) / (1093 + 0.444 * TDryBulb - TWetBulb)
    Autre
      HumRatio = ((1220 - 0.04 * TWetBulb) * Wsstar - 0.24 * (TDDryBulb - TWetBulb)) / (1220 + 0.444 * TDryBulb - 0.48 * TWetBulb)
    Fin Si
  Autre
    Si (TWetBulb >= FREEZING_POINT_WATER_SI) Alors
      HumRatio = ((2501 - 2.326 * TWetBulb) * Wsstar - 1.006 * (TDDryBulb - TWetBulb)) / (2501 + 1.86 * TDryBulb - 4.186 * TWetBulb)
    Autre
      HumRatio = ((2830 - 0.24 * TWetBulb) * Wsstar - 1.006 * (TDDryBulb - TWetBulb)) / (2830 + 1.86 * TDryBulb - 2.1 * TWetBulb)
    Fin Si
  Fin Si
  ' Contrôle de validité.
  GetHumRatioFromTWetBulb = max(HumRapport, MIN_HUM_RATIO)
  Sortie Une fonction

ErrHandler:
  GetHumRatioFromTWetBulb = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetHumRatioFromRelHum(ParVal TDryBulb Comme Une variante, ParVal RelHum Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Rapport d'humidité de retour en fonction de la température du bulbe sec, de l'humidité relative et de la pression.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' RelHum : Humidité relative dans la plage [0, 1]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Rapport d'humidité en lb_H2O/lb_Air [IP] ou kg_H2O/kg_Air [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1
'
  Faible VapPres Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si RelHum < 0 Ou alors RelHum > 1 Alors
    MaBoîteMsg ("L'humidité relative est en dehors de la plage [0, 1]")
    Aller à ErrHandler
  Fin Si

  VapPres = GetVapPresFromRelHum(TDryBulb, RelHum)
  GetHumRatioFromRelHum = GetHumRatioFromVapPres(VapPres, Pression)
  Sortie Une fonction

ErrHandler:
  GetHumRatioFromRelHum = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetRelHumFromHumRatio(ParVal TDryBulb Comme Une variante, ParVal HumRatio Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Renvoie l'humidité relative en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' HumRatio : Rapport d'humidité en lb_H2O/lb_Air [IP] ou kg_H2O/kg_Air [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Humidité relative dans la plage [0, 1]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1
'
  Faible VapPres Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si HumRatio < 0 Alors
    MaBoîteMsg ("Le taux d'humidité est négatif")
    Aller à ErrHandler
  Fin Si

  VapPres = GetVapPresFromHumRatio(HumRatio, Pression)
  GetRelHumFromHumRatio = GetRelHumFromVapPres(TDDryBulb, VapPres)
  Sortie Une fonction

ErrHandler:
  GetRelHumFromHumRatio = CVErr(xlErrNA)

Fin Une fonction


Une fonction GetHumRatioFromTDewPoint(ParVal TDewPoint Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Taux d'humidité de retour en fonction de la température et de la pression du point de rosée.
'
' Arguments :
' TDewPoint : Température du point de rosée en °F [IP] ou °C [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Rapport d'humidité en lb_H2O/lb_Air [IP] ou kg_H2O/kg_Air [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 13
'
  Faible VapPres Comme Une variante

  Sur Erreur Aller à ErrHandler

  VapPres = ObtenirSatVapPres(TDewPoint)
  GetHumRatioFromTDewPoint = GetHumRatioFromVapPres(VapPres, Pression)
  Sortie Une fonction

ErrHandler:
  GetHumRatioFromTDewPoint = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetTDewPointFromHumRatio(ParVal TDryBulb Comme Une variante, ParVal HumRatio Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Température de retour du point de rosée en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' HumRatio : Rapport d'humidité en lb_H2O/lb_Air [IP] ou kg_H2O/kg_Air [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Température du point de rosée en °F [IP] ou °C [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1
'
  Faible VapPres Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si HumRatio < 0 Alors
    MaBoîteMsg ("Le taux d'humidité est négatif")
    Aller à ErrHandler
  Fin Si

  VapPres = GetVapPresFromHumRatio(HumRatio, Pression)
  GetTDewPointFromHumRatio = GetTDewPointFromVapPres(TDryBulb, VapPres)
  Sortie Une fonction

ErrHandler:
  GetTDewPointFromHumRatio = CVErr(xlErrNA)
Fin Une fonction


'*************************************************** ************************************************** ***
' Conversions entre taux d'humidité et pression de vapeur
'*************************************************** ************************************************** ***

Une fonction GetHumRatioFromVapPres(ParVal VapPres Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Taux d'humidité de retour étant donné la pression de vapeur d'eau et la pression atmosphérique.
'
' Arguments :
' VapPres : Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Rapport d'humidité en lb_H2O/lb_Air [IP] ou kg_H2O/kg_Air [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 20
'
  Faible HumRatio Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si VapPres < 0 Alors
    MaBoîteMsg ("La pression partielle de la vapeur d'eau dans l'air humide est négative")
    Aller à ErrHandler
  Fin Si

  HumRatio = 0.621945 * VapPres / (Pression - VapPres)
  ' Contrôle de validité.
  GetHumRatioFromVapPres = max(HumRapport, MIN_HUM_RATIO)
  Sortie Une fonction

ErrHandler:
  GetHumRatioFromVapPres = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetVapPresFromHumRatio(ParVal HumRatio Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Pression de vapeur de retour étant donné le taux d'humidité et la pression.
'
' Arguments :
' HumRatio : Rapport d'humidité en lb_H2O/lb_Air [IP] ou kg_H2O/kg_Air [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 20 résolue pour pw
'

  Faible VapPres Comme Une variante, BoundedHumRatio Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si HumRatio < 0 Alors
    MaBoîteMsg ("Le taux d'humidité est négatif")
    Aller à ErrHandler
  Fin Si
  BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO)

  VapPres = Pression * BoundedHumRatio / (0.621945 + BoundedHumRatio)
  GetVapPresFromHumRatio = VapPres
  Sortie Une fonction

ErrHandler:
  GetVapPresFromHumRatio = CVErr(xlErrNA)

Fin Une fonction


'*************************************************** ************************************************** ***
' Conversions entre taux d'humidité et humidité spécifique
'*************************************************** ************************************************** ***

Une fonction GetSpecificHumFromHumRatio(ParVal HumRatio Comme Une variante) Comme Une variante
'
' Renvoie l'humidité spécifique à partir du rapport d'humidité (c'est-à-dire le rapport de mélange).
'
' Arguments :
' HumRatio : Taux d'humidité en lb_H₂O lb_Dry_Air⁻¹ [IP] ou kg_H₂O kg_Dry_Air⁻¹ [SI]
'
' Retour:
' Humidité spécifique en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 9b
'
'
  Faible SpécifiqueHum Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si (HumRapport < 0) Alors
    MaBoîteMsg ("Le taux d'humidité est négatif")
    Aller à ErrHandler
  Fin Si

  SpécifiqueHum = HumRatio / (1.0 + HumRatio)
  GetSpecificHumFromHumRatio = SpécifiqueHum
  Sortie Une fonction

ErrHandler:
  GetSpecificHumFromHumRatio = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetHumRatioFromSpecificHum(ParVal SpécifiqueHum Comme Une variante) Comme Une variante
'
' Renvoie le taux d'humidité (c'est-à-dire le taux de mélange) à partir de l'humidité spécifique.
'
' Arguments :
' SpecificHum : Humidité spécifique en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
'
' Retour:
' Taux d'humidité en lb_H₂O lb_Dry_Air⁻¹ [IP] ou kg_H₂O kg_Dry_Air⁻¹ [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 9b (résolu pour le taux d'humidité)
'
'
  Faible HumRatio comme Une variante

  Sur Erreur Aller à ErrHandler

  Si (SpécifiqueHum < 0 Ou alors SpécifiqueHum >= 1) Alors
    MaBoîteMsg ("L'humidité spécifique est en dehors de la plage [0, 1[")
    Aller à ErrHandler
  Fin Si

    HumRatio = SpécifiqueHum / (1.0 - SpécifiqueHum)
    GetHumRatioFromSpecificHum = max(HumRapport, MIN_HUM_RATIO)
  Sortie Une fonction

ErrHandler:
  GetHumRatioFromSpecificHum = CVErr(xlErrNA)

Fin Une fonction


'*************************************************** ************************************************** ***
' Calculs d'air sec
'*************************************************** ************************************************** ***

Une fonction GetDryAirEnthalpy(ParVal TDryBulb Comme Une variante) Comme Une variante
'
' Renvoie l'enthalpie de l'air sec en fonction de la température du bulbe sec.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
'
' Retour:
' Enthalpie de l'air sec en Btu/lb [IP] ou J/kg [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 28
'
  Sur Erreur Aller à ErrHandler

  Si (estIP()) Alors
    GetDryAirEnthalpy = 0.24 * TDryBulb
  Autre
    GetDryAirEnthalpy = 1006 * TDryBulb
  Fin Si
  Sortie Une fonction

ErrHandler:
  GetDryAirEnthalpy = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetDryAirDensity(ParVal TDryBulb Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Renvoyez la densité de l'air sec en fonction de la température et de la pression du bulbe sec.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Densité de l'air sec en lb/ft³ [IP] ou kg/m³ [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1
'
' Remarques:
' Éqn 14 pour la relation gazeuse parfaite pour l'air sec.
' Eqn 1 pour la constante universelle des gaz.
' Le facteur 144 en IP est destiné à la conversion de Psi = lb/in² en lb/ft².
'
  Sur Erreur Aller à ErrHandler

  Si (estIP()) Alors
    GetDryAirDensity = (144 * Pression) / R_DA_IP / ObtenirTRankineFromTFahrenheit(TDryBulb)
  Autre
    GetDryAirDensity = Pression / R_DA_SI / ObtenirTKelvinFromTCelsius(TDryBulb)
  Fin Si
  Sortie Une fonction

ErrHandler:
  GetDryAirDensity = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetDryAirVolume(ParVal TDryBulb Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Restituez le volume d'air sec en fonction de la température et de la pression du bulbe sec.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Volume d'air sec en pi³/lb [IP] ou en m³/kg [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1
'
' Remarques:
' Éqn 14 pour la relation gazeuse parfaite pour l'air sec.
' Eqn 1 pour la constante universelle des gaz.
' Le facteur 144 en IP est destiné à la conversion de Psi = lb/in² en lb/ft².
'
  Sur Erreur Aller à ErrHandler

  Si (estIP()) Alors
    GetDryAirVolume = ObtenirTRankineFromTFahrenheit(TDryBulb) * R_DA_IP / (144 * Pression)
  Autre:
    GetDryAirVolume = ObtenirTKelvinFromTCelsius(TDryBulb) * R_DA_SI / Pression
  Fin Si
  Sortie Une fonction

ErrHandler:
  GetDryAirVolume = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetTDryBulbFromEnthalpyAndHumRatio(ParVal Enthalpie de l'air humide Comme Une variante, ParVal HumRatio Comme Une variante) Comme Une variante
'
' Renvoie la température du bulbe sec à partir du rapport d'enthalpie et d'humidité.
'
'
' Arguments :
' MoistAirEnthalpy : Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹
' HumRatio : Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
'
' Retour:
' Température du bulbe sec en °F [IP] ou °C [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 30
'
' Remarques:
' Basé sur la fonction `GetMoistAirEnthalpy`, réorganisée en fonction de la température.
'

  Sur Erreur Aller à ErrHandler

  Si HumRatio < 0 Alors
    MaBoîteMsg ("Le taux d'humidité est négatif")
    Aller à ErrHandler
  Fin Si

  Si (estIP()) Alors
    GetTDryBulbFromEnthalpyAndHumRatio = (Enthalpie de l'air humide - 1061.0 * HumRatio) / (0.24 + 0.444 * HumRatio)
  Autre:
    GetTDryBulbFromEnthalpyAndHumRatio = (Enthalpie de l'air humide / 1000.0 - 2501.0 * HumRatio) / (1.006 + 1.86 * HumRatio)
  Fin Si
  Sortie Une fonction

ErrHandler:
  GetTDryBulbFromEnthalpyAndHumRatio = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetHumRatioFromEnthalpyAndTDryBulb(ParVal Enthalpie de l'air humide Comme Une variante, ParVal TDryBulb Comme Une variante) Comme Une variante
'
' Renvoie le rapport d'humidité à partir de l'enthalpie et de la température du bulbe sec.
'
'
' Arguments :
' MoistAirEnthalpy : Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
'
' Retour:
' Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 30
'
' Remarques:
' Basé sur la fonction `GetMoistAirEnthalpy`, réorganisée en fonction du taux d'humidité.
'

  Sur Erreur Aller à ErrHandler

  Si (estIP()) Alors
    GetHumRatioFromEnthalpyAndTDryBulb = (Enthalpie de l'air humide - 0.24 * TDryBulb) / (1061.0 + 0.444 * TDryBulb)
  Autre:
    GetHumRatioFromEnthalpyAndTDryBulb = (Enthalpie de l'air humide / 1000.0 - 1.006 * TDryBulb) / (2501.0 + 1.86 * TDryBulb)
  Fin Si
  Sortie Une fonction

ErrHandler:
  GetHumRatioFromEnthalpyAndTDryBulb = CVErr(xlErrNA)

Fin Une fonction


'*************************************************** ************************************************** ***
' Calculs d'air saturé
'*************************************************** ************************************************** ***

Une fonction GetSatVapPres(ParVal TDryBulb Comme Une variante) Comme Une variante
'
' Pression de vapeur saturante de retour étant donné la température du bulbe sec.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
'
' Retour:
' Pression de vapeur de l'air saturé en Psi [IP] ou Pa [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équations 5 et 6
' Remarque importante : les formules ASHRAE sont définies au dessus et en dessous du point de congélation mais ont
' une discontinuité au point de congélation. Il s'agit d'une petite inexactitude de la part d'ASHRAE : les formules
' doit être défini au-dessus et au-dessous du point triple de l'eau (et non du point de congélation), auquel cas
" La discontinuité disparaît. Il est indispensable d'utiliser le point triple d'eau sinon fonctionne
' GetTDewPointFromVapPres, qui inverse la fonction actuelle, ne converge pas correctement autour de
' le point de congélation.
'
  Faible LnPws Comme Une variante, J Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si (estIP()) Alors
    Si (TDDryBulb < -148 Ou alors TDryBulb > 392) Alors
      MaBoîteMsg ("La température du bulbe sec est en dehors de la plage [-148, 392] °F")
      Aller à ErrHandler
    Fin Si

    J = ObtenirTRankineFromTFahrenheit(TDryBulb)

    Si (TDDryBulb <= TRIPLE_POINT_WATER_IP) Alors
      LnPws = (-10214.165 / J - 4.8932428 - 0.0053765794 * J + 0.00000019202377 * J ^ 2 _
            + 3.5575832E-10 * J ^ 3 - 9.0344688E-14 * J ^ 4 + 4.1635019 * Log(T))
    Autre
      LnPws = -10440.397 / J - 11.29465 - 0.027022355 * J + 0.00001289036 * J ^ 2 _
            - 2.4780681E-09 * J ^ 3 + 6.5459673 * Log(T)
    Fin Si

  Autre
    Si (TDDryBulb < -100 Ou alors TDryBulb > 200) Alors
      MaBoîteMsg ("La température du bulbe sec est en dehors de la plage [-100, 200] °C")
      Aller à ErrHandler
    Fin Si

    J = ObtenirTKelvinFromTCelsius(TDryBulb)

    Si (TDDryBulb <= TRIPLE_POINT_WATER_SI) Alors
        LnPws = -5674.5359 / J + 6.3925247 - 0.009677843 * J + 0.00000062215701 * J ^ 2 _
              + 2.0747825E-09 * J ^ 3 - 9.484024E-13 * J ^ 4 + 4.1635019 * Log(T)
    Autre
        LnPws = -5800.2206 / J + 1.3914993 - 0.048640239 * J + 0.000041764768 * J ^ 2 _
              - 0.000000014452093 * J ^ 3 + 6.5459673 * Log(T)
    Fin Si
  Fin Si

  GetSatVapPres = Exp(LnPws)
  Sortie Une fonction

ErrHandler:
  GetSatVapPres = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetSatHumRatio(ParVal TDryBulb Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Taux d'humidité de retour de l'air saturé en fonction de la température et de la pression du bulbe sec.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Rapport d'humidité de l'air saturé en lb_H2O/lb_Air [IP] ou kg_H2O/kg_Air [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 36, résolue pour W
'
  Faible SatVaporPres Comme Une variante, SatHumRatio Comme Une variante

  Sur Erreur Aller à ErrHandler

  SatVaporPres = ObtenirSatVapPres(TDryBulb)
  SatHumRatio = 0.621945 * SatVaporPres / (Pression - SatVaporPres)
  GetSatHumRatio = max(SatHumRatio, MIN_HUM_RATIO)
  Sortie Une fonction

ErrHandler:
  GetSatHumRatio = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetSatAirEnthalpy(ParVal TDryBulb Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Renvoyez l'enthalpie de l'air saturé en fonction de la température et de la pression du bulbe sec.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Enthalpie de l'air saturé en Btu/lb [IP] ou J/kg [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1
'
  Sur Erreur Aller à ErrHandler

  GetSatAirEnthalpy = GetMoistAirEnthalpy(TDDryBulb, GetSatHumRatio(TDDryBulb, Pression))
  Sortie Une fonction

ErrHandler:
  GetSatAirEnthalpy = CVErr(xlErrNA)

Fin Une fonction


'*************************************************** ************************************************** ***
' Calculs d'air humide
'*************************************************** ************************************************** ***


Une fonction GetVaporPressureDeficit(ParVal TDryBulb Comme Une variante, ParVal HumRatio Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Retour Déficit de pression de vapeur en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' HumRatio : Rapport d'humidité en lb_H2O/lb_Air [IP] ou kg_H2O/kg_Air [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Déficit de pression de vapeur en Psi [IP] ou Pa [SI]
'
' Référence:
' Oke (1987) équation 2.13a
'
  Faible RelHum Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si HumRatio < 0 Alors
    MaBoîteMsg ("Le taux d'humidité est négatif")
    Aller à ErrHandler
  Fin Si

  RelHum = GetRelHumFromHumRatio(TDryBulb, HumRatio, Pression)
  GetVaporPressureDeficit = ObtenirSatVapPres(TDryBulb) * (1 - RelHum)
  Sortie Une fonction

ErrHandler:
  GetVaporPressureDeficit = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetDegreeOfSaturation(ParVal TDryBulb Comme Une variante, ParVal HumRatio Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Renvoie le degré de saturation (c'est à dire le rapport humidité de l'air/rapport humidité de l'air à saturation
' à la même température et pression) étant donné la température du bulbe sec, le taux d'humidité et la pression atmosphérique.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' HumRatio : Rapport d'humidité en lb_H2O/lb_Air [IP] ou kg_H2O/kg_Air [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Degré de saturation en unité arbitraire
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2009) ch. 1 équation 12
'
' Remarques:
" Cette définition est absente du Manuel de 2017. Utiliser plutôt la version 2009.
'
  Faible BoundedHumRatio Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si HumRatio < 0 Alors
    MaBoîteMsg ("Le taux d'humidité est négatif")
    Aller à ErrHandler
  Fin Si
  BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO)

  GetDegreeOfSaturation = BoundedHumRatio / GetSatHumRatio(TDDryBulb, Pression)
  Sortie Une fonction

ErrHandler:
  GetDegreeOfSaturation = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetMoistAirEnthalpy(ParVal TDryBulb Comme Une variante, ParVal HumRatio Comme Une variante) Comme Une variante
'
' Renvoyez l'enthalpie de l'air humide en fonction de la température du bulbe sec et du rapport d'humidité.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' HumRatio : Rapport d'humidité en lb_H2O/lb_Air [IP] ou kg_H2O/kg_Air [SI]
'
' Retour:
' Enthalpie de l'air humide en Btu/lb [IP] ou J/kg
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 30
'
  Faible BoundedHumRatio Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si (HumRapport < 0) Alors
    MaBoîteMsg ("Le taux d'humidité est négatif")
    Aller à ErrHandler
  Fin Si
  BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO)

  Si (estIP()) Alors
    GetMoistAirEnthalpy = 0.24 * TDryBulb + BoundedHumRatio * (1061 + 0.444 * TDryBulb)
  Autre
    GetMoistAirEnthalpy = (1.006 * TDryBulb + BoundedHumRatio * (2501 + 1.86 * TDryBulb)) * 1000
  Fin Si
  Sortie Une fonction

ErrHandler:
  GetMoistAirEnthalpy = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetMoistAirVolume(ParVal TDryBulb Comme Une variante, ParVal HumRatio Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Renvoyez le volume spécifique d'air humide en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' HumRatio : Rapport d'humidité en lb_H2O/lb_Air [IP] ou kg_H2O/kg_Air [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Volume spécifique d'air humide en pi³/lb d'air sec [IP] ou en m³/kg d'air sec [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 26
'
' Remarques:
' En unités IP, R_DA_IP/144 est égal à 0,370486 qui est le coefficient apparaissant dans l'équation 26
' Le facteur 144 est destiné à la conversion de Psi = lb/in² en lb/ft².
'
  Faible BoundedHumRatio Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si (HumRapport < 0) Alors
    MaBoîteMsg ("Le taux d'humidité est négatif")
    Aller à ErrHandler
  Fin Si
  BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO)

  Si (estIP()) Alors
    GetMoistAirVolume = R_DA_IP * ObtenirTRankineFromTFahrenheit(TDryBulb) * (1 + 1.607858 * BoundedHumRatio) / (144 * Pression)
  Autre
    GetMoistAirVolume = R_DA_SI * ObtenirTKelvinFromTCelsius(TDryBulb) * (1 + 1.607858 * BoundedHumRatio) / Pression
  Fin Si
  Sortie Une fonction

ErrHandler:
  GetMoistAirVolume = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetTDryBulbFromMoistAirVolumeAndHumRatio(ParVal Volume d'air humide Comme Une variante, ParVal HumRatio Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Température de retour du bulbe sec en fonction du volume spécifique de l'air humide, du taux d'humidité et de la pression.
'
' Arguments :
' MoistAirVolume : Volume spécifique d'air humide en ft³ lb⁻¹ d'air sec [IP] ou en m³ kg⁻¹ d'air sec [SI]
' HumRatio : Rapport d'humidité en lb_H2O/lb_Air [IP] ou kg_H2O/kg_Air [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Volume spécifique d'air humide en pi³/lb d'air sec [IP] ou en m³/kg d'air sec [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 26
'
' Remarques:
' En unités IP, R_DA_IP/144 est égal à 0,370486 qui est le coefficient apparaissant dans l'équation 26
' Le facteur 144 est destiné à la conversion de Psi = lb/in² en lb/ft².
' Basé sur la fonction « GetMoistAirVolume », réorganisée pour la température sèche.
'
  Faible BoundedHumRatio Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si (HumRapport < 0) Alors
    MaBoîteMsg ("Le taux d'humidité est négatif")
    Aller à ErrHandler
  Fin Si
  BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO)

  Si (estIP()) Alors
    GetTDryBulbFromMoistAirVolumeAndHumRatio = GetTFahrenheitFromTRankine(MoistAirVolume * (144 * Pression) / (R_DA_IP * (1 + 1.607858 * BoundedHumRatio)))
  Autre
    GetTDryBulbFromMoistAirVolumeAndHumRatio = GetTCelsiusFromTKelvin(MoistAirVolume * Pression / (R_DA_SI * (1 + 1.607858 * BoundedHumRatio)))
  Fin Si
  Sortie Une fonction

ErrHandler:
  GetTDryBulbFromMoistAirVolumeAndHumRatio = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetMoistAirDensity(ParVal TDryBulb Comme Une variante, ParVal HumRatio Comme Une variante, ParVal Pression Comme Une variante) Comme Une variante
'
' Renvoyez la densité de l'air humide en fonction du taux d'humidité, de la température du bulbe sec et de la pression.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' HumRatio : Rapport d'humidité en lb_H2O/lb_Air [IP] ou kg_H2O/kg_Air [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' MoistAirDensity : densité de l'air humide en lb/ft³ [IP] ou kg/m³ [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 11
'
  Faible Volume d'air humide Comme Une variante, BoundedHumRatio Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si (HumRapport < 0) Alors
    MaBoîteMsg ("Le taux d'humidité est négatif")
    Aller à ErrHandler
  Fin Si
  BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO)

  Volume d'air humide = GetMoistAirVolume(TDDryBulb, Rapport HumBounded, Pression)
  GetMoistAirDensity = (1 + BoundedHumRatio) / Volume d'air humide
  Sortie Une fonction

ErrHandler:
  GetMoistAirDensity = CVErr(xlErrNA)

Fin Une fonction


'*************************************************** ************************************************** ***
' Atmosphère normale
'*************************************************** ************************************************** ***

Une fonction GetStandardAtmPressure(ParVal Altitude Comme Une variante) Comme Une variante
'
' Renvoie la pression barométrique de l'atmosphère standard, compte tenu de l'élévation (altitude).
'
' Arguments :
' Altitude : altitude en pieds [IP] ou en m [SI]
'
' Retour:
' Pression barométrique de l'atmosphère standard en Psi [IP] ou Pa [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 3
'
  Sur Erreur Aller à ErrHandler

  Si (estIP()) Alors
    GetStandardAtmPressure = 14.696 * (1 - 0.0000068754 * Altitude) ^ 5.2559
  Autre
    GetStandardAtmPressure = 101325 * (1 - 0.0000225577 * Altitude) ^ 5.2559
  Fin Si
  Sortie Une fonction

ErrHandler:
  GetStandardAtmPressure = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetStandardAtmTemperature(ParVal Altitude Comme Une variante) Comme Une variante
'
' Renvoie la température atmosphérique standard, compte tenu de l'élévation (altitude).
'
' Arguments :
' Altitude : Altitude en pieds
'
' Retour:
' Température du bulbe sec de l'atmosphère standard en °F [IP] ou °C [SI]
'
' Référence:
' Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 4
'
  Sur Erreur Aller à ErrHandler

  Si (estIP()) Alors
    GetStandardAtmTemperature = 59 - 0.0035662 * Altitude
  Autre
    GetStandardAtmTemperature = 15 - 0.0065 * Altitude
  Fin Si
  Sortie Une fonction

ErrHandler:
  GetStandardAtmTemperature = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetSeaLevelPressure(ParVal StationPression Comme Une variante, ParVal Altitude Comme Une variante, ParVal TDryBulb Comme Une variante) Comme Une variante
'
' Pression de retour au niveau de la mer étant donné la température du bulbe sec, l'altitude au-dessus du niveau de la mer et la pression.
'
' Arguments :
' StationPressure : Pression de la station observée en Psi [IP] ou Pa [SI]
' Altitude : altitude en pieds [IP] ou en m [SI]
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
'
' Retour:
' Pression barométrique au niveau de la mer en Psi [IP] ou Pa [SI]
'
' Référence:
' Hess SL, Introduction à la météorologie théorique, Holt Rinehart et Winston, NY 1959,
'ch. 6,5 ; Stull RB, Météorologie pour les scientifiques et les ingénieurs, 2e édition,
' Brooks/Cole 2000, chap. 1.
'
' Remarques:
' La procédure standard aux États-Unis consiste à utiliser pour TDryBulb la moyenne
' de la température actuelle de la station et de la température de la station d'il y a 12 heures.
'

  ' Calculer la température moyenne dans la colonne d'air, en supposant un taux de déchéance
  ' de 6,5 °C/km
  Faible TColonne Comme Une variante
  Faible H Comme Une variante

  Sur Erreur Aller à ErrHandler

  Si (estIP()) Alors
    ' Calculer la température moyenne dans la colonne d'air, en supposant un taux de déchéance
    ' de 3,6 °F/1000 pieds
    TColonne = TDryBulb + 0.0036 * Altitude / 2

    ' Déterminer la hauteur de l'échelle
    H = 53.351 * GetTRankineFromTFahrenheit(TColumn)
  Autre
    ' Calculer la température moyenne dans la colonne d'air, en supposant un taux de déchéance
    ' de 6,5 °C/km
    TColonne = TDryBulb + 0.0065 * Altitude / 2

    ' Déterminer la hauteur de l'échelle
    H = 287.055 * GetTKelvinFromTCelsius(TColonne) / 9.807
  Fin Si

  ' Calculer la pression au niveau de la mer
  GetSeaLevelPressure = StationPression * Exp(Altitude / H)
  Sortie Une fonction

ErrHandler:
  GetSeaLevelPressure = CVErr(xlErrNA)

Fin Une fonction

Une fonction GetStationPressure(ParVal PressionNiveau De La Mer Comme Une variante, ParVal Altitude Comme Une variante, ParVal TDryBulb Comme Une variante) Comme Une variante
'
' Arguments :
' SeaLevelPressure : Pression barométrique au niveau de la mer en Psi [IP] ou Pa [SI]
' Altitude : altitude en pieds [IP] ou en m [SI]
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
'
' Retour:
' Pression de la station en Psi [IP] ou Pa [SI]
'
' Référence:
" Voir " Obtenir la pression du niveau de la mer ".
'
' Remarques:
' Cette fonction est juste l'inverse de 'GetSeaLevelPressure'.
'
  Sur Erreur Aller à ErrHandler

  GetStationPressure = PressionNiveau De La Mer / GetSeaLevelPressure(1, Altitude, TDryBulb)
  Sortie Une fonction

ErrHandler:
  GetStationPressure = CVErr(xlErrNA)

Fin Une fonction

'*************************************************** ************************************************** ***
' Fonctions pour définir toutes les valeurs psychrométriques
'*************************************************** ************************************************** ***

Sous CalcPsychrometricsFromTWetBulb(ParVal TDryBulb Comme Une variante, ParVal TWetBulbComment Comme Une variante, ParVal Pression Comme Une variante, _
    ParRéf HumRatio Comme Une variante, ParRéf TDewPoint Comme Une variante, ParRéf RelHum Comme Une variante, ParRéf VapPres Comme Une variante, _
    ParRéf Enthalpie de l'air humide Comme Une variante, ParRéf Volume d'air humide Comme Une variante, ParRéf DegréDeSaturation Comme Une variante)
'
' Fonction utilitaire pour calculer le taux d'humidité, la température du point de rosée, l'humidité relative,
' Pression de vapeur, enthalpie de l'air humide, volume d'air humide et degré de saturation de l'air donnés
' La température du bulbe sec, la température du bulbe humide et la pression.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' TWetBulb : Température du bulbe humide en °F [IP] ou °C [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Rapport d'humidité en lb_H2O/lb_Air [IP] ou kg_H2O/kg_Air [SI]
' Température du point de rosée en °F [IP] ou °C [SI]
' Humidité relative dans la plage [0, 1]
' Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
' Enthalpie de l'air humide en Btu/lb [IP] ou J/kg [SI]
' Volume spécifique d'air humide en ft³/lb [IP] ou en m³/kg [SI]
' Degré de saturation [sans unité]
'
  HumRatio = GetHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pression)
  TDewPoint = GetTDewPointFromHumRatio(TDryBulb, HumRatio, Pression)
  RelHum = GetRelHumFromHumRatio(TDryBulb, HumRatio, Pression)
  VapPres = GetVapPresFromHumRatio(HumRatio, Pression)
  Enthalpie de l'air humide = GetMoistAirEnthalpy(TDDryBulb, HumRatio)
  Volume d'air humide = GetMoistAirVolume(TDDryBulb, HumRatio, Pression)
  DegréDeSaturation = ObtenirDegréDeSaturation(TDryBulb, HumRatio, Pression)

Fin Sous

Sous CalcPsychrometricsFromTDewPoint(ParVal TDryBulb Comme Une variante, ParVal TDewPoint Comme Une variante, ParVal Pression Comme Une variante, _
    ParRéf HumRatio Comme Une variante, ParRéf TWetBulbComment Comme Une variante, ParRéf RelHum Comme Une variante, ParRéf VapPres Comme Une variante, _
    ParRéf Enthalpie de l'air humide Comme Une variante, ParRéf Volume d'air humide Comme Une variante, ParRéf DegréDeSaturation Comme Une variante)
'
' Fonction utilitaire pour calculer le taux d'humidité, la température du bulbe humide, l'humidité relative,
' Pression de vapeur, enthalpie de l'air humide, volume d'air humide et degré de saturation de l'air donnés
' Température du bulbe sec, température du point de rosée et pression.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' TDewPoint : Température du point de rosée en °F [IP] ou °C [SI]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Rapport d'humidité en lb_H2O/lb_Air [IP] ou kg_H2O/kg_Air [SI]
' Température du thermomètre mouillé en °F [IP] ou °C [SI]
' Humidité relative dans la plage [0, 1]
' Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
' Enthalpie de l'air humide en Btu/lb [IP] ou J/kg [SI]
' Volume spécifique d'air humide en ft³/lb [IP] ou en m³/kg [SI]
' Degré de saturation [sans unité]
'
  HumRatio = GetHumRatioFromTDewPoint(TDewPoint, Pression)
  TWetBulbComment = GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pression)
  RelHum = GetRelHumFromHumRatio(TDryBulb, HumRatio, Pression)
  VapPres = GetVapPresFromHumRatio(HumRatio, Pression)
  Enthalpie de l'air humide = GetMoistAirEnthalpy(TDDryBulb, HumRatio)
  Volume d'air humide = GetMoistAirVolume(TDDryBulb, HumRatio, Pression)
  DegréDeSaturation = ObtenirDegréDeSaturation(TDryBulb, HumRatio, Pression)

Fin Sous

Sous CalcPsychrometricsFromRelHum(ParVal TDryBulb Comme Une variante, ParVal RelHum Comme Une variante, ParVal Pression Comme Une variante, _
    ParRéf HumRatio Comme Une variante, ParRéf TWetBulbComment Comme Une variante, ParRéf TDewPoint Comme Une variante, ParRéf VapPres Comme Une variante, _
    ParRéf Enthalpie de l'air humide Comme Une variante, ParRéf Volume d'air humide Comme Une variante, ParRéf DegréDeSaturation Comme Une variante)
'
' Fonction utilitaire pour calculer le taux d'humidité, la température du bulbe humide, la température du point de rosée,
' Pression de vapeur, enthalpie de l'air humide, volume d'air humide et degré de saturation de l'air donnés
' Température sèche, humidité relative et pression.
'
' Arguments :
' TDryBulb : Température du bulbe sec en °F [IP] ou °C [SI]
' RelHum : Humidité relative dans la plage [0, 1]
' Pression : Pression atmosphérique en Psi [IP] ou Pa [SI]
'
' Retour:
' Rapport d'humidité en lb_H2O/lb_Air [IP] ou kg_H2O/kg_Air [SI]
' Température du thermomètre mouillé en °F [IP] ou °C [SI]
' Température du point de rosée en °F [IP] ou °C [SI].
' Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
' Enthalpie de l'air humide en Btu/lb [IP] ou J/kg [SI]
' Volume spécifique d'air humide en ft³/lb [IP] ou en m³/kg [SI]
' Degré de saturation [sans unité]
'
  HumRatio = GetHumRatioFromRelHum(TDryBulb, RelHum, Pression)
  TWetBulbComment = GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pression)
  TDewPoint = GetTDewPointFromHumRatio(TDryBulb, HumRatio, Pression)
  VapPres = GetVapPresFromHumRatio(HumRatio, Pression)
  Enthalpie de l'air humide = GetMoistAirEnthalpy(TDDryBulb, HumRatio)
  Volume d'air humide = GetMoistAirVolume(TDDryBulb, HumRatio, Pression)
  DegréDeSaturation = ObtenirDegréDeSaturation(TDryBulb, HumRatio, Pression)

Fin Sous

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 (version 2.3.0) (https://github.com/psychrometrics/psychrolib)
 * Copyright (c) 2018 D. Thevenard et D. Meyer pour l'implémentation actuelle de la bibliothèque
 * Copyright (c) Manuel ASHRAE 2017 — Principes fondamentaux des équations et coefficients ASHRAE
 * Sous licence MIT.
 */

fonction Psychrométrie() {
  /**
   * Présentation des modules
   * Contient des fonctions de calcul des propriétés thermodynamiques des mélanges gaz-vapeur
   * et atmosphère standard adaptée à la plupart des applications techniques, physiques et météorologiques
   * applications.
   *
   * La plupart des fonctions sont une implémentation des formules trouvées dans le
   * Manuel ASHRAE 2017 - Fondamentaux, dans les deux systèmes internationaux (SI),
   * et unités impériales (IP). Veuillez vous référer aux informations incluses dans
   * chaque fonction pour sa référence respective.
   *
   * Exemple (par exemple Node.JS)
   * // Importer la PsychroLib
   * var psychrolib = require('psychrolib.js')
   * // Définir le système d'unités
   * psychrolib.SetUnitSystem(psychrolib.SI)
   * // Calculer la température du point de rosée pour une température sèche de 25 C et une humidité relative de 80 %
   * var TDewPoint = psychrolib.GetTDewPointFromRelHum(25.0, 0.80);
   * console.log('TDewPoint : %d', TDewPoint);
   * 21.3094
   *
   * Droits d'auteur
   * - Pour l'implémentation actuelle de la bibliothèque
   * Copyright (c) 2018 D. Thevenard et D. Meyer.
   * - Pour les équations et les coefficients publiés ASHRAE Handbook — Fundamentals, Chapitre 1
   * Copyright (c) Manuel ASHRAE 2017 — Fondamentaux (https://www.ashrae.org)
   *
   * Licence
   * MIT (https://github.com/psychrometrics/psychrolib/LICENSE.txt)
   *
   * Remarque des auteurs
   * Nous avons fait tous les efforts possibles pour garantir que le code soit adéquat, mais nous ne faisons aucun
   * représentation quant à son exactitude. À utiliser à vos risques et périls. Si vous remarquez
   * une erreur, ou si vous avez une suggestion, veuillez nous en informer via GitHub à l'adresse
   * https://github.com/psychrometrics/psychrolib/issues.
   */


  // Fonctions standards
  var enregistrer = Mathématiques.enregistrer;
  var exp = Mathématiques.exp;
  var pow = Mathématiques.pow ;
  var min = Mathématiques.min ;
  var maximum = Mathématiques.max;
  var abdos = Mathématiques.abdos;


  /*************************************************** ************************************************** ***
   * Constantes globales
   ************************************************** ************************************************** */

  var ZERO_FAHRENHEIT_AS_RANKINE = 459.67;  // Zéro degré Fahrenheit (°F) exprimé en degré Rankine (°R).
                                            // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 39.

  var ZERO_CELSIUS_AS_KELVIN = 273.15;      // Zéro degré Celsius (°C) exprimé en Kelvin (K).
                                            // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 39.

  var R_DA_IP = 53.350;               // Constante de gaz universelle pour air sec (version IP) en ft lb_Force lb_DryAir⁻¹ R⁻¹.
                                      // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1.

  var R_DA_SI = 287.042;              // Constante de gaz universelle pour air sec (version SI) en J kg_DryAir⁻¹ K⁻¹.
                                      // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1.

  var INVALIDE = -99999;               // Valeur invalide (sans dimension).

  var MAX_ITER_COUNT = 100            // Nombre maximum d'itérations avant de quitter les boucles while.

  var MIN_HUM_RATIO = 1e-7            // Rapport d'humidité minimum acceptable utilisé/renvoyé par toutes les fonctions.
                                      // Toute valeur supérieure à 0 ou inférieure au MIN_HUM_RATIO sera réinitialisée à cette valeur.

  var FREEZING_POINT_WATER_IP = 32.0  // Point de congélation de l'eau en Fahrenheit.

  var FREEZING_POINT_WATER_SI = 0.0   // Point de congélation de l'eau en Celsius.

  var TRIPLE_POINT_WATER_IP = 32.018  // Triple point d'eau en Fahrenheit.

  var TRIPLE_POINT_WATER_SI = 0.01    // Triple point d'eau en Celsius.



  /*************************************************** ************************************************** ***
   * Fonctions d'assistance
   ************************************************** ************************************************** */

  // Systèmes d'unités (IP ou SI)
  var PSYCHROLIB_UNITS = indéfini;

  cette.IP = 1;
  cette.SI = 2;

  // Fonction pour définir le système d'unités
  // Remarque : cette fonction *DOIT ÊTRE APPELÉE* avant que la bibliothèque puisse être utilisée
  cette.SetUnitSystem = fonction(Système d'unité) {
    si (Système d'unité != cette.IP && Système d'unité != cette.SI) {
      jeter Nouveau Erreur('UnitSystem doit être IP ou SI');
    }
    PSYCHROLIB_UNITS = Système d'unité;
    // Définir la tolérance des calculs de température
    // La tolérance est la même en IP et SI
    si (PSYCHROLIB_UNITS == cette.IP)
      PSYCHROLIB_TOLERANCE = 0.001 * 9. / 5.;
    autre
      PSYCHROLIB_TOLERANCE = 0.001;
  }

  // Renvoie le système d'unités utilisé.
  cette.GetUnitSystem = fonction() {
    retour PSYCHROLIB_UNITS ;
  }

  // Fonction pour vérifier si le système d'unités actuel est SI ou IP
  // La fonction se termine en erreur si le système d'unités n'est pas défini
  cette.isIP = fonction() {
    si (PSYCHROLIB_UNITS == cette.IP)
      retour vrai;
    autre si (PSYCHROLIB_UNITS == cette.SI)
      retour faux;
    autre
      jeter Nouveau Erreur("Le système d'unités n'est pas défini");
  }


  /*************************************************** ************************************************** ***
   * Conversion entre unités de température
   ************************************************** ************************************************** */

  // Fonction utilitaire pour convertir la température en degré Rankine (°R)
  // température donnée en degrés Fahrenheit (°F).
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 chapitre 3
  cette.GetTRankineFromTFahrenheit = fonction (T_F) { retour T_F + ZERO_FAHRENHEIT_AS_RANKINE ; }       /* exact */

  // Fonction utilitaire pour convertir la température en degrés Fahrenheit (°F)
  // température donnée en degré Rankine (°R).
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 chapitre 3
  cette.GetTFahrenheitFromTRankine = fonction (T_R) { retour T_R - ZERO_FAHRENHEIT_AS_RANKINE ; }       /* exact */

  // Fonction utilitaire pour convertir la température en Kelvin (K)
  // température donnée en degrés Celsius (°C).
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 chapitre 3
  cette.GetTKelvinFromTCelsius = fonction (T_C) { retour T_C + ZERO_CELSIUS_AS_KELVIN ; }               /* exact */

  // Fonction utilitaire pour convertir la température en degrés Celsius (°C)
  // température donnée en Kelvin (K).
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 chapitre 3
  cette.GetTCelsiusFromTKelvin = fonction (T_K) { retour T_K - ZERO_CELSIUS_AS_KELVIN ; }                /* exact */

  /*************************************************** ************************************************** ***
   * Conversions entre point de rosée, bulbe humide et humidité relative
   ************************************************** ************************************************** */

  // Renvoie la température du bulbe humide en fonction de la température du bulbe sec, de la température du point de rosée et de la pression.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
  cette.GetTWetBulbFromTDewPoint = fonction  // (o) Température du bulbe humide en °F [IP] ou °C [SI]
    ( TDryBulb                              // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , TDewPoint                             // (i) Température du point de rosée en °F [IP] ou °C [SI]
    , Pression                              // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var HumRatio ;

    si (!(TDewPoint <= TDryBulb))
      jeter Nouveau Erreur("La température du point de rosée est supérieure à la température du bulbe sec");

    HumRatio = cette.GetHumRatioFromTDewPoint(TDewPoint, Pression);
    retour cette.GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pression);
  }

  // Renvoie la température du bulbe humide en fonction de la température du bulbe sec, de l'humidité relative et de la pression.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
  cette.GetTWetBulbFromRelHum = fonction // (o) Température du bulbe humide en °F [IP] ou °C [SI]
    ( TDryBulb                          // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , RelHum                            // (i) Humidité relative [0-1]
    , Pression                          // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var HumRatio ;

    si (!(RelHum >= 0. && RelHum <= 1.))
      jeter Nouveau Erreur("L'humidité relative est en dehors de la plage [0,1]");

    HumRatio = cette.GetHumRatioFromRelHum(TDryBulb, RelHum, Pression);
    retour cette.GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pression);
  }

  // Renvoie l'humidité relative en fonction de la température du bulbe sec et de la température du point de rosée.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 22
  cette.GetRelHumFromTDewPoint = fonction  // (o) Humidité relative [0-1]
    ( TDryBulb                            // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , TDewPoint                           // (i) Température du point de rosée en °F [IP] ou °C [SI]
    ) {
    var VapPres, SatVapPres ;

    si (!(TDewPoint <= TDryBulb))
      jeter Nouveau Erreur("La température du point de rosée est supérieure à la température du bulbe sec");

    VapPres = cette.GetSatVapPres(TDewPoint);
    SatVapPres = cette.GetSatVapPres(TDryBulb);
    retour VapPres / SatVapPres ;
  }

  // Renvoie l'humidité relative en fonction de la température du bulbe sec, de la température du bulbe humide et de la pression.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
  cette.GetRelHumFromTWetBulb = fonction // (o) Humidité relative [0-1]
    ( TDryBulb                          // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , TWetBulbComment                          // (i) Température du bulbe humide en °F [IP] ou °C [SI]
    , Pression                          // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var HumRatio ;

    si (!(TWetBulb <= TDryBulb))
      jeter Nouveau Erreur("La température du bulbe humide est supérieure à la température du bulbe sec");

    HumRatio = cette.GetHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pression);
    retour cette.GetRelHumFromHumRatio(TDryBulb, HumRatio, Pression);
  }

  // Renvoie la température du point de rosée en fonction de la température du bulbe sec et de l'humidité relative.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
  cette.GetTDewPointFromRelHum = fonction  // (o) Température du point de rosée en °F [IP] ou °C [SI]
    ( TDryBulb                            // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , RelHum                              // (i) Humidité relative [0-1]
    ) {
    var VapPres ;

    si (!(RelHum >= 0. && RelHum <= 1.))
      jeter Nouveau Erreur("L'humidité relative est en dehors de la plage [0,1]");

    VapPres = cette.GetVapPresFromRelHum(TDryBulb, RelHum);
    retour cette.GetTDewPointFromVapPres(TDryBulb, VapPres);
  }

  // Renvoie la température du point de rosée en fonction de la température du bulbe sec, de la température du bulbe humide et de la pression.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
  cette.GetTDewPointFromTWetBulb = fonction  // (o) Température du point de rosée en °F [IP] ou °C [SI]
    ( TDryBulb                              // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , TWetBulbComment                              // (i) Température du bulbe humide en °F [IP] ou °C [SI]
    , Pression                              // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var HumRatio ;

    si (!(TWetBulb <= TDryBulb))
      jeter Nouveau Erreur("La température du bulbe humide est supérieure à la température du bulbe sec");

    HumRatio = cette.GetHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pression);
    retour cette.GetTDewPointFromHumRatio(TDryBulb, HumRatio, Pression);
  }


  /*************************************************** ************************************************** ***
   * Conversions entre point de rosée ou humidité relative et pression de vapeur
   ************************************************** ************************************************** */

  // Renvoie la pression partielle de vapeur d'eau en fonction de l'humidité relative et de la température.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 12, 22
  cette.GetVapPresFromRelHum = fonction  // (o) Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
    ( TDryBulb                          // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , RelHum                            // (i) Humidité relative [0-1]
    ) {

    si (!(RelHum >= 0. && RelHum <= 1.))
      jeter Nouveau Erreur("L'humidité relative est en dehors de la plage [0,1]");

    retour RelHum * cette.GetSatVapPres(TDryBulb);
  }

  // Renvoie l'humidité relative en fonction de la température du bulbe sec et de la pression de vapeur.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 12, 22
  cette.GetRelHumFromVapPres = fonction  // (o) Humidité relative [0-1]
    ( TDryBulb                          // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , VapPres                           // (i) Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
    ) {

    si (!(VapPres >= 0.))
      jeter Nouveau Erreur("La pression partielle de la vapeur d'eau dans l'air humide est négative");

    retour VapPres / cette.GetSatVapPres(TDryBulb);
  }

  // Fonction d'assistance renvoyant la dérivée du logarithme népérien de la pression de vapeur saturante
  // en fonction de la température du bulbe sec.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 5 et 6
  cette.dLnPws_ = fonction       // (o) Dérivée du logarithme naturel de la pression de vapeur de l'air saturé en Psi [IP] ou Pa [SI]
    ( TDryBulb                  // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    ) {
    var dLnPws, T;

    si (cette.isIP())
    {
      J = cette.GetTRankineFromTFahrenheit(TDryBulb);

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

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

    retour dLnPws ;
  }

  // Renvoie la température du point de rosée en fonction de la température du bulbe sec et de la pression de vapeur.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 5 et 6
  // Notes : la température du point de rosée est résolue en inversant l'équation donnant la pression de vapeur d'eau
  // à saturation à partir de la température plutôt que d'utiliser les régressions fournies
  // par ASHRAE (équations 37 et 38) qui sont beaucoup moins précises et ont un
  // plage de validité plus étroite.
  // La méthode Newton-Raphson (NR) est utilisée sur le logarithme de la vapeur d'eau
  // pression en fonction de la température, qui est une fonction très fluide
  // La convergence est généralement obtenue en 3 à 5 itérations.
  // TDryBulb n'est pas vraiment nécessaire ici, juste utilisé pour plus de commodité.
  cette.GetTDewPointFromVapPres = fonction // (o) Température du point de rosée en °F [IP] ou °C [SI]
    ( TDryBulb                            // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , VapPres                             // (i) Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
    ) {
   // Fonction limites du système d'unités
  var BORNES              // Domaine de validité des équations

  si (cette.isIP())
  {
    BORNES = [-148., 392.] ;   // Domaine de validité des équations
  }
  autre
  {
    BORNES = [-100., 200.] ;   // Domaine de validité des équations
  }

  // Limites en dehors desquelles aucune solution ne peut être trouvée
  si (VapPres < cette.GetSatVapPres(LIMITES[0]) || VapPres > cette.GetSatVapPres(LIMITES[1]))
    jeter Nouveau Erreur("La pression partielle de la vapeur d'eau se situe en dehors du domaine de validité des équations");

  // Nous utilisons NR pour approximer la solution.
  // Première estimation
  var TDewPoint = TDryBulb ;      // Valeur calculée des températures du point de rosée, résolue de manière itérative en °F [IP] ou °C [SI]
  var lnVP = log(VapPres);       // Logarithme naturel de la pression partielle de la vapeur d'eau dans l'air humide

  var TDewPoint_iter ;            // Valeur de TDewPoint utilisée dans le calcul NR
  var lnVP_iter ;                 // Valeur du log de pression de vapeur d'eau utilisée dans le calcul du NR
  var indice = 1;
  faire
  {
    // Point courant
    TDewPoint_iter = TDewPoint ;
    lnVP_iter = enregistrer(cette.GetSatVapPres(TDewPoint_iter));

    // Dérivée de fonction, calculée analytiquement
    var d_lnVP = cette.dLnPws_(TDewPoint_iter);

    // Nouvelle estimation, délimitée par le domaine de validité de l'équation. 5 et 6
    TDewPoint = TDewPoint_iter - (lnVP_iter - lnVP) / d_lnVP ;
    TDewPoint = max(TDewPoint, BORNES[0]);
    TDewPoint = min(TDewPoint, BORNES[1]);

    si (indice > MAX_ITER_COUNT)
      jeter Nouveau Erreur("Convergence non atteinte dans GetTDewPointFromVapPres. Arrêt.");

    indice++ ;
  }
  tandis que (abs(TDewPoint - TDewPoint_iter) > PSYCHROLIB_TOLERANCE );
  retour min(TDewPoint, TDryBulb);
  }

  // Pression de vapeur de retour étant donné la température du point de rosée.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 36
  cette.GetVapPresFromTDewPoint = fonction // (o) Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
    ( TDewPoint                           // (i) Température du point de rosée en °F [IP] ou °C [SI]
    ) {
    retour cette.GetSatVapPres(TDewPoint);
  }


  /*************************************************** ************************************************** ***
   * Conversions de la température du bulbe humide, de la température du point de rosée ou du rapport humidité relative/humidité
   ************************************************** ************************************************** */

  // Renvoie la température du bulbe humide en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équations 33 et 35 résolues pour Tstar
  cette.GetTWetBulbFromHumRatio = fonction // (o) Température du bulbe humide en °F [IP] ou °C [SI]
    ( TDryBulb                            // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , HumRatio                            // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    , Pression                            // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    // Déclarations
    var Wstar ;
    var TDewPoint, TWetBulb, TWetBulbSup, TWetBulbInf, BoundedHumRatio ;
    var indice = 1;

    si (!(HumRapport >= 0.))
      jeter Nouveau Erreur("Le taux d'humidité est négatif");
    BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO);

    TDewPoint = cette.GetTDewPointFromHumRatio(TDryBulb, Rapport HumBounded, Pression);

    // Premières suppositions
    TWetBulbSup = TDryBulb ;
    TWetBulbInf = TDewPoint ;
    TWetBulbComment = (TWetBulbInf + TWetBulbSup) / 2.;

    // Boucle de bissection
    tandis que ((TWetBulbSup - TWetBulbInf) > PSYCHROLIB_TOLERANCE) {
      // Calculer le taux d'humidité à la température Tstar
      Wstar = cette.GetHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pression);

      // Obtenir de nouvelles limites
      si (Wstar > BoundedHumRatio)
        TWetBulbSup = TWetBulb ;
      autre
        TWetBulbInf = TWetBulb ;

      // Nouvelle estimation de la température du bulbe humide
      TWetBulbComment = (TWetBulbSup + TWetBulbInf) / 2.;

      si (indice > MAX_ITER_COUNT)
        jeter Nouveau Erreur("Convergence non atteinte dans GetTWetBulbFromHumRatio. Arrêt.");

      indice++ ;
    }

    retour TWetBulb ;
  }

  // Renvoie le rapport d'humidité en fonction de la température du bulbe sec, de la température du bulbe humide et de la pression.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équations 33 et 35
  cette.GetHumRatioFromTWetBulb = fonction // (o) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    ( TDryBulb                            // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , TWetBulbComment                            // (i) Température du bulbe humide en °F [IP] ou °C [SI]
    , Pression                            // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var Wsstar ;
    HumRatio = INVALIDE

    si (!(TWetBulb <= TDryBulb))
      jeter Nouveau Erreur("La température du bulbe humide est supérieure à la température du bulbe sec");

      Wsstar = cette.GetSatHumRatio(TWetBulb, Pression);

      si (cette.isIP())
      {
        si (TWetBulb >= FREEZING_POINT_WATER_IP)
          HumRatio = ((1093. - 0.556 * TWetBulb) * Wsstar - 0.240 * (TDDryBulb - TWetBulb))
          / (1093. + 0.444 * TDryBulb - TWetBulb);
        autre
          HumRatio = ((1220. - 0.04 * TWetBulb) * Wsstar - 0.240 * (TDDryBulb - TWetBulb))
          / (1220. + 0.444 * TDryBulb - 0.48 * TWetBulb);
      }
      autre
      {
        si (TWetBulb >= FREEZING_POINT_WATER_SI)
          HumRatio = ((2501. - 2.326 * TWetBulb) * Wsstar - 1.006 * (TDDryBulb - TWetBulb))
             / (2501. + 1.86 * TDryBulb - 4.186 * TWetBulb);
        autre
          HumRatio = ((2830. - 0.24 * TWetBulb) * Wsstar - 1.006 * (TDDryBulb - TWetBulb))
             / (2830. + 1.86 * TDryBulb - 2.1 * TWetBulb);
      }
      // Contrôle de validité.
      retour max(HumRapport, MIN_HUM_RATIO);
    }

  // Renvoie le rapport d'humidité en fonction de la température du bulbe sec, de l'humidité relative et de la pression.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
  cette.GetHumRatioFromRelHum = fonction // (o) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    ( TDryBulb                          // (i) Température du bulbe sec [F]
    , RelHum                            // (i) Humidité relative [0-1]
    , Pression                          // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var VapPres ;

    si (!(RelHum >= 0. && RelHum <= 1.))
      jeter Nouveau Erreur("L'humidité relative est en dehors de la plage [0,1]");

    VapPres = cette.GetVapPresFromRelHum(TDryBulb, RelHum);
    retour cette.GetHumRatioFromVapPres(VapPres, Pression);
  }

  // Renvoie l'humidité relative en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
  cette.GetRelHumFromHumRatio = fonction // (o) Humidité relative [0-1]
    ( TDryBulb                          // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , HumRatio                          // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    , Pression                          // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var VapPres ;

    si (!(HumRapport >= 0.))
      jeter Nouveau Erreur("Le taux d'humidité est négatif");

    VapPres = cette.GetVapPresFromHumRatio(HumRatio, Pression);
    retour cette.GetRelHumFromVapPres(TDryBulb, VapPres);
  }

  // Renvoie le taux d'humidité en fonction de la température et de la pression du point de rosée.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
  cette.GetHumRatioFromTDewPoint = fonction  // (o) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    ( TDewPoint                             // (i) Température du point de rosée en °F [IP] ou °C [SI]
    , Pression                              // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var VapPres ;

    VapPres = cette.GetSatVapPres(TDewPoint);
    retour cette.GetHumRatioFromVapPres(VapPres, Pression);
  }

  // Renvoie la température du point de rosée en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
  cette.GetTDewPointFromHumRatio = fonction  // (o) Température du point de rosée en °F [IP] ou °C [SI]
    ( TDryBulb                              // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , HumRatio                              // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    , Pression                              // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var VapPres ;

    si (!(HumRapport >= 0.))
      jeter Nouveau Erreur("Le taux d'humidité est négatif");

    VapPres = cette.GetVapPresFromHumRatio(HumRatio, Pression);
    retour cette.GetTDewPointFromVapPres(TDryBulb, VapPres);
  }


  /*************************************************** ************************************************** ***
   * Conversions entre taux d'humidité et pression de vapeur
   ************************************************** ************************************************** */

  // Rapport d'humidité de retour étant donné la pression de vapeur d'eau et la pression atmosphérique.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 20
  cette.GetHumRatioFromVapPres = fonction  // (o) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    ( VapPres                             // (i) Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
    , Pression                            // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var HumRatio ;

    si (!(VapPres >= 0.))
      jeter Nouveau Erreur("La pression partielle de la vapeur d'eau dans l'air humide est négative");

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

    // Contrôle de validité.
    retour max(HumRapport, MIN_HUM_RATIO);
  }

  // Pression de vapeur de retour étant donné le taux d'humidité et la pression.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 20 résolue pour pw
  cette.GetVapPresFromHumRatio = fonction  // (o) Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
    ( HumRatio                            // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    , Pression                            // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var VapPres, BoundedHumRatio ;

    si (!(HumRapport >= 0.))
      jeter Nouveau Erreur("Le taux d'humidité est négatif");
    BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO);

    VapPres = Pression * BoundedHumRatio / (0.621945 + BoundedHumRatio );
    retour VapPres ;
  }


  /*************************************************** ************************************************** ***
   * Conversions entre taux d'humidité et humidité spécifique
   ************************************************** ************************************************** */

  // Renvoie l'humidité spécifique à partir du rapport d'humidité (alias rapport de mélange)
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 9b
  cette.GetSpecificHumFromHumRatio = fonction  // (o) Taux d'humidité spécifique en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    ( HumRatio                                // (i) Taux d'humidité en lb_H₂O lb_Dry_Air⁻¹ [IP] ou kg_H₂O kg_Dry_Air⁻¹ [SI]
    ) {
    var BoundedHumRatio ;
    si (!(HumRapport >= 0.))
      jeter Nouveau Erreur("Le taux d'humidité est négatif");
    BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO);

    retour BoundedHumRatio / (1.0 + BoundedHumRatio );
  }

  // Renvoie le taux d'humidité (alias taux de mélange) à partir d'une humidité spécifique
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 9b (résolu pour le taux d'humidité)
  cette.GetHumRatioFromSpecificHum = fonction  // (o) Taux d'humidité en lb_H₂O lb_Dry_Air⁻¹ [IP] ou kg_H₂O kg_Dry_Air⁻¹ [SI]
    ( SpécifiqueHum                             // (i) Taux d'humidité spécifique en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    ) {
    var HumRatio ;

    si (!(SpécifiqueHum >= 0.0 && SpécifiqueHum < 1.0))
      jeter Nouveau Erreur("L'humidité spécifique est en dehors de la plage [0, 1[");

    HumRatio = SpécifiqueHum / (1.0 - SpecificHum);

    // Contrôle de validité
    retour max(HumRapport, MIN_HUM_RATIO);
  }


  /*************************************************** ************************************************** ***
   * Calculs d'air sec
   ************************************************** ************************************************** */

  // Renvoie l'enthalpie de l'air sec en fonction de la température du bulbe sec.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 28
  cette.GetDryAirEnthalpy = fonction // (o) Enthalpie de l'air sec en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
    ( TDryBulb                      // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    ) {
    si (cette.isIP())
      retour 0.240 * TDryBulb ;
    autre
      retour 1006. * TDryBulb ;
  }

  // Renvoie la densité de l'air sec en fonction de la température et de la pression du bulbe sec.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
  // Notes : équation 14 pour la relation gazeuse parfaite pour l'air sec.
  // Eqn 1 pour la constante universelle des gaz.
  // Le facteur 144 en IP est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².
  cette.GetDryAirDensity = fonction  // (o) Densité de l'air sec en lb ft⁻³ [IP] ou kg m⁻³ [SI]
    ( TDryBulb                      // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , Pression                      // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    si (cette.isIP())
      retour (144. * Pression) / R_DA_IP / cette.GetTRankineFromTFahrenheit(TDryBulb);
    autre
      retour Pression / R_DA_SI / cette.GetTKelvinFromTCelsius(TDryBulb);
  }

  // Renvoie le volume d'air sec en fonction de la température et de la pression du bulbe sec.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1.
  // Notes : équation 14 pour la relation gazeuse parfaite pour l'air sec.
  // Eqn 1 pour la constante universelle des gaz.
  // Le facteur 144 en IP est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².
  cette.GetDryAirVolume = fonction // (o) Volume d'air sec ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
    ( TDryBulb                    // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , Pression                    // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    si (cette.isIP())
      retour R_DA_IP * cette.GetTRankineFromTFahrenheit(TDryBulb) / (144. * Pression);
    autre
      retour R_DA_SI * cette.GetTKelvinFromTCelsius(TDryBulb) / Pression;
  }

  // Renvoie la température du bulbe sec à partir de l'enthalpie et du rapport d'humidité.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 30.
  // Notes : basé sur la fonction `GetMoistAirEnthalpy`, réorganisé pour la température.
  cette.GetTDryBulbFromEnthalpyAndHumRatio = fonction   // (o) Température du bulbe sec en °F [IP] ou °C [SI]
    ( Enthalpie de l'air humide                                 // (i) Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹
    , HumRatio                                         // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    ) {
    var BoundedHumRatio ;
    si (!(HumRapport >= 0.))
      jeter Nouveau Erreur("Le taux d'humidité est négatif");
    BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO);

    si (cette.isIP())
      retour (Enthalpie de l'air humide - 1061.0 * BoundedHumRatio) / (0.240 + 0.444 * BoundedHumRatio );
    autre
      retour (Enthalpie de l'air humide / 1000.0 - 2501.0 * BoundedHumRatio) / (1.006 + 1.86 * BoundedHumRatio );
    }

  // Renvoie le rapport d'humidité à partir de l'enthalpie et de la température du bulbe sec.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 30.
  // Notes : basé sur la fonction `GetMoistAirEnthalpy`, réorganisé pour le taux d'humidité.
  cette.GetHumRatioFromEnthalpyAndTDryBulb = fonction   // (o) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻
    ( Enthalpie de l'air humide                                 // (i) Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹
    , TDryBulb                                         // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    ) {
    var HumRatio ;
    si (cette.isIP())
      HumRatio = (Enthalpie de l'air humide - 0.240 * TDryBulb) / (1061.0 + 0.444 * TDryBulb);
    autre
      HumRatio = (Enthalpie de l'air humide / 1000.0 - 1.006 * TDryBulb) / (2501.0 + 1.86 * TDryBulb);

    // Contrôle de validité.
    retour max(HumRapport, MIN_HUM_RATIO);
    }


  /*************************************************** ************************************************** ***
   * Calculs d'air saturé
   ************************************************** ************************************************** */

  // Renvoie la pression de vapeur saturante étant donné la température du bulbe sec.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 5 et 6
  // Note importante : les formules ASHRAE sont définies au dessus et en dessous du point de congélation mais ont
  // une discontinuité au point de congélation. Il s'agit d'une petite inexactitude de la part d'ASHRAE : les formules
  // doit être défini au-dessus et en dessous du point triple de l'eau (et non du point de congélation), auquel cas
  // la discontinuité disparaît. Il est indispensable d'utiliser le point triple d'eau sinon fonctionne
  // GetTDewPointFromVapPres, qui inverse la fonction actuelle, ne converge pas correctement autour
  // le point de congélation.
  cette.GetSatVapPres = fonction // (o) Pression de vapeur de l'air saturé en Psi [IP] ou Pa [SI]
    ( TDryBulb                  // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    ) {
    var LnPws, T;

    si (cette.isIP())
    {
      si (!(TDampoule sèche >= -148. && TDryBulb <= 392.))
        jeter Nouveau Erreur("La température du bulbe sec est en dehors de la plage [-148, 392]");

      J = cette.GetTRankineFromTFahrenheit(TDryBulb);
      si (TDDryBulb <= TRIPLE_POINT_WATER_IP)
        LnPws = (-1.0214165Mi+04 / J - 4.8932428 - 5.3765794E-03 * J + 1.9202377E-07 * J * J
                + 3.5575832E-10 * pow(T, 3) - 9.0344688E-14 * pow(T, 4) + 4.1635019 * log(T));
      autre
        LnPws = -1.0440397Mi+04 / J - 1.1294650Mi+01 - 2.7022355E-02 * J + 1.2890360E-05 * J * J
                - 2.4780681E-09 * pow(T, 3) + 6.5459673 * log(T);
    }
    autre
    {
      si (!(TDampoule sèche >= -100. && TDryBulb <= 200.))
        jeter Nouveau Erreur("La température du bulbe sec est en dehors de la plage [-100, 200]");

      J = cette.GetTKelvinFromTCelsius(TDryBulb);
      si (TDDryBulb <= TRIPLE_POINT_WATER_SI)
        LnPws = -5.6745359Mi+03 / J + 6.3925247 - 9.677843E-03 * J + 6.2215701E-07 * J * J
                + 2.0747825E-09 * pow(T, 3) - 9.484024E-13 * pow(T, 4) + 4.1635019 * log(T);
      autre
        LnPws = -5.8002206Mi+03 / J + 1.3914993 - 4.8640239E-02 * J + 4.1764768E-05 * J * J
                - 1.4452093E-08 * pow(T, 3) + 6.5459673 * log(T);
    }

    retour exp(LnPws);
  }

  // Taux d'humidité de retour de l'air saturé en fonction de la température et de la pression du bulbe sec.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 36, résolue pour W
  cette.GetSatHumRatio = fonction  // (o) Taux d'humidité de l'air saturé en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    ( TDryBulb                    // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , Pression                    // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var SatVaporPres, SatHumRatio ;

    SatVaporPres = cette.GetSatVapPres(TDryBulb);
    SatHumRatio = 0.621945 * SatVaporPres / (Pression - SatVaporPres);

    // Contrôle de validité.
    retour max(SatHumRatio, MIN_HUM_RATIO);
  }

  // Renvoie l'enthalpie de l'air saturé en fonction de la température et de la pression du bulbe sec.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
  cette.GetSatAirEnthalpy = fonction // (o) Enthalpie de l'air saturé en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
    ( TDryBulb                      // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , Pression                      // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    retour cette.GetMoistAirEnthalpy(TDDryBulb, cette.GetSatHumRatio(TDDryBulb, Pression));
  }


  /*************************************************** ************************************************** ***
   * Calculs d'air humide
   ************************************************** ************************************************** */

  // Retour Déficit de pression de vapeur en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
  // Référence : voir Oke (1987) eqn. 2.13a
  cette.GetVaporPressureDeficit = fonction  // (o) Déficit de pression de vapeur en Psi [IP] ou Pa [SI]
    ( TDryBulb            // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , HumRatio            // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    , Pression            // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var RelHum ;

    si (!(HumRapport >= 0.))
      jeter Nouveau Erreur("Le taux d'humidité est négatif");

    RelHum = cette.GetRelHumFromHumRatio(TDryBulb, HumRatio, Pression);
    retour cette.GetSatVapPres(TDryBulb) * (1. - RelHum);
  }

  // Renvoie le degré de saturation (c'est à dire le rapport humidité de l'air / rapport humidité de l'air à saturation
  // à la même température et pression) étant donné la température du bulbe sec, le taux d'humidité et la pression atmosphérique.
  // Référence : ASHRAE Handbook - Fundamentals (2009) ch. 1 éq. 12
  // Notes : la définition est absente du Manuel 2017
  cette.GetDegreeOfSaturation = fonction // (o) Degré de saturation (sans unité)
    ( TDryBulb                          // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , HumRatio                          // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    , Pression                          // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var BoundedHumRatio ;

    si (!(HumRapport >= 0.))
      jeter Nouveau Erreur("Le taux d'humidité est négatif");
    BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO);

    retour BoundedHumRatio / cette.GetSatHumRatio(TDDryBulb, Pression);
  }

  // Renvoie l'enthalpie de l'air humide en fonction de la température du bulbe sec et du rapport d'humidité.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 30
  cette.GetMoistAirEnthalpy = fonction // (o) Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
    ( TDryBulb                        // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , HumRatio                        // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    ) {
    var BoundedHumRatio ;

    si (!(HumRapport >= 0.))
      jeter Nouveau Erreur("Le taux d'humidité est négatif");
    BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO);

    si (cette.isIP())
      retour 0.240 * TDryBulb + BoundedHumRatio * (1061. + 0.444 * TDryBulb);
    autre
      retour (1.006 * TDryBulb + BoundedHumRatio * (2501. + 1.86 * TDryBulb)) * 1000.;
  }

  // Renvoie le volume spécifique d'air humide en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 26
  // Notes : en unités IP, R_DA_IP / 144 est égal à 0,370486 qui est le coefficient apparaissant dans l'équation 26.
  // Le facteur 144 est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².
  cette.GetMoistAirVolume = fonction // (o) Volume spécifique ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
    ( TDryBulb                      // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , HumRatio                      // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    , Pression                      // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var BoundedHumRatio ;

    si (!(HumRapport >= 0.))
      jeter Nouveau Erreur("Le taux d'humidité est négatif");
    BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO);

    si (cette.isIP())
      retour R_DA_IP * cette.GetTRankineFromTFahrenheit(TDryBulb) * (1. + 1.607858 * BoundedHumRatio) / (144. * Pression);
    autre
      retour R_DA_SI * cette.GetTKelvinFromTCelsius(TDryBulb) * (1. + 1.607858 * BoundedHumRatio) / Pression;
  }

  // Renvoie la température du bulbe sec en fonction du volume spécifique de l'air humide, du taux d'humidité et de la pression.
  // Référence:
  // Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 26
  // Remarques:
  // En unités IP, R_DA_IP/144 est égal à 0,370486 qui est le coefficient apparaissant dans l'équation 26
  // Le facteur 144 est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².
  // Basé sur la fonction `GetMoistAirVolume`, réorganisée pour la température sèche.
  cette.GetTDryBulbFromMoistAirVolumeAndHumRatio = fonction  // (o) Température du bulbe sec en °F [IP] ou °C [SI]
    ( Volume d'air humide                                        // (i) Volume spécifique d'air humide en pi³ lb⁻¹ d'air sec [IP] ou en m³ kg⁻¹ d'air sec [SI]
    , HumRatio                                              // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    , Pression                                              // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var BoundedHumRatio ;

    si (!(HumRapport >= 0.))
      jeter Nouveau Erreur("Le taux d'humidité est négatif");
    BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO);

    si (cette.isIP())
      retour cette.GetTFahrenheitFromTRankine (MoistAirVolume * (144 * Pression) / (R_DA_IP * (1 + 1.607858 * BoundedHumRatio)));
    autre
      retour  cette.GetTCelsiusFromTKelvin (MoistAirVolume * Pression / (R_DA_SI * (1 + 1.607858 * BoundedHumRatio)));
  }

  // Renvoie la densité de l'air humide en fonction du taux d'humidité, de la température du bulbe sec et de la pression.
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 11
  cette.GetMoistAirDensity = fonction  // (o) Densité de l'air humide en lb ft⁻³ [IP] ou kg m⁻³ [SI]
    ( TDryBulb                        // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , HumRatio                        // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
    , Pression                        // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var BoundedHumRatio ;

    si (!(HumRapport >= 0.))
      jeter Nouveau Erreur("Le taux d'humidité est négatif");
    BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO);

    retour (1. + BoundedHumRatio) / cette.GetMoistAirVolume(TDDryBulb, Rapport HumBounded, Pression);
  }


  /*************************************************** ************************************************** ***
   * Atmosphère normale
   ************************************************** ************************************************** */

  // Renvoie la pression barométrique de l'atmosphère standard, compte tenu de l'élévation (altitude).
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 3
  cette.GetStandardAtmPressure = fonction  // (o) Pression barométrique de l'atmosphère standard en Psi [IP] ou Pa [SI]
    ( Altitude                            // (i) Altitude en ft [IP] ou m [SI]
    ) {
    var Pression;

    si (cette.isIP())
      Pression = 14.696 * Pow (1. - 6.8754e-06 * Altitude, 5.2559);
    autre
      Pression = 101325.* Pow (1. - 2.25577e-05 * Altitude, 5.2559);
    retour Pression;
  }

  // Renvoie la température atmosphérique standard, compte tenu de l'élévation (altitude).
  // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 4
  cette.GetStandardAtmTemperature = fonction // (o) Température du bulbe sec dans l'atmosphère standard en °F [IP] ou °C [SI]
    ( Altitude                              // (i) Altitude en ft [IP] ou m [SI]
    ) {
    var Température;
    si (cette.isIP())
      Température = 59. - 0.00356620 * Altitude;
    autre
      Température = 15. - 0.0065 * Altitude;
    retour Température;
  }

  // Renvoie la pression au niveau de la mer en fonction de la température du bulbe sec, de l'altitude au-dessus du niveau de la mer et de la pression.
  // Référence : Hess SL, Introduction à la météorologie théorique, Holt Rinehart et Winston, NY 1959,
  // ch. 6,5 ; Stull RB, Météorologie pour les scientifiques et les ingénieurs, 2e édition,
  // Brooks/Cole 2000, ch. 1.
  // Notes : la procédure standard pour les États-Unis consiste à utiliser pour TDryBulb la moyenne
  // de la température actuelle de la station et de la température de la station d'il y a 12 heures.
  cette.GetSeaLevelPressure = fonction // (o) Pression barométrique au niveau de la mer en Psi [IP] ou Pa [SI]
    ( StnPression                     // (i) Pression de station observée en Psi [IP] ou Pa [SI]
    , Altitude                        // (i) Altitude au-dessus du niveau de la mer en pieds [IP] ou m [SI]
    , TDryBulb                        // (i) Température du bulbe sec ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
    ) {
      var TColonne, H;
      si (cette.isIP())
      {
        // Calculer la température moyenne dans la colonne d'air, en supposant un taux de déchéance
        // de 3,6 °F/1000 pieds
        TColonne = TDryBulb + 0.0036 * Altitude / 2.;

        // Déterminer la hauteur de l'échelle
        H = 53.351 * cette.GetTRankineFromTFahrenheit(TColumn);
      }
      autre
      {
        // Calculer la température moyenne dans la colonne d'air, en supposant un taux de déchéance
        // de 6,5 °C/km
        TColonne = TDryBulb + 0.0065 * Altitude / 2.;

        // Déterminer la hauteur de l'échelle
        H = 287.055 * cette.GetTKelvinFromTCelsius(TColonne) / 9.807;
      }

      // Calculer la pression au niveau de la mer
      var PressionNiveau De La Mer = StnPression * exp(altitude / H);
      retour pression au niveau de la mer ;
  }

  // Pression de retour de la station à partir de la pression au niveau de la mer
  // Référence : voir 'GetSeaLevelPressure'
  // Notes : cette fonction est juste l'inverse de 'GetSeaLevelPressure'.
  cette.GetStationPressure = fonction  // (o) Pression de la station en Psi [IP] ou Pa [SI]
    ( PressionNiveau De La Mer                // (i) Pression barométrique au niveau de la mer en Psi [IP] ou Pa [SI]
    , Altitude                        // (i) Altitude au-dessus du niveau de la mer en pieds [IP] ou m [SI]
    , TDryBulb                        // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    ) {
    retour PressionNiveau De La Mer / cette.GetSeaLevelPressure(1., Altitude, TDryBulb);
  }


  /*************************************************** ************************************************** ***
   * Fonctions pour définir toutes les valeurs psychrométriques
   ************************************************** ************************************************** */

  // Fonction utilitaire pour calculer le taux d'humidité, la température du point de rosée, l'humidité relative,
  // pression de vapeur, enthalpie de l'air humide, volume d'air humide et degré de saturation de l'air donné
  // température du bulbe sec, température du bulbe humide et pression.
  cette.CalcPsychrometricsFromTWetBulb = fonction
    /**
     * HumRatio // (o) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
     * TDewPoint // (o) Température du point de rosée en °F [IP] ou °C [SI]
     * RelHum // (o) Humidité relative [0-1]
     * VapPres // (o) Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
     * MoistAirEnthalpy // (o) Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
     * MoistAirVolume // (o) Volume spécifique ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
     * DegreeOfSaturation // (o) Degré de saturation [sans unité]
     */
    ( TDryBulb            // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , TWetBulbComment            // (i) Température du bulbe humide en °F [IP] ou °C [SI]
    , Pression            // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var HumRatio = cette.GetHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pression);
    var TDewPoint = cette.GetTDewPointFromHumRatio(TDryBulb, HumRatio, Pression);
    var RelHum = cette.GetRelHumFromHumRatio(TDryBulb, HumRatio, Pression);
    var VapPres = cette.GetVapPresFromHumRatio(HumRatio, Pression);
    var Enthalpie de l'air humide = cette.GetMoistAirEnthalpy(TDDryBulb, HumRatio);
    var Volume d'air humide = cette.GetMoistAirVolume(TDDryBulb, HumRatio, Pression);
    var DegréDeSaturation = cette.GetDegreeOfSaturation(TDryBulb, HumRatio, Pression);
    retour [HumRapport, TDewPoint, RelHum, VapPres, Enthalpie de l'air humide, Volume d'air humide, DegréDeSaturation] ;
  }

  // Fonction utilitaire pour calculer le taux d'humidité, la température du bulbe humide, l'humidité relative,
  // pression de vapeur, enthalpie de l'air humide, volume d'air humide et degré de saturation de l'air donné
  // température du bulbe sec, température du point de rosée et pression.
  cette.CalcPsychrometricsFromTDewPoint = fonction
    /**
     * HumRatio // (o) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
     * TWetBulb // (o) Température du bulbe humide en °F [IP] ou °C [SI]
     * RelHum // (o) Humidité relative [0-1]
     * VapPres // (o) Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
     * MoistAirEnthalpy // (o) Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
     * MoistAirVolume // (o) Volume spécifique ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
     * DegreeOfSaturation // (o) Degré de saturation [sans unité]
     */
    ( TDryBulb            // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , TDewPoint           // (i) Température du point de rosée en °F [IP] ou °C [SI]
    , Pression            // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var HumRatio = cette.GetHumRatioFromTDewPoint(TDewPoint, Pression);
    var TWetBulbComment = cette.GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pression);
    var RelHum = cette.GetRelHumFromHumRatio(TDryBulb, HumRatio, Pression);
    var VapPres = cette.GetVapPresFromHumRatio(HumRatio, Pression);
    var Enthalpie de l'air humide = cette.GetMoistAirEnthalpy(TDDryBulb, HumRatio);
    var Volume d'air humide = cette.GetMoistAirVolume(TDDryBulb, HumRatio, Pression);
    var DegréDeSaturation = cette.GetDegreeOfSaturation(TDryBulb, HumRatio, Pression);
    retour [HumRapport, TWetBulb, RelHum, VapPres, Enthalpie de l'air humide, Volume d'air humide, DegréDeSaturation] ;
  }

  // Fonction utilitaire pour calculer le taux d'humidité, la température du bulbe humide, la température du point de rosée,
  // pression de vapeur, enthalpie de l'air humide, volume d'air humide et degré de saturation de l'air donné
  // température du bulbe sec, humidité relative et pression.
  cette.CalcPsychrometricsFromRelHum = fonction
    /**
     * HumRatio // (o) Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
     * TWetBulb // (o) Température du bulbe humide en °F [IP] ou °C [SI]
     * TDewPoint // (o) Température du point de rosée en °F [IP] ou °C [SI]
     * VapPres // (o) Pression partielle de vapeur d'eau dans l'air humide [Psi]
     * MoistAirEnthalpy // (o) Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
     * MoistAirVolume // (o) Volume spécifique ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
     * DegreeOfSaturation // (o) Degré de saturation [sans unité]
    */
    ( TDryBulb            // (i) Température du bulbe sec en °F [IP] ou °C [SI]
    , RelHum              // (i) Humidité relative [0-1]
    , Pression            // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
    ) {
    var HumRatio = cette.GetHumRatioFromRelHum(TDryBulb, RelHum, Pression);
    var TWetBulbComment = cette.GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pression);
    var TDewPoint = cette.GetTDewPointFromHumRatio(TDryBulb, HumRatio, Pression);
    var VapPres = cette.GetVapPresFromHumRatio(HumRatio, Pression);
    var Enthalpie de l'air humide = cette.GetMoistAirEnthalpy(TDDryBulb, HumRatio);
    var Volume d'air humide = cette.GetMoistAirVolume(TDDryBulb, HumRatio, Pression);
    var DegréDeSaturation = cette.GetDegreeOfSaturation(TDryBulb, HumRatio, Pression);
    retour [HumRapport, TWetBulb, TDewPoint, VapPres, Enthalpie de l'air humide, Volume d'air humide, DegréDeSaturation] ;
  }
}

// https://github.com/umdjs/umd
(fonction (racine, usine) {
  si (Type de définir === 'fonction' && définir.amd) {
      // DMLA. Inscrivez-vous en tant que module anonyme.
      définir([], usine);
  } autre si (Type de module === 'objet' && module.exports) {
      // Nœud. Ne fonctionne pas avec CommonJS strict, mais
      // uniquement les environnements de type CommonJS prenant en charge module.exports,
      // comme Node.
      module.exports = usine();
  } autre {
      // Globales du navigateur (la racine est la fenêtre)
      racine.psychrolib = usine();
}
}(Type de soi !== 'indéfini' ? soi : cette, fonction () {
  retour Nouveau Psychrométrie();
}));

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 (version 2.3.0) (https://github.com/psychrometrics/psychrolib)
 * Copyright (c) 2018 D. Thevenard et D. Meyer pour l'implémentation actuelle de la bibliothèque
 * Copyright (c) Manuel ASHRAE 2017 — Principes fondamentaux des équations et coefficients ASHRAE
 * Sous licence MIT.
 *
 * Présentation des modules
 * Contient des fonctions de calcul des propriétés thermodynamiques des mélanges gaz-vapeur
 * et atmosphère standard adaptée à la plupart des applications techniques, physiques et météorologiques
 * applications.
 *
 * La plupart des fonctions sont une implémentation des formules trouvées dans le
 * Manuel ASHRAE 2017 - Fondamentaux, dans les deux systèmes internationaux (SI),
 * et unités impériales (IP). Veuillez vous référer aux informations incluses dans
 * chaque fonction pour sa référence respective.
 *
 * Exemple
 * #include "psychrolib.h"
 * // Définit le système d'unités, par exemple sur SI (peut être 'SI' ou 'IP')
 * SetUnitSystem(SI);
 * // Calculer la température du point de rosée pour une température sèche de 25 C et une humidité relative de 80 %
 * double TDewPoint = GetTDewPointFromRelHum(25,0, 0,80) ;
 * printf("%lg", TDewPoint);
 * 21.3094
 *
 * Droits d'auteur
 * - Pour l'implémentation actuelle de la bibliothèque
 * Copyright (c) 2018 D. Thevenard et D. Meyer.
 * - Pour les équations et les coefficients publiés ASHRAE Handbook — Fundamentals, Chapitre 1
 * Copyright (c) Manuel ASHRAE 2017 — Fondamentaux (https://www.ashrae.org)
 *
 * Licence
 * MIT (https://github.com/psychrometrics/psychrolib/LICENSE.txt)
 *
 * Remarque des auteurs
 * Nous avons fait tous les efforts possibles pour garantir que le code soit adéquat, mais nous ne faisons aucun
 * représentation quant à son exactitude. À utiliser à vos risques et périls. Si vous remarquez
 * une erreur, ou si vous avez une suggestion, veuillez nous en informer via GitHub à l'adresse
 * https://github.com/psychrometrics/psychrolib/issues.
 */

// Fichiers d'en-tête C standard
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

// En-tête spécifique à ce fichier
#include "psychrolib.h"


/*************************************************** ************************************************** ***
 * Constantes globales
 ************************************************** ************************************************** */

# définir ZERO_FAHRENHEIT_AS_RANKINE 459,67  // Zéro degré Fahrenheit (°F) exprimé en degré Rankine (°R).
                                            // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 39.

# définir ZERO_CELSIUS_AS_KELVIN 273.15      // Zéro degré Celsius (°C) exprimé en Kelvin (K).
                                            // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 39.

#définir R_DA_IP 53.350                  // Constante de gaz universelle pour l'air sec (version IP) en ft∙lbf/lb_da/R.
                                        // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1.

#définir R_DA_SI 287.042                 // Constante universelle des gaz pour l'air sec (version SI) en J/kg_da/K.
                                        // Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1.

#define INVALIDE -99999                  // Valeur invalide.

#define MAX_ITER_COUNT 100              // Nombre maximum d'itérations avant de quitter les boucles while.

#définir MIN_HUM_RATIO 1e-7              // Rapport d'humidité minimum acceptable utilisé/renvoyé par toutes les fonctions.
                                        // Toute valeur supérieure à 0 ou inférieure au MIN_HUM_RATIO sera réinitialisée à cette valeur.

#définir FREEZING_POINT_WATER_IP 32.0    // Point de congélation de l'eau en Fahrenheit.

#définir FREEZING_POINT_WATER_SI 0.0     // Point de congélation de l'eau en Celsius.

#définir TRIPLE_POINT_WATER_IP 32.018    // Triple point d'eau en Fahrenheit.

#définir TRIPLE_POINT_WATER_SI 0.01      // Triple point d'eau en Celsius.


/*************************************************** ************************************************** ***
 * Fonctions d'assistance
 ************************************************** ************************************************** */

#define ASSERT(condition, msg) \
  si (! (condition)) \
  { \
    Assert(msg, __FILE__, __LINE__); \
  }

// Fonction appelée si une assertion échoue
// Remplacez cette fonction par votre propre fonction pour un meilleur traitement des erreurs
annuler Affirmer
    ( carboniser *Msg                 // (i) message à imprimer à l'écran
    , carboniser *Nom de fichier            // (i) nom du fichier dans lequel l'erreur s'est produite
    , entier N°Ligne                // (i) numéro de ligne dans laquelle l'erreur s'est produite
    )
{
  printf("L'assertion a échoué dans le fichier %s à la ligne %d :", Nom de fichier, N°Ligne);
  printf("%s", Msg);
  printf("Programme abandonné...");
  printf("\un");
  sortie(1);
}

// Macros Min et Max (au cas où elles ne seraient pas définies)
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#fin si

#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#fin si

// Systèmes d'unités (IP ou SI)
statique énumération Système d'unité PSYCHROLIB_UNITS = INDÉFINI;

// Tolérance des calculs de température
statique double PSYCHROLIB_TOLERANCE = 1.;

// Définit le système d'unités à utiliser (SI ou IP).
// Remarque : cette fonction *DOIT ÊTRE APPELÉE* avant que la bibliothèque puisse être utilisée
annuler DéfinirSystèmeUnité
  ( énumération Système d'unité Unités       // (i) Système d'unités (IP ou SI)
  )
{
  PSYCHROLIB_UNITS = Unités;

  // Définir la tolérance sur les calculs de température
  // La tolérance est la même en IP et SI
  si (PSYCHROLIB_UNITS == IP)
    PSYCHROLIB_TOLERANCE = 0.001 * 9. / 5.;
  autre
    PSYCHROLIB_TOLERANCE = 0.001;
}

// Renvoie le système d'unités utilisé.
énumération Système d'unité ObtenirUnitSystem  // (o) Système d'unités (SI ou IP)
  (
  )
{
  retour PSYCHROLIB_UNITS ;
}

// Vérifiez si le système utilisé est IP ou SI.
// La fonction se termine en erreur si le système d'unités n'est pas défini
entier estIP                    // (o) 1 si IP, 0 si SI, erreur sinon
(
)
{
  si (PSYCHROLIB_UNITS == IP)
    retour 1;
  autre si (PSYCHROLIB_UNITS == SI)
    retour 0;
  autre
  {
    printf("Le système d'unités n'a pas été défini");
    sortie(1);
  }
}


/*************************************************** ************************************************** ***
 * Conversion entre unités de température
 ************************************************** ************************************************** */

// Fonction utilitaire pour convertir la température en degré Rankine (°R)
// température donnée en degrés Fahrenheit (°F).
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 chapitre 3
double GetTRankineFromTFahrenheit(double T_F) { retour T_F + ZERO_FAHRENHEIT_AS_RANKINE ; }         /* exact */

// Fonction utilitaire pour convertir la température en degrés Fahrenheit (°F)
// température donnée en degré Rankine (°R).
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 chapitre 3
double GetTFahrenheitFromTRankine(double T_R) { retour T_R - ZERO_FAHRENHEIT_AS_RANKINE ; }        /* exact */

// Fonction utilitaire pour convertir la température en Kelvin (K)
// température donnée en degrés Celsius (°C).
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 chapitre 3
double GetTKelvinDeTCelsius(double T_C) { retour T_C + ZERO_CELSIUS_AS_KELVIN ; }                /* exact */

// Fonction utilitaire pour convertir la température en degrés Celsius (°C)
// température donnée en Kelvin (K).
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 chapitre 3
double GetTCelsiusFromTKelvin(double T_K) { retour T_K - ZERO_CELSIUS_AS_KELVIN ; }                /* exact */


/*************************************************** ************************************************** ***
 * Conversions entre point de rosée, bulbe humide et humidité relative
 ************************************************** ************************************************** */

// Renvoie la température du bulbe humide en fonction de la température du bulbe sec, de la température du point de rosée et de la pression.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
double GetTWetBulbFromTDewPoint // (o) Température du bulbe humide en °F [IP] ou °C [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double TDewPoint            // (i) Température du point de rosée en °F [IP] ou °C [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  double HumRatio ;

  AFFIRMER (TDewPoint <= TDryBulb, "La température du point de rosée est supérieure à la température du bulbe sec")

  HumRatio = GetHumRatioFromTDewPoint(TDewPoint, Pression);
  retour GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pression);
}

// Renvoie la température du bulbe humide en fonction de la température du bulbe sec, de l'humidité relative et de la pression.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
double GetTWetBulbFromRelHum    // (o) Température du bulbe humide en °F [IP] ou °C [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double RelHum               // (i) Humidité relative [0-1]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  double HumRatio ;

  AFFIRMER (RelHum >= 0 && RelHum <= 1, "L'humidité relative est en dehors de la plage [0,1]")

  HumRatio = GetHumRatioFromRelHum(TDryBulb, RelHum, Pression);
  retour GetTWetBulbFromHumRatio(TDryBulb, HumRatio, Pression);
}

// Renvoie l'humidité relative en fonction de la température du bulbe sec et de la température du point de rosée.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 22
double GetRelHumFromTDewPoint   // (o) Humidité relative [0-1]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double TDewPoint            // (i) Température du point de rosée en °F [IP] ou °C [SI]
  )
{
  double VapPres, SatVapPres ;

  AFFIRMER (TDewPoint <= TDryBulb, "La température du point de rosée est supérieure à la température du bulbe sec")

  VapPres = GetSatVapPres(TDewPoint);
  SatVapPres = GetSatVapPres(TDryBulb);
  retour VapPres/SatVapPres ;
}

// Renvoie l'humidité relative en fonction de la température du bulbe sec, de la température du bulbe humide et de la pression.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
double GetRelHumFromTWetBulb    // (o) Humidité relative [0-1]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double TWetBulbComment             // (i) Température du bulbe humide en °F [IP] ou °C [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  double HumRatio ;

  AFFIRMER (TWetBulb <= TDryBulb, "La température du bulbe humide est supérieure à la température du bulbe sec")

  HumRatio = GetHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pression);
  retour GetRelHumFromHumRatio(TDryBulb, HumRatio, Pression);
}

// Renvoie la température du point de rosée en fonction de la température du bulbe sec et de l'humidité relative.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
double ObtenirTDewPointFromRelHum   // (o) Température du point de rosée en °F [IP] ou °C [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double RelHum               // (i) Humidité relative [0-1]
  )
{
  double VapPres ;

  AFFIRMER (RelHum >= 0 && RelHum <= 1, "L'humidité relative est en dehors de la plage [0,1]")

  VapPres = GetVapPresFromRelHum(TDryBulb, RelHum);
  retour GetTDewPointFromVapPres(TDryBulb, VapPres);
}

// Renvoie la température du point de rosée en fonction de la température du bulbe sec, de la température du bulbe humide et de la pression.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
double GetTDewPointFromTWetBulb // (o) Température du point de rosée en °F [IP] ou °C [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double TWetBulbComment             // (i) Température du bulbe humide en °F [IP] ou °C [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  double HumRatio ;

  AFFIRMER (TWetBulb <= TDryBulb, "La température du bulbe humide est supérieure à la température du bulbe sec")

  HumRatio = GetHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pression);
  retour GetTDewPointFromHumRatio(TDryBulb, HumRatio, Pression);
}


/*************************************************** ************************************************** ***
 * Conversions entre point de rosée ou humidité relative et pression de vapeur
 ************************************************** ************************************************** */

// Renvoie la pression partielle de vapeur d'eau en fonction de l'humidité relative et de la température.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 12, 22
double GetVapPresFromRelHum     // (o) Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double RelHum               // (i) Humidité relative [0-1]
  )
{
  AFFIRMER (RelHum >= 0. && RelHum <= 1., "L'humidité relative est en dehors de la plage [0,1]")

  retour RelHum*GetSatVapPres(TDryBulb);
}

// Renvoie l'humidité relative en fonction de la température du bulbe sec et de la pression de vapeur.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 12, 22
double GetRelHumFromVapPres     // (o) Humidité relative [0-1]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double VapPres              // (i) Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
  )
{
  AFFIRMER (VapPres >= 0., "La pression partielle de la vapeur d'eau dans l'air humide est négative")

  retour VapPres/GetSatVapPres(TDryBulb);
}

// Fonction d'assistance renvoyant la dérivée du logarithme népérien de la pression de vapeur saturante
// en fonction de la température du bulbe sec.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 5 et 6
double dLnPws_        // (o) Dérivée du logarithme naturel de la pression de vapeur de l'air saturé en Psi [IP] ou Pa [SI]
  ( double TDryBulb   // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  )
{
  double dLnPws, T;

  si (estIP())
  {
    J = GetTRankineFromTFahrenheit(TDryBulb);

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

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

  retour dLnPws ;
}

// Renvoie la température du point de rosée en fonction de la température du bulbe sec et de la pression de vapeur.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 5 et 6
// Notes : la température du point de rosée est résolue en inversant l'équation donnant la pression de vapeur d'eau
// à saturation à partir de la température plutôt que d'utiliser les régressions fournies
// par ASHRAE (équations 37 et 38) qui sont beaucoup moins précises et ont un
// plage de validité plus étroite.
// La méthode Newton-Raphson (NR) est utilisée sur le logarithme de la vapeur d'eau
// pression en fonction de la température, qui est une fonction très fluide
// La convergence est généralement obtenue en 3 à 5 itérations.
// TDryBulb n'est pas vraiment nécessaire ici, juste utilisé pour plus de commodité.
double GetTDewPointFromVapPres  // (o) Température du point de rosée en °F [IP] ou °C [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double VapPres              // (i) Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
  )
{
  // Fonction limites du système d'unités
  double BORNES[2] ;              // Domaine de validité des équations

  si (estIP())
  {
    BORNES[0] = -148.;
    BORNES[1] = 392.;
  }
  autre
  {
    BORNES[0] = -100.;
    BORNES[1] = 200.;
  }

  // Limites en dehors desquelles aucune solution ne peut être trouvée
  AFFIRMER (VapPres >= GetSatVapPres(LIMES[0]) && VapPres <= GetSatVapPres(LIMES[1]),
          "La pression partielle de la vapeur d'eau se situe en dehors du domaine de validité des équations")

  // Nous utilisons NR pour approximer la solution.
  // Première estimation
  double TDewPoint = TDryBulb ;      // Valeur calculée des températures du point de rosée, résolue de manière itérative en °F [IP] ou °C [SI]
  double lnVP = log(VapPres);       // Logarithme naturel de la pression partielle de la vapeur d'eau dans l'air humide

  double TDewPoint_iter ;            // Valeur de TDewPoint utilisée dans le calcul NR
  double lnVP_iter ;                 // Valeur du log de pression de vapeur d'eau utilisée dans le calcul du NR
  entier indice = 1;

  faire
  {
    TDewPoint_iter = TDewPoint ; // TDewPoint utilisé dans le calcul NR
    lnVP_iter = log(GetSatVapPres(TDewPoint_iter));

    // Dérivée de fonction, calculée analytiquement
    double d_lnVP = dLnPws_(TDewPoint_iter);

    // Nouvelle estimation, délimitée par le domaine de validité de l'équation. 5 et 6
    TDewPoint = TDewPoint_iter - (lnVP_iter - lnVP) / d_lnVP ;
    TDewPoint = max(TDewPoint, BORNES[0]);
    TDewPoint = min(TDewPoint, BORNES[1]);

    AFFIRMER (indice <= MAX_ITER_COUNT, "Convergence non atteinte dans GetTDewPointFromVapPres. Arrêt.")

    indice++ ;
  }
  tandis que (fabs(TDewPoint - TDewPoint_iter) > PSYCHROLIB_TOLERANCE );
  retour min(TDewPoint, TDryBulb);
}

// Pression de vapeur de retour étant donné la température du point de rosée.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 36
double GetVapPresFromTDewPoint  // (o) Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
  ( double TDewPoint            // (i) Température du point de rosée en °F [IP] ou °C [SI]
  )
{
  retour GetSatVapPres(TDewPoint);
}


/*************************************************** ************************************************** ***
 * Conversions de la température du bulbe humide, de la température du point de rosée ou du rapport humidité relative/humidité
 ************************************************** ************************************************** */

// Renvoie la température du bulbe humide en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équations 33 et 35 résolues pour Tstar
double GetTWetBulbFromHumRatio  // (o) Température du bulbe humide en °F [IP] ou °C [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double HumRatio             // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  // Déclarations
  double Wstar ;
  double TDewPoint, TWetBulb, TWetBulbSup, TWetBulbInf, BoundedHumRatio ;
  entier indice = 1;

  AFFIRMER (HumRapport >= 0., "Le taux d'humidité est négatif")
  BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO);

  TDewPoint = GetTDewPointFromHumRatio(TDryBulb, Rapport HumBounded, Pression);

  // Premières suppositions
  TWetBulbSup = TDryBulb ;
  TWetBulbInf = TDewPoint ;
  TWetBulbComment = (TWetBulbInf + TWetBulbSup) / 2.;

  // Boucle de bissection
  tandis que ((TWetBulbSup - TWetBulbInf) > PSYCHROLIB_TOLERANCE)
  {
   // Calculer le taux d'humidité à la température Tstar
   Wstar = GetHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pression);

   // Obtenir de nouvelles limites
   si (Wstar > BoundedHumRatio)
    TWetBulbSup = TWetBulb ;
   autre
    TWetBulbInf = TWetBulb ;

   // Nouvelle estimation de la température du bulbe humide
   TWetBulbComment = (TWetBulbSup+TWetBulbInf) / 2.;

   AFFIRMER (indice <= MAX_ITER_COUNT, "Convergence non atteinte dans GetTWetBulbFromHumRatio. Arrêt.")

   indice++ ;
  }

  retour TWetBulb ;
}

// Renvoie le rapport d'humidité en fonction de la température du bulbe sec, de la température du bulbe humide et de la pression.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équations 33 et 35
double GetHumRatioFromTWetBulb  // (o) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double TWetBulbComment             // (i) Température du bulbe humide en °F [IP] ou °C [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  double Wsstar ;
  double HumRatio = INVALIDE;

  AFFIRMER (TWetBulb <= TDryBulb, "La température du bulbe humide est supérieure à la température du bulbe sec")

  Wsstar = GetSatHumRatio(TWetBulb, Pression);

  si (estIP())
  {
    si (TWetBulb >= FREEZING_POINT_WATER_IP)
      HumRatio = ((1093. - 0.556 * TWetBulb) * Wsstar - 0.240 * (TDDryBulb - TWetBulb))
      / (1093. + 0.444 * TDryBulb - TWetBulb);
    autre
      HumRatio = ((1220. - 0.04 * TWetBulb) * Wsstar - 0.240 * (TDDryBulb - TWetBulb))
      / (1220. + 0.444 * TDryBulb - 0.48 * TWetBulb);
  }
  autre
  {
    si (TWetBulb >= FREEZING_POINT_WATER_SI)
      HumRatio = ((2501. - 2.326 * TWetBulb) * Wsstar - 1.006 * (TDDryBulb - TWetBulb))
         / (2501. + 1.86 * TDryBulb - 4.186 * TWetBulb);
    autre
      HumRatio = ((2830. - 0.24 * TWetBulb) * Wsstar - 1.006 * (TDDryBulb - TWetBulb))
         / (2830. + 1.86 * TDryBulb - 2.1 * TWetBulb);
  }
  // Contrôle de validité.
  retour max(HumRapport, MIN_HUM_RATIO);
}

// Renvoie le rapport d'humidité en fonction de la température du bulbe sec, de l'humidité relative et de la pression.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
double GetHumRatioFromRelHum    // (o) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double RelHum               // (i) Humidité relative [0-1]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  double VapPres ;

  AFFIRMER (RelHum >= 0. && RelHum <= 1., "L'humidité relative est en dehors de la plage [0,1]")

  VapPres = GetVapPresFromRelHum(TDryBulb, RelHum);
  retour GetHumRatioFromVapPres(VapPres, Pression);
}

// Renvoie l'humidité relative en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
double GetRelHumFromHumRatio    // (o) Humidité relative [0-1]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double HumRatio             // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  double VapPres ;

  AFFIRMER (HumRapport >= 0., "Le taux d'humidité est négatif")

  VapPres = GetVapPresFromHumRatio(HumRatio, Pression);
  retour GetRelHumFromVapPres(TDryBulb, VapPres);
}

// Renvoie le taux d'humidité en fonction de la température et de la pression du point de rosée.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
double GetHumRatioFromTDewPoint // (o) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  ( double TDewPoint            // (i) Température du point de rosée en °F [IP] ou °C [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  double VapPres ;

  VapPres = GetSatVapPres(TDewPoint);
  retour GetHumRatioFromVapPres(VapPres, Pression);
}

// Renvoie la température du point de rosée en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
double GetTDewPointFromHumRatio // (o) Température du point de rosée en °F [IP] ou °C [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double HumRatio             // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  double VapPres ;

  AFFIRMER (HumRapport >= 0., "Le taux d'humidité est négatif")

  VapPres = GetVapPresFromHumRatio(HumRatio, Pression);
  retour GetTDewPointFromVapPres(TDryBulb, VapPres);
}


/*************************************************** ************************************************** ***
 * Conversions entre taux d'humidité et pression de vapeur
 ************************************************** ************************************************** */

// Rapport d'humidité de retour étant donné la pression de vapeur d'eau et la pression atmosphérique.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 20
double GetHumRatioFromVapPres   // (o) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  ( double VapPres              // (i) Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  double HumRatio ;

  AFFIRMER (VapPres >= 0., "La pression partielle de la vapeur d'eau dans l'air humide est négative")

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

  // Contrôle de validité.
  retour maximum(HumRapport, MIN_HUM_RATIO);
}

// Pression de vapeur de retour étant donné le taux d'humidité et la pression.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 20 résolue pour pw
double GetVapPresFromHumRatio   // (o) Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
  ( double HumRatio             // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  double VapPres, BoundedHumRatio ;

  AFFIRMER (HumRapport >= 0., "Le taux d'humidité est négatif")
  BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO);

  VapPres = Pression * BoundedHumRatio / (0.621945 + BoundedHumRatio );
  retour VapPres ;
}


/*************************************************** ************************************************** ***
 * Conversions entre taux d'humidité et humidité spécifique
 ************************************************** ************************************************** */

// Renvoie l'humidité spécifique à partir du rapport d'humidité (alias rapport de mélange)
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 9b
double GetSpecificHumFromHumRatio // (o) Taux d'humidité spécifique en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  ( double HumRatio               // (i) Taux d'humidité en lb_H₂O lb_Dry_Air⁻¹ [IP] ou kg_H₂O kg_Dry_Air⁻¹ [SI]
  )
{
  double BoundedHumRatio ;

  AFFIRMER (HumRapport >= 0., "Le taux d'humidité est négatif")
  BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO);

  retour BoundedHumRatio / (1.0 + BoundedHumRatio );
}

// Renvoie le taux d'humidité (alias taux de mélange) à partir d'une humidité spécifique
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 9b (résolu pour le taux d'humidité)
double GetHumRatioFromSpecificHum // (o) Taux d'humidité en lb_H₂O lb_Dry_Air⁻¹ [IP] ou kg_H₂O kg_Dry_Air⁻¹ [SI]
  ( double SpécifiqueHum            // (i) Taux d'humidité spécifique en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  )
{
  double HumRatio ;

  AFFIRMER (SpécifiqueHum >= 0.0 && SpécifiqueHum < 1.0, "L'humidité spécifique est en dehors de la plage [0,1[")

  HumRatio = SpécifiqueHum / (1.0 - SpecificHum);

  // Contrôle de validité
  retour maximum(HumRapport, MIN_HUM_RATIO);
}


/*************************************************** ************************************************** ***
 * Calculs d'air sec
 ************************************************** ************************************************** */

// Renvoie l'enthalpie de l'air sec en fonction de la température du bulbe sec.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 28
double GetDryAirEnthalpy        // (o) Enthalpie de l'air sec en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  )
{
  si (estIP())
    retour 0.240 * TDryBulb ;
  autre
    retour 1006 * TDryBulb ;
}

// Renvoie la densité de l'air sec en fonction de la température et de la pression du bulbe sec.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
// Notes : équation 14 pour la relation gazeuse parfaite pour l'air sec.
// Eqn 1 pour la constante universelle des gaz.
// Le facteur 144 en IP est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².
double GetDryAirDensity         // (o) Densité de l'air sec en lb ft⁻³ [IP] ou kg m⁻³ [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  si (estIP())
    retour (144. * Pression) / R_DA_IP / GetTRankineFromTFahrenheit(TDryBulb);
  autre
    retour Pression / R_DA_SI / GetTKelvinFromTCelsius(TDryBulb);
}

// Renvoie le volume d'air sec en fonction de la température et de la pression du bulbe sec.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
// Notes : équation 14 pour la relation gazeuse parfaite pour l'air sec.
// Eqn 1 pour la constante universelle des gaz.
// Le facteur 144 en IP est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².
double GetDryAirVolume          // (o) Volume d'air sec ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  si (estIP())
    retour R_DA_IP * ObtenirTRankineFromTFahrenheit(TDryBulb) / (144. * Pression);
  autre
    retour R_DA_SI * ObtenirTKelvinFromTCelsius(TDryBulb) / Pression;
}

// Renvoie la température du bulbe sec à partir de l'enthalpie et du rapport d'humidité.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 30.
// Notes : basé sur la fonction `GetMoistAirEnthalpy`, réorganisé pour la température.
double GetTDryBulbFromEnthalpyAndHumRatio  // (o) Température du bulbe sec en °F [IP] ou °C [SI]
  ( double Enthalpie de l'air humide                // (i) Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹
  , double HumRatio                        // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  )
{
  double BoundedHumRatio ;

  AFFIRMER (HumRapport >= 0., "Le taux d'humidité est négatif")
  BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO);

  si (estIP())
    retour (Enthalpie de l'air humide - 1061.0 * BoundedHumRatio) / (0.240 + 0.444 * BoundedHumRatio );
  autre
    retour (Enthalpie de l'air humide / 1000.0 - 2501.0 * BoundedHumRatio) / (1.006 + 1.86 * BoundedHumRatio );
}

// Renvoie le rapport d'humidité à partir de l'enthalpie et de la température du bulbe sec.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 30.
// Notes : basé sur la fonction `GetMoistAirEnthalpy`, réorganisé pour le taux d'humidité.
double GetHumRatioFromEnthalpyAndTDryBulb  // (o) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  ( double Enthalpie de l'air humide                // (i) Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹
  , double TDryBulb                        // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  )
{
  double HumRatio ;
  si (estIP())
    HumRatio = (Enthalpie de l'air humide - 0.240 * TDryBulb) / (1061.0 + 0.444 * TDryBulb);
  autre
    HumRatio = (Enthalpie de l'air humide / 1000.0 - 1.006 * TDryBulb) / (2501.0 + 1.86 * TDryBulb);

  // Contrôle de validité.
  retour maximum(HumRapport, MIN_HUM_RATIO);
}


/*************************************************** ************************************************** ***
 * Calculs d'air saturé
 ************************************************** ************************************************** */

// Renvoie la pression de vapeur saturante étant donné la température du bulbe sec.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 5 et 6
// Note importante : les formules ASHRAE sont définies au dessus et en dessous du point de congélation mais ont
// une discontinuité au point de congélation. Il s'agit d'une petite inexactitude de la part d'ASHRAE : les formules
// doit être défini au-dessus et en dessous du point triple de l'eau (et non du point de congélation), auquel cas
// la discontinuité disparaît. Il est indispensable d'utiliser le point triple d'eau sinon fonctionne
// GetTDewPointFromVapPres, qui inverse la fonction actuelle, ne converge pas correctement autour
// le point de congélation.
double GetSatVapPres            // (o) Pression de vapeur de l'air saturé en Psi [IP] ou Pa [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  )
{
  double LnPws, T;

  si (estIP())
  {
    ASSERT(TDBulbeSec >= -148. && TDryBulb <= 392., "La température du bulbe sec est en dehors de la plage [-148, 392]")

    J = GetTRankineFromTFahrenheit(TDryBulb);

    si (TDDryBulb <= TRIPLE_POINT_WATER_IP)
      LnPws = (-1.0214165E+04 / J - 4.8932428 - 5.3765794E-03 * J + 1.9202377E-07 * J * J
        + 3.5575832E-10 * pow(T, 3) - 9.0344688E-14 * pow(T, 4) + 4.1635019 * log(T));
    autre
      LnPws = -1.0440397E+04 / J - 1.1294650E+01 - 2.7022355E-02 * J + 1.2890360E-05 * J * J
      - 2.4780681E-09 * pow(T, 3) + 6.5459673 * log(T);
  }
  autre
  {
    ASSERT(TDBulbeSec >= -100. && TDryBulb <= 200., "La température du bulbe sec est en dehors de la plage [-100, 200]")

    J = GetTKelvinFromTCelsius(TDryBulb);

    si (TDDryBulb <= TRIPLE_POINT_WATER_SI)
      LnPws = -5.6745359E+03 / J + 6.3925247 - 9.677843E-03 * J + 6.2215701E-07 * J * J
          + 2.0747825E-09 * pow(T, 3) - 9.484024E-13 * pow(T, 4) + 4.1635019 * log(T);
    autre
      LnPws = -5.8002206E+03 / J + 1.3914993 - 4.8640239E-02 * J + 4.1764768E-05 * J * J
        - 1.4452093E-08 * pow(T, 3) + 6.5459673 * log(T);
  }

  retour exp(LnPws);
}

// Taux d'humidité de retour de l'air saturé en fonction de la température et de la pression du bulbe sec.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 36, résolue pour W
double GetSatHumRatio           // (o) Taux d'humidité de l'air saturé en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  double SatVaporPres, SatHumRatio ;

  SatVaporPres = GetSatVapPres(TDryBulb);
  SatHumRatio = 0.621945 * SatVaporPres / (Pression - SatVaporPres);

  // Contrôle de validité.
  retour maximum(SatHumRatio, MIN_HUM_RATIO);
}

// Renvoie l'enthalpie de l'air saturé en fonction de la température et de la pression du bulbe sec.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1
double GetSatAirEnthalpy        // (o) Enthalpie de l'air saturé en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  retour GetMoistAirEnthalpy(TDDryBulb, GetSatHumRatio(TDDryBulb, Pression));
}

/*************************************************** ************************************************** ***
 * Calculs d'air humide
 ************************************************** ************************************************** */

// Retour Déficit de pression de vapeur en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
// Référence : voir Oke (1987) eqn. 2.13a
double GetVaporPressureDeficit  // (o) Déficit de pression de vapeur en Psi [IP] ou Pa [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double HumRatio             // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  double RelHum ;

  AFFIRMER (HumRapport >= 0., "Le taux d'humidité est négatif")

  RelHum = GetRelHumFromHumRatio(TDryBulb, HumRatio, Pression);
  retour GetSatVapPres(TDryBulb) * (1. - RelHum);
}

// Renvoie le degré de saturation (c'est à dire le rapport humidité de l'air / rapport humidité de l'air à saturation
// à la même température et pression) étant donné la température du bulbe sec, le taux d'humidité et la pression atmosphérique.
// Référence : ASHRAE Handbook - Fundamentals (2009) ch. 1 éq. 12
// Notes : la définition est absente du Manuel 2017
double GetDegreeOfSaturation    // (o) Degré de saturation []
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double HumRatio             // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  double BoundedHumRatio ;

  AFFIRMER (HumRapport >= 0., "Le taux d'humidité est négatif")
  BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO);

  retour BoundedHumRatio / GetSatHumRatio(TDDryBulb, Pression);
}

// Renvoie l'enthalpie de l'air humide en fonction de la température du bulbe sec et du rapport d'humidité.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 30
double GetMoistAirEnthalpy      // (o) Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double HumRatio             // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  )
{
  double BoundedHumRatio ;

  AFFIRMER (HumRapport >= 0., "Le taux d'humidité est négatif")
  BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO);

  si (estIP())
    retour 0.240 * TDryBulb + BoundedHumRatio*(1061. + 0.444 * TDryBulb);
  autre
    retour (1.006 * TDryBulb + BoundedHumRatio*(2501. + 1.86 * TDryBulb)) * 1000.;
}

// Renvoie le volume spécifique d'air humide en fonction de la température du bulbe sec, du taux d'humidité et de la pression.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 26
// Notes : en unités IP, R_DA_IP / 144 est égal à 0,370486 qui est le coefficient apparaissant dans l'équation 26.
// Le facteur 144 est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².
double GetMoistAirVolume        // (o) Volume spécifique ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double HumRatio             // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  double BoundedHumRatio ;

  AFFIRMER (HumRapport >= 0., "Le taux d'humidité est négatif")
  BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO);

  si (estIP())
    retour R_DA_IP * ObtenirTRankineFromTFahrenheit(TDryBulb) * (1. + 1.607858 * BoundedHumRatio) / (144. * Pression);
  autre
    retour R_DA_SI * ObtenirTKelvinFromTCelsius(TDryBulb) * (1. + 1.607858 * BoundedHumRatio) / Pression;
}

// Renvoie la température du bulbe sec en fonction du volume spécifique de l'air humide, du taux d'humidité et de la pression.
// Référence:
// Manuel ASHRAE - Fondamentaux (2017) ch. 1 équation 26
// Remarques:
// En unités IP, R_DA_IP/144 est égal à 0,370486 qui est le coefficient apparaissant dans l'équation 26
// Le facteur 144 est destiné à la conversion de Psi = lb in⁻² en lb ft⁻².
// Basé sur la fonction `GetMoistAirVolume`, réorganisée pour la température sèche.
double GetTDryBulbFromMoistAirVolumeAndHumRatio   // (o) Température du bulbe sec en °F [IP] ou °C [SI]
  ( double Volume d'air humide                         // (i) Volume spécifique d'air humide en pi³ lb⁻¹ d'air sec [IP] ou en m³ kg⁻¹ d'air sec [SI]
  , double HumRatio                               // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  , double Pression                               // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  double BoundedHumRatio ;

  AFFIRMER (HumRapport >= 0., "Le taux d'humidité est négatif")
  BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO);

  si (estIP())
    retour GetTFahrenheitFromTRankine(MoistAirVolume * (144 * Pression) / (R_DA_IP * (1 + 1.607858 * BoundedHumRatio)));
  autre
    retour  ObtenirTCelsiusFromTKelvin(Volume d'air humide * Pression / (R_DA_SI * (1 + 1.607858 * BoundedHumRatio)));
}

// Renvoie la densité de l'air humide en fonction du taux d'humidité, de la température du bulbe sec et de la pression.
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 éq. 11
double GetMoistAirDensity       // (o) Densité de l'air humide en lb ft⁻³ [IP] ou kg m⁻³ [SI]
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double HumRatio             // (i) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  )
{
  double BoundedHumRatio ;

  AFFIRMER (HumRapport >= 0., "Le taux d'humidité est négatif")
  BoundedHumRatio = max(HumRapport, MIN_HUM_RATIO);

  retour (1. + BoundedHumRatio) / GetMoistAirVolume(TDDryBulb, Rapport HumBounded, Pression);
}


/*************************************************** ************************************************** ***
 * Atmosphère normale
 ************************************************** ************************************************** */

// Renvoie la pression barométrique de l'atmosphère standard, compte tenu de l'élévation (altitude).
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 3
double GetStandardAtmPressure   // (o) Pression barométrique de l'atmosphère standard en Psi [IP] ou Pa [SI]
  ( double Altitude             // (i) Altitude en ft [IP] ou m [SI]
  )
{
  double Pression;
  si (estIP())
    Pression = 14.696 * Pow (1. - 6.8754e-06 * Altitude, 5.2559);
  autre
    Pression = 101325. * Pow (1. - 2.25577e-05 * Altitude, 5.2559);
  retour Pression;
}

// Renvoie la température atmosphérique standard, compte tenu de l'élévation (altitude).
// Référence : ASHRAE Handbook - Fundamentals (2017) ch. 1 équation 4
double GetStandardAtmTemperature // (o) Température du bulbe sec dans l'atmosphère standard en °F [IP] ou °C [SI]
  ( double Altitude              // (i) Altitude en ft [IP] ou m [SI]
  )
 {
  double Température;
  si (estIP())
    Température = 59. - 0.00356620 * Altitude;
  autre
    Température = 15. - 0.0065 * Altitude;
  retour Température;
}

// Renvoie la pression au niveau de la mer en fonction de la température du bulbe sec, de l'altitude au-dessus du niveau de la mer et de la pression.
// Référence : Hess SL, Introduction à la météorologie théorique, Holt Rinehart et Winston, NY 1959,
// ch. 6,5 ; Stull RB, Météorologie pour les scientifiques et les ingénieurs, 2e édition,
// Brooks/Cole 2000, ch. 1.
// Notes : la procédure standard pour les États-Unis consiste à utiliser pour TDryBulb la moyenne
// de la température actuelle de la station et de la température de la station d'il y a 12 heures.
double GetSeaLevelPressure   // (o) Pression barométrique au niveau de la mer en Psi [IP] ou Pa [SI]
  ( double StnPression       // (i) Pression de station observée en Psi [IP] ou Pa [SI]
  , double Altitude          // (i) Altitude au-dessus du niveau de la mer en pieds [IP] ou m [SI]
  , double TDryBulb          // (i) Température du bulbe sec ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
  )
{
  double TColonne, H;
  si (estIP())
  {
    // Calculer la température moyenne dans la colonne d'air, en supposant un taux de déchéance
    // de 3,6 °F/1000 pieds
    TColonne = TDryBulb + 0.0036 * Altitude / 2.;

    // Déterminer la hauteur de l'échelle
    H = 53.351 * GetTRankineFromTFahrenheit(TColumn);
  }
  autre
  {
    // Calculer la température moyenne dans la colonne d'air, en supposant un taux de déchéance
    // de 6,5 °C/km
    TColonne = TDryBulb + 0.0065 * Altitude / 2.;

    // Déterminer la hauteur de l'échelle
    H = 287.055 * GetTKelvinFromTCelsius(TColonne) / 9.807;
  }

  // Calculer la pression au niveau de la mer
  double PressionNiveau De La Mer = StnPression * exp(altitude / H);
  retour pression au niveau de la mer ;
}

// Pression de retour de la station à partir de la pression au niveau de la mer
// Référence : voir 'GetSeaLevelPressure'
// Notes : cette fonction est juste l'inverse de 'GetSeaLevelPressure'.
double GetStationPressure    // (o) Pression de la station en Psi [IP] ou Pa [SI]
  ( double PressionNiveau De La Mer  // (i) Pression barométrique au niveau de la mer en Psi [IP] ou Pa [SI]
  , double Altitude          // (i) Altitude au-dessus du niveau de la mer en pieds [IP] ou m [SI]
  , double TDryBulb          // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  )
{
  retour PressionNiveau De La Mer / GetSeaLevelPressure(1., Altitude, TDryBulb);
}


/*************************************************** ************************************************** ***
 * Fonctions pour définir toutes les valeurs psychrométriques
 ************************************************** ************************************************** */

// Fonction utilitaire pour calculer le taux d'humidité, la température du point de rosée, l'humidité relative,
// pression de vapeur, enthalpie de l'air humide, volume d'air humide et degré de saturation de l'air donné
// température du bulbe sec, température du bulbe humide et pression.
annuler CalcPsychrometricsFromTWetBulb
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double TWetBulbComment             // (i) Température du bulbe humide en °F [IP] ou °C [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  , double *HumRapport            // (o) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  , double *TDewPoint           // (o) Température du point de rosée en °F [IP] ou °C [SI]
  , double *RelHum              // (o) Humidité relative [0-1]
  , double *VapPres             // (o) Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
  , double *Enthalpie de l'air humide    // (o) Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
  , double *Volume d'air humide      // (o) Volume spécifique ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
  , double *DegréDeSaturation  // (o) Degré de saturation [sans unité]
)
{
  ASSERT(TWetBulb <= TDryBulb, "La température du bulbe humide est supérieure à la température du bulbe sec")

  *HumRapport = GetHumRatioFromTWetBulb(TDryBulb, TWetBulb, Pression);
  *TDewPoint = GetTDewPointFromHumRatio(TDryBulb, *HumRapport, Pression);
  *RelHum = GetRelHumFromHumRatio(TDryBulb, *HumRapport, Pression);
  *VapPres = GetVapPresFromHumRatio(*HumRatio, Pression);
  *Enthalpie de l'air humide = GetMoistAirEnthalpy(TDDryBulb, *HumRatio);
  *Volume d'air humide = GetMoistAirVolume(TDDryBulb, *HumRapport, Pression);
  *DegréDeSaturation = ObtenirDegréDeSaturation(TDryBulb, *HumRapport, Pression);
}

// Fonction utilitaire pour calculer le taux d'humidité, la température du bulbe humide, l'humidité relative,
// pression de vapeur, enthalpie de l'air humide, volume d'air humide et degré de saturation de l'air donné
// température du bulbe sec, température du point de rosée et pression.
annuler CalcPsychrometricsFromTDewPoint
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double TDewPoint            // (i) Température du point de rosée en °F [IP] ou °C [SI]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  , double *HumRapport            // (o) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  , double *TWetBulb            // (o) Température du bulbe humide en °F [IP] ou °C [SI]
  , double *RelHum              // (o) Humidité relative [0-1]
  , double *VapPres             // (o) Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
  , double *Enthalpie de l'air humide    // (o) Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
  , double *Volume d'air humide      // (o) Volume spécifique ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
  , double *DegréDeSaturation  // (o) Degré de saturation [sans unité]
)
{
  ASSERT(TDewPoint <= TDryBulb, "La température du point de rosée est supérieure à la température du bulbe sec")

  *HumRapport = GetHumRatioFromTDewPoint(TDewPoint, Pression);
  *TWetBulb = GetTWetBulbFromHumRatio(TDryBulb, *HumRapport, Pression);
  *RelHum = GetRelHumFromHumRatio(TDryBulb, *HumRapport, Pression);
  *VapPres = GetVapPresFromHumRatio(*HumRatio, Pression);
  *Enthalpie de l'air humide = GetMoistAirEnthalpy(TDDryBulb, *HumRatio);
  *Volume d'air humide = GetMoistAirVolume(TDDryBulb, *HumRapport, Pression);
  *DegréDeSaturation = ObtenirDegréDeSaturation(TDryBulb, *HumRapport, Pression);
}

// Fonction utilitaire pour calculer le taux d'humidité, la température du bulbe humide, la température du point de rosée,
// pression de vapeur, enthalpie de l'air humide, volume d'air humide et degré de saturation de l'air donné
// température du bulbe sec, humidité relative et pression.
annuler CalcPsychrometricsFromRelHum
  ( double TDryBulb             // (i) Température du bulbe sec en °F [IP] ou °C [SI]
  , double RelHum               // (i) Humidité relative [0-1]
  , double Pression             // (i) Pression atmosphérique en Psi [IP] ou Pa [SI]
  , double *HumRapport            // (o) Taux d'humidité en lb_H₂O lb_Air⁻¹ [IP] ou kg_H₂O kg_Air⁻¹ [SI]
  , double *TWetBulb            // (o) Température du bulbe humide en °F [IP] ou °C [SI]
  , double *TDewPoint           // (o) Température du point de rosée en °F [IP] ou °C [SI]
  , double *VapPres             // (o) Pression partielle de vapeur d'eau dans l'air humide en Psi [IP] ou Pa [SI]
  , double *Enthalpie de l'air humide    // (o) Enthalpie de l'air humide en Btu lb⁻¹ [IP] ou J kg⁻¹ [SI]
  , double *Volume d'air humide      // (o) Volume spécifique ft³ lb⁻¹ [IP] ou en m³ kg⁻¹ [SI]
  , double *DegréDeSaturation  // (o) Degré de saturation [sans unité]
)
{
  ASSERT(RelHum >= 0 && RelHum <= 1, "L'humidité relative est en dehors de la plage [0,1]")

  *HumRapport = GetHumRatioFromRelHum(TDryBulb, RelHum, Pression);
  *TWetBulb = GetTWetBulbFromHumRatio(TDryBulb, *HumRapport, Pression);
  *TDewPoint = GetTDewPointFromHumRatio(TDryBulb, *HumRapport, Pression);
  *VapPres = GetVapPresFromHumRatio(*HumRatio, Pression);
  *Enthalpie de l'air humide = GetMoistAirEnthalpy(TDDryBulb, *HumRatio);
  *Volume d'air humide = GetMoistAirVolume(TDDryBulb, *HumRapport, Pression);
  *DegréDeSaturation = ObtenirDegréDeSaturation(TDryBulb, *HumRapport, Pression);
}