@theerapat-s28/ts-structural-eng-tools 1.5.0 → 2.1.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 (193) hide show
  1. package/README.md +57 -6
  2. package/dist/core/constants/frame.constant.d.ts +19 -0
  3. package/dist/core/constants/frame.constant.js +23 -0
  4. package/dist/core/constants/frame.constant.js.map +1 -0
  5. package/dist/core/errors/frame-analysis.error.d.ts +36 -0
  6. package/dist/core/errors/frame-analysis.error.js +86 -0
  7. package/dist/core/errors/frame-analysis.error.js.map +1 -0
  8. package/dist/core/index.d.ts +4 -0
  9. package/dist/core/index.js +13 -1
  10. package/dist/core/index.js.map +1 -1
  11. package/dist/core/types/section-properties.type.d.ts +13 -0
  12. package/dist/core/types/section-properties.type.js +3 -0
  13. package/dist/core/types/section-properties.type.js.map +1 -0
  14. package/dist/esm/core/constants/frame.constant.js +20 -0
  15. package/dist/esm/core/constants/frame.constant.js.map +1 -0
  16. package/dist/esm/core/constants/rc.constant.js +63 -0
  17. package/dist/esm/core/constants/rc.constant.js.map +1 -0
  18. package/dist/esm/core/errors/frame-analysis.error.js +82 -0
  19. package/dist/esm/core/errors/frame-analysis.error.js.map +1 -0
  20. package/dist/esm/core/errors/rc-design.error.js +64 -0
  21. package/dist/esm/core/errors/rc-design.error.js.map +1 -0
  22. package/dist/esm/core/index.js +9 -0
  23. package/dist/esm/core/index.js.map +1 -0
  24. package/dist/esm/core/types/output-message.type.js +2 -0
  25. package/dist/esm/core/types/output-message.type.js.map +1 -0
  26. package/dist/esm/core/types/plate-jacketing.type.js +18 -0
  27. package/dist/esm/core/types/plate-jacketing.type.js.map +1 -0
  28. package/dist/esm/core/types/rc-beam.type.js +11 -0
  29. package/dist/esm/core/types/rc-beam.type.js.map +1 -0
  30. package/dist/esm/core/types/section-properties.type.js +2 -0
  31. package/dist/esm/core/types/section-properties.type.js.map +1 -0
  32. package/dist/esm/core/types/unit.type.js +2 -0
  33. package/dist/esm/core/types/unit.type.js.map +1 -0
  34. package/dist/esm/fea/frame/area/area-geometry.js +132 -0
  35. package/dist/esm/fea/frame/area/area-geometry.js.map +1 -0
  36. package/dist/esm/fea/frame/area/distribute-area-loads.js +267 -0
  37. package/dist/esm/fea/frame/area/distribute-area-loads.js.map +1 -0
  38. package/dist/esm/fea/frame/area/edge-members.js +62 -0
  39. package/dist/esm/fea/frame/area/edge-members.js.map +1 -0
  40. package/dist/esm/fea/frame/elements/beam-3d-stiffness.js +84 -0
  41. package/dist/esm/fea/frame/elements/beam-3d-stiffness.js.map +1 -0
  42. package/dist/esm/fea/frame/elements/fixed-end-forces.js +88 -0
  43. package/dist/esm/fea/frame/elements/fixed-end-forces.js.map +1 -0
  44. package/dist/esm/fea/frame/elements/static-condensation.js +55 -0
  45. package/dist/esm/fea/frame/elements/static-condensation.js.map +1 -0
  46. package/dist/esm/fea/frame/index.js +7 -0
  47. package/dist/esm/fea/frame/index.js.map +1 -0
  48. package/dist/esm/fea/frame/post/demand-envelope.js +97 -0
  49. package/dist/esm/fea/frame/post/demand-envelope.js.map +1 -0
  50. package/dist/esm/fea/frame/post/envelope.js +59 -0
  51. package/dist/esm/fea/frame/post/envelope.js.map +1 -0
  52. package/dist/esm/fea/frame/post/member-diagram.js +375 -0
  53. package/dist/esm/fea/frame/post/member-diagram.js.map +1 -0
  54. package/dist/esm/fea/frame/post/present-state.js +106 -0
  55. package/dist/esm/fea/frame/post/present-state.js.map +1 -0
  56. package/dist/esm/fea/frame/solver/analyze-frame.js +131 -0
  57. package/dist/esm/fea/frame/solver/analyze-frame.js.map +1 -0
  58. package/dist/esm/fea/frame/solver/boundary-conditions.js +33 -0
  59. package/dist/esm/fea/frame/solver/boundary-conditions.js.map +1 -0
  60. package/dist/esm/fea/frame/solver/combinations.js +69 -0
  61. package/dist/esm/fea/frame/solver/combinations.js.map +1 -0
  62. package/dist/esm/fea/frame/solver/frame-system.js +122 -0
  63. package/dist/esm/fea/frame/solver/frame-system.js.map +1 -0
  64. package/dist/esm/fea/frame/solver/global-assembly.js +27 -0
  65. package/dist/esm/fea/frame/solver/global-assembly.js.map +1 -0
  66. package/dist/esm/fea/frame/solver/load-case-solver.js +133 -0
  67. package/dist/esm/fea/frame/solver/load-case-solver.js.map +1 -0
  68. package/dist/esm/fea/frame/transformation/coordinate-transform.js +71 -0
  69. package/dist/esm/fea/frame/transformation/coordinate-transform.js.map +1 -0
  70. package/dist/esm/fea/frame/types/model.type.js +2 -0
  71. package/dist/esm/fea/frame/types/model.type.js.map +1 -0
  72. package/dist/esm/fea/frame/types/results.type.js +2 -0
  73. package/dist/esm/fea/frame/types/results.type.js.map +1 -0
  74. package/dist/esm/fea/frame/validation/validate-model.js +389 -0
  75. package/dist/esm/fea/frame/validation/validate-model.js.map +1 -0
  76. package/dist/esm/fea/index.js +3 -0
  77. package/dist/esm/fea/index.js.map +1 -0
  78. package/dist/esm/index.js +10 -0
  79. package/dist/esm/index.js.map +1 -0
  80. package/dist/esm/package.json +1 -0
  81. package/dist/esm/rc/general.js +32 -0
  82. package/dist/esm/rc/general.js.map +1 -0
  83. package/dist/esm/rc/index.js +5 -0
  84. package/dist/esm/rc/index.js.map +1 -0
  85. package/dist/esm/rc/rc-bar-layout.js +89 -0
  86. package/dist/esm/rc/rc-bar-layout.js.map +1 -0
  87. package/dist/esm/rc/rc-beam-design.js +320 -0
  88. package/dist/esm/rc/rc-beam-design.js.map +1 -0
  89. package/dist/esm/rc/rc-section-properties.js +55 -0
  90. package/dist/esm/rc/rc-section-properties.js.map +1 -0
  91. package/dist/esm/strengthening/index.js +4 -0
  92. package/dist/esm/strengthening/index.js.map +1 -0
  93. package/dist/esm/strengthening/rc-beam-plate-interface-bolts.js +338 -0
  94. package/dist/esm/strengthening/rc-beam-plate-interface-bolts.js.map +1 -0
  95. package/dist/esm/strengthening/rc-beam-side-plate-shear.js +381 -0
  96. package/dist/esm/strengthening/rc-beam-side-plate-shear.js.map +1 -0
  97. package/dist/esm/strengthening/rc-beam-steel-plate-jacketing.js +90 -0
  98. package/dist/esm/strengthening/rc-beam-steel-plate-jacketing.js.map +1 -0
  99. package/dist/esm/utils/index.js +5 -0
  100. package/dist/esm/utils/index.js.map +1 -0
  101. package/dist/esm/utils/math.js +30 -0
  102. package/dist/esm/utils/math.js.map +1 -0
  103. package/dist/esm/utils/matrix.js +145 -0
  104. package/dist/esm/utils/matrix.js.map +1 -0
  105. package/dist/esm/utils/merge-warning.js +11 -0
  106. package/dist/esm/utils/merge-warning.js.map +1 -0
  107. package/dist/esm/utils/skyline.js +151 -0
  108. package/dist/esm/utils/skyline.js.map +1 -0
  109. package/dist/fea/frame/area/area-geometry.d.ts +56 -0
  110. package/dist/fea/frame/area/area-geometry.js +142 -0
  111. package/dist/fea/frame/area/area-geometry.js.map +1 -0
  112. package/dist/fea/frame/area/distribute-area-loads.d.ts +30 -0
  113. package/dist/fea/frame/area/distribute-area-loads.js +272 -0
  114. package/dist/fea/frame/area/distribute-area-loads.js.map +1 -0
  115. package/dist/fea/frame/area/edge-members.d.ts +25 -0
  116. package/dist/fea/frame/area/edge-members.js +67 -0
  117. package/dist/fea/frame/area/edge-members.js.map +1 -0
  118. package/dist/fea/frame/elements/beam-3d-stiffness.d.ts +29 -0
  119. package/dist/fea/frame/elements/beam-3d-stiffness.js +90 -0
  120. package/dist/fea/frame/elements/beam-3d-stiffness.js.map +1 -0
  121. package/dist/fea/frame/elements/fixed-end-forces.d.ts +36 -0
  122. package/dist/fea/frame/elements/fixed-end-forces.js +93 -0
  123. package/dist/fea/frame/elements/fixed-end-forces.js.map +1 -0
  124. package/dist/fea/frame/elements/static-condensation.d.ts +19 -0
  125. package/dist/fea/frame/elements/static-condensation.js +59 -0
  126. package/dist/fea/frame/elements/static-condensation.js.map +1 -0
  127. package/dist/fea/frame/index.d.ts +10 -0
  128. package/dist/fea/frame/index.js +18 -0
  129. package/dist/fea/frame/index.js.map +1 -0
  130. package/dist/fea/frame/post/demand-envelope.d.ts +36 -0
  131. package/dist/fea/frame/post/demand-envelope.js +101 -0
  132. package/dist/fea/frame/post/demand-envelope.js.map +1 -0
  133. package/dist/fea/frame/post/envelope.d.ts +8 -0
  134. package/dist/fea/frame/post/envelope.js +63 -0
  135. package/dist/fea/frame/post/envelope.js.map +1 -0
  136. package/dist/fea/frame/post/member-diagram.d.ts +26 -0
  137. package/dist/fea/frame/post/member-diagram.js +379 -0
  138. package/dist/fea/frame/post/member-diagram.js.map +1 -0
  139. package/dist/fea/frame/post/present-state.d.ts +19 -0
  140. package/dist/fea/frame/post/present-state.js +111 -0
  141. package/dist/fea/frame/post/present-state.js.map +1 -0
  142. package/dist/fea/frame/solver/analyze-frame.d.ts +70 -0
  143. package/dist/fea/frame/solver/analyze-frame.js +136 -0
  144. package/dist/fea/frame/solver/analyze-frame.js.map +1 -0
  145. package/dist/fea/frame/solver/boundary-conditions.d.ts +14 -0
  146. package/dist/fea/frame/solver/boundary-conditions.js +37 -0
  147. package/dist/fea/frame/solver/boundary-conditions.js.map +1 -0
  148. package/dist/fea/frame/solver/combinations.d.ts +11 -0
  149. package/dist/fea/frame/solver/combinations.js +73 -0
  150. package/dist/fea/frame/solver/combinations.js.map +1 -0
  151. package/dist/fea/frame/solver/frame-system.d.ts +42 -0
  152. package/dist/fea/frame/solver/frame-system.js +126 -0
  153. package/dist/fea/frame/solver/frame-system.js.map +1 -0
  154. package/dist/fea/frame/solver/global-assembly.d.ts +17 -0
  155. package/dist/fea/frame/solver/global-assembly.js +33 -0
  156. package/dist/fea/frame/solver/global-assembly.js.map +1 -0
  157. package/dist/fea/frame/solver/load-case-solver.d.ts +34 -0
  158. package/dist/fea/frame/solver/load-case-solver.js +138 -0
  159. package/dist/fea/frame/solver/load-case-solver.js.map +1 -0
  160. package/dist/fea/frame/transformation/coordinate-transform.d.ts +21 -0
  161. package/dist/fea/frame/transformation/coordinate-transform.js +76 -0
  162. package/dist/fea/frame/transformation/coordinate-transform.js.map +1 -0
  163. package/dist/fea/frame/types/model.type.d.ts +170 -0
  164. package/dist/fea/frame/types/model.type.js +3 -0
  165. package/dist/fea/frame/types/model.type.js.map +1 -0
  166. package/dist/fea/frame/types/results.type.d.ts +134 -0
  167. package/dist/fea/frame/types/results.type.js +3 -0
  168. package/dist/fea/frame/types/results.type.js.map +1 -0
  169. package/dist/fea/frame/validation/validate-model.d.ts +18 -0
  170. package/dist/fea/frame/validation/validate-model.js +395 -0
  171. package/dist/fea/frame/validation/validate-model.js.map +1 -0
  172. package/dist/fea/index.d.ts +1 -0
  173. package/dist/fea/index.js +19 -0
  174. package/dist/fea/index.js.map +1 -0
  175. package/dist/index.d.ts +8 -4
  176. package/dist/index.js +37 -1
  177. package/dist/index.js.map +1 -1
  178. package/dist/rc/index.d.ts +2 -0
  179. package/dist/rc/index.js +3 -1
  180. package/dist/rc/index.js.map +1 -1
  181. package/dist/rc/rc-section-properties.d.ts +35 -0
  182. package/dist/rc/rc-section-properties.js +59 -0
  183. package/dist/rc/rc-section-properties.js.map +1 -0
  184. package/dist/utils/index.d.ts +4 -0
  185. package/dist/utils/index.js +19 -1
  186. package/dist/utils/index.js.map +1 -1
  187. package/dist/utils/matrix.d.ts +45 -0
  188. package/dist/utils/matrix.js +157 -0
  189. package/dist/utils/matrix.js.map +1 -0
  190. package/dist/utils/skyline.d.ts +49 -0
  191. package/dist/utils/skyline.js +161 -0
  192. package/dist/utils/skyline.js.map +1 -0
  193. package/package.json +28 -4
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.combineStates = exports.solveLoadCase = void 0;
4
+ const frame_analysis_error_1 = require("../../../core/errors/frame-analysis.error");
5
+ const matrix_1 = require("../../../utils/matrix");
6
+ const skyline_1 = require("../../../utils/skyline");
7
+ const fixed_end_forces_1 = require("../elements/fixed-end-forces");
8
+ const global_assembly_1 = require("./global-assembly");
9
+ const GLOBAL_DIRECTIONS = {
10
+ X: [1, 0, 0],
11
+ Y: [0, 1, 0],
12
+ Z: [0, 0, 1],
13
+ };
14
+ /** Resolves a member load into local-axis loads in N and mm. */
15
+ const toLocalLoads = (load, lambda, L) => {
16
+ const components = (direction) => {
17
+ if (direction === "1" || direction === "2" || direction === "3") {
18
+ return [{ axis: Number(direction), factor: 1 }];
19
+ }
20
+ const v = GLOBAL_DIRECTIONS[direction];
21
+ return [1, 2, 3]
22
+ .map((axis) => ({
23
+ axis,
24
+ factor: lambda[axis - 1][0] * v[0] + lambda[axis - 1][1] * v[1] + lambda[axis - 1][2] * v[2],
25
+ }))
26
+ .filter((c) => Math.abs(c.factor) > 1e-12);
27
+ };
28
+ if (load.type === "torque") {
29
+ // kN·m/m = 10³ N·mm/mm
30
+ return [{ type: "torque", t: load.t * 1e3, start: load.start ?? 0, end: load.end ?? L }];
31
+ }
32
+ return components(load.direction).map(({ axis, factor }) => {
33
+ if (load.type === "point")
34
+ return { type: "point", axis, P: load.P * factor * 1e3, a: load.a };
35
+ const [w1, w2] = load.type === "udl" ? [load.w, load.w] : [load.w1, load.w2];
36
+ return {
37
+ type: "distributed",
38
+ axis,
39
+ w1: w1 * factor, // kN/m = N/mm
40
+ w2: w2 * factor,
41
+ start: load.start ?? 0,
42
+ end: load.end ?? L,
43
+ };
44
+ });
45
+ };
46
+ /**
47
+ * Solves one load case against the prepared, factorised system.
48
+ *
49
+ * Self-weight is `selfWeight · unitWeight · A` per unit member length along global −Z.
50
+ *
51
+ * @param loadCase - The load case (id and self-weight multiplier)
52
+ * @param loads - The nodal and member loads tagged with this load case
53
+ *
54
+ * @throws {FrameAnalysisError} 308 for a load outside its member, 313 if self-weight is
55
+ * requested for a member without `unitWeight`
56
+ */
57
+ const solveLoadCase = (system, loadCase, loads) => {
58
+ const { members, dofCount, boundary, equation, free, factor, nodeIndex, memberIndex } = system;
59
+ const F = new Array(dofCount).fill(0);
60
+ const loadsByMember = members.map(() => []);
61
+ for (const load of loads.memberLoads) {
62
+ loadsByMember[memberIndex.get(load.memberId)].push(load);
63
+ }
64
+ const selfWeight = loadCase.selfWeight ?? 0;
65
+ const memberLoads = members.map((member, m) => {
66
+ const memberLoadsHere = [...loadsByMember[m]];
67
+ if (selfWeight !== 0) {
68
+ const { unitWeight, A } = member.section;
69
+ if (unitWeight === undefined)
70
+ throw new frame_analysis_error_1.FrameAnalysisError(frame_analysis_error_1.FrameErrors.MISSING_UNIT_WEIGHT);
71
+ // kN/m³ · m² = kN/m
72
+ const w = -selfWeight * unitWeight * A * 1e-6;
73
+ if (w !== 0) {
74
+ memberLoadsHere.push({
75
+ loadCase: loadCase.id,
76
+ type: "udl",
77
+ memberId: member.id,
78
+ direction: "Z",
79
+ w,
80
+ });
81
+ }
82
+ }
83
+ return memberLoadsHere.flatMap((load) => toLocalLoads(load, member.lambda, member.length));
84
+ });
85
+ const fixed = members.map((member, m) => {
86
+ const condensed = member.condenseFixedEndForces((0, fixed_end_forces_1.fixedEndForces)(memberLoads[m], member.length));
87
+ (0, global_assembly_1.scatterMemberForces)(F, member, condensed, -1);
88
+ return condensed;
89
+ });
90
+ for (const load of loads.nodalLoads) {
91
+ const base = 6 * nodeIndex.get(load.nodeId);
92
+ [load.fx, load.fy, load.fz].forEach((v, k) => (F[base + k] += (v ?? 0) * 1e3));
93
+ [load.mx, load.my, load.mz].forEach((v, k) => (F[base + 3 + k] += (v ?? 0) * 1e6));
94
+ }
95
+ const U = new Array(dofCount).fill(0);
96
+ if (factor) {
97
+ const solution = (0, skyline_1.skylineSolve)(factor, free.map((dof) => F[dof]));
98
+ free.forEach((dof) => (U[dof] = solution[equation[dof]]));
99
+ }
100
+ // Elastic end forces k·u per member; their global sum is K·U, from which R = K·U − F
101
+ const KU = new Array(dofCount).fill(0);
102
+ const memberForces = members.map((member, m) => {
103
+ const uLocal = (0, matrix_1.matVec)(member.T, (0, global_assembly_1.memberDofs)(member).map((d) => U[d]));
104
+ const elastic = (0, matrix_1.matVec)(member.k, uLocal);
105
+ (0, global_assembly_1.scatterMemberForces)(KU, member, elastic, 1);
106
+ return elastic.map((v, i) => v + fixed[m][i]);
107
+ });
108
+ const R = KU.map((v, i) => (boundary.restrained[i] ? v - F[i] : 0));
109
+ return { U, R, F, memberForces, memberLoads };
110
+ };
111
+ exports.solveLoadCase = solveLoadCase;
112
+ const scaleLoad = (load, factor) => {
113
+ if (load.type === "distributed")
114
+ return { ...load, w1: load.w1 * factor, w2: load.w2 * factor };
115
+ if (load.type === "torque")
116
+ return { ...load, t: load.t * factor };
117
+ return { ...load, P: load.P * factor };
118
+ };
119
+ /** Superposes factored states: `Σ factor × state`. Member loads are concatenated, scaled. */
120
+ const combineStates = (terms) => {
121
+ const first = terms[0].state;
122
+ const add = (pick, length) => {
123
+ const out = new Array(length).fill(0);
124
+ for (const { state, factor } of terms) {
125
+ pick(state).forEach((v, i) => (out[i] += factor * v));
126
+ }
127
+ return out;
128
+ };
129
+ return {
130
+ U: add((s) => s.U, first.U.length),
131
+ R: add((s) => s.R, first.R.length),
132
+ F: add((s) => s.F, first.F.length),
133
+ memberForces: first.memberForces.map((_, m) => add((s) => s.memberForces[m], 12)),
134
+ memberLoads: first.memberLoads.map((_, m) => terms.flatMap(({ state, factor }) => factor === 0 ? [] : state.memberLoads[m].map((l) => scaleLoad(l, factor)))),
135
+ };
136
+ };
137
+ exports.combineStates = combineStates;
138
+ //# sourceMappingURL=load-case-solver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-case-solver.js","sourceRoot":"","sources":["../../../../src/fea/frame/solver/load-case-solver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { type Matrix } from "../../../utils/matrix";
2
+ /**
3
+ * ETABS-style local axes of a member as the rows of a 3×3 direction-cosine matrix.
4
+ *
5
+ * Local 1 runs from the start to the end node. For a non-vertical member local 3 is
6
+ * horizontal (`1 × Z`) and local 2 lies in the vertical plane pointing up; for a vertical
7
+ * member local 2 is global +X and local 3 is `1 × 2`. `angle` then rotates local 2 and 3
8
+ * about local 1 by the right-hand rule.
9
+ *
10
+ * @param start - Start node coordinates in mm
11
+ * @param end - End node coordinates in mm
12
+ * @param angle - Member angle in rad (default 0)
13
+ * @returns `{ length, lambda }` with `lambda` rows = local 1, 2, 3 in global components
14
+ * @throws {FrameAnalysisError} 301 if the nodes coincide
15
+ */
16
+ export declare const memberAxes: (start: [number, number, number], end: [number, number, number], angle?: number) => {
17
+ length: number;
18
+ lambda: Matrix;
19
+ };
20
+ /** Builds the 12×12 transformation `T` (global → local) from the 3×3 direction cosines. */
21
+ export declare const transformationMatrix: (lambda: Matrix) => Matrix;
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.transformationMatrix = exports.memberAxes = void 0;
4
+ const frame_constant_1 = require("../../../core/constants/frame.constant");
5
+ const frame_analysis_error_1 = require("../../../core/errors/frame-analysis.error");
6
+ const matrix_1 = require("../../../utils/matrix");
7
+ const cross = (a, b) => [
8
+ a[1] * b[2] - a[2] * b[1],
9
+ a[2] * b[0] - a[0] * b[2],
10
+ a[0] * b[1] - a[1] * b[0],
11
+ ];
12
+ const norm = (a) => Math.hypot(a[0], a[1], a[2]);
13
+ const scale = (a, s) => [a[0] * s, a[1] * s, a[2] * s];
14
+ /**
15
+ * ETABS-style local axes of a member as the rows of a 3×3 direction-cosine matrix.
16
+ *
17
+ * Local 1 runs from the start to the end node. For a non-vertical member local 3 is
18
+ * horizontal (`1 × Z`) and local 2 lies in the vertical plane pointing up; for a vertical
19
+ * member local 2 is global +X and local 3 is `1 × 2`. `angle` then rotates local 2 and 3
20
+ * about local 1 by the right-hand rule.
21
+ *
22
+ * @param start - Start node coordinates in mm
23
+ * @param end - End node coordinates in mm
24
+ * @param angle - Member angle in rad (default 0)
25
+ * @returns `{ length, lambda }` with `lambda` rows = local 1, 2, 3 in global components
26
+ * @throws {FrameAnalysisError} 301 if the nodes coincide
27
+ */
28
+ const memberAxes = (start, end, angle = 0) => {
29
+ const d = [end[0] - start[0], end[1] - start[1], end[2] - start[2]];
30
+ const length = norm(d);
31
+ if (!(length > 0))
32
+ throw new frame_analysis_error_1.FrameAnalysisError(frame_analysis_error_1.FrameErrors.ZERO_LENGTH_MEMBER);
33
+ const e1 = scale(d, 1 / length);
34
+ let e2;
35
+ let e3;
36
+ if (Math.hypot(e1[0], e1[1]) < frame_constant_1.VERTICAL_MEMBER_TOLERANCE) {
37
+ e2 = [1, 0, 0];
38
+ e3 = cross(e1, e2);
39
+ }
40
+ else {
41
+ const c = cross(e1, [0, 0, 1]);
42
+ e3 = scale(c, 1 / norm(c));
43
+ e2 = cross(e3, e1);
44
+ }
45
+ if (angle !== 0) {
46
+ const cos = Math.cos(angle);
47
+ const sin = Math.sin(angle);
48
+ const r2 = [
49
+ cos * e2[0] + sin * e3[0],
50
+ cos * e2[1] + sin * e3[1],
51
+ cos * e2[2] + sin * e3[2],
52
+ ];
53
+ const r3 = [
54
+ -sin * e2[0] + cos * e3[0],
55
+ -sin * e2[1] + cos * e3[1],
56
+ -sin * e2[2] + cos * e3[2],
57
+ ];
58
+ e2 = r2;
59
+ e3 = r3;
60
+ }
61
+ return { length, lambda: [e1, e2, e3] };
62
+ };
63
+ exports.memberAxes = memberAxes;
64
+ /** Builds the 12×12 transformation `T` (global → local) from the 3×3 direction cosines. */
65
+ const transformationMatrix = (lambda) => {
66
+ const T = (0, matrix_1.zeros)(12, 12);
67
+ for (let block = 0; block < 4; block++) {
68
+ for (let i = 0; i < 3; i++) {
69
+ for (let j = 0; j < 3; j++)
70
+ T[3 * block + i][3 * block + j] = lambda[i][j];
71
+ }
72
+ }
73
+ return T;
74
+ };
75
+ exports.transformationMatrix = transformationMatrix;
76
+ //# sourceMappingURL=coordinate-transform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinate-transform.js","sourceRoot":"","sources":["../../../../src/fea/frame/transformation/coordinate-transform.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,170 @@
1
+ import type { SectionProperties } from "../../../core/types/section-properties.type";
2
+ export type FrameId = string | number;
3
+ export interface FrameNode {
4
+ id: FrameId;
5
+ x: number;
6
+ y: number;
7
+ z: number;
8
+ }
9
+ /** A restrained DOF: `true` is fixed, a number is a spring stiffness, omitted/`false` is free. */
10
+ export type DofRestraint = boolean | number;
11
+ export interface Restraint {
12
+ nodeId: FrameId;
13
+ ux?: DofRestraint;
14
+ uy?: DofRestraint;
15
+ uz?: DofRestraint;
16
+ rx?: DofRestraint;
17
+ ry?: DofRestraint;
18
+ rz?: DofRestraint;
19
+ }
20
+ /** Local end DOFs of a member that transmit no force (hinges, rollers…). */
21
+ export interface MemberEndRelease {
22
+ u1?: boolean;
23
+ u2?: boolean;
24
+ u3?: boolean;
25
+ r1?: boolean;
26
+ r2?: boolean;
27
+ r3?: boolean;
28
+ }
29
+ export interface Member {
30
+ id: FrameId;
31
+ startNodeId: FrameId;
32
+ endNodeId: FrameId;
33
+ section: SectionProperties;
34
+ angle?: number;
35
+ releases?: {
36
+ start?: MemberEndRelease;
37
+ end?: MemberEndRelease;
38
+ };
39
+ }
40
+ export interface NodalLoad {
41
+ loadCase: string;
42
+ nodeId: FrameId;
43
+ fx?: number;
44
+ fy?: number;
45
+ fz?: number;
46
+ mx?: number;
47
+ my?: number;
48
+ mz?: number;
49
+ }
50
+ /** Load direction: local member axes "1", "2", "3" or global axes "X", "Y", "Z". */
51
+ export type LoadDirection = "1" | "2" | "3" | "X" | "Y" | "Z";
52
+ /** Uniform load per unit length of member, along the whole member or from `start` to `end`. */
53
+ export interface UniformMemberLoad {
54
+ loadCase: string;
55
+ type: "udl";
56
+ memberId: FrameId;
57
+ direction: LoadDirection;
58
+ w: number;
59
+ start?: number;
60
+ end?: number;
61
+ }
62
+ export interface PointMemberLoad {
63
+ loadCase: string;
64
+ type: "point";
65
+ memberId: FrameId;
66
+ direction: LoadDirection;
67
+ P: number;
68
+ a: number;
69
+ }
70
+ /**
71
+ * Linearly varying load per unit length of member, from `w1` at `start` to `w2` at `end`
72
+ * (triangular when one of them is 0).
73
+ */
74
+ export interface TrapezoidalMemberLoad {
75
+ loadCase: string;
76
+ type: "trapezoidal";
77
+ memberId: FrameId;
78
+ direction: LoadDirection;
79
+ w1: number;
80
+ w2: number;
81
+ start?: number;
82
+ end?: number;
83
+ }
84
+ /**
85
+ * Uniform torque per unit length of member, about local axis 1 (right-hand rule), along the
86
+ * whole member or from `start` to `end`.
87
+ */
88
+ export interface TorqueMemberLoad {
89
+ loadCase: string;
90
+ type: "torque";
91
+ memberId: FrameId;
92
+ t: number;
93
+ start?: number;
94
+ end?: number;
95
+ }
96
+ export type MemberLoad = UniformMemberLoad | PointMemberLoad | TrapezoidalMemberLoad | TorqueMemberLoad;
97
+ /**
98
+ * How a null area sends its load to the members along its edges:
99
+ * - `"twoWay"`: each point to the nearest edge (corner bisectors); every edge needs members.
100
+ * - `"oneWay"`: strips spanning between `supportEdges`, parallel to the unsupported edges.
101
+ * - `"cantilever"`: everything to the one edge in `supportEdges`, as a line load plus a torque.
102
+ */
103
+ export type AreaDistribution = "twoWay" | "oneWay" | "cantilever";
104
+ /**
105
+ * A load-distribution-only area: it adds no stiffness and only turns area loads into member
106
+ * loads on the members along its edges. Edge i runs from `nodeIds[i]` to `nodeIds[i + 1]`
107
+ * (the last back to the first); local axis 3 is the normal by the right-hand rule around the
108
+ * nodes, so nodes listed counter-clockwise seen from above give local 3 = +Z.
109
+ */
110
+ export interface NullArea {
111
+ id: FrameId;
112
+ nodeIds: FrameId[];
113
+ distribution: AreaDistribution;
114
+ /** Edge indices that carry the load: one-way supports, or the one cantilever support. */
115
+ supportEdges?: number[];
116
+ }
117
+ /** Area load direction: the area's local normal "3" or a global axis. */
118
+ export type AreaLoadDirection = "3" | "X" | "Y" | "Z";
119
+ export interface AreaLoad {
120
+ loadCase: string;
121
+ areaId: FrameId;
122
+ direction: AreaLoadDirection;
123
+ q: number;
124
+ }
125
+ /** Descriptive category of a load case; it labels the case and does not change the analysis. */
126
+ export type LoadCaseType = "dead" | "superDead" | "live" | "roofLive" | "snow" | "wind" | "seismic" | "other";
127
+ /**
128
+ * One independently analysed set of loads, e.g. dead, superimposed dead or live. The loads
129
+ * themselves are listed in `FrameModel.nodalLoads` and `FrameModel.memberLoads`, each tagged
130
+ * with its `loadCase`.
131
+ */
132
+ export interface LoadCase {
133
+ id: string;
134
+ name?: string;
135
+ type?: LoadCaseType;
136
+ /**
137
+ * Self-weight multiplier (1 = full self-weight). Applies `selfWeight · unitWeight · A` per unit
138
+ * length of every member along global −Z. Default 0.
139
+ */
140
+ selfWeight?: number;
141
+ }
142
+ /** One term of a load combination: a factor times a load case or another combination. */
143
+ export type CombinationTerm = {
144
+ case: string;
145
+ factor: number;
146
+ } | {
147
+ combination: string;
148
+ factor: number;
149
+ };
150
+ /** A linear combination (sum of factored terms) of load cases and other combinations. */
151
+ export interface LoadCombination {
152
+ id: string;
153
+ name?: string;
154
+ terms: CombinationTerm[];
155
+ }
156
+ export interface FrameModel {
157
+ nodes: FrameNode[];
158
+ members: Member[];
159
+ restraints: Restraint[];
160
+ loadCases: LoadCase[];
161
+ /** Nodal loads of every load case, each tagged with its `loadCase`. */
162
+ nodalLoads?: NodalLoad[];
163
+ /** Member loads of every load case, each tagged with its `loadCase`. */
164
+ memberLoads?: MemberLoad[];
165
+ /** Null areas that distribute `areaLoads` to the members along their edges. */
166
+ areas?: NullArea[];
167
+ /** Area loads of every load case, each tagged with its `loadCase`. */
168
+ areaLoads?: AreaLoad[];
169
+ combinations?: LoadCombination[];
170
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=model.type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.type.js","sourceRoot":"","sources":["../../../../src/fea/frame/types/model.type.ts"],"names":[],"mappings":""}
@@ -0,0 +1,134 @@
1
+ import type { Warnings } from "../../../core/types/output-message.type";
2
+ import type { FrameId, LoadCaseType } from "./model.type";
3
+ export interface NodalDisplacement {
4
+ nodeId: FrameId;
5
+ ux: number;
6
+ uy: number;
7
+ uz: number;
8
+ rx: number;
9
+ ry: number;
10
+ rz: number;
11
+ }
12
+ export interface NodalReaction {
13
+ nodeId: FrameId;
14
+ fx: number;
15
+ fy: number;
16
+ fz: number;
17
+ mx: number;
18
+ my: number;
19
+ mz: number;
20
+ }
21
+ /** Force the node exerts on one member end, in local axes 1, 2, 3 (right-hand rotations). */
22
+ export interface MemberEndForce {
23
+ f1: number;
24
+ f2: number;
25
+ f3: number;
26
+ m1: number;
27
+ m2: number;
28
+ m3: number;
29
+ }
30
+ export interface MemberEndForces {
31
+ memberId: FrameId;
32
+ start: MemberEndForce;
33
+ end: MemberEndForce;
34
+ }
35
+ /**
36
+ * Internal forces and displacements at a distance `x` from the member start. Forces act on
37
+ * the positive (+1) face of the cut; N is positive in tension. Displacements include the
38
+ * rigid-body motion of the member, so at the ends they equal the node displacements (except
39
+ * across a released translation).
40
+ */
41
+ export interface MemberStation {
42
+ x: number;
43
+ N: number;
44
+ V2: number;
45
+ V3: number;
46
+ T: number;
47
+ M2: number;
48
+ M3: number;
49
+ u1: number;
50
+ u2: number;
51
+ u3: number;
52
+ ux: number;
53
+ uy: number;
54
+ uz: number;
55
+ }
56
+ /** Station components with extremes: internal forces and local displacements. */
57
+ export type StationComponent = "N" | "V2" | "V3" | "T" | "M2" | "M3" | "u1" | "u2" | "u3";
58
+ export interface ExtremeValue {
59
+ value: number;
60
+ x: number;
61
+ }
62
+ export interface MemberDiagram {
63
+ memberId: FrameId;
64
+ length: number;
65
+ stations: MemberStation[];
66
+ extremes: Record<StationComponent, {
67
+ max: ExtremeValue;
68
+ min: ExtremeValue;
69
+ }>;
70
+ }
71
+ /** Max or min of a result across combinations, with the combination that produces it. */
72
+ export interface GoverningValue {
73
+ value: number;
74
+ combinationId: string;
75
+ }
76
+ export interface GoverningExtremeValue extends GoverningValue {
77
+ x: number;
78
+ }
79
+ export type Bound<T> = {
80
+ max: T;
81
+ min: T;
82
+ };
83
+ /** Results of one load case or one load combination. */
84
+ export interface FrameCaseResult {
85
+ id: string;
86
+ kind: "case" | "combination";
87
+ name?: string;
88
+ type?: LoadCaseType;
89
+ nodalDisplacements: NodalDisplacement[];
90
+ reactions: NodalReaction[];
91
+ memberEndForces: MemberEndForces[];
92
+ memberDiagrams: MemberDiagram[];
93
+ equilibriumResidual: {
94
+ force: number;
95
+ moment: number;
96
+ };
97
+ warnings: Warnings;
98
+ }
99
+ /** Max/min of every result across a set of combinations, with the governing combination. */
100
+ export interface FrameEnvelope {
101
+ combinationIds: string[];
102
+ nodalDisplacements: ({
103
+ nodeId: FrameId;
104
+ } & Record<"ux" | "uy" | "uz" | "rx" | "ry" | "rz", Bound<GoverningValue>>)[];
105
+ reactions: ({
106
+ nodeId: FrameId;
107
+ } & Record<"fx" | "fy" | "fz" | "mx" | "my" | "mz", Bound<GoverningValue>>)[];
108
+ members: {
109
+ memberId: FrameId;
110
+ extremes: Record<StationComponent, Bound<GoverningExtremeValue>>;
111
+ }[];
112
+ }
113
+ export interface FrameResult {
114
+ cases: Record<string, FrameCaseResult>;
115
+ combinations: Record<string, FrameCaseResult>;
116
+ /** Envelope over all combinations; absent when the model has none. */
117
+ envelope?: FrameEnvelope;
118
+ calculationDetails: {
119
+ nodeCount: number;
120
+ memberCount: number;
121
+ dofCount: number;
122
+ freeDofCount: number;
123
+ profileSize: number;
124
+ loadCaseCount: number;
125
+ combinationCount: number;
126
+ };
127
+ units: {
128
+ force: "kN";
129
+ moment: "kN·m";
130
+ length: "mm";
131
+ rotation: "rad";
132
+ };
133
+ warnings: Warnings;
134
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=results.type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"results.type.js","sourceRoot":"","sources":["../../../../src/fea/frame/types/results.type.ts"],"names":[],"mappings":""}
@@ -0,0 +1,18 @@
1
+ import { type FrameErrorDetails, type FrameModelIssue } from "../../../core/errors/frame-analysis.error";
2
+ import type { FrameModel } from "../types/model.type";
3
+ /** Builds an issue whose message names where the problem is. */
4
+ export declare const frameIssue: (std: {
5
+ code: number;
6
+ message: string;
7
+ }, details?: FrameErrorDetails) => FrameModelIssue;
8
+ /** Throws the first issue as a `FrameAnalysisError` carrying all of them. */
9
+ export declare const throwIssues: (issues: FrameModelIssue[]) => never;
10
+ /**
11
+ * Checks a frame model without analysing it and returns every problem found, each with the
12
+ * node, member, load case, combination and field it concerns. An empty array means the
13
+ * model can be analysed, apart from an unstable structure (304), which only the solve detects.
14
+ *
15
+ * @param model - The model to check
16
+ * @returns Every problem found (codes 301–303 and 305–317), in model order
17
+ */
18
+ export declare const validateFrameModel: (model: FrameModel) => FrameModelIssue[];