@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,272 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.distributeAreaLoads = exports.areaMemberLoads = void 0;
4
+ const frame_constant_1 = require("../../../core/constants/frame.constant");
5
+ const validate_model_1 = require("../validation/validate-model");
6
+ const area_geometry_1 = require("./area-geometry");
7
+ const edge_members_1 = require("./edge-members");
8
+ const GLOBAL_AXES = [
9
+ ["X", 0],
10
+ ["Y", 1],
11
+ ["Z", 2],
12
+ ];
13
+ const dot2 = (a, b) => a[0] * b[0] + a[1] * b[1];
14
+ /** Linear interpolation of a profile at `s` (0 outside it). */
15
+ const valueAt = (profile, s) => {
16
+ for (let k = 1; k < profile.length; k++) {
17
+ const a = profile[k - 1];
18
+ const b = profile[k];
19
+ if (s >= a.s && s <= b.s)
20
+ return b.s > a.s ? a.w + ((b.w - a.w) * (s - a.s)) / (b.s - a.s) : b.w;
21
+ }
22
+ return 0;
23
+ };
24
+ /**
25
+ * Width of a convex polygon, given in (s, d) coordinates, across the s axis: the extent in d
26
+ * at each vertex position s. Between vertices the width is linear, so this is exact.
27
+ */
28
+ const widthProfile = (polygon, tolerance) => {
29
+ const positions = [];
30
+ for (const s of polygon.map((p) => p[0]).sort((a, b) => a - b)) {
31
+ if (positions.length === 0 || s - positions[positions.length - 1] > tolerance)
32
+ positions.push(s);
33
+ }
34
+ return positions.map((s) => {
35
+ let min = Infinity;
36
+ let max = -Infinity;
37
+ polygon.forEach((p, i) => {
38
+ const q = polygon[(i + 1) % polygon.length];
39
+ const lo = Math.min(p[0], q[0]) - tolerance;
40
+ const hi = Math.max(p[0], q[0]) + tolerance;
41
+ if (s < lo || s > hi)
42
+ return;
43
+ const ds = q[0] - p[0];
44
+ const values = Math.abs(ds) <= tolerance ? [p[1], q[1]] : [p[1] + ((s - p[0]) / ds) * (q[1] - p[1])];
45
+ for (const d of values) {
46
+ min = Math.min(min, d);
47
+ max = Math.max(max, d);
48
+ }
49
+ });
50
+ return { s, w: max - min };
51
+ });
52
+ };
53
+ /** Unit inward normal of edge i of a counter-clockwise polygon (the area is on its left). */
54
+ const inwardNormal = (corners, i) => {
55
+ const e = (0, area_geometry_1.edgeVector)(corners, i);
56
+ const L = Math.hypot(...e);
57
+ return [-e[1] / L, e[0] / L];
58
+ };
59
+ /** A profile pinned to the edge ends: clamped to [0, L], with breakpoints at 0 and L. */
60
+ const pinToEdge = (profile, L) => {
61
+ const inside = profile.filter((p) => p.s > 0 && p.s < L);
62
+ return [{ s: 0, w: valueAt(profile, 0) }, ...inside, { s: L, w: valueAt(profile, L) }];
63
+ };
64
+ /**
65
+ * Two-way: every point of the area goes to the nearest edge line, so edge i takes the area
66
+ * clipped by `dᵢ(p) ≤ dⱼ(p)` for every other edge j (the corner-bisector, or straight-skeleton,
67
+ * split of a convex polygon), carried straight across onto the edge.
68
+ */
69
+ const twoWayProfile = (plane, i, tolerance) => {
70
+ const { corners } = plane;
71
+ const ni = inwardNormal(corners, i);
72
+ let region = corners;
73
+ corners.forEach((cj, j) => {
74
+ if (j === i)
75
+ return;
76
+ const nj = inwardNormal(corners, j);
77
+ // dᵢ(p) ≤ dⱼ(p) ⇔ (nᵢ − nⱼ)·p ≤ nᵢ·cᵢ − nⱼ·cⱼ
78
+ region = (0, area_geometry_1.clipPolygon)(region, [ni[0] - nj[0], ni[1] - nj[1]], dot2(ni, corners[i]) - dot2(nj, cj));
79
+ });
80
+ const e = (0, area_geometry_1.edgeVector)(corners, i);
81
+ const L = Math.hypot(...e);
82
+ const t = [e[0] / L, e[1] / L];
83
+ const local = region.map((p) => {
84
+ const r = [p[0] - corners[i][0], p[1] - corners[i][1]];
85
+ return [dot2(r, t), dot2(r, ni)];
86
+ });
87
+ return pinToEdge(widthProfile(local, tolerance), L);
88
+ };
89
+ /**
90
+ * One-way: strips parallel to `span` run across the area and half of each strip goes to each
91
+ * edge it ends on. A strip of width db meets edge i (at angle θ to the span) over ds = db/sin θ,
92
+ * so the edge takes `chord(b) / 2 · sin θ` per unit length; edges parallel to the span take none.
93
+ */
94
+ const oneWayProfile = (plane, i, span, tolerance) => {
95
+ const { corners } = plane;
96
+ const across = [-span[1], span[0]];
97
+ const chord = widthProfile(corners.map((p) => [dot2(p, across), dot2(p, span)]), tolerance);
98
+ const e = (0, area_geometry_1.edgeVector)(corners, i);
99
+ const L = Math.hypot(...e);
100
+ const sin = Math.abs(e[0] * span[1] - e[1] * span[0]) / L;
101
+ if (sin <= frame_constant_1.AREA_GEOMETRY_TOLERANCE)
102
+ return null;
103
+ const b0 = dot2(corners[i], across);
104
+ const b1 = b0 + dot2(e, across);
105
+ const at = (b) => (valueAt(chord, b) / 2) * sin;
106
+ const inside = chord
107
+ .filter((p) => (p.s - b0) * (p.s - b1) < 0)
108
+ .map((p) => ({ s: ((p.s - b0) / (b1 - b0)) * L, w: at(p.s) }));
109
+ const profile = [{ s: 0, w: at(b0) }, ...inside, { s: L, w: at(b1) }];
110
+ return profile.sort((a, b) => a.s - b.s);
111
+ };
112
+ /**
113
+ * Cuts an edge profile at the members along the edge and maps each piece onto its member, as
114
+ * positions from the member start. Pieces that carry nothing are dropped.
115
+ */
116
+ const segmentPieces = (profile, segment, memberLength, tolerance) => {
117
+ const { from, to, reversed } = segment;
118
+ const cuts = [
119
+ from,
120
+ ...profile.map((p) => p.s).filter((s) => s > from + tolerance && s < to - tolerance),
121
+ to,
122
+ ];
123
+ const x = (s) => {
124
+ const along = ((s - from) / (to - from)) * memberLength;
125
+ return Math.min(memberLength, Math.max(0, reversed ? memberLength - along : along));
126
+ };
127
+ const peak = Math.max(...profile.map((p) => Math.abs(p.w)));
128
+ const pieces = [];
129
+ for (let k = 1; k < cuts.length; k++) {
130
+ const wa = valueAt(profile, cuts[k - 1]);
131
+ const wb = valueAt(profile, cuts[k]);
132
+ if (Math.max(Math.abs(wa), Math.abs(wb)) <= frame_constant_1.AREA_GEOMETRY_TOLERANCE * peak)
133
+ continue;
134
+ const [xa, xb] = [x(cuts[k - 1]), x(cuts[k])];
135
+ pieces.push(xa < xb ? { start: xa, end: xb, w1: wa, w2: wb } : { start: xb, end: xa, w1: wb, w2: wa });
136
+ }
137
+ return pieces;
138
+ };
139
+ /**
140
+ * Turns the area loads of a model into member loads, assuming the model is valid (as
141
+ * `validateFrameModel` checks): each area's edge profiles are built once, then scaled for each
142
+ * of its loads and split into global X, Y and Z trapezoidal loads (plus torques for a cantilever).
143
+ * Everything is linear in `q`, so load-case superposition still holds.
144
+ */
145
+ const areaMemberLoads = (model) => {
146
+ const areas = model.areas ?? [];
147
+ const areaLoads = model.areaLoads ?? [];
148
+ const memberLoads = [];
149
+ const warnings = [];
150
+ if (areas.length === 0 || areaLoads.length === 0)
151
+ return { memberLoads, warnings };
152
+ const nodeById = new Map(model.nodes.map((n) => [n.id, n]));
153
+ const position = (id) => {
154
+ const node = nodeById.get(id);
155
+ return [node.x, node.y, node.z];
156
+ };
157
+ const lengthOf = (member) => {
158
+ const [a, b] = [position(member.startNodeId), position(member.endNodeId)];
159
+ return Math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2]);
160
+ };
161
+ const loadedAreas = new Set(areaLoads.map((l) => l.areaId));
162
+ const adjacency = (0, edge_members_1.memberAdjacency)(model.members);
163
+ const prepared = new Map();
164
+ for (const area of areas) {
165
+ if (!loadedAreas.has(area.id))
166
+ continue;
167
+ const ids = area.nodeIds;
168
+ const plane = (0, area_geometry_1.areaPlane)(ids.map(position));
169
+ const supports = (0, area_geometry_1.resolveAreaSupports)(plane, area.distribution, area.supportEdges);
170
+ const tolerance = frame_constant_1.AREA_GEOMETRY_TOLERANCE * plane.size;
171
+ const n = ids.length;
172
+ const edges = [];
173
+ for (const i of supports.loadedEdges) {
174
+ const chain = (0, edge_members_1.edgeMemberChain)(ids[i], ids[(i + 1) % n], position, adjacency);
175
+ const L = Math.hypot(...(0, area_geometry_1.edgeVector)(plane.corners, i));
176
+ if (area.distribution === "cantilever") {
177
+ const depth = Math.hypot(...(0, area_geometry_1.edgeVector)(plane.corners, (i + 1) % n));
178
+ edges.push({
179
+ chain,
180
+ profile: [
181
+ { s: 0, w: depth },
182
+ { s: L, w: depth },
183
+ ],
184
+ torque: depth ** 2 / 2,
185
+ });
186
+ }
187
+ else if (area.distribution === "twoWay") {
188
+ edges.push({ chain, profile: twoWayProfile(plane, i, tolerance) });
189
+ }
190
+ else {
191
+ const profile = oneWayProfile(plane, i, supports.span, tolerance);
192
+ if (profile)
193
+ edges.push({ chain, profile });
194
+ else {
195
+ warnings.push({
196
+ reference: "Null area, one-way distribution",
197
+ message: `Area "${String(area.id)}": support edge ${i} runs parallel to the span and receives no load.`,
198
+ });
199
+ }
200
+ }
201
+ }
202
+ prepared.set(area.id, { plane, edges });
203
+ }
204
+ for (const load of areaLoads) {
205
+ const area = prepared.get(load.areaId);
206
+ if (!area || load.q === 0)
207
+ continue;
208
+ const { plane, edges } = area;
209
+ const e = load.direction === "3"
210
+ ? plane.normal
211
+ : GLOBAL_AXES.map(([axis]) => (axis === load.direction ? 1 : 0));
212
+ const components = GLOBAL_AXES.filter(([, k]) => Math.abs(e[k]) > frame_constant_1.AREA_GEOMETRY_TOLERANCE);
213
+ // Lever arm (inward, in plane) × load: only the normal part of the load twists the edge,
214
+ // about +edge direction; validation rejects a load along a cantilever's support edge.
215
+ const normalPart = e[0] * plane.normal[0] + e[1] * plane.normal[1] + e[2] * plane.normal[2];
216
+ const tolerance = frame_constant_1.AREA_GEOMETRY_TOLERANCE * plane.size;
217
+ for (const { chain, profile, torque } of edges) {
218
+ for (const segment of chain) {
219
+ const { member } = segment;
220
+ const L = lengthOf(member);
221
+ for (const piece of segmentPieces(profile, segment, L, tolerance)) {
222
+ for (const [axis, k] of components) {
223
+ memberLoads.push({
224
+ loadCase: load.loadCase,
225
+ type: "trapezoidal",
226
+ memberId: member.id,
227
+ direction: axis,
228
+ w1: load.q * e[k] * piece.w1 * 1e-3, // kN/m² · mm → kN/m
229
+ w2: load.q * e[k] * piece.w2 * 1e-3,
230
+ start: piece.start,
231
+ end: piece.end,
232
+ });
233
+ }
234
+ }
235
+ if (torque !== undefined && Math.abs(normalPart) > frame_constant_1.AREA_GEOMETRY_TOLERANCE) {
236
+ // member local 1 is ±edge direction
237
+ const sign = segment.reversed ? -1 : 1;
238
+ memberLoads.push({
239
+ loadCase: load.loadCase,
240
+ type: "torque",
241
+ memberId: member.id,
242
+ t: load.q * normalPart * torque * sign * 1e-6, // kN/m² · mm² → kN·m/m
243
+ });
244
+ }
245
+ }
246
+ }
247
+ }
248
+ return { memberLoads, warnings };
249
+ };
250
+ exports.areaMemberLoads = areaMemberLoads;
251
+ /**
252
+ * The member loads that a model's null areas send to the members along their edges — what
253
+ * `analyzeFrame` adds to `memberLoads` — so they can be checked or previewed.
254
+ *
255
+ * Two-way areas send each point to the nearest edge (corner-bisector split); one-way areas
256
+ * split strips parallel to their unsupported edges half to each end; cantilever areas send
257
+ * `q · c` and a torque `q · c² / 2` per unit length to their support edge (c = depth). Edges
258
+ * split by intermediate nodes are cut at those nodes. Loads are per unit true area and come
259
+ * out as trapezoidal loads in global X, Y and Z (and torques), each tagged with its load case.
260
+ *
261
+ * @param model - The frame model, validated first
262
+ * @returns `memberLoads` and `warnings` (a one-way support edge parallel to the span)
263
+ * @throws {FrameAnalysisError} 301–317 for an invalid model, with every problem in `issues`
264
+ */
265
+ const distributeAreaLoads = (model) => {
266
+ const issues = (0, validate_model_1.validateFrameModel)(model);
267
+ if (issues.length > 0)
268
+ (0, validate_model_1.throwIssues)(issues);
269
+ return (0, exports.areaMemberLoads)(model);
270
+ };
271
+ exports.distributeAreaLoads = distributeAreaLoads;
272
+ //# sourceMappingURL=distribute-area-loads.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distribute-area-loads.js","sourceRoot":"","sources":["../../../../src/fea/frame/area/distribute-area-loads.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { FrameId, Member } from "../types/model.type";
2
+ import type { Vec3 } from "./area-geometry";
3
+ /** The members meeting at each node, with the node at their other end. */
4
+ export type MemberAdjacency = Map<FrameId, {
5
+ member: Member;
6
+ other: FrameId;
7
+ }[]>;
8
+ /** One member covering part of an area edge, with positions along the edge from its start. */
9
+ export interface EdgeSegment {
10
+ member: Member;
11
+ from: number;
12
+ to: number;
13
+ reversed: boolean;
14
+ }
15
+ /** Indexes members by the nodes they connect. */
16
+ export declare const memberAdjacency: (members: Member[]) => MemberAdjacency;
17
+ /**
18
+ * The chain of collinear members covering an area edge from `start` to `end`, found by walking
19
+ * the members at each node towards `end`: each step takes the member whose far node lies on the
20
+ * edge nearest ahead, so intermediate nodes (beams framing in) split the edge into segments.
21
+ *
22
+ * @param position - Node coordinates in mm
23
+ * @returns The segments in order along the edge, or `null` if a gap leaves part of it uncovered
24
+ */
25
+ export declare const edgeMemberChain: (start: FrameId, end: FrameId, position: (id: FrameId) => Vec3, adjacency: MemberAdjacency) => EdgeSegment[] | null;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.edgeMemberChain = exports.memberAdjacency = void 0;
4
+ const frame_constant_1 = require("../../../core/constants/frame.constant");
5
+ /** Indexes members by the nodes they connect. */
6
+ const memberAdjacency = (members) => {
7
+ const adjacency = new Map();
8
+ const link = (node, entry) => {
9
+ const list = adjacency.get(node);
10
+ if (list)
11
+ list.push(entry);
12
+ else
13
+ adjacency.set(node, [entry]);
14
+ };
15
+ for (const member of members) {
16
+ link(member.startNodeId, { member, other: member.endNodeId });
17
+ link(member.endNodeId, { member, other: member.startNodeId });
18
+ }
19
+ return adjacency;
20
+ };
21
+ exports.memberAdjacency = memberAdjacency;
22
+ /**
23
+ * The chain of collinear members covering an area edge from `start` to `end`, found by walking
24
+ * the members at each node towards `end`: each step takes the member whose far node lies on the
25
+ * edge nearest ahead, so intermediate nodes (beams framing in) split the edge into segments.
26
+ *
27
+ * @param position - Node coordinates in mm
28
+ * @returns The segments in order along the edge, or `null` if a gap leaves part of it uncovered
29
+ */
30
+ const edgeMemberChain = (start, end, position, adjacency) => {
31
+ const A = position(start);
32
+ const B = position(end);
33
+ const d = [B[0] - A[0], B[1] - A[1], B[2] - A[2]];
34
+ const L = Math.hypot(...d);
35
+ const t = [d[0] / L, d[1] / L, d[2] / L];
36
+ const tolerance = frame_constant_1.AREA_GEOMETRY_TOLERANCE * L;
37
+ const segments = [];
38
+ let current = start;
39
+ let s = 0;
40
+ while (current !== end) {
41
+ let next;
42
+ for (const { member, other } of adjacency.get(current) ?? []) {
43
+ const P = position(other);
44
+ const r = [P[0] - A[0], P[1] - A[1], P[2] - A[2]];
45
+ const along = r[0] * t[0] + r[1] * t[1] + r[2] * t[2];
46
+ const off = Math.hypot(r[0] - along * t[0], r[1] - along * t[1], r[2] - along * t[2]);
47
+ if (off > tolerance || along <= s + tolerance || along > L + tolerance)
48
+ continue;
49
+ if (!next || along < next.s)
50
+ next = { member, other, s: along };
51
+ }
52
+ if (!next)
53
+ return null;
54
+ const to = next.other === end ? L : next.s;
55
+ segments.push({
56
+ member: next.member,
57
+ from: s,
58
+ to,
59
+ reversed: next.member.startNodeId !== current,
60
+ });
61
+ current = next.other;
62
+ s = to;
63
+ }
64
+ return segments;
65
+ };
66
+ exports.edgeMemberChain = edgeMemberChain;
67
+ //# sourceMappingURL=edge-members.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edge-members.js","sourceRoot":"","sources":["../../../../src/fea/frame/area/edge-members.ts"],"names":[],"mappings":";;;AAAA,uEAA6E;AAgB7E,iDAAiD;AAC1C,MAAM,eAAe,GAAG,CAAC,OAAiB,EAAmB,EAAE;IACpE,MAAM,SAAS,GAAoB,IAAI,GAAG,EAAE,CAAC;IAC7C,MAAM,IAAI,GAAG,CAAC,IAAa,EAAE,KAAyC,EAAE,EAAE;QACxE,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;;YACtB,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IACpC,CAAC,CAAC;IACF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAZW,QAAA,eAAe,mBAY1B;AAEF;;;;;;;GAOG;AACI,MAAM,eAAe,GAAG,CAC7B,KAAc,EACd,GAAY,EACZ,QAA+B,EAC/B,SAA0B,EACJ,EAAE;IACxB,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1B,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IACxB,MAAM,CAAC,GAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,MAAM,CAAC,GAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,wCAAuB,GAAG,CAAC,CAAC;IAE9C,MAAM,QAAQ,GAAkB,EAAE,CAAC;IACnC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,OAAO,KAAK,GAAG,EAAE,CAAC;QACvB,IAAI,IAA+D,CAAC;QACpE,KAAK,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;YAC7D,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC1B,MAAM,CAAC,GAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACxD,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACtD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACtF,IAAI,GAAG,GAAG,SAAS,IAAI,KAAK,IAAI,CAAC,GAAG,SAAS,IAAI,KAAK,GAAG,CAAC,GAAG,SAAS;gBAAE,SAAS;YACjF,IAAI,CAAC,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,CAAC;gBAAE,IAAI,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC;QAClE,CAAC;QACD,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3C,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,IAAI,EAAE,CAAC;YACP,EAAE;YACF,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,KAAK,OAAO;SAC9C,CAAC,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC;QACrB,CAAC,GAAG,EAAE,CAAC;IACT,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAtCW,QAAA,eAAe,mBAsC1B"}
@@ -0,0 +1,29 @@
1
+ import { type Matrix } from "../../../utils/matrix";
2
+ /**
3
+ * Local stiffness matrix of a 3D prismatic beam element, exactly as in the reference
4
+ * "Complete Beam Stiffness Matrix".
5
+ *
6
+ * DOF order for node i then node j: [U1, U2, U3, R1, R2, R3]. Local 1 runs along the member.
7
+ * The reference matrix measures the bending rotations R2 and R3 opposite to the right-hand
8
+ * rule; use `beam3dLocalStiffnessRightHanded` for the right-handed form.
9
+ *
10
+ * The reference uses one `EI`; here the U2–R3 terms use `E·I33` and the U3–R2 terms use
11
+ * `E·I22`, which reduces to the reference when `I22 = I33`.
12
+ *
13
+ * @param E - Young's modulus in MPa
14
+ * @param G - Shear modulus in MPa
15
+ * @param A - Area in mm²
16
+ * @param I22 - Second moment about local 2 in mm⁴
17
+ * @param I33 - Second moment about local 3 in mm⁴
18
+ * @param J - Torsion constant in mm⁴
19
+ * @param L - Member length in mm
20
+ * @returns 12×12 symmetric matrix in N and mm
21
+ */
22
+ export declare const beam3dLocalStiffness: (E: number, G: number, A: number, I22: number, I33: number, J: number, L: number) => Matrix;
23
+ /**
24
+ * Converts a local matrix between the reference rotation convention and the right-hand rule
25
+ * (`D·k·D`, with `D` flipping the sign of R2 and R3 at both ends). The conversion is its own inverse.
26
+ */
27
+ export declare const flipBendingRotationSigns: (k: Matrix) => Matrix;
28
+ /** Same element as `beam3dLocalStiffness` with all rotations following the right-hand rule. */
29
+ export declare const beam3dLocalStiffnessRightHanded: (E: number, G: number, A: number, I22: number, I33: number, J: number, L: number) => Matrix;
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.beam3dLocalStiffnessRightHanded = exports.flipBendingRotationSigns = exports.beam3dLocalStiffness = void 0;
4
+ const matrix_1 = require("../../../utils/matrix");
5
+ /**
6
+ * Local DOF indices (0-based) whose reference-matrix rotation sign is opposite to the
7
+ * right-hand rule: R2 and R3 at the start and end nodes.
8
+ */
9
+ const FLIPPED_DOFS = [4, 5, 10, 11];
10
+ /**
11
+ * Local stiffness matrix of a 3D prismatic beam element, exactly as in the reference
12
+ * "Complete Beam Stiffness Matrix".
13
+ *
14
+ * DOF order for node i then node j: [U1, U2, U3, R1, R2, R3]. Local 1 runs along the member.
15
+ * The reference matrix measures the bending rotations R2 and R3 opposite to the right-hand
16
+ * rule; use `beam3dLocalStiffnessRightHanded` for the right-handed form.
17
+ *
18
+ * The reference uses one `EI`; here the U2–R3 terms use `E·I33` and the U3–R2 terms use
19
+ * `E·I22`, which reduces to the reference when `I22 = I33`.
20
+ *
21
+ * @param E - Young's modulus in MPa
22
+ * @param G - Shear modulus in MPa
23
+ * @param A - Area in mm²
24
+ * @param I22 - Second moment about local 2 in mm⁴
25
+ * @param I33 - Second moment about local 3 in mm⁴
26
+ * @param J - Torsion constant in mm⁴
27
+ * @param L - Member length in mm
28
+ * @returns 12×12 symmetric matrix in N and mm
29
+ */
30
+ const beam3dLocalStiffness = (E, G, A, I22, I33, J, L) => {
31
+ const k = (0, matrix_1.zeros)(12, 12);
32
+ // 1-based row/column, upper triangle as written in the reference; mirrored for symmetry.
33
+ const set = (row, col, value) => {
34
+ k[row - 1][col - 1] = value;
35
+ k[col - 1][row - 1] = value;
36
+ };
37
+ const ax = (E * A) / L;
38
+ const tor = (G * J) / L;
39
+ // U2–R3 bending (I33)
40
+ const a3 = (12 * E * I33) / L ** 3;
41
+ const b3 = (6 * E * I33) / L ** 2;
42
+ const c3 = (4 * E * I33) / L;
43
+ const d3 = (2 * E * I33) / L;
44
+ // U3–R2 bending (I22)
45
+ const a2 = (12 * E * I22) / L ** 3;
46
+ const b2 = (6 * E * I22) / L ** 2;
47
+ const c2 = (4 * E * I22) / L;
48
+ const d2 = (2 * E * I22) / L;
49
+ set(1, 1, ax);
50
+ set(1, 7, -ax);
51
+ set(7, 7, ax);
52
+ set(2, 2, a3);
53
+ set(2, 6, -b3);
54
+ set(2, 8, -a3);
55
+ set(2, 12, -b3);
56
+ set(6, 6, c3);
57
+ set(6, 8, b3);
58
+ set(6, 12, d3);
59
+ set(8, 8, a3);
60
+ set(8, 12, b3);
61
+ set(12, 12, c3);
62
+ set(3, 3, a2);
63
+ set(3, 5, b2);
64
+ set(3, 9, -a2);
65
+ set(3, 11, b2);
66
+ set(5, 5, c2);
67
+ set(5, 9, -b2);
68
+ set(5, 11, d2);
69
+ set(9, 9, a2);
70
+ set(9, 11, -b2);
71
+ set(11, 11, c2);
72
+ set(4, 4, tor);
73
+ set(4, 10, -tor);
74
+ set(10, 10, tor);
75
+ return k;
76
+ };
77
+ exports.beam3dLocalStiffness = beam3dLocalStiffness;
78
+ /**
79
+ * Converts a local matrix between the reference rotation convention and the right-hand rule
80
+ * (`D·k·D`, with `D` flipping the sign of R2 and R3 at both ends). The conversion is its own inverse.
81
+ */
82
+ const flipBendingRotationSigns = (k) => {
83
+ const flipped = new Set(FLIPPED_DOFS);
84
+ return k.map((row, i) => row.map((value, j) => (flipped.has(i) !== flipped.has(j) ? -value : value)));
85
+ };
86
+ exports.flipBendingRotationSigns = flipBendingRotationSigns;
87
+ /** Same element as `beam3dLocalStiffness` with all rotations following the right-hand rule. */
88
+ const beam3dLocalStiffnessRightHanded = (E, G, A, I22, I33, J, L) => (0, exports.flipBendingRotationSigns)((0, exports.beam3dLocalStiffness)(E, G, A, I22, I33, J, L));
89
+ exports.beam3dLocalStiffnessRightHanded = beam3dLocalStiffnessRightHanded;
90
+ //# sourceMappingURL=beam-3d-stiffness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"beam-3d-stiffness.js","sourceRoot":"","sources":["../../../../src/fea/frame/elements/beam-3d-stiffness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * A member load resolved into local axes, in N and mm. A distributed load varies linearly
3
+ * from `w1` at `start` to `w2` at `end` (uniform when they are equal); a torque is uniform
4
+ * about local 1.
5
+ */
6
+ export type LocalMemberLoad = {
7
+ type: "distributed";
8
+ axis: 1 | 2 | 3;
9
+ w1: number;
10
+ w2: number;
11
+ start: number;
12
+ end: number;
13
+ } | {
14
+ type: "point";
15
+ axis: 1 | 2 | 3;
16
+ P: number;
17
+ a: number;
18
+ } | {
19
+ type: "torque";
20
+ t: number;
21
+ start: number;
22
+ end: number;
23
+ };
24
+ /** Intensity of a distributed load at `x` (inside its extent), in N/mm. */
25
+ export declare const loadIntensity: (load: Extract<LocalMemberLoad, {
26
+ type: "distributed";
27
+ }>, x: number) => number;
28
+ /**
29
+ * Fixed-end forces of a member under local loads: the end forces (right-hand local axes,
30
+ * N and N·mm) that hold both ends fully fixed. Equivalent nodal loads are the negative.
31
+ *
32
+ * @param loads - Loads in local axes, N and mm
33
+ * @param L - Member length in mm
34
+ * @throws {FrameAnalysisError} 308 if a load lies outside the member
35
+ */
36
+ export declare const fixedEndForces: (loads: LocalMemberLoad[], L: number) => number[];
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fixedEndForces = exports.loadIntensity = void 0;
4
+ const frame_analysis_error_1 = require("../../../core/errors/frame-analysis.error");
5
+ /** Intensity of a distributed load at `x` (inside its extent), in N/mm. */
6
+ const loadIntensity = (load, x) => load.w1 + ((load.w2 - load.w1) * (x - load.start)) / (load.end - load.start);
7
+ exports.loadIntensity = loadIntensity;
8
+ // 4-point Gauss–Legendre rule, exact up to degree 7: cubic shape functions × linear loads
9
+ const GAUSS_POINTS = [
10
+ -0.8611363115940526, -0.3399810435848563, 0.3399810435848563, 0.8611363115940526,
11
+ ];
12
+ const GAUSS_WEIGHTS = [
13
+ 0.3478548451374538, 0.6521451548625461, 0.6521451548625461, 0.3478548451374538,
14
+ ];
15
+ /**
16
+ * Equivalent nodal loads of a unit transverse/axial load at distance `x`, from the
17
+ * Euler–Bernoulli shape functions: the exact fixed-end solution for a prismatic member.
18
+ * Returned per unit of load, right-hand local DOF order [i: U1..R3, j: U1..R3].
19
+ */
20
+ const unitEquivalentLoad = (axis, x, L) => {
21
+ const xi = x / L;
22
+ const out = new Array(12).fill(0);
23
+ if (axis === 1) {
24
+ out[0] = 1 - xi;
25
+ out[6] = xi;
26
+ return out;
27
+ }
28
+ const n1 = 1 - 3 * xi ** 2 + 2 * xi ** 3;
29
+ const n2 = L * (xi - 2 * xi ** 2 + xi ** 3);
30
+ const n3 = 3 * xi ** 2 - 2 * xi ** 3;
31
+ const n4 = L * (-(xi ** 2) + xi ** 3);
32
+ if (axis === 2) {
33
+ // load along local 2: force U2, moment about 3 (R3 = +dv/dx)
34
+ out[1] = n1;
35
+ out[5] = n2;
36
+ out[7] = n3;
37
+ out[11] = n4;
38
+ }
39
+ else {
40
+ // load along local 3: force U3, moment about 2 (R2 = −dw/dx)
41
+ out[2] = n1;
42
+ out[4] = -n2;
43
+ out[8] = n3;
44
+ out[10] = -n4;
45
+ }
46
+ return out;
47
+ };
48
+ /**
49
+ * Fixed-end forces of a member under local loads: the end forces (right-hand local axes,
50
+ * N and N·mm) that hold both ends fully fixed. Equivalent nodal loads are the negative.
51
+ *
52
+ * @param loads - Loads in local axes, N and mm
53
+ * @param L - Member length in mm
54
+ * @throws {FrameAnalysisError} 308 if a load lies outside the member
55
+ */
56
+ const fixedEndForces = (loads, L) => {
57
+ const equivalent = new Array(12).fill(0);
58
+ const add = (unit, factor) => {
59
+ for (let i = 0; i < 12; i++)
60
+ equivalent[i] += unit[i] * factor;
61
+ };
62
+ for (const load of loads) {
63
+ if (load.type === "torque") {
64
+ if (!(load.start >= 0 && load.end <= L && load.start < load.end)) {
65
+ throw new frame_analysis_error_1.FrameAnalysisError(frame_analysis_error_1.FrameErrors.LOAD_OUTSIDE_MEMBER);
66
+ }
67
+ // linear torsion shape functions 1 − ξ and ξ, integrated over [start, end]
68
+ const resultant = load.t * (load.end - load.start);
69
+ const centroid = (load.start + load.end) / 2;
70
+ equivalent[3] += resultant * (1 - centroid / L);
71
+ equivalent[9] += (resultant * centroid) / L;
72
+ }
73
+ else if (load.type === "point") {
74
+ if (!(load.a >= 0 && load.a <= L))
75
+ throw new frame_analysis_error_1.FrameAnalysisError(frame_analysis_error_1.FrameErrors.LOAD_OUTSIDE_MEMBER);
76
+ add(unitEquivalentLoad(load.axis, load.a, L), load.P);
77
+ }
78
+ else {
79
+ if (!(load.start >= 0 && load.end <= L && load.start < load.end)) {
80
+ throw new frame_analysis_error_1.FrameAnalysisError(frame_analysis_error_1.FrameErrors.LOAD_OUTSIDE_MEMBER);
81
+ }
82
+ const half = (load.end - load.start) / 2;
83
+ const mid = (load.end + load.start) / 2;
84
+ GAUSS_POINTS.forEach((p, index) => {
85
+ const x = mid + half * p;
86
+ add(unitEquivalentLoad(load.axis, x, L), (0, exports.loadIntensity)(load, x) * half * GAUSS_WEIGHTS[index]);
87
+ });
88
+ }
89
+ }
90
+ return equivalent.map((v) => -v);
91
+ };
92
+ exports.fixedEndForces = fixedEndForces;
93
+ //# sourceMappingURL=fixed-end-forces.js.map