@ferscloud/fers-calculation-web 0.2.48 → 0.2.50

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/LICENSE ADDED
@@ -0,0 +1,12 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2024, Jeroen Hermsen
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10
+ 3. Neither the name of the Jeroen Hermsen nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11
+
12
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/fers-models.d.ts CHANGED
@@ -130,17 +130,22 @@ export interface components {
130
130
  * @description Controls the geometric stiffness matrix formulation for P-Delta analysis.
131
131
  * `Consistent` (default) uses full Przemieniecki K_g; `Simplified` uses
132
132
  * P/L-only diagonal terms matching commercial solvers.
133
+ * Only affects second-order (nonlinear) analysis: linear buckling always
134
+ * uses the consistent K_g.
133
135
  */
134
136
  pdelta_formulation?: components["schemas"]["PdeltaFormulation"];
135
137
  /**
136
138
  * @description High-level P-Delta strategy. `Full` (default) amplifies all directions.
137
- * `InPlaneOnly` auto-detects the out-of-plane axis from the model's
138
- * bounding box and suppresses it, matching commercial solver behavior.
139
+ * `InPlaneOnly` auto-detects the out-of-plane axis by counting unique node
140
+ * coordinate layers per axis and suppresses the thin one, matching
141
+ * commercial solver behavior.
139
142
  * Overrides `pdelta_suppress_axes` when set to `InPlaneOnly`.
143
+ * Only affects second-order (nonlinear) analysis.
140
144
  */
141
145
  pdelta_mode?: components["schemas"]["PdeltaMode"];
142
146
  /**
143
147
  * @description Global translational axes to exclude from P-Delta amplification.
148
+ * Only affects second-order (nonlinear) analysis.
144
149
  *
145
150
  * When a structure is near buckling in an out-of-plane direction,
146
151
  * the consistent P-Delta amplification can produce forces that differ
@@ -152,6 +157,10 @@ export interface components {
152
157
  * all translational directions are amplified.
153
158
  *
154
159
  * Maps to global DOFs: "X"→0,7 "Y"→1,8 "Z"→2,9 per element.
160
+ *
161
+ * This is a P-Delta convergence aid, not a physical property: it is
162
+ * deliberately ignored by linear buckling, where suppressing an axis would
163
+ * erase that axis's modes and inflate α_cr.
155
164
  */
156
165
  pdelta_suppress_axes?: string[];
157
166
  /**
@@ -162,6 +171,20 @@ export interface components {
162
171
  * @default false
163
172
  */
164
173
  render_unity_reports: boolean;
174
+ /**
175
+ * @description Whitelist of result blocks to emit. `None`/absent (default) = full output
176
+ * (backward compatible). When present, only the listed blocks are emitted:
177
+ * scalar force/displacement blocks are omitted from member results; list/map
178
+ * blocks (`section_forces`, `internal_force_series`, `displacement_nodes`,
179
+ * `reaction_nodes`) are emitted empty. Applies to load cases and load
180
+ * combinations alike. Unity checks, `summary`, `solver_diagnostics`,
181
+ * `errors_and_warnings`, plate/modal/buckling/seismic results and
182
+ * `report_html` are never filtered, and unity checks always evaluate on the
183
+ * full results (the filter is applied after them, just before
184
+ * serialization). `member_displacements` stays governed solely by
185
+ * `include_member_deflected_shape`. An empty list is a maximal strip.
186
+ */
187
+ result_filter?: components["schemas"]["ResultBlock"][] | null;
165
188
  rigid_strategy: components["schemas"]["RigidStrategy"];
166
189
  /**
167
190
  * Format: int32
@@ -277,6 +300,12 @@ export interface components {
277
300
  */
278
301
  BucklingResults: {
279
302
  modes: components["schemas"]["BucklingMode"][];
303
+ /**
304
+ * @description Advisories that qualify these results — e.g. model content the
305
+ * geometric stiffness does not cover. Empty when α_cr is unqualified.
306
+ * @default []
307
+ */
308
+ warnings: components["schemas"]["SolverMessage"][];
280
309
  };
281
310
  /**
282
311
  * @description One line of the transparent hand-calc: a symbolic formula, the same formula
@@ -993,13 +1022,15 @@ export interface components {
993
1022
  * `T`, and the interior sections inherit it. Consumers that need a
994
1023
  * tension-positive axial value (e.g. code checks classifying compression) must
995
1024
  * flip the sign of the series value.
1025
+ *
1026
+ * All force/displacement blocks except `section_forces` are `Option` so that
1027
+ * `AnalysisOptions::result_filter` can omit unrequested blocks from the output;
1028
+ * they are always `Some` during the solve and are only set to `None` by the
1029
+ * post-unity-check strip pass (`functions::result_filter`). Absent (default =
1030
+ * no filter) every block is emitted.
996
1031
  */
997
1032
  MemberResult: {
998
- /**
999
- * @description Member-end force at the end node, in the **global** frame (Newton's-3rd-law
1000
- * opposite of the start-node internal force).
1001
- */
1002
- end_node_forces: components["schemas"]["NodeForces"];
1033
+ end_node_forces?: null | components["schemas"]["NodeForces"];
1003
1034
  /**
1004
1035
  * @description Continuous, ready-to-plot internal force diagram from `x_frac = 0` (start) to
1005
1036
  * `x_frac = 1` (end), in the local frame: `local_start_forces`, then
@@ -1008,25 +1039,13 @@ export interface components {
1008
1039
  * is continuous with no sawtooth across shared nodes.
1009
1040
  */
1010
1041
  internal_force_series?: components["schemas"]["SectionForce"][];
1011
- local_displacement_end_node: components["schemas"]["NodeDisplacement"];
1012
- local_displacement_start_node: components["schemas"]["NodeDisplacement"];
1013
- /**
1014
- * @description Internal force at the end node, in the member **local centroidal** frame.
1015
- * This is the nodal-reaction convention, i.e. the Newton's-3rd-law opposite of
1016
- * the internal force at the end — negate it to get the continuous internal value.
1017
- */
1018
- local_end_forces: components["schemas"]["NodeForces"];
1019
- /** @description Per-component maxima over the member, in the local frame. */
1020
- local_maximums: components["schemas"]["NodeForces"];
1021
- /** @description Per-component minima over the member, in the local frame. */
1022
- local_minimums: components["schemas"]["NodeForces"];
1023
- /**
1024
- * @description Internal force at the start node, in the member **local centroidal** frame
1025
- * (corotated frame for nonlinear results). Equals `internal_force_series[0]`.
1026
- */
1027
- local_start_forces: components["schemas"]["NodeForces"];
1028
- /** @description Per-component maxima over the member (global frame). */
1029
- maximums: components["schemas"]["NodeForces"];
1042
+ local_displacement_end_node?: null | components["schemas"]["NodeDisplacement"];
1043
+ local_displacement_start_node?: null | components["schemas"]["NodeDisplacement"];
1044
+ local_end_forces?: null | components["schemas"]["NodeForces"];
1045
+ local_maximums?: null | components["schemas"]["NodeForces"];
1046
+ local_minimums?: null | components["schemas"]["NodeForces"];
1047
+ local_start_forces?: null | components["schemas"]["NodeForces"];
1048
+ maximums?: null | components["schemas"]["NodeForces"];
1030
1049
  /**
1031
1050
  * @description Optional sampled deflected shape: the member's global displacement at
1032
1051
  * evenly-spaced stations from `x_frac = 0` to `1`, reconstructed by
@@ -1037,8 +1056,7 @@ export interface components {
1037
1056
  * is slightly under-rendered (matching client-side Hermite reconstructions).
1038
1057
  */
1039
1058
  member_displacements?: components["schemas"]["MemberDisplacementSample"][];
1040
- /** @description Per-component minima over the member (global frame). */
1041
- minimums: components["schemas"]["NodeForces"];
1059
+ minimums?: null | components["schemas"]["NodeForces"];
1042
1060
  /**
1043
1061
  * @description Continuous internal forces at evenly-spaced **interior** fractions
1044
1062
  * (`0 < x_frac < 1`), in the local frame. These already follow the internal-force
@@ -1046,8 +1064,7 @@ export interface components {
1046
1064
  * endpoints use [`MemberResult::internal_force_series`].
1047
1065
  */
1048
1066
  section_forces: components["schemas"]["SectionForce"][];
1049
- /** @description Member-end force at the start node, in the **global** frame. */
1050
- start_node_forces: components["schemas"]["NodeForces"];
1067
+ start_node_forces?: null | components["schemas"]["NodeForces"];
1051
1068
  };
1052
1069
  /**
1053
1070
  * @description A member set represents one physical beam: the ordered chain of collinear
@@ -1936,6 +1953,24 @@ export interface components {
1936
1953
  points: number[][];
1937
1954
  };
1938
1955
  };
1956
+ /**
1957
+ * @description Selectable result-block groups for [`AnalysisOptions::result_filter`].
1958
+ * Wire tokens are snake_case, mirroring the JSON result field names they govern.
1959
+ *
1960
+ * Python:
1961
+ * class ResultBlock(Enum):
1962
+ * LOCAL_ENVELOPES = "local_envelopes"
1963
+ * GLOBAL_ENVELOPES = "global_envelopes"
1964
+ * LOCAL_END_FORCES = "local_end_forces"
1965
+ * GLOBAL_END_FORCES = "global_end_forces"
1966
+ * SECTION_FORCES = "section_forces"
1967
+ * INTERNAL_FORCE_SERIES = "internal_force_series"
1968
+ * LOCAL_DISPLACEMENTS = "local_displacements"
1969
+ * NODE_DISPLACEMENTS = "node_displacements"
1970
+ * REACTIONS = "reactions"
1971
+ * @enum {string}
1972
+ */
1973
+ ResultBlock: "local_envelopes" | "global_envelopes" | "local_end_forces" | "global_end_forces" | "section_forces" | "internal_force_series" | "local_displacements" | "node_displacements" | "reactions";
1939
1974
  ResultType: {
1940
1975
  /** Format: int32 */
1941
1976
  Loadcase: number;
@@ -1974,6 +2009,15 @@ export interface components {
1974
2009
  /** @description All analysis results: per load case, per load combination, unity-check results and the optional HTML report. */
1975
2010
  ResultsBundle: {
1976
2011
  buckling?: null | components["schemas"]["BucklingResults"];
2012
+ /**
2013
+ * @description Version of the `fers_calculations` engine that produced these results.
2014
+ *
2015
+ * The input's `schema_version` says which contract the *caller* wrote to;
2016
+ * this says which engine answered. Stored results therefore record the
2017
+ * solver that produced them, and a caller can tell a fixed engine from a
2018
+ * broken one without inspecting the wheel.
2019
+ */
2020
+ engine_version?: string;
1977
2021
  loadcases: {
1978
2022
  [key: string]: components["schemas"]["Results"];
1979
2023
  };
@@ -1987,6 +2031,13 @@ export interface components {
1987
2031
  */
1988
2032
  report_html?: string | null;
1989
2033
  seismic?: null | components["schemas"]["SeismicResults"];
2034
+ /**
2035
+ * @description Load combinations that failed to solve and are therefore missing from
2036
+ * `loadcombinations`. Always inspect before trusting envelopes or
2037
+ * unity-check verdicts computed over the surviving combinations.
2038
+ * @default []
2039
+ */
2040
+ solve_failures: components["schemas"]["SolveFailure"][];
1990
2041
  /**
1991
2042
  * @description Unity-check results (one entry per check definition), enveloped over the
1992
2043
  * applicable load combinations.
@@ -2289,6 +2340,24 @@ export interface components {
2289
2340
  name: string;
2290
2341
  shape_commands: components["schemas"]["ShapeCommand"][];
2291
2342
  };
2343
+ /**
2344
+ * @description A load combination that failed to solve (e.g. second-order non-convergence).
2345
+ * Failed combinations are absent from `ResultsBundle::loadcombinations`, so a
2346
+ * non-empty failure list means the result set is INCOMPLETE. Consumers must
2347
+ * surface this: non-convergence is often the physical signature of
2348
+ * instability — i.e. exactly the governing case.
2349
+ */
2350
+ SolveFailure: {
2351
+ /**
2352
+ * Format: int32
2353
+ * @description Id of the load combination that failed to solve.
2354
+ */
2355
+ combination_id: number;
2356
+ /** @description Human-readable solver error (non-convergence, singular system, …). */
2357
+ error: string;
2358
+ /** @description Name of the load combination that failed to solve. */
2359
+ name: string;
2360
+ };
2292
2361
  /**
2293
2362
  * @description Per-result solver run diagnostics: how the solve for this load case /
2294
2363
  * combination actually ran. Populated best-effort; fields that are not
@@ -2509,13 +2578,20 @@ export interface components {
2509
2578
  /** @default [] */
2510
2579
  per_entity: components["schemas"]["EntityUnityResult"][];
2511
2580
  status: components["schemas"]["UnityStatus"];
2581
+ /**
2582
+ * @description Applicable load combinations that failed to solve and therefore could
2583
+ * not be evaluated. Non-empty ⇒ `status` is `Indeterminate` and the
2584
+ * reported utilizations cover only the combinations that solved.
2585
+ * @default []
2586
+ */
2587
+ unsolved_combination_ids: number[];
2512
2588
  };
2513
2589
  /**
2514
2590
  * @description 4-colour utilization status. Derived from utilization vs the check's
2515
2591
  * thresholds `[green→yellow, yellow→orange, orange→red]`.
2516
2592
  * @enum {string}
2517
2593
  */
2518
- UnityStatus: "Green" | "Yellow" | "Orange" | "Red";
2594
+ UnityStatus: "Green" | "Yellow" | "Orange" | "Red" | "Indeterminate";
2519
2595
  /** @description Binds a friendly placeholder name (used in `{{name}}`) to a value source. */
2520
2596
  VarBinding: {
2521
2597
  name: string;
@@ -27,3 +27,20 @@ export function load_fers_from_file(path: string): string;
27
27
  * `report_html`. Returns the JSON envelope.
28
28
  */
29
29
  export function render_reports_from_json(json_data: string): string;
30
+
31
+ /**
32
+ * The engine version, queryable without solving anything. The npm package
33
+ * version is set from the same `Cargo.toml` at build time, but a caller
34
+ * holding only the module needs a way to ask the engine which features it has.
35
+ */
36
+ export function version(): string;
37
+
38
+ /**
39
+ * Route panic messages to the browser console. wasm32-unknown-unknown does
40
+ * not unwind, so `run_enveloped`'s catch_unwind never fires in the browser —
41
+ * a panic aborts the instance with an opaque `RuntimeError: unreachable`.
42
+ * The hook at least makes the panic message + location readable in the
43
+ * console. Callers must still treat a thrown exception as fatal for the
44
+ * instance and recycle the worker.
45
+ */
46
+ export function wasm_init(): void;
@@ -5,5 +5,5 @@ import { __wbg_set_wasm } from "./fers_calculations_bg.js";
5
5
  __wbg_set_wasm(wasm);
6
6
  wasm.__wbindgen_start();
7
7
  export {
8
- calculate_from_json, calculate_from_json_with_token, load_fers_from_file, render_reports_from_json
8
+ calculate_from_json, calculate_from_json_with_token, load_fers_from_file, render_reports_from_json, version, wasm_init
9
9
  } from "./fers_calculations_bg.js";
@@ -87,13 +87,66 @@ export function render_reports_from_json(json_data) {
87
87
  wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
88
88
  }
89
89
  }
90
+
91
+ /**
92
+ * The engine version, queryable without solving anything. The npm package
93
+ * version is set from the same `Cargo.toml` at build time, but a caller
94
+ * holding only the module needs a way to ask the engine which features it has.
95
+ * @returns {string}
96
+ */
97
+ export function version() {
98
+ let deferred1_0;
99
+ let deferred1_1;
100
+ try {
101
+ const ret = wasm.version();
102
+ deferred1_0 = ret[0];
103
+ deferred1_1 = ret[1];
104
+ return getStringFromWasm0(ret[0], ret[1]);
105
+ } finally {
106
+ wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Route panic messages to the browser console. wasm32-unknown-unknown does
112
+ * not unwind, so `run_enveloped`'s catch_unwind never fires in the browser —
113
+ * a panic aborts the instance with an opaque `RuntimeError: unreachable`.
114
+ * The hook at least makes the panic message + location readable in the
115
+ * console. Callers must still treat a thrown exception as fatal for the
116
+ * instance and recycle the worker.
117
+ */
118
+ export function wasm_init() {
119
+ wasm.wasm_init();
120
+ }
90
121
  export function __wbg___wbindgen_throw_344f42d3211c4765(arg0, arg1) {
91
122
  throw new Error(getStringFromWasm0(arg0, arg1));
92
123
  }
124
+ export function __wbg_error_a6fa202b58aa1cd3(arg0, arg1) {
125
+ let deferred0_0;
126
+ let deferred0_1;
127
+ try {
128
+ deferred0_0 = arg0;
129
+ deferred0_1 = arg1;
130
+ console.error(getStringFromWasm0(arg0, arg1));
131
+ } finally {
132
+ wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
133
+ }
134
+ }
135
+ export function __wbg_new_227d7c05414eb861() {
136
+ const ret = new Error();
137
+ return ret;
138
+ }
93
139
  export function __wbg_now_86c0d4ba3fa605b8() {
94
140
  const ret = Date.now();
95
141
  return ret;
96
142
  }
143
+ export function __wbg_stack_3b0d974bbf31e44f(arg0, arg1) {
144
+ const ret = arg1.stack;
145
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
146
+ const len1 = WASM_VECTOR_LEN;
147
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
148
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
149
+ }
97
150
  export function __wbindgen_init_externref_table() {
98
151
  const table = wasm.__wbindgen_externrefs;
99
152
  const offset = table.grow(4);
@@ -103,6 +156,14 @@ export function __wbindgen_init_externref_table() {
103
156
  table.set(offset + 2, true);
104
157
  table.set(offset + 3, false);
105
158
  }
159
+ let cachedDataViewMemory0 = null;
160
+ function getDataViewMemory0() {
161
+ if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
162
+ cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
163
+ }
164
+ return cachedDataViewMemory0;
165
+ }
166
+
106
167
  function getStringFromWasm0(ptr, len) {
107
168
  return decodeText(ptr >>> 0, len);
108
169
  }
Binary file
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@ferscloud/fers-calculation-web",
3
3
  "type": "module",
4
- "version": "0.2.48",
4
+ "version": "0.2.50",
5
+ "license": "BSD-3-Clause",
5
6
  "repository": {
6
7
  "type": "git",
7
8
  "url": "git+https://github.com/Jeroen124/FERS_calculations.git"