Man Pages#
iapws(1)#
NAME#
iapws - Compute light and heavy water properties.
SYNOPSIS#
iapws SUBCOMMAND [OPTION...]
DESCRIPTION#
iapws is a command line interface for computing properties of light and heavy water according to IAPWS.
SUBCOMMANDS#
Valid subcommands are:
- + kh
Compute the Henry’s constant for gases in H2O or D2O. The default behavior is to compute the constant kH for O2 at 25°C. See options.
- + kd
Compute the vapor-liquid distribution constant for gases in H2O or D The default behavior is to compute the constant kD for H2 at 25°C. See options.
- + psat
Compute the saturation pressure. The default behavior is to compute psat at 25°C. See options.
- + Tsat
Compute the saturation temperature. The default behavior is to compute Tsat at 1 bar. See options.
Their syntax is:
- + kh
[OPTION…]
- + kd
[OPTION…]
- + psat
[OPTION…]
- + Tsat
[OPTION…]
OPTIONS#
kh:
- –temperature, -T TEMPERATURE…
Temperature in °C. Default to 25°C.
- –fugacity, -f FUGACITY…
Liquid-phase fugacity in MPa. Default to 1 b
- –gases, -g GAS…
Gases for which to compute kH. Default to O2
- –D2O
Set heavywater as the solvent.
- –listgases
Display available gases for computing kH.
kd:
- –temperature, -T TEMPERATURE…
Temperature in °C. Default to 25°C.
- –x2, -x x2…
Molar fraction of gas in water. Default to 1
- –gases, -g GAS…
Gases for which to compute kD. Default to H2
- –D2O,
Set heavywater as the solvent.
- –listgases
Display available gases for computing kD.
psat:
- –temperature, -T TEMPERATURE…
Temperature in °C. Default to 25°C.
Tsat:
- –pressure, -p PRESSURE…
Pressure in bar. Default to 1 bar.
all:
- –usage, -u
Show usage text and exit.
- –help, -h
Show help text and exit.
- –verbose, -V
Display additional information when availabl
- –version, -v
Show version information and exit.
NOTES#
You may replace the default options from a file if your first options begin with @file. Initial options will then be read from the “response file” “file.rsp” in the current directory.
If “file” does not exist or cannot be read, then an error occurs and the program stops. Each line of the file is prefixed with “options” and interpreted as a separate argument. The file itself may not contain @file arguments. That is, it is not processed recursively.
For more information on response files see https://urbanjost.github.io/M_CLI2/set_args.3m_cli2.html
EXAMPLE#
Minimal example
iapws kh -T 25,100 -f 1,0.2 -g O2,H2
iapws kd -T 25,100 -x2 1d-9,1d-6 -g O2,H2
SEE ALSO#
ciaaw(3), codata(3)
iapws(3)#
NAME#
iapws - library for light and heavy water properties according to IAPWS.
LIBRARY#
iapws (-libiapws, -libiapws)
SYNOPSIS#
use iapws
include "iapws.h"
import pyiapws
DESCRIPTION#
Numerical implementation for reports:
R2-83
[x] Tc in H2O and D2O
[x] pc in H2O and D2O
[x] rhoc in H2O and D2O
G7-04
[x] kH
[x] kD
R7-97
[x] Region 1
[ ] Region 2
[ ] Region 3
[x] Region 4
[ ] Region 5
R11-24:
[x] Kw
Fortran API
- o real(dp), parameter :: Tc_H2O = 647.096_dp
Critical temperature for H2O in K
- o real(dp), parameter :: Tc_D2O = 643.847_dp
Critical temperature for D2O in K
- o real(dp), parameter :: pc_H2O = 22.064_dp
Critical pressure for H2O in MPa
- o real(dp), parameter :: pc_D2O = 21.671_dp
Critical pressure for H2O in MPa
- o real(dp), parameter :: rhoc_H2O = 322.0_dp
Critical density for H2O in kg.m-3
- o real(dp), parameter :: rhoc_D2O = 356.0_dp
Critical density for H2O in kg.m-3
- o function get_version()result(fptr)
Return the version
- o character(len=:), pointer :: fptr
Fortran pointer to a string indicating the version.
- o pure subroutine kh(T, gas, heavywater, k)
Compute the henry constant kH in MPa for a given temperature (x_2=1/kH).
- o real(dp), intent(in), contiguous :: T(:)
Temperature in K.
- o character(len=*), intent(in) :: gas
Gas.
- o integer(int32), intent(in) :: heavywater
Flag if D2O (1) is used or H2O(0).
- o real(dp), intent(out), contiguous :: k(:)
Henry constant in MPa. Filled with NaNs if gas not found.
- o pure subroutine kd(T, gas, heavywater, k)
Compute the vapor-liquid constant kd for a given temperature (kd=y_2/x_2).
- o real(dp), intent(in), contiguous :: T(:)
Temperature in K.
- o character(len=*), intent(in) :: gas
Gas.
- o integer(int32), intent(in) :: heavywater
Flag if D2O (1) is used or H2O(0).
- o real(dp), intent(out), contiguous :: k(:)
Vapor-liquid constant (adimensional). Filled with NaNs if gas not found.
- o pure function ngases(heavywater)result(n)
Returns the number of gases.
- o integer(int32), intent(in) :: heavywater
Flag if D2O (1) is used or H2O(0).
- o integer(int32) :: n
Number of gases.
- o function gases(heavywater)result(list_gases)
Returns the list of available gases.
- o integer(int32), intent(in) :: heavywater
Flag if D2O (1) is used or H2O(0).
- o type(gas_type), pointer :: list_gases(:)
Available gases.
- o function gases2(heavywater)result(str_gases)
Returns the available gases as a string.
- o integer(int32), intent(in) :: heavywater
Flag if D2O (1) is used or H2O(0).
- o character(len=:), pointer :: str_gases
Available gases
- o pure subroutine psat(Ts, ps)
Compute the saturation pressure at temperature Ts (273.13 K <= Ts <= 647.096 K).
- o real(dp), intent(in), contiguous :: Ts(:)
Saturation temperature in K.
- o real(dp), intent(out), contiguous :: ps(:)
Saturation pressure in MPa. Filled with nan if out of validity range.
- o pure subroutine Tsat(ps, Ts)
Compute the saturation temperature at pressure ps (611.213 Pa <= ps <= 22.064 MPa).
- o real(dp), intent(in), contiguous :: ps(:)
Saturation pressure in MPa.
- o real(dp), intent(out), contiguous :: Ts(:)
Saturation temperature in K. Filled with nan if out of validity range.
- o pure subroutine wp(p, T, prop, res)
Compute water properties at pressure p in MPa and temperature T in Kelvin.
- o real(dp), intent(in) :: p(:)
Pressure in MPa.
- o real(dp), intent(in) :: T(:)
Pressure in K.
- o character(len=*), intent(in) :: prop
Property (v, u, s, h, cp, cv, w)
- o real(dp), intent(out) :: res(:)
Filled with NaN if no adequate region is found.
- o pure subroutine wr(p, T, res)
Get the water region corresponding to p and T.
- o real(dp), intent(in) :: p(:)
Pressure in MPa.
- o real(dp), intent(in) :: T(:)
Temperature in K.
- o integer(int32), intent(out) :: res(:)
Region 1 to 5 if found or -1.
- o pure subroutine wph(p, T, res)
Get the water phase corresponding to p and T.
- o real(dp), intent(in) :: p(:)
pressure in MPa.
- o real(dp), intent(in) :: T(:)
Temperature in K.
- o character(len=1), intent(out) :: res(:)
Phases: l(liquid), v(VAPOR), c(SUPER CRITICAL), s(SATURATION), n(UNKNOWN).
- o pure subroutine Kw(T, rhow, k)
Compute the ionization constant of water Kw (273.13 K <= T <= 1273.15 K and 0 <= p <= 1000 MPa).
- o real(dp), intent(in) :: T(:)
Temperature in K.
- o real(dp), intent(in) :: rhow(:)
Mass density in g.cm^{-3}.
- o real(dp), intent(out) :: k(:)
Ionization constant. Filled with NaN if out of validity range.
C API
char* iapws_get_version(void)
const double iapws_r283_Tc_H2O
const double iapws_r283_Tc_D2O
const double iapws_r283_pc_H2O
const double iapws_r283_pc_D2O
const double iapws_r283_rhoc_H2O
const double iapws_r283_rhoc_D2O
void iapws_g704_kh(double *T, char *gas, int heavywater, double *k, int size_gas, size_t size_T)
void iapws_g704_kd(double *T, char *gas, int heavywater, double *k, int size_gas, size_t size_T)
int iapws_g704_ngases(int heavywater)
char **iapws_g704_gases(int heavywater)
char *iapws_g704_gases2(int heavywater)
void iapws_r797_psat(size_t N, double *Ts, double *ps)
void iapws_r797_Tsat(size_t N, double *ps, double *Ts)
void iapws_r797_wp(double *p, double *T, char *prop, double *res, size_t N, size_t len)
void iapws_r797_wr(double *p, double *T, int *res, size_t N)
void iapws_r797_wph(double *p, double *T, char *res, size_t N)
void iapws_r1124_Kw(size_t N, double *T, double *rhow, double *k)
Python wrapper
kh(T: np.ndarray, gas: str, heavywater: bool=False)->Union[np.ndarray, float]
kd(T: np.ndarray, gas: str, heavywater: bool=False)->Union[np.ndarray, float]
ngases(heavywater:bool=False)->int
gases(heavywater: bool=False)->List[str]
gases2(heavywater: bool=False)->str
psat(Ts)->Union[np.ndarray, float]
Tsat(ps)->Union[np.ndarray, float]
wp(p, T, prop)->Union[np.ndarray, float]
wr(p, T)->Union[np.ndarray, float]
wph(p, T)->Union[np.ndarray, str]
Kw(T: np.ndarray, rhow: np.ndarray)->Union[np.ndarray, float]
NOTES#
To use iapws within your fpm project, add the following to your fpm.toml file:
[dependencies]
iapws = { git="https://github.com/MilanSkocic/iapws.git" }
dp stands for double precision and it is an alias to real64 from the iso_fortran_env module.
l => liquid
v => vapor
c => super critical
s => saturation
n => unknown
EXAMPLE#
Example in Fortran
program example_in_f
use stdlib_kinds, only: dp, int32
use iapws
implicit none
integer(int32) :: i, ngas
real(dp) :: T(1), kh_res(1), kd_res(1), wp_res(1), p(1)
real(dp) :: Ts(7), ps(7)
real(dp) :: x(3), y(3)
integer(int32) :: r(3)
character(len=1) :: s(3)
character(len=2) :: gas = "O2"
integer(int32) :: heavywater = 0
type(gas_type), pointer :: gases_list(:)
character(len=:), pointer :: gases_str
print *, '########################## IAPWS VERSION ##########################'
print *, "version ", get_version()
print *, '########################## IAPWS R2-83 ##########################'
print "(a, f10.3, a)", "Tc in h2o=", Tc_H2O, " k"
print "(a, f10.3, a)", "pc in h2o=", pc_H2O, " mpa"
print "(a, f10.3, a)", "rhoc in h2o=", rhoc_H2O, " kg/m3"
print "(a, f10.3, a)", "Tc in D2O=", Tc_D2O, " k"
print "(a, f10.3, a)", "pc in D2O=", pc_D2O, " mpa"
print "(a, f10.3, a)", "rhoc in D2O=", rhoc_D2O, " kg/m3"
print *, ''
print *, '########################## IAPWS G7-04 ##########################'
! Compute kh and kd in H2O
T(1) = 25.0_dp + 273.15_dp
call kh(T, gas, heavywater, kh_res)
print "(A10, 1X, A10, 1X, A2, F10.1, A, 4X, A3, SP, F10.4)", "Gas=", gas, "T=", T, "K", "kh=", kh_res
call kd(T, gas, heavywater, kd_res)
print "(A10, 1X, A10, 1X, A2, F10.1, A, 4X, A3, SP, F15.4)", "Gas=", gas, "T=", T, "K", "kh=", kd_res
! Get and print available gases
heavywater = 0
ngas = ngases(heavywater)
gases_list => null()
gases_list => gases(heavywater)
gases_str => gases2(heavywater)
print *, "Gases in H2O: ", ngas
print *, gases_str
do i=1, ngas
print *, gases_list(i)%gas
enddo
heavywater = 1
ngas = ngases(heavywater)
gases_list => null()
gases_list => gases(heavywater)
gases_str => gases2(heavywater)
print *, "Gases in D2O: ", ngas
print *, gases_str
do i=1, ngas
print *, gases_list(i)%gas
enddo
print *, '########################## IAPWS R7-97 ##########################'
! Compute ps from Ts.
Ts(:) = [-1.0_dp, 25.0_dp, 100.0_dp, 200.0_dp, 300.0_dp, 360.0_dp, 374.0_dp]
Ts(:) = Ts(:) + 273.15_dp
call psat(Ts, ps)
do i=1, size(Ts)
print "(SP, F23.3, A3, 4X, F23.3, A3)", Ts(i), "K", ps(i), "MPa"
end do
! Compute Ts from ps
call Tsat(ps, Ts)
do i=1, size(Ts)
print "(SP, F23.3, A3, 4X, F23.3, A3)", Ts(i), "K", ps(i), "MPa"
end do
! Compute water properties at 280°C/8 Mpa
p(1) = 8.0_dp
T(1) = 273.15_dp + 280.0_dp
call wp(p, T, "v", wp_res)
print "(A5, F23.16, X, A)", "v(8MPa,280°C)=", wp_res(1)*1000.0_dp, "L/kg"
! Compute region and phase
x = [8.0_dp, 4.0_dp, 6.0_dp ]
y = [553.15_dp, 1200.0_dp, 2000.0_dp]
call wr(x, y, r)
call wph(x, y, s)
print *, r
print *, s
end program
Example in C
#include <string.h>
#include <stdio.h>
#include "iapws.h"
int main(void){
double T = 25.0 + 273.15; /* in C*/
double p; /* p in Mpa */
char *gas = "O2";
double kh, kd, wp_res;
char **gases_list;
char *gases_str;
int ngas;
int i;
int heavywater = 0;
double x[3]= {8.0, 4.0, 6.0 };
double y[3] = {553.15, 1200.0, 2000.0};
int r[3];
char s[3];
printf("%s, "########################## IAPWS VERSION ##########################");
printf("version %s, iapws_get_version());
printf("%s, "########################## IAPWS R2-83 ##########################");
printf("%s %10.3f %s, "Tc in H2O", iapws_r283_Tc_H2O, "K");
printf("%s %10.3f %s, "pc in H2O", iapws_r283_pc_H2O, "MPa");
printf("%s %10.3f %s, "rhoc in H2O", iapws_r283_rhoc_H2O, "kg/m3");
printf("%s %10.3f %s, "Tc in D2O", iapws_r283_Tc_D2O, "K");
printf("%s %10.3f %s, "pc in D2O", iapws_r283_pc_D2O, "MPa");
printf("%s %10.3f %s, "rhoc in D2O", iapws_r283_rhoc_D2O, "kg/m3");
printf(");
printf("%s, "########################## IAPWS G7-04 ##########################");
/* Compute kh and kd in H2O*/
iapws_g704_kh(&T, gas, heavywater, &kh, strlen(gas), 1);
printf("Gas=%s T=%fK kh=%+10.4f, gas, T, kh);
iapws_g704_kd(&T, gas, heavywater, &kd, strlen(gas), 1);
printf("Gas=%s T=%fK kd=%+15.4f, gas, T, kd);
/* Get and print the available gases */
ngas = iapws_g704_ngases(heavywater);
gases_list = iapws_g704_gases(heavywater);
gases_str = iapws_g704_gases2(heavywater);
printf("Gases in H2O: %d, ngas);
printf("%s, gases_str);
for(i=0; i<ngas; i++){
printf("%s, gases_list[i]);
}
heavywater = 1;
ngas = iapws_g704_ngases(heavywater);
gases_list = iapws_g704_gases(heavywater);
gases_str = iapws_g704_gases2(heavywater);
printf("Gases in D2O: %d, ngas);
printf("%s, gases_str);
for(i=0; i<ngas; i++){
printf("%s, gases_list[i]);
}
printf("%s, "########################## IAPWS R7-97 ##########################");
double Ts[7] = {-1.0, 25.0, 100.0, 200.0, 300.0, 360.0, 374.0};
double ps[7] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
for(i=0; i<7; i++){
Ts[i] = Ts[i] + 273.15;
}
iapws_r797_psat(7, Ts, ps);
for(i=0; i<7; i++){
printf("%+23.3f %s %+23.3f %s, Ts[i], "K", ps[i], "MPa");
}
iapws_r797_Tsat(7, ps, Ts);
for(i=0; i<7; i++){
printf("%+23.3f %s %+23.3f %s, Ts[i], "K", ps[i], "MPa");
}
T = 273.15 + 280.0;
p = 8.0;
iapws_r797_wp(&p, &T, "v", &wp_res, 1, 1);
printf("v(8MPa,280°C) = %+23.16f L/kg, wp_res * 1000.0);
iapws_r797_wr(x, y, r, 3);
iapws_r797_wph(x, y, s, 3);
for(i=0; i<3; i++){
printf("%i", r[i]);
}
printf(");
for(i=0; i<3; i++){
printf("%c", s[i]);
}
printf(");
return 0;
}
Example in Python
import array
import numpy as np
import matplotlib.pyplot as plt
import pyiapws
print("########################## IAPWS VERSION ##########################")
print(pyiapws.__version__)
print("########################## IAPWS R2-83 ##########################")
print("Tc in H2O", pyiapws.Tc_H2O, "K")
print("pc in H2O", pyiapws.pc_H2O, "MPa")
print("rhoc in H2O", pyiapws.rhoc_H2O, "kg/m3")
print("Tc in D2O", pyiapws.Tc_D2O, "K")
print("pc in D2O", pyiapws.pc_D2O, "MPa")
print("rhoc in D2O", pyiapws.rhoc_D2O, "kg/m3")
print("")
print("########################## IAPWS G7-04 ##########################")
gas = "O2"
T = array.array("d", (25.0+273.15,))
# Compute kh and kd in H2O
heavywater = False
k = pyiapws.kh(T, "O2", heavywater)
print(f"Gas={gas} T={T[0]}K kh={k[0]:+10.4f})
k = pyiapws.kd(T, "O2", heavywater)
print(f"Gas={gas} T={T[0]}K kd={k[0]:+10.4f})
# Get and print the available gases
heavywater = False
gases_list = pyiapws.gases(heavywater)
gases_str = pyiapws.gases2(heavywater)
ngas = pyiapws.ngases(heavywater)
print(f"Gases in H2O: {ngas:}")
print(gases_str)
for gas in gases_list:
print(gas)
heavywater = True
gases_list = pyiapws.gases(heavywater)
gases_str = pyiapws.gases2(heavywater)
ngas = pyiapws.ngases(heavywater)
print(f"Gases in D2O: {ngas:}")
print(gases_str)
for gas in gases_list:
print(gas)
style = {"marker":".", "ls":"", "ms":2}
T_KELVIN = 273.15
T = np.linspace(0.0, 360.0, 1000) + 273.15
solvent = {True: "D2O", False: "H2O"}
print("Generating plot for kh")
kname = "kh"
for HEAVYWATER in (False, True):
print(solvent[HEAVYWATER])
fig = plt.figure()
ax = fig.add_subplot()
ax.grid(visible=True, ls=':')
ax.set_xlabel("T /°K")
ax.set_ylabel("ln (kh/1GPa)")
gases = pyiapws.gases(HEAVYWATER)
for gas in gases:
k = pyiapws.kh(T, gas, HEAVYWATER) / 1000.0
ln_k = np.log(k)
ax.plot(T, ln_k, label=gas, **style)
ax.legend(ncol=3)
fig.savefig(f"../media/g704-{kname:s}_{solvent[HEAVYWATER]}.png", dpi=100, format="png")
print("Generating plot for kd")
kname = "kd"
for HEAVYWATER in (False, True):
print(solvent[HEAVYWATER])
fig = plt.figure()
ax = fig.add_subplot()
ax.grid(visible=True, ls=':')
ax.set_xlabel("T /°K")
ax.set_ylabel("ln kd")
gases = pyiapws.gases(HEAVYWATER)
for gas in gases:
k = pyiapws.kd(T, gas, HEAVYWATER)
ln_k = np.log(k)
ax.plot(T, ln_k, label=gas, **style)
ax.legend(ncol=3)
fig.savefig(f"../media/g704-{kname:s}_{solvent[HEAVYWATER]}.png", dpi=100, format="png")
print("########################## IAPWS R7-97 ##########################")
Ts = np.asarray([-1.0, 25.0, 100.0, 200.0, 300.0, 360.0, 374.0])
Ts = Ts + 273.15
ps = pyiapws.psat(Ts)
for i in range(Ts.size):
print(f"{Ts[i]:23.3f} K {ps[i]:23.3f} MPa.")
Ts = pyiapws.Tsat(ps)
for i in range(Ts.size):
print(f"{Ts[i]:23.3f} K {ps[i]:23.3f} MPa.")
fig = plt.figure()
ax = fig.add_subplot()
ax.grid(visible=True, ls=':')
ax.set_xlabel("Ts /K")
ax.set_ylabel("ps /MPa")
Ts = np.linspace(0.0, 370.0, 500)
Ts = Ts + 273.15
ps = pyiapws.psat(Ts)
ax.plot(Ts, ps, "r-", label="ps(Ts)")
Ts = pyiapws.Tsat(ps)
ax.plot(Ts, ps, "b--", label="Ts(ps)")
ax.legend()
fig.savefig(f"../media/r797-r4.png", dpi=100, format="png")
T = 280.0 + 273.15
p = 8.0
res = pyiapws.wp(p, T, "v")*1000.0
print(f"v(8MPa,280°C) = {res:+23.16f} L/kg)")
x = np.asarray([8.0, 4.0, 6.0 ])
y = np.asarray([553.15, 1200.0, 2000.0])
r=pyiapws.wr(x, y)
s=pyiapws.wph(x, y)
print(r)
print(s)
plt.show()
SEE ALSO#
codata(3), ciaaw(3)