A test corpus can be wrong too, and an independent steam-property verifier found three invalid states that were valid
An independent Rust implementation of the IAPWS-IF97 steam-property formulation, compared with the published verification tables, and a correction to its test corpus.
Keywords: IAPWS-IF97; steam properties; software verification; independent implementation; test oracles
Abstract
Engineering models of steam systems depend on correct implementations of the IAPWS-IF97 property formulation. We wrote a second, independent implementation of Regions 1 and 2 in Rust and compared it with the verification values printed in the IAPWS release. All 36 property values at the 6 verification states are reproduced within half a unit of the last printed digit; the largest relative error is 2.8 × 10-9. The only disagreement encountered was with the project's own test corpus: 3 states declared invalid are valid superheated vapor, as the implementation reported and an independent saturation-curve calculation confirms. The corpus was amended and 5 genuinely invalid states were added. In the amended corpus all 17 invalid or out-of-scope inputs are refused and all 8 valid control states are accepted. Component balance checks close to 3.1 × 10-16, but we show that most of them hold nearly by construction and should not be read as evidence of property accuracy.
1. Introduction
IAPWS-IF97 is the standard industrial formulation for the thermodynamic properties of water and steam [1, 2]. Its release prints verification values for each region so that implementations can be checked. Agreement with these values is evidence of a correct implementation at the tested states, though not a proof of correctness across each region; whether IF97 describes real steam sufficiently well is a separate question addressed by IAPWS and not considered here.
Independent reimplementation is a standard way to detect coding errors in scientific software [3]. This study reports such a reimplementation, the agreement it achieved with the published tables, and an instance in which the disagreement lay in the test expectations rather than in the code.
2. Methods
2.1 Implementation
The Region 1 and Region 2 fundamental equations were implemented in Rust from the published coefficients. States outside the declared scope are refused rather than extrapolated: liquid below the triple point, pressures above the standard's range, the near-critical Region 3, and the saturation line, where pressure and temperature do not fix a single-phase state.
2.2 Comparison with the published tables
The release prints specific volume, enthalpy, internal energy, entropy, isobaric heat capacity and speed of sound at three states per region to nine significant digits. All 36 values were compared, both as relative error and as absolute error divided by half a unit in the last printed digit, the precision the table itself states.
2.3 Domain tests and component balances
A domain test corpus of 25 cases was evaluated: 17 invalid or out-of-scope inputs that must be refused and 8 valid control states that must be accepted. Saturation pressures for disputed states were computed independently with the Modelica Standard Library [4]. Mass and energy balances were checked for 6 components: a boiler, valves, a mixer and turbines. A WebAssembly build of the library was compared with the command-line build across 8 states.
3. Results
3.1 Agreement with the published tables
The largest relative error across all 36 values is 2.8 × 10-9, against an acceptance criterion of 1 × 10-7. Because the printed values are rounded, the more informative measure is the error relative to half a unit in the last printed digit: its largest value is 0.81, so all 36 values agree with the table to the table's own precision (Figure 1).
3.2 Reclassification of three corpus states
Three states listed in the corpus as invalid were accepted by the implementation (Table 1). At each of these temperatures the pressure is below the saturation pressure, which places the state in Region 2, superheated vapor, within the declared scope. The independent saturation calculation gives 2.6389 MPa at 500 K and 0.9992 MPa at 453 K, confirming that each listed pressure lies below saturation (Figure 2). The corpus labels had been assigned from the names of the regions rather than from their definitions.
Table 1. The three states declared invalid in the original corpus.
| State | Pressure, MPa | Temperature, K |
|---|---|---|
| State A | 0.001 | 500 |
| State B | 2 | 500 |
| State C | 0.1 | 453 |
The correction is a change to expected outputs made after results were seen, and is reported as such. It was recorded as a corpus amendment with approval, the original labels were retained as identifiers, and 5 genuinely invalid states were added so that refusal coverage did not decrease. With the amended corpus, 0 of the 17 invalid or out-of-scope inputs are accepted, and 8 of the 8 valid control states are accepted.
3.3 Component balances
The largest relative balance residual across the 6 components is 3.1 × 10-16. This agreement is nearly automatic: the boiler and mixer cases use inputs that close exactly, a valve outlet is found by inverting the same enthalpy function the check uses, and a turbine's work cannot exceed its isentropic work at any efficiency between zero and one. The checks confirm that the arithmetic is connected correctly; property accuracy rests on the table comparison. A turbine expanding at an efficiency of 0.85 delivers 390.6 kJ/kg against an isentropic 459.5 kJ/kg at 0.5 MPa; a second turbine and one valve expand into the two-phase region, and those 2 cases are returned as unsupported rather than as wet-steam values. The WebAssembly and command-line builds agree to a relative difference of 0 across 8 states, which establishes interface consistency only.
4. Discussion
For an engineering model whose turbine and balance calculations rest on IF97, an independent implementation provides a check on the code that the published tables alone cannot. It also checks the tests: here the error was in the test corpus, not in either implementation. Test expectations written from category names rather than definitions are a plausible and general source of such errors, and an independent implementation is one way to expose them.
5. Limitations
- Only Regions 1 and 2 are implemented; the near-critical and high-temperature regions, metastable states and wet steam are refused.
- The implementation is independent of the original code but not of the formulation; a flaw in IF97 itself would be reproduced, not detected.
- The corpus amendment, although physically correct, was made after a failure was observed.
- Agreement at 6 verification states and 25 domain cases is evidence of correct implementation at those points, not a proof over each region, its boundaries or inverse functions.
- Evidence was obtained on one operating system and toolchain.
6. Conclusions
An independent Rust implementation of IAPWS-IF97 Regions 1 and 2 reproduces all 36 published verification values to their printed precision. Its one disagreement exposed 3 misclassified states in the test corpus, which were corrected.
References
- International Association for the Properties of Water and Steam. Revised Release on the IAPWS Industrial Formulation 1997 for the Thermodynamic Properties of Water and Steam, IAPWS R7-97(2012). 2012.
- Wagner W, Cooper JR, Dittmann A, et al. The IAPWS Industrial Formulation 1997 for the Thermodynamic Properties of Water and Steam. Journal of Engineering for Gas Turbines and Power, 122(1):150-182, 2000.
- Peng RD. Reproducible research in computational science. Science, 334(6060):1226-1227, 2011.
- Modelica Association. Modelica Standard Library, version 4.1.0. Linkoping, 2025.