iapws-if97 2.1.1 → 2.1.5
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 +8 -0
- package/dist/backward/hs.js +43 -9
- package/dist/backward/objective-normalization.d.ts +7 -0
- package/dist/backward/objective-normalization.js +8 -0
- package/dist/backward/ph.js +21 -5
- package/dist/backward/ps.js +15 -3
- package/dist/backward/th.js +3 -0
- package/dist/backward/tolerances.js +1 -1
- package/dist/backward/ts.js +3 -0
- package/dist/constants.d.ts +6 -2
- package/dist/constants.js +6 -2
- package/dist/core/input-validation.d.ts +2 -0
- package/dist/core/input-validation.js +7 -0
- package/dist/core/public-normalization.d.ts +2 -3
- package/dist/core/public-normalization.js +32 -9
- package/dist/core/region-detector.js +73 -49
- package/dist/core/region3-pt.js +6 -1
- package/dist/core/solve-input-normalization.js +4 -1
- package/dist/core/solver.js +3 -0
- package/dist/index.d.ts +8 -8
- package/dist/index.js +7 -16
- package/dist/regions/boundaries.d.ts +0 -9
- package/dist/regions/boundaries.js +8 -0
- package/dist/regions/region3-subregions.js +9 -6
- package/dist/regions/region3.d.ts +5 -1
- package/dist/regions/region3.js +9 -2
- package/dist/saturation/common.d.ts +1 -0
- package/dist/saturation/common.js +30 -3
- package/dist/saturation/region4-hs.js +89 -6
- package/dist/saturation/two-phase.js +5 -0
- package/dist/solvers/nelder-mead.d.ts +0 -4
- package/dist/solvers/nelder-mead.js +29 -12
- package/dist/solvers/newton-raphson.d.ts +1 -4
- package/dist/solvers/newton-raphson.js +15 -4
- package/dist/transport/properties.d.ts +1 -0
- package/dist/transport/properties.js +44 -4
- package/package.json +3 -2
- package/dist/backward/fixed-temperature-solver.d.ts.map +0 -1
- package/dist/backward/fixed-temperature-solver.js.map +0 -1
- package/dist/backward/hs.d.ts.map +0 -1
- package/dist/backward/hs.js.map +0 -1
- package/dist/backward/ph.d.ts.map +0 -1
- package/dist/backward/ph.js.map +0 -1
- package/dist/backward/ps.d.ts.map +0 -1
- package/dist/backward/ps.js.map +0 -1
- package/dist/backward/solution-validation.d.ts.map +0 -1
- package/dist/backward/solution-validation.js.map +0 -1
- package/dist/backward/th.d.ts.map +0 -1
- package/dist/backward/th.js.map +0 -1
- package/dist/backward/tolerances.d.ts.map +0 -1
- package/dist/backward/tolerances.js.map +0 -1
- package/dist/backward/ts.d.ts.map +0 -1
- package/dist/backward/ts.js.map +0 -1
- package/dist/boundaries.d.ts.map +0 -1
- package/dist/boundaries.js.map +0 -1
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js.map +0 -1
- package/dist/core/public-normalization.d.ts.map +0 -1
- package/dist/core/public-normalization.js.map +0 -1
- package/dist/core/region-detector.d.ts.map +0 -1
- package/dist/core/region-detector.js.map +0 -1
- package/dist/core/region3-pt.d.ts.map +0 -1
- package/dist/core/region3-pt.js.map +0 -1
- package/dist/core/solve-input-normalization.d.ts.map +0 -1
- package/dist/core/solve-input-normalization.js.map +0 -1
- package/dist/core/solver.d.ts.map +0 -1
- package/dist/core/solver.js.map +0 -1
- package/dist/detect.d.ts.map +0 -1
- package/dist/detect.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/regions/boundaries.d.ts.map +0 -1
- package/dist/regions/boundaries.js.map +0 -1
- package/dist/regions/region1.d.ts.map +0 -1
- package/dist/regions/region1.js.map +0 -1
- package/dist/regions/region2.d.ts.map +0 -1
- package/dist/regions/region2.js.map +0 -1
- package/dist/regions/region3-data.d.ts.map +0 -1
- package/dist/regions/region3-data.js.map +0 -1
- package/dist/regions/region3-eval.d.ts.map +0 -1
- package/dist/regions/region3-eval.js.map +0 -1
- package/dist/regions/region3-subregions.d.ts.map +0 -1
- package/dist/regions/region3-subregions.js.map +0 -1
- package/dist/regions/region3.d.ts.map +0 -1
- package/dist/regions/region3.js.map +0 -1
- package/dist/regions/region4.d.ts.map +0 -1
- package/dist/regions/region4.js.map +0 -1
- package/dist/regions/region5.d.ts.map +0 -1
- package/dist/regions/region5.js.map +0 -1
- package/dist/regions.d.ts.map +0 -1
- package/dist/regions.js.map +0 -1
- package/dist/saturation/common.d.ts.map +0 -1
- package/dist/saturation/common.js.map +0 -1
- package/dist/saturation/region4-boundaries.d.ts.map +0 -1
- package/dist/saturation/region4-boundaries.js.map +0 -1
- package/dist/saturation/region4-hs.d.ts.map +0 -1
- package/dist/saturation/region4-hs.js.map +0 -1
- package/dist/saturation/two-phase.d.ts.map +0 -1
- package/dist/saturation/two-phase.js.map +0 -1
- package/dist/saturation.d.ts.map +0 -1
- package/dist/saturation.js.map +0 -1
- package/dist/solvers/bracketed-newton.d.ts.map +0 -1
- package/dist/solvers/bracketed-newton.js.map +0 -1
- package/dist/solvers/nelder-mead.d.ts.map +0 -1
- package/dist/solvers/nelder-mead.js.map +0 -1
- package/dist/solvers/newton-raphson.d.ts.map +0 -1
- package/dist/solvers/newton-raphson.js.map +0 -1
- package/dist/transport/properties.d.ts.map +0 -1
- package/dist/transport/properties.js.map +0 -1
- package/dist/transport.d.ts.map +0 -1
- package/dist/transport.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
package/CHANGELOG.md
CHANGED
package/dist/backward/hs.js
CHANGED
|
@@ -12,11 +12,14 @@ import { region1 } from '../regions/region1.js';
|
|
|
12
12
|
import { region2 } from '../regions/region2.js';
|
|
13
13
|
import { region3ByRhoT } from '../regions/region3.js';
|
|
14
14
|
import { region5 } from '../regions/region5.js';
|
|
15
|
+
import { assertFiniteNumber } from '../core/input-validation.js';
|
|
15
16
|
import { detectRegionHS } from '../core/region-detector.js';
|
|
16
17
|
import { newtonRaphson } from '../solvers/newton-raphson.js';
|
|
17
18
|
import { nelderMead } from '../solvers/nelder-mead.js';
|
|
18
19
|
import { solvePH } from './ph.js';
|
|
19
20
|
import { validateBackwardState } from './solution-validation.js';
|
|
21
|
+
import { sumNormalizedResiduals } from './objective-normalization.js';
|
|
22
|
+
import { backwardConstraintTolerance } from './tolerances.js';
|
|
20
23
|
import { tryRegion4HSState, } from '../saturation/region4-hs.js';
|
|
21
24
|
import { assertCriticalRegion4HSInput, } from '../saturation/region4-boundaries.js';
|
|
22
25
|
// ─── Backward Polynomial Evaluator ─────────────────────────────────────────
|
|
@@ -105,9 +108,11 @@ function r2cPhs(h, s) {
|
|
|
105
108
|
}
|
|
106
109
|
function r2Phs(h, s) {
|
|
107
110
|
const hBound = b2abBoundary(s);
|
|
111
|
+
// Region 2 h-s subregion selection: 2a below the h(s) boundary,
|
|
112
|
+
// otherwise split 2b/2c at the published entropy crossover.
|
|
108
113
|
if (h <= hBound)
|
|
109
114
|
return r2aPhs(h, s);
|
|
110
|
-
if (s >=
|
|
115
|
+
if (s >= C.R2_S_CRT)
|
|
111
116
|
return r2bPhs(h, s);
|
|
112
117
|
return r2cPhs(h, s);
|
|
113
118
|
}
|
|
@@ -154,6 +159,33 @@ function r3Phs(h, s) {
|
|
|
154
159
|
return r3aPhs(h, s);
|
|
155
160
|
return r3bPhs(h, s);
|
|
156
161
|
}
|
|
162
|
+
const REGION5_HS_OUT_OF_DOMAIN_PENALTY = 1e18;
|
|
163
|
+
function normalizedHsObjective(h, s, stateAt) {
|
|
164
|
+
const enthalpyTolerance = backwardConstraintTolerance('enthalpy', h);
|
|
165
|
+
const entropyTolerance = backwardConstraintTolerance('entropy', s);
|
|
166
|
+
return (pair) => {
|
|
167
|
+
const state = stateAt(pair);
|
|
168
|
+
return sumNormalizedResiduals([
|
|
169
|
+
{ actual: state.enthalpy, expected: h, tolerance: enthalpyTolerance },
|
|
170
|
+
{ actual: state.entropy, expected: s, tolerance: entropyTolerance },
|
|
171
|
+
]);
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function normalizedRegion5HsObjective(h, s) {
|
|
175
|
+
const enthalpyTolerance = backwardConstraintTolerance('enthalpy', h);
|
|
176
|
+
const entropyTolerance = backwardConstraintTolerance('entropy', s);
|
|
177
|
+
return (pair) => {
|
|
178
|
+
const [p, T] = pair;
|
|
179
|
+
if (p <= 0 || p > C.R5_P_MAX || T <= C.R5_T_MIN || T > C.R5_T_MAX) {
|
|
180
|
+
return REGION5_HS_OUT_OF_DOMAIN_PENALTY;
|
|
181
|
+
}
|
|
182
|
+
const state = region5(p, T);
|
|
183
|
+
return sumNormalizedResiduals([
|
|
184
|
+
{ actual: state.enthalpy, expected: h, tolerance: enthalpyTolerance },
|
|
185
|
+
{ actual: state.entropy, expected: s, tolerance: entropyTolerance },
|
|
186
|
+
]);
|
|
187
|
+
};
|
|
188
|
+
}
|
|
157
189
|
// ─── Main HS Solver ─────────────────────────────────────────────────────────
|
|
158
190
|
/**
|
|
159
191
|
* Solve for thermodynamic state given H and S.
|
|
@@ -161,6 +193,8 @@ function r3Phs(h, s) {
|
|
|
161
193
|
* @param s - Specific entropy [kJ/(kg·K)]
|
|
162
194
|
*/
|
|
163
195
|
export function solveHS(h, s) {
|
|
196
|
+
assertFiniteNumber('Enthalpy', h);
|
|
197
|
+
assertFiniteNumber('Entropy', s);
|
|
164
198
|
if (h < C.H_MIN || h > C.H_MAX) {
|
|
165
199
|
throw new OutOfRangeError('Enthalpy', h, C.H_MIN, C.H_MAX);
|
|
166
200
|
}
|
|
@@ -179,8 +213,8 @@ export function solveHS(h, s) {
|
|
|
179
213
|
switch (region) {
|
|
180
214
|
case Region.Region1: {
|
|
181
215
|
const P0 = r1Phs(h, s);
|
|
182
|
-
const
|
|
183
|
-
|
|
216
|
+
const objective = normalizedHsObjective(h, s, (pair) => region1(pair[0], pair[1]));
|
|
217
|
+
const sol = nelderMead(objective, [P0, 400], { maxIterations: 1000, minErrorDelta: 1e-8, minTolerance: 1e-9 });
|
|
184
218
|
return validateBackwardState(region1(sol.x[0], sol.x[1]), [
|
|
185
219
|
{ label: 'enthalpy', expected: h },
|
|
186
220
|
{ label: 'entropy', expected: s },
|
|
@@ -189,8 +223,8 @@ export function solveHS(h, s) {
|
|
|
189
223
|
case Region.Region2: {
|
|
190
224
|
const P0 = r2Phs(h, s);
|
|
191
225
|
const T0 = newtonRaphson((T) => region2(P0, T).enthalpy - h, 500);
|
|
192
|
-
const
|
|
193
|
-
|
|
226
|
+
const objective = normalizedHsObjective(h, s, (pair) => region2(pair[0], pair[1]));
|
|
227
|
+
const sol = nelderMead(objective, [P0, T0], { maxIterations: 1000, minErrorDelta: 1e-8, minTolerance: 1e-9 });
|
|
194
228
|
return validateBackwardState(region2(sol.x[0], sol.x[1]), [
|
|
195
229
|
{ label: 'enthalpy', expected: h },
|
|
196
230
|
{ label: 'entropy', expected: s },
|
|
@@ -201,8 +235,8 @@ export function solveHS(h, s) {
|
|
|
201
235
|
const init = solvePH(P0, h);
|
|
202
236
|
const rho0 = 1 / init.specificVolume;
|
|
203
237
|
const T0 = init.temperature;
|
|
204
|
-
const
|
|
205
|
-
|
|
238
|
+
const objective = normalizedHsObjective(h, s, (pair) => region3ByRhoT(pair[0], pair[1]));
|
|
239
|
+
const sol = nelderMead(objective, [rho0, T0], { maxIterations: 1000, minErrorDelta: 1e-8, minTolerance: 1e-9 });
|
|
206
240
|
return validateBackwardState(region3ByRhoT(sol.x[0], sol.x[1]), [
|
|
207
241
|
{ label: 'enthalpy', expected: h },
|
|
208
242
|
{ label: 'entropy', expected: s },
|
|
@@ -212,8 +246,8 @@ export function solveHS(h, s) {
|
|
|
212
246
|
throw new IF97Error('solveHS identified Region 4 but failed to construct a valid saturation state');
|
|
213
247
|
}
|
|
214
248
|
case Region.Region5: {
|
|
215
|
-
const
|
|
216
|
-
|
|
249
|
+
const objective = normalizedRegion5HsObjective(h, s);
|
|
250
|
+
const sol = nelderMead(objective, [1, 1400], { maxIterations: 1000, minErrorDelta: 1e-8, minTolerance: 1e-9 });
|
|
217
251
|
return validateBackwardState(region5(sol.x[0], sol.x[1]), [
|
|
218
252
|
{ label: 'enthalpy', expected: h },
|
|
219
253
|
{ label: 'entropy', expected: s },
|
package/dist/backward/ph.js
CHANGED
|
@@ -13,10 +13,13 @@ import { region2 } from '../regions/region2.js';
|
|
|
13
13
|
import { region3ByRhoT } from '../regions/region3.js';
|
|
14
14
|
import { region5 } from '../regions/region5.js';
|
|
15
15
|
import { saturationTemperature } from '../regions/region4.js';
|
|
16
|
+
import { assertFiniteNumber } from '../core/input-validation.js';
|
|
16
17
|
import { detectRegionPH } from '../core/region-detector.js';
|
|
17
18
|
import { newtonRaphson } from '../solvers/newton-raphson.js';
|
|
18
19
|
import { nelderMead } from '../solvers/nelder-mead.js';
|
|
19
20
|
import { validateBackwardState } from './solution-validation.js';
|
|
21
|
+
import { backwardConstraintTolerance } from './tolerances.js';
|
|
22
|
+
import { sumNormalizedResiduals } from './objective-normalization.js';
|
|
20
23
|
import { mixSaturationState, qualityFromSaturationProperty, saturationEndpointsAtPressure, } from '../saturation/common.js';
|
|
21
24
|
import { assertCriticalRegion4PHInput, assertRegion4StateAllowed, } from '../saturation/region4-boundaries.js';
|
|
22
25
|
// ─── Backward Polynomial Evaluator ─────────────────────────────────────────
|
|
@@ -40,6 +43,10 @@ function r1BackwardT(p, h) {
|
|
|
40
43
|
return evalPoly(R1_PH, 0, -1, p, h / 2500);
|
|
41
44
|
}
|
|
42
45
|
// ─── Region 2 Backward T(P,H) ─────────────────────────────────────────────
|
|
46
|
+
// Lowest pressure where Region 2c can appear in the P-H backward formulation.
|
|
47
|
+
// For 4 < p <= 6.546699678 MPa the supplementary release selects subregion 2b
|
|
48
|
+
// directly; above this threshold use the B2bc(h) boundary to discriminate 2b/2c.
|
|
49
|
+
const R2_PH_B2BC_P_MIN = 6.546699678;
|
|
43
50
|
// B2bc boundary (exported for future use)
|
|
44
51
|
export function b2bc_H_P(h) {
|
|
45
52
|
return 0.90584278514723e-3 - 0.67955786399241 * h + 0.12809002730136e-3 * h * h;
|
|
@@ -94,11 +101,11 @@ function r2BackwardT(p, h) {
|
|
|
94
101
|
if (p <= C.R2_P_CRT) {
|
|
95
102
|
T = r2aBackwardT(p, h);
|
|
96
103
|
}
|
|
97
|
-
else if (p <=
|
|
104
|
+
else if (p <= R2_PH_B2BC_P_MIN) {
|
|
98
105
|
T = r2bBackwardT(p, h);
|
|
99
106
|
}
|
|
100
107
|
else {
|
|
101
|
-
if (p <
|
|
108
|
+
if (p < b2bc_H_P(h)) {
|
|
102
109
|
T = r2bBackwardT(p, h);
|
|
103
110
|
}
|
|
104
111
|
else {
|
|
@@ -190,6 +197,8 @@ export function r4EnthalpyToPsat(h) {
|
|
|
190
197
|
* @param h - Specific enthalpy [kJ/kg]
|
|
191
198
|
*/
|
|
192
199
|
export function solvePH(p, h) {
|
|
200
|
+
assertFiniteNumber('Pressure', p);
|
|
201
|
+
assertFiniteNumber('Enthalpy', h);
|
|
193
202
|
if (p < C.P_MIN || p > C.P_MAX) {
|
|
194
203
|
throw new OutOfRangeError('Pressure', p, C.P_MIN, C.P_MAX);
|
|
195
204
|
}
|
|
@@ -217,6 +226,8 @@ export function solvePH(p, h) {
|
|
|
217
226
|
}
|
|
218
227
|
case Region.Region3: {
|
|
219
228
|
const hBound = b3ab_P_to_H(p);
|
|
229
|
+
const pressureTolerance = 1e-5 * Math.max(1, Math.abs(p));
|
|
230
|
+
const enthalpyTolerance = backwardConstraintTolerance('enthalpy', h);
|
|
220
231
|
let T0, v0;
|
|
221
232
|
if (h < hBound) {
|
|
222
233
|
T0 = 760 * evalPoly(R3A_PH_T, -0.240, 0.615, p / 100, h / 2300);
|
|
@@ -226,10 +237,15 @@ export function solvePH(p, h) {
|
|
|
226
237
|
T0 = 860 * evalPoly(R3B_PH_T, -0.298, 0.720, p / 100, h / 2800);
|
|
227
238
|
v0 = 0.0088 * evalPoly(R3B_PH_V, -0.0661, 0.720, p / 100, h / 2800);
|
|
228
239
|
}
|
|
229
|
-
const sol = nelderMead((pair) =>
|
|
230
|
-
|
|
240
|
+
const sol = nelderMead((pair) => {
|
|
241
|
+
const state = region3ByRhoT(1 / pair[0], pair[1]);
|
|
242
|
+
return sumNormalizedResiduals([
|
|
243
|
+
{ actual: state.enthalpy, expected: h, tolerance: enthalpyTolerance },
|
|
244
|
+
{ actual: state.pressure, expected: p, tolerance: pressureTolerance },
|
|
245
|
+
]);
|
|
246
|
+
}, [v0, T0], { maxIterations: 1000, minErrorDelta: 1e-8, minTolerance: 1e-9 });
|
|
231
247
|
return validateBackwardState(region3ByRhoT(1 / sol.x[0], sol.x[1]), [
|
|
232
|
-
{ label: 'pressure', expected: p, tolerance:
|
|
248
|
+
{ label: 'pressure', expected: p, tolerance: pressureTolerance },
|
|
233
249
|
{ label: 'enthalpy', expected: h },
|
|
234
250
|
], { solverName: 'solvePH', expectedRegion: Region.Region3 });
|
|
235
251
|
}
|
package/dist/backward/ps.js
CHANGED
|
@@ -9,10 +9,13 @@ import { region1 } from '../regions/region1.js';
|
|
|
9
9
|
import { region2 } from '../regions/region2.js';
|
|
10
10
|
import { region3ByRhoT } from '../regions/region3.js';
|
|
11
11
|
import { region5 } from '../regions/region5.js';
|
|
12
|
+
import { assertFiniteNumber } from '../core/input-validation.js';
|
|
12
13
|
import { detectRegionPS } from '../core/region-detector.js';
|
|
13
14
|
import { newtonRaphson } from '../solvers/newton-raphson.js';
|
|
14
15
|
import { nelderMead } from '../solvers/nelder-mead.js';
|
|
15
16
|
import { validateBackwardState } from './solution-validation.js';
|
|
17
|
+
import { backwardConstraintTolerance } from './tolerances.js';
|
|
18
|
+
import { sumNormalizedResiduals } from './objective-normalization.js';
|
|
16
19
|
import { mixSaturationState, qualityFromSaturationProperty, saturationEndpointsAtPressure, } from '../saturation/common.js';
|
|
17
20
|
import { assertCriticalRegion4PSInput, assertRegion4StateAllowed, } from '../saturation/region4-boundaries.js';
|
|
18
21
|
function evalPoly(table, piShift, sigShift, pi, sig) {
|
|
@@ -149,6 +152,8 @@ const R3B_PS_V_TABLE = [
|
|
|
149
152
|
* @param s - Specific entropy [kJ/(kg·K)]
|
|
150
153
|
*/
|
|
151
154
|
export function solvePS(p, s) {
|
|
155
|
+
assertFiniteNumber('Pressure', p);
|
|
156
|
+
assertFiniteNumber('Entropy', s);
|
|
152
157
|
if (p < C.P_MIN || p > C.P_MAX) {
|
|
153
158
|
throw new OutOfRangeError('Pressure', p, C.P_MIN, C.P_MAX);
|
|
154
159
|
}
|
|
@@ -175,6 +180,8 @@ export function solvePS(p, s) {
|
|
|
175
180
|
], { solverName: 'solvePS', expectedRegion: Region.Region2 });
|
|
176
181
|
}
|
|
177
182
|
case Region.Region3: {
|
|
183
|
+
const pressureTolerance = 1e-5 * Math.max(1, Math.abs(p));
|
|
184
|
+
const entropyTolerance = backwardConstraintTolerance('entropy', s);
|
|
178
185
|
let T0, v0;
|
|
179
186
|
if (s <= C.R3_S_CRT) {
|
|
180
187
|
T0 = 760 * evalPoly(R3A_PS_T_TABLE, -0.240, 0.703, p / 100, s / 4.4);
|
|
@@ -184,10 +191,15 @@ export function solvePS(p, s) {
|
|
|
184
191
|
T0 = 860 * evalPoly(R3B_PS_T_TABLE, -0.760, 0.818, p / 100, s / 5.3);
|
|
185
192
|
v0 = 0.0088 * evalPoly(R3B_PS_V_TABLE, -0.298, 0.816, p / 100, s / 5.3);
|
|
186
193
|
}
|
|
187
|
-
const sol = nelderMead((pair) =>
|
|
188
|
-
|
|
194
|
+
const sol = nelderMead((pair) => {
|
|
195
|
+
const state = region3ByRhoT(1 / pair[0], pair[1]);
|
|
196
|
+
return sumNormalizedResiduals([
|
|
197
|
+
{ actual: state.entropy, expected: s, tolerance: entropyTolerance },
|
|
198
|
+
{ actual: state.pressure, expected: p, tolerance: pressureTolerance },
|
|
199
|
+
]);
|
|
200
|
+
}, [v0, T0], { maxIterations: 1000, minErrorDelta: 1e-8, minTolerance: 1e-9 });
|
|
189
201
|
return validateBackwardState(region3ByRhoT(1 / sol.x[0], sol.x[1]), [
|
|
190
|
-
{ label: 'pressure', expected: p, tolerance:
|
|
202
|
+
{ label: 'pressure', expected: p, tolerance: pressureTolerance },
|
|
191
203
|
{ label: 'entropy', expected: s },
|
|
192
204
|
], { solverName: 'solvePS', expectedRegion: Region.Region3 });
|
|
193
205
|
}
|
package/dist/backward/th.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as C from '../constants.js';
|
|
2
2
|
import { IF97Error, OutOfRangeError, Region } from '../types.js';
|
|
3
|
+
import { assertFiniteNumber } from '../core/input-validation.js';
|
|
3
4
|
import { detectRegionTH } from '../core/region-detector.js';
|
|
4
5
|
import { solveRegion3PTBasic } from '../core/region3-pt.js';
|
|
5
6
|
import { region1 } from '../regions/region1.js';
|
|
@@ -28,6 +29,8 @@ const extractH = (s) => s.enthalpy;
|
|
|
28
29
|
* @throws {IF97Error} if T is within the critical exclusion band
|
|
29
30
|
*/
|
|
30
31
|
export function solveTH(T, h) {
|
|
32
|
+
assertFiniteNumber('Temperature', T);
|
|
33
|
+
assertFiniteNumber('Enthalpy', h);
|
|
31
34
|
if (T < C.T_MIN || T > C.T_MAX) {
|
|
32
35
|
throw new OutOfRangeError('Temperature', T, C.T_MIN, C.T_MAX);
|
|
33
36
|
}
|
|
@@ -5,7 +5,7 @@ export function backwardConstraintTolerance(label, expected) {
|
|
|
5
5
|
case 'temperature':
|
|
6
6
|
return 1e-9 * Math.max(1, Math.abs(expected));
|
|
7
7
|
case 'enthalpy':
|
|
8
|
-
return 1e-
|
|
8
|
+
return 1e-6 * Math.max(1, Math.abs(expected));
|
|
9
9
|
case 'entropy':
|
|
10
10
|
return 1e-6 * Math.max(1, Math.abs(expected));
|
|
11
11
|
default:
|
package/dist/backward/ts.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as C from '../constants.js';
|
|
2
2
|
import { IF97Error, OutOfRangeError, Region } from '../types.js';
|
|
3
|
+
import { assertFiniteNumber } from '../core/input-validation.js';
|
|
3
4
|
import { detectRegionTS } from '../core/region-detector.js';
|
|
4
5
|
import { solveRegion3PTBasic } from '../core/region3-pt.js';
|
|
5
6
|
import { region1 } from '../regions/region1.js';
|
|
@@ -28,6 +29,8 @@ const extractS = (s) => s.entropy;
|
|
|
28
29
|
* @throws {IF97Error} if T is within the critical exclusion band
|
|
29
30
|
*/
|
|
30
31
|
export function solveTS(T, s) {
|
|
32
|
+
assertFiniteNumber('Temperature', T);
|
|
33
|
+
assertFiniteNumber('Entropy', s);
|
|
31
34
|
if (T < C.T_MIN || T > C.T_MAX) {
|
|
32
35
|
throw new OutOfRangeError('Temperature', T, C.T_MIN, C.T_MAX);
|
|
33
36
|
}
|
package/dist/constants.d.ts
CHANGED
|
@@ -5,9 +5,13 @@
|
|
|
5
5
|
* for the IAPWS Industrial Formulation 1997.
|
|
6
6
|
*/
|
|
7
7
|
/** Specific gas constant for water [kJ/(kg·K)].
|
|
8
|
-
* IAPWS-IF97, §2 (Table 1). Fixed value for IF97 internal consistency
|
|
9
|
-
*
|
|
8
|
+
* IAPWS-IF97, §2 (Table 1). Fixed value for IF97 internal consistency.
|
|
9
|
+
* Do not replace transport correlations with this value; thermal conductivity
|
|
10
|
+
* critical enhancement intentionally uses `R_IAPWS_2011_THERMAL`. */
|
|
10
11
|
export declare const R = 0.461526;
|
|
12
|
+
/** Specific gas constant used by the IAPWS 2011 thermal conductivity λ₂ correlation [kJ/(kg·K)].
|
|
13
|
+
* Intentionally differs from IF97's `R`; keep both constants distinct and named. */
|
|
14
|
+
export declare const R_IAPWS_2011_THERMAL = 0.46151805;
|
|
11
15
|
/** Critical temperature [K] */
|
|
12
16
|
export declare const Tc = 647.096;
|
|
13
17
|
/** Temperature exclusion half-band around the critical point [K] */
|
package/dist/constants.js
CHANGED
|
@@ -6,9 +6,13 @@
|
|
|
6
6
|
*/
|
|
7
7
|
// ─── Fundamental Constants ──────────────────────────────────────────────────
|
|
8
8
|
/** Specific gas constant for water [kJ/(kg·K)].
|
|
9
|
-
* IAPWS-IF97, §2 (Table 1). Fixed value for IF97 internal consistency
|
|
10
|
-
*
|
|
9
|
+
* IAPWS-IF97, §2 (Table 1). Fixed value for IF97 internal consistency.
|
|
10
|
+
* Do not replace transport correlations with this value; thermal conductivity
|
|
11
|
+
* critical enhancement intentionally uses `R_IAPWS_2011_THERMAL`. */
|
|
11
12
|
export const R = 0.461526;
|
|
13
|
+
/** Specific gas constant used by the IAPWS 2011 thermal conductivity λ₂ correlation [kJ/(kg·K)].
|
|
14
|
+
* Intentionally differs from IF97's `R`; keep both constants distinct and named. */
|
|
15
|
+
export const R_IAPWS_2011_THERMAL = 0.46151805;
|
|
12
16
|
// ─── Critical Point ─────────────────────────────────────────────────────────
|
|
13
17
|
/** Critical temperature [K] */
|
|
14
18
|
export const Tc = 647.096;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { IF97Error } from '../types.js';
|
|
2
|
+
export function assertFiniteNumber(parameter, value) {
|
|
3
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
4
|
+
throw new IF97Error(`${parameter} must be a finite number`);
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=input-validation.js.map
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { BasicProperties, SteamState } from '../types.js';
|
|
2
|
-
|
|
3
|
-
export declare function normalizePublicState
|
|
4
|
-
export {};
|
|
2
|
+
export declare function normalizePublicState(state: SteamState): SteamState;
|
|
3
|
+
export declare function normalizePublicState(state: BasicProperties): BasicProperties;
|
|
5
4
|
//# sourceMappingURL=public-normalization.d.ts.map
|
|
@@ -17,15 +17,38 @@ function snapSimpleDecimal(value) {
|
|
|
17
17
|
}
|
|
18
18
|
return Object.is(value, -0) ? 0 : value;
|
|
19
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
|
+
}
|
|
20
51
|
export function normalizePublicState(state) {
|
|
21
|
-
|
|
22
|
-
for (const [key, value] of Object.entries(state)) {
|
|
23
|
-
// Preserve enum/null fields exactly; only normalize exposed numeric outputs.
|
|
24
|
-
if (key === 'region' || value === null || typeof value !== 'number') {
|
|
25
|
-
continue;
|
|
26
|
-
}
|
|
27
|
-
normalized[key] = snapSimpleDecimal(value);
|
|
28
|
-
}
|
|
29
|
-
return normalized;
|
|
52
|
+
return 'density' in state ? normalizeSteamState(state) : normalizeBasicProperties(state);
|
|
30
53
|
}
|
|
31
54
|
//# sourceMappingURL=public-normalization.js.map
|