iapws-if97 2.2.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -2
- package/README.md +69 -246
- package/dist/backward/candidate-resolution.d.ts +8 -0
- package/dist/backward/candidate-resolution.js +40 -0
- package/dist/backward/fixed-temperature-candidates.d.ts +4 -0
- package/dist/backward/fixed-temperature-candidates.js +188 -0
- package/dist/backward/fixed-temperature-solver.d.ts +3 -3
- package/dist/backward/fixed-temperature-solver.js +38 -17
- package/dist/backward/fixed-temperature-stationary.d.ts +4 -0
- package/dist/backward/fixed-temperature-stationary.js +146 -0
- package/dist/backward/hs-region.d.ts +50 -0
- package/dist/backward/hs-region.js +695 -0
- package/dist/backward/hs-state.d.ts +15 -0
- package/dist/backward/hs-state.js +316 -0
- package/dist/backward/hs.js +28 -242
- package/dist/backward/ph.d.ts +2 -0
- package/dist/backward/ph.js +72 -21
- package/dist/backward/pressure-property-region.d.ts +13 -0
- package/dist/backward/pressure-property-region.js +262 -0
- package/dist/backward/ps.d.ts +6 -0
- package/dist/backward/ps.js +81 -28
- package/dist/backward/solution-validation.d.ts +7 -1
- package/dist/backward/solution-validation.js +138 -41
- package/dist/backward/th.d.ts +3 -5
- package/dist/backward/th.js +10 -71
- package/dist/backward/tolerances.d.ts +3 -0
- package/dist/backward/tolerances.js +9 -3
- package/dist/backward/ts.d.ts +3 -5
- package/dist/backward/ts.js +10 -71
- package/dist/constants.d.ts +11 -15
- package/dist/constants.js +14 -15
- package/dist/core/floating-point.d.ts +2 -0
- package/dist/core/floating-point.js +7 -0
- package/dist/core/formulation-seams.d.ts +27 -0
- package/dist/core/formulation-seams.js +289 -0
- package/dist/core/input-validation.d.ts +1 -0
- package/dist/core/input-validation.js +5 -0
- package/dist/core/region-detector.d.ts +3 -40
- package/dist/core/region-detector.js +37 -762
- package/dist/core/region3-pt.d.ts +1 -1
- package/dist/core/region3-pt.js +42 -16
- package/dist/core/solve-input-normalization.js +4 -1
- package/dist/core/solver.d.ts +7 -10
- package/dist/core/solver.js +26 -17
- package/dist/detect.d.ts +16 -2
- package/dist/detect.js +36 -2
- package/dist/errors.d.ts +11 -0
- package/dist/errors.js +16 -0
- package/dist/gas-constant.d.ts +5 -0
- package/dist/gas-constant.js +5 -0
- package/dist/index.d.ts +4 -5
- package/dist/index.js +10 -21
- package/dist/regions/region1.d.ts +2 -1
- package/dist/regions/region1.js +1 -1
- package/dist/regions/region2.d.ts +2 -1
- package/dist/regions/region2.js +1 -1
- package/dist/regions/region3-data.js +3 -3
- package/dist/regions/region3-subregions.js +15 -10
- package/dist/regions/region3.d.ts +4 -1
- package/dist/regions/region3.js +32 -2
- package/dist/regions/region4.d.ts +2 -0
- package/dist/regions/region4.js +39 -12
- package/dist/regions/region5.d.ts +2 -1
- package/dist/regions/region5.js +2 -2
- package/dist/saturation/common.d.ts +2 -8
- package/dist/saturation/common.js +64 -36
- package/dist/saturation/region4-boundaries.js +13 -13
- package/dist/saturation/region4-hs.js +282 -58
- package/dist/saturation/two-phase.d.ts +2 -2
- package/dist/saturation/two-phase.js +7 -7
- package/dist/solvers/bracketed-newton.d.ts +6 -3
- package/dist/solvers/bracketed-newton.js +15 -8
- package/dist/solvers/extended-arithmetic.d.ts +6 -0
- package/dist/solvers/extended-arithmetic.js +38 -0
- package/dist/transport/properties.d.ts +4 -2
- package/dist/transport/properties.js +14 -4
- package/dist/types.d.ts +18 -0
- package/dist/types.js +14 -0
- package/package.json +4 -4
- package/dist/core/public-normalization.d.ts +0 -3
- package/dist/core/public-normalization.js +0 -53
- /package/dist/{backward → core}/thermodynamic-derivatives.d.ts +0 -0
- /package/dist/{backward → core}/thermodynamic-derivatives.js +0 -0
|
@@ -35,6 +35,7 @@ const MU1_H = [
|
|
|
35
35
|
* Dynamic viscosity of water/steam [Pa·s]
|
|
36
36
|
* @param T Temperature [K]
|
|
37
37
|
* @param rho Density [kg/m³]
|
|
38
|
+
* @throws {IF97Error} If the calculated viscosity is non-finite or non-positive.
|
|
38
39
|
*/
|
|
39
40
|
export function viscosity(T, rho) {
|
|
40
41
|
assertFiniteNumber('Temperature', T);
|
|
@@ -64,7 +65,10 @@ export function viscosity(T, rho) {
|
|
|
64
65
|
// (within ~1 K and ~1 MPa). The original reference library also omits it.
|
|
65
66
|
// Keeping μ₂ = 1 (no enhancement) for practical use.
|
|
66
67
|
const mu2 = 1;
|
|
67
|
-
|
|
68
|
+
const mu = mu0 * mu1 * mu2 / 1e6; // Convert μPa·s to Pa·s
|
|
69
|
+
assertFiniteNumber('Dynamic viscosity', mu);
|
|
70
|
+
assertPositiveNumber('Dynamic viscosity', mu);
|
|
71
|
+
return mu;
|
|
68
72
|
}
|
|
69
73
|
// ─── Thermal Conductivity (IAPWS 2011) ──────────────────────────────────────
|
|
70
74
|
const K0_L = [2.443221e-3, 1.323095e-2, 6.770357e-3, -3.454586e-3, 4.096266e-4];
|
|
@@ -92,7 +96,7 @@ const DRHO_REF_COEFFS = [
|
|
|
92
96
|
*
|
|
93
97
|
* @param T Temperature [K]
|
|
94
98
|
* @param rho Density [kg/m³]
|
|
95
|
-
* @param cp
|
|
99
|
+
* @param cp Positive isobaric heat capacity [kJ/(kg·K)] (optional)
|
|
96
100
|
* @param cv Isochoric heat capacity [kJ/(kg·K)] (optional)
|
|
97
101
|
* @param drhodP_T Isothermal density derivative ∂ρ/∂P|_T [kg/m³/MPa] (optional)
|
|
98
102
|
* @param mu Dynamic viscosity [Pa·s] (optional)
|
|
@@ -102,8 +106,10 @@ export function thermalConductivity(T, rho, cp, cv, drhodP_T, mu) {
|
|
|
102
106
|
assertFiniteNumber('Density', rho);
|
|
103
107
|
assertPositiveNumber('Temperature', T);
|
|
104
108
|
assertNonNegativeNumber('Density', rho);
|
|
105
|
-
if (cp !== undefined)
|
|
109
|
+
if (cp !== undefined) {
|
|
106
110
|
assertFiniteNumber('Isobaric heat capacity', cp);
|
|
111
|
+
assertPositiveNumber('Isobaric heat capacity', cp);
|
|
112
|
+
}
|
|
107
113
|
if (cv !== undefined) {
|
|
108
114
|
assertFiniteNumber('Isochoric heat capacity', cv);
|
|
109
115
|
assertPositiveNumber('Isochoric heat capacity', cv);
|
|
@@ -198,14 +204,18 @@ const DC_Ih = [1, 1, 1, 2, 3, 3, 4, 5, 6, 7, 10];
|
|
|
198
204
|
const DC_Jh = [0.25, 1, 2.5, 1.5, 1.5, 2.5, 2, 2, 5, 0.5, 10];
|
|
199
205
|
/**
|
|
200
206
|
* Static dielectric constant [dimensionless]
|
|
201
|
-
* @param T Temperature [K]
|
|
207
|
+
* @param T Temperature [K], must be greater than 228 K
|
|
202
208
|
* @param rho Density [kg/m³]
|
|
209
|
+
* @throws {IF97Error} If T is at or below the equation's 228 K singularity.
|
|
203
210
|
*/
|
|
204
211
|
export function dielectricConstant(T, rho) {
|
|
205
212
|
assertFiniteNumber('Temperature', T);
|
|
206
213
|
assertFiniteNumber('Density', rho);
|
|
207
214
|
assertPositiveNumber('Temperature', T);
|
|
208
215
|
assertNonNegativeNumber('Density', rho);
|
|
216
|
+
if (T <= 228) {
|
|
217
|
+
throw new IF97Error('Temperature must be greater than 228 K for the dielectric constant');
|
|
218
|
+
}
|
|
209
219
|
const MW = 0.018015268;
|
|
210
220
|
const rhoM = rho / MW;
|
|
211
221
|
const rhoRc = rhoM / (RHOc / MW);
|
package/dist/types.d.ts
CHANGED
|
@@ -46,6 +46,8 @@ export interface SteamState {
|
|
|
46
46
|
speedOfSound: number | null;
|
|
47
47
|
/** Vapour quality (0–1), only defined on accepted Region 4 saturation states */
|
|
48
48
|
quality: number | null;
|
|
49
|
+
/** Saturation phases without transport properties, only present for Region 4. */
|
|
50
|
+
saturation?: SaturationEndpoints;
|
|
49
51
|
/** Dynamic viscosity [Pa·s], null for two-phase mixtures */
|
|
50
52
|
viscosity: number | null;
|
|
51
53
|
/** Thermal conductivity [W/(m·K)], null for two-phase mixtures */
|
|
@@ -79,6 +81,14 @@ export interface BasicProperties {
|
|
|
79
81
|
quality: number | null;
|
|
80
82
|
isobaricExpansion: number | null;
|
|
81
83
|
isothermalCompressibility: number | null;
|
|
84
|
+
saturation?: SaturationEndpoints;
|
|
85
|
+
}
|
|
86
|
+
/** Saturated liquid/vapor EOS states without nested saturation metadata. */
|
|
87
|
+
export interface SaturationEndpoints {
|
|
88
|
+
pressure: number;
|
|
89
|
+
temperature: number;
|
|
90
|
+
liquid: Omit<BasicProperties, 'saturation'>;
|
|
91
|
+
vapor: Omit<BasicProperties, 'saturation'>;
|
|
82
92
|
}
|
|
83
93
|
/** Supported thermodynamic input combinations */
|
|
84
94
|
export type InputMode = 'PT' | 'PH' | 'PS' | 'HS' | 'Px' | 'Tx' | 'TH' | 'TS';
|
|
@@ -137,6 +147,14 @@ export type CoefficientTable = readonly (readonly [number, number, number])[];
|
|
|
137
147
|
export declare class IF97Error extends Error {
|
|
138
148
|
constructor(message: string);
|
|
139
149
|
}
|
|
150
|
+
/** Thrown when TH or TS inputs identify multiple physical states. */
|
|
151
|
+
export declare class AmbiguousStateError extends IF97Error {
|
|
152
|
+
/** Validated basic states in ascending pressure order; order does not imply preference. */
|
|
153
|
+
readonly candidates: readonly BasicProperties[];
|
|
154
|
+
constructor(T: number, value: number, property?: 'enthalpy' | 'entropy',
|
|
155
|
+
/** Validated basic states in ascending pressure order; order does not imply preference. */
|
|
156
|
+
candidates?: readonly BasicProperties[]);
|
|
157
|
+
}
|
|
140
158
|
/** Thrown when input values are outside IAPWS-IF97 valid ranges */
|
|
141
159
|
export declare class OutOfRangeError extends IF97Error {
|
|
142
160
|
readonly parameter: string;
|
package/dist/types.js
CHANGED
|
@@ -27,6 +27,20 @@ export class IF97Error extends Error {
|
|
|
27
27
|
this.name = 'IF97Error';
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
+
/** Thrown when TH or TS inputs identify multiple physical states. */
|
|
31
|
+
export class AmbiguousStateError extends IF97Error {
|
|
32
|
+
candidates;
|
|
33
|
+
constructor(T, value, property = 'enthalpy',
|
|
34
|
+
/** Validated basic states in ascending pressure order; order does not imply preference. */
|
|
35
|
+
candidates = []) {
|
|
36
|
+
const symbol = property === 'enthalpy' ? 'h' : 's';
|
|
37
|
+
const unit = property === 'enthalpy' ? 'kJ/kg' : 'kJ/(kg·K)';
|
|
38
|
+
const pressureMode = property === 'enthalpy' ? 'PH' : 'PS';
|
|
39
|
+
super(`Ambiguous T-${symbol} state for T=${T} K, ${symbol}=${value} ${unit}: multiple physical states exist; supply an independent state constraint, for example using PT, ${pressureMode}, or Tx`);
|
|
40
|
+
this.candidates = candidates;
|
|
41
|
+
this.name = 'AmbiguousStateError';
|
|
42
|
+
}
|
|
43
|
+
}
|
|
30
44
|
/** Thrown when input values are outside IAPWS-IF97 valid ranges */
|
|
31
45
|
export class OutOfRangeError extends IF97Error {
|
|
32
46
|
parameter;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iapws-if97",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"description": "TypeScript implementation of IAPWS-IF97 for water and steam properties, including forward/backward solvers, saturation states, and transport properties.",
|
|
5
5
|
"author": "jltonghui",
|
|
6
6
|
"repository": {
|
|
@@ -64,15 +64,15 @@
|
|
|
64
64
|
"scripts": {
|
|
65
65
|
"prebuild": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
66
66
|
"build": "tsc",
|
|
67
|
+
"typecheck": "tsc -p tsconfig.test.json",
|
|
67
68
|
"test": "vitest run",
|
|
68
|
-
"test:package": "npm run build && node scripts/check-package.mjs",
|
|
69
|
+
"test:package": "npm run build && node --test scripts/check-package.test.mjs",
|
|
69
70
|
"test:watch": "vitest",
|
|
70
71
|
"test:coverage": "vitest run --coverage",
|
|
71
72
|
"test:standards": "vitest run tests/standards-asme tests/standards-cn",
|
|
72
73
|
"test:standards:asme": "vitest run tests/standards-asme",
|
|
73
74
|
"test:standards:cn": "vitest run tests/standards-cn",
|
|
74
|
-
"prepack": "npm run test:package && npm test"
|
|
75
|
-
"prepublishOnly": "npm run build && npm test"
|
|
75
|
+
"prepack": "npm run typecheck && npm run test:package && npm run test:coverage"
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
78
|
"@vitest/coverage-v8": "^4.1.0",
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
// Only snap values that are effectively simple decimals plus machine-noise.
|
|
2
|
-
const SIMPLE_DECIMAL_PLACES = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
3
|
-
const SNAP_ULPS = 8;
|
|
4
|
-
function snapSimpleDecimal(value) {
|
|
5
|
-
if (!Number.isFinite(value)) {
|
|
6
|
-
return value;
|
|
7
|
-
}
|
|
8
|
-
for (const decimals of SIMPLE_DECIMAL_PLACES) {
|
|
9
|
-
const factor = 10 ** decimals;
|
|
10
|
-
const candidate = Math.round(value * factor) / factor;
|
|
11
|
-
// Scale the acceptance window with magnitude so we only absorb
|
|
12
|
-
// binary floating-point residue, not meaningful engineering deltas.
|
|
13
|
-
const tolerance = SNAP_ULPS * Number.EPSILON * Math.max(1, Math.abs(value), Math.abs(candidate));
|
|
14
|
-
if (Math.abs(value - candidate) <= tolerance) {
|
|
15
|
-
return Object.is(candidate, -0) ? 0 : candidate;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
return Object.is(value, -0) ? 0 : value;
|
|
19
|
-
}
|
|
20
|
-
function normalizeNullableNumber(value) {
|
|
21
|
-
return value === null ? null : snapSimpleDecimal(value);
|
|
22
|
-
}
|
|
23
|
-
function normalizeBasicProperties(state) {
|
|
24
|
-
return {
|
|
25
|
-
region: state.region,
|
|
26
|
-
pressure: snapSimpleDecimal(state.pressure),
|
|
27
|
-
temperature: snapSimpleDecimal(state.temperature),
|
|
28
|
-
specificVolume: snapSimpleDecimal(state.specificVolume),
|
|
29
|
-
internalEnergy: snapSimpleDecimal(state.internalEnergy),
|
|
30
|
-
entropy: snapSimpleDecimal(state.entropy),
|
|
31
|
-
enthalpy: snapSimpleDecimal(state.enthalpy),
|
|
32
|
-
cp: normalizeNullableNumber(state.cp),
|
|
33
|
-
cv: normalizeNullableNumber(state.cv),
|
|
34
|
-
speedOfSound: normalizeNullableNumber(state.speedOfSound),
|
|
35
|
-
quality: normalizeNullableNumber(state.quality),
|
|
36
|
-
isobaricExpansion: normalizeNullableNumber(state.isobaricExpansion),
|
|
37
|
-
isothermalCompressibility: normalizeNullableNumber(state.isothermalCompressibility),
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
function normalizeSteamState(state) {
|
|
41
|
-
return {
|
|
42
|
-
...normalizeBasicProperties(state),
|
|
43
|
-
density: snapSimpleDecimal(state.density),
|
|
44
|
-
viscosity: normalizeNullableNumber(state.viscosity),
|
|
45
|
-
thermalConductivity: normalizeNullableNumber(state.thermalConductivity),
|
|
46
|
-
surfaceTension: normalizeNullableNumber(state.surfaceTension),
|
|
47
|
-
dielectricConstant: normalizeNullableNumber(state.dielectricConstant),
|
|
48
|
-
ionizationConstant: normalizeNullableNumber(state.ionizationConstant),
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
export function normalizePublicState(state) {
|
|
52
|
-
return 'density' in state ? normalizeSteamState(state) : normalizeBasicProperties(state);
|
|
53
|
-
}
|
|
File without changes
|
|
File without changes
|