iapws-if97 2.1.5 → 2.2.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.
Files changed (87) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +134 -94
  3. package/dist/backward/fixed-temperature-solver.d.ts +6 -6
  4. package/dist/backward/fixed-temperature-solver.js +34 -8
  5. package/dist/backward/hs.d.ts +1 -2
  6. package/dist/backward/hs.js +66 -56
  7. package/dist/backward/ph.d.ts +8 -5
  8. package/dist/backward/ph.js +43 -46
  9. package/dist/backward/ps.d.ts +0 -1
  10. package/dist/backward/ps.js +30 -18
  11. package/dist/backward/solution-validation.d.ts +0 -1
  12. package/dist/backward/solution-validation.js +33 -5
  13. package/dist/backward/th.d.ts +0 -1
  14. package/dist/backward/th.js +4 -6
  15. package/dist/backward/thermodynamic-derivatives.d.ts +17 -0
  16. package/dist/backward/thermodynamic-derivatives.js +27 -0
  17. package/dist/backward/tolerances.d.ts +0 -1
  18. package/dist/backward/tolerances.js +0 -1
  19. package/dist/backward/ts.d.ts +0 -1
  20. package/dist/backward/ts.js +4 -6
  21. package/dist/boundaries.d.ts +0 -1
  22. package/dist/boundaries.js +0 -1
  23. package/dist/constants.d.ts +0 -9
  24. package/dist/constants.js +3 -13
  25. package/dist/core/input-validation.d.ts +0 -1
  26. package/dist/core/input-validation.js +0 -1
  27. package/dist/core/public-normalization.d.ts +0 -1
  28. package/dist/core/public-normalization.js +0 -1
  29. package/dist/core/region-detector.d.ts +0 -1
  30. package/dist/core/region-detector.js +232 -65
  31. package/dist/core/region3-pt.d.ts +12 -1
  32. package/dist/core/region3-pt.js +38 -9
  33. package/dist/core/solve-input-normalization.d.ts +0 -1
  34. package/dist/core/solve-input-normalization.js +0 -1
  35. package/dist/core/solver.d.ts +0 -1
  36. package/dist/core/solver.js +0 -1
  37. package/dist/detect.d.ts +0 -1
  38. package/dist/detect.js +0 -1
  39. package/dist/index.d.ts +0 -1
  40. package/dist/index.js +0 -1
  41. package/dist/regions/boundaries.d.ts +0 -1
  42. package/dist/regions/boundaries.js +0 -1
  43. package/dist/regions/region1.d.ts +0 -1
  44. package/dist/regions/region1.js +0 -1
  45. package/dist/regions/region2.d.ts +0 -1
  46. package/dist/regions/region2.js +0 -1
  47. package/dist/regions/region3-data.d.ts +0 -1
  48. package/dist/regions/region3-data.js +0 -1
  49. package/dist/regions/region3-eval.d.ts +0 -1
  50. package/dist/regions/region3-eval.js +0 -1
  51. package/dist/regions/region3-subregions.d.ts +0 -1
  52. package/dist/regions/region3-subregions.js +0 -1
  53. package/dist/regions/region3.d.ts +0 -1
  54. package/dist/regions/region3.js +0 -1
  55. package/dist/regions/region4.d.ts +0 -1
  56. package/dist/regions/region4.js +0 -1
  57. package/dist/regions/region5.d.ts +0 -1
  58. package/dist/regions/region5.js +0 -1
  59. package/dist/regions.d.ts +0 -1
  60. package/dist/regions.js +0 -1
  61. package/dist/saturation/common.d.ts +0 -1
  62. package/dist/saturation/common.js +6 -13
  63. package/dist/saturation/region4-boundaries.d.ts +0 -5
  64. package/dist/saturation/region4-boundaries.js +4 -5
  65. package/dist/saturation/region4-hs.d.ts +2 -1
  66. package/dist/saturation/region4-hs.js +277 -108
  67. package/dist/saturation/two-phase.d.ts +0 -1
  68. package/dist/saturation/two-phase.js +0 -1
  69. package/dist/saturation.d.ts +0 -1
  70. package/dist/saturation.js +0 -1
  71. package/dist/solvers/bracketed-newton.d.ts +5 -4
  72. package/dist/solvers/bracketed-newton.js +5 -6
  73. package/dist/solvers/damped-newton-2d.d.ts +12 -0
  74. package/dist/solvers/damped-newton-2d.js +68 -0
  75. package/dist/solvers/newton-raphson.d.ts +0 -1
  76. package/dist/solvers/newton-raphson.js +0 -1
  77. package/dist/transport/properties.d.ts +0 -1
  78. package/dist/transport/properties.js +0 -1
  79. package/dist/transport.d.ts +0 -1
  80. package/dist/transport.js +0 -1
  81. package/dist/types.d.ts +0 -1
  82. package/dist/types.js +0 -1
  83. package/package.json +17 -9
  84. package/dist/backward/objective-normalization.d.ts +0 -7
  85. package/dist/backward/objective-normalization.js +0 -8
  86. package/dist/solvers/nelder-mead.d.ts +0 -17
  87. package/dist/solvers/nelder-mead.js +0 -116
@@ -0,0 +1,68 @@
1
+ /** Damped Newton solver for two coupled nonlinear equations. */
2
+ import { ConvergenceError, IF97Error } from '../types.js';
3
+ function maxNorm([a, b]) {
4
+ return Math.max(Math.abs(a), Math.abs(b));
5
+ }
6
+ function isFiniteEvaluation(value) {
7
+ return value.residual.every(Number.isFinite) &&
8
+ value.jacobian.every((row) => row.every(Number.isFinite));
9
+ }
10
+ export function dampedNewton2D(evaluate, initial, options) {
11
+ const tolerance = options?.tolerance ?? 1e-10;
12
+ const maxIterations = options?.maxIterations ?? 20;
13
+ const maxBacktracks = options?.maxBacktracks ?? 20;
14
+ const isValid = (point) => point.every(Number.isFinite) && (options?.isValid?.(point) ?? true);
15
+ const tryEvaluate = (point) => {
16
+ if (!isValid(point))
17
+ return null;
18
+ try {
19
+ const value = evaluate(point);
20
+ return isFiniteEvaluation(value) ? value : null;
21
+ }
22
+ catch (error) {
23
+ if (error instanceof IF97Error)
24
+ return null;
25
+ throw error;
26
+ }
27
+ };
28
+ let point = [...initial];
29
+ let value = tryEvaluate(point);
30
+ if (value === null)
31
+ throw new ConvergenceError('dampedNewton2D', 1);
32
+ for (let iteration = 0; iteration < maxIterations; iteration += 1) {
33
+ const norm = maxNorm(value.residual);
34
+ if (norm <= tolerance)
35
+ return point;
36
+ const [[a, b], [c, d]] = value.jacobian;
37
+ const determinant = a * d - b * c;
38
+ const determinantScale = Math.abs(a * d) + Math.abs(b * c);
39
+ if (!Number.isFinite(determinant) || determinantScale === 0 ||
40
+ Math.abs(determinant) <= Number.EPSILON * determinantScale) {
41
+ throw new ConvergenceError('dampedNewton2D', iteration + 1);
42
+ }
43
+ const [r1, r2] = value.residual;
44
+ const step = [
45
+ (d * r1 - b * r2) / determinant,
46
+ (a * r2 - c * r1) / determinant,
47
+ ];
48
+ let damping = 1;
49
+ let accepted = false;
50
+ for (let backtrack = 0; backtrack <= maxBacktracks; backtrack += 1) {
51
+ const candidate = [
52
+ point[0] - damping * step[0],
53
+ point[1] - damping * step[1],
54
+ ];
55
+ const candidateValue = tryEvaluate(candidate);
56
+ if (candidateValue !== null && maxNorm(candidateValue.residual) < norm) {
57
+ point = candidate;
58
+ value = candidateValue;
59
+ accepted = true;
60
+ break;
61
+ }
62
+ damping /= 2;
63
+ }
64
+ if (!accepted)
65
+ throw new ConvergenceError('dampedNewton2D', iteration + 1);
66
+ }
67
+ throw new ConvergenceError('dampedNewton2D', maxIterations);
68
+ }
@@ -19,4 +19,3 @@ export interface NewtonRaphsonOptions {
19
19
  * @throws {ConvergenceError} if the iteration diverges or does not converge
20
20
  */
21
21
  export declare function newtonRaphson(f: (x: number) => number, x0: number, fp?: ((x: number) => number) | null, options?: NewtonRaphsonOptions): number;
22
- //# sourceMappingURL=newton-raphson.d.ts.map
@@ -52,4 +52,3 @@ export function newtonRaphson(f, x0, fp, options) {
52
52
  }
53
53
  throw new ConvergenceError('newtonRaphson', maxIter);
54
54
  }
55
- //# sourceMappingURL=newton-raphson.js.map
@@ -46,4 +46,3 @@ export declare function dielectricConstant(T: number, rho: number): number;
46
46
  * @param rho Density [kg/m³]
47
47
  */
48
48
  export declare function ionizationConstant(T: number, rho: number): number | null;
49
- //# sourceMappingURL=properties.d.ts.map
@@ -249,4 +249,3 @@ export function ionizationConstant(T, rho) {
249
249
  return -2 * n * (log10(1 + Z)
250
250
  - Z / (Z + 1) * density * beta) + pKwG + 2 * log10(molarMass / 1000);
251
251
  }
252
- //# sourceMappingURL=properties.js.map
@@ -2,4 +2,3 @@
2
2
  * Public transport-property exports.
3
3
  */
4
4
  export { viscosity, thermalConductivity, surfaceTension, dielectricConstant, ionizationConstant, } from './transport/properties.js';
5
- //# sourceMappingURL=transport.d.ts.map
package/dist/transport.js CHANGED
@@ -2,4 +2,3 @@
2
2
  * Public transport-property exports.
3
3
  */
4
4
  export { viscosity, thermalConductivity, surfaceTension, dielectricConstant, ionizationConstant, } from './transport/properties.js';
5
- //# sourceMappingURL=transport.js.map
package/dist/types.d.ts CHANGED
@@ -152,4 +152,3 @@ export declare class ConvergenceError extends IF97Error {
152
152
  constructor(solver: string, iterations: number);
153
153
  }
154
154
  export {};
155
- //# sourceMappingURL=types.d.ts.map
package/dist/types.js CHANGED
@@ -53,4 +53,3 @@ export class ConvergenceError extends IF97Error {
53
53
  this.name = 'ConvergenceError';
54
54
  }
55
55
  }
56
- //# sourceMappingURL=types.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iapws-if97",
3
- "version": "2.1.5",
3
+ "version": "2.2.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": {
@@ -16,28 +16,34 @@
16
16
  "types": "./dist/index.d.ts",
17
17
  "exports": {
18
18
  ".": {
19
+ "types": "./dist/index.d.ts",
19
20
  "import": "./dist/index.js",
20
- "types": "./dist/index.d.ts"
21
+ "default": "./dist/index.js"
21
22
  },
22
23
  "./transport": {
24
+ "types": "./dist/transport.d.ts",
23
25
  "import": "./dist/transport.js",
24
- "types": "./dist/transport.d.ts"
26
+ "default": "./dist/transport.js"
25
27
  },
26
28
  "./regions": {
29
+ "types": "./dist/regions.d.ts",
27
30
  "import": "./dist/regions.js",
28
- "types": "./dist/regions.d.ts"
31
+ "default": "./dist/regions.js"
29
32
  },
30
33
  "./saturation": {
34
+ "types": "./dist/saturation.d.ts",
31
35
  "import": "./dist/saturation.js",
32
- "types": "./dist/saturation.d.ts"
36
+ "default": "./dist/saturation.js"
33
37
  },
34
38
  "./boundaries": {
39
+ "types": "./dist/boundaries.d.ts",
35
40
  "import": "./dist/boundaries.js",
36
- "types": "./dist/boundaries.d.ts"
41
+ "default": "./dist/boundaries.js"
37
42
  },
38
43
  "./detect": {
44
+ "types": "./dist/detect.d.ts",
39
45
  "import": "./dist/detect.js",
40
- "types": "./dist/detect.d.ts"
46
+ "default": "./dist/detect.js"
41
47
  },
42
48
  "./package.json": "./package.json"
43
49
  },
@@ -49,21 +55,23 @@
49
55
  "README.md"
50
56
  ],
51
57
  "engines": {
52
- "node": ">=18"
58
+ "node": ">=20.19.0"
53
59
  },
54
60
  "publishConfig": {
55
61
  "access": "public"
56
62
  },
57
63
  "sideEffects": false,
58
64
  "scripts": {
65
+ "prebuild": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
59
66
  "build": "tsc",
60
67
  "test": "vitest run",
68
+ "test:package": "npm run build && node scripts/check-package.mjs",
61
69
  "test:watch": "vitest",
62
70
  "test:coverage": "vitest run --coverage",
63
71
  "test:standards": "vitest run tests/standards-asme tests/standards-cn",
64
72
  "test:standards:asme": "vitest run tests/standards-asme",
65
73
  "test:standards:cn": "vitest run tests/standards-cn",
66
- "prepack": "npm run build && npm test",
74
+ "prepack": "npm run test:package && npm test",
67
75
  "prepublishOnly": "npm run build && npm test"
68
76
  },
69
77
  "devDependencies": {
@@ -1,7 +0,0 @@
1
- export interface NormalizedResidual {
2
- actual: number;
3
- expected: number;
4
- tolerance: number;
5
- }
6
- export declare function sumNormalizedResiduals(terms: readonly NormalizedResidual[]): number;
7
- //# sourceMappingURL=objective-normalization.d.ts.map
@@ -1,8 +0,0 @@
1
- export function sumNormalizedResiduals(terms) {
2
- let sum = 0;
3
- for (const term of terms) {
4
- sum += Math.abs(term.actual - term.expected) / term.tolerance;
5
- }
6
- return sum;
7
- }
8
- //# sourceMappingURL=objective-normalization.js.map
@@ -1,17 +0,0 @@
1
- export interface NelderMeadOptions {
2
- maxIterations?: number;
3
- nonZeroDelta?: number;
4
- zeroDelta?: number;
5
- minErrorDelta?: number;
6
- minTolerance?: number;
7
- rho?: number;
8
- chi?: number;
9
- psi?: number;
10
- sigma?: number;
11
- }
12
- export interface NelderMeadResult {
13
- x: number[];
14
- fx: number;
15
- }
16
- export declare function nelderMead(f: (x: number[]) => number, x0: number[], opts?: NelderMeadOptions): NelderMeadResult;
17
- //# sourceMappingURL=nelder-mead.d.ts.map
@@ -1,116 +0,0 @@
1
- /**
2
- * Nelder-Mead (downhill simplex) minimizer.
3
- * Minimizes f(x) where x is an array of numbers.
4
- */
5
- import { ConvergenceError } from '../types.js';
6
- export function nelderMead(f, x0, opts) {
7
- const maxIter = opts?.maxIterations ?? x0.length * 200;
8
- const nonZeroDelta = opts?.nonZeroDelta ?? 1.05;
9
- const zeroDelta = opts?.zeroDelta ?? 0.001;
10
- const minErrDelta = opts?.minErrorDelta ?? 1e-11;
11
- const minTol = opts?.minTolerance ?? 1e-11;
12
- const rho = opts?.rho ?? 1;
13
- const chi = opts?.chi ?? 2;
14
- const psi = opts?.psi ?? -0.5;
15
- const sigma = opts?.sigma ?? 0.5;
16
- const N = x0.length;
17
- let converged = false;
18
- function evaluate(point, iteration) {
19
- const value = f(point);
20
- if (!Number.isFinite(value)) {
21
- throw new ConvergenceError('nelderMead', iteration);
22
- }
23
- return value;
24
- }
25
- const simplex = new Array(N + 1);
26
- // Initialize simplex
27
- const v0 = [...x0];
28
- v0.fx = evaluate(x0, 1);
29
- simplex[0] = v0;
30
- for (let i = 0; i < N; i++) {
31
- const pt = [...x0];
32
- pt[i] = pt[i] ? pt[i] * nonZeroDelta : zeroDelta;
33
- pt.fx = evaluate(pt, 1);
34
- simplex[i + 1] = pt;
35
- }
36
- const sortOrder = (a, b) => a.fx - b.fx;
37
- function weightedSum(ret, w1, v1, w2, v2) {
38
- for (let j = 0; j < ret.length; j++) {
39
- ret[j] = w1 * v1[j] + w2 * v2[j];
40
- }
41
- return ret;
42
- }
43
- const centroid = [...x0];
44
- const reflected = [...x0];
45
- const contracted = [...x0];
46
- const expanded = [...x0];
47
- function updateSimplex(value) {
48
- for (let i = 0; i < N; i++)
49
- simplex[N][i] = value[i];
50
- simplex[N].fx = value.fx;
51
- }
52
- for (let iter = 0; iter < maxIter; iter++) {
53
- simplex.sort(sortOrder);
54
- let maxDiff = 0;
55
- for (let i = 1; i < simplex.length; i++) {
56
- for (let j = 0; j < N; j++) {
57
- maxDiff = Math.max(maxDiff, Math.abs(simplex[0][j] - simplex[i][j]));
58
- }
59
- }
60
- if (Math.abs(simplex[0].fx - simplex[N].fx) < minErrDelta && maxDiff < minTol) {
61
- converged = true;
62
- break;
63
- }
64
- for (let i = 0; i < N; i++) {
65
- centroid[i] = 0;
66
- for (let j = 0; j < N; j++)
67
- centroid[i] += simplex[j][i];
68
- centroid[i] /= N;
69
- }
70
- const worst = simplex[N];
71
- weightedSum(reflected, 1 + rho, centroid, -rho, worst);
72
- reflected.fx = evaluate(reflected, iter + 1);
73
- if (reflected.fx < simplex[0].fx) {
74
- weightedSum(expanded, 1 + chi, centroid, -chi, worst);
75
- expanded.fx = evaluate(expanded, iter + 1);
76
- updateSimplex(expanded.fx < reflected.fx ? expanded : reflected);
77
- }
78
- else if (reflected.fx >= simplex[N - 1].fx) {
79
- let shouldReduce = false;
80
- if (reflected.fx > worst.fx) {
81
- weightedSum(contracted, 1 + psi, centroid, -psi, worst);
82
- contracted.fx = evaluate(contracted, iter + 1);
83
- if (contracted.fx < worst.fx)
84
- updateSimplex(contracted);
85
- else
86
- shouldReduce = true;
87
- }
88
- else {
89
- weightedSum(contracted, 1 - psi * rho, centroid, psi * rho, worst);
90
- contracted.fx = evaluate(contracted, iter + 1);
91
- if (contracted.fx < reflected.fx)
92
- updateSimplex(contracted);
93
- else
94
- shouldReduce = true;
95
- }
96
- if (shouldReduce) {
97
- if (sigma >= 1) {
98
- throw new ConvergenceError('nelderMead', iter + 1);
99
- }
100
- for (let i = 1; i < simplex.length; i++) {
101
- weightedSum(simplex[i], 1 - sigma, simplex[0], sigma, simplex[i]);
102
- simplex[i].fx = evaluate(simplex[i], iter + 1);
103
- }
104
- }
105
- }
106
- else {
107
- updateSimplex(reflected);
108
- }
109
- }
110
- if (!converged) {
111
- throw new ConvergenceError('nelderMead', maxIter);
112
- }
113
- simplex.sort(sortOrder);
114
- return { fx: simplex[0].fx, x: simplex[0].slice(0, N) };
115
- }
116
- //# sourceMappingURL=nelder-mead.js.map