@theerapat-s28/ts-structural-eng-tools 2.0.1 → 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 (61) hide show
  1. package/README.md +26 -6
  2. package/dist/core/constants/frame.constant.d.ts +5 -0
  3. package/dist/core/constants/frame.constant.js +6 -1
  4. package/dist/core/constants/frame.constant.js.map +1 -1
  5. package/dist/core/errors/frame-analysis.error.d.ts +3 -0
  6. package/dist/core/errors/frame-analysis.error.js +14 -2
  7. package/dist/core/errors/frame-analysis.error.js.map +1 -1
  8. package/dist/core/index.d.ts +1 -1
  9. package/dist/core/index.js +2 -1
  10. package/dist/core/index.js.map +1 -1
  11. package/dist/esm/core/constants/frame.constant.js +5 -0
  12. package/dist/esm/core/constants/frame.constant.js.map +1 -1
  13. package/dist/esm/core/errors/frame-analysis.error.js +14 -2
  14. package/dist/esm/core/errors/frame-analysis.error.js.map +1 -1
  15. package/dist/esm/core/index.js +1 -1
  16. package/dist/esm/core/index.js.map +1 -1
  17. package/dist/esm/fea/frame/area/area-geometry.js +132 -0
  18. package/dist/esm/fea/frame/area/area-geometry.js.map +1 -0
  19. package/dist/esm/fea/frame/area/distribute-area-loads.js +267 -0
  20. package/dist/esm/fea/frame/area/distribute-area-loads.js.map +1 -0
  21. package/dist/esm/fea/frame/area/edge-members.js +62 -0
  22. package/dist/esm/fea/frame/area/edge-members.js.map +1 -0
  23. package/dist/esm/fea/frame/elements/fixed-end-forces.js +16 -3
  24. package/dist/esm/fea/frame/elements/fixed-end-forces.js.map +1 -1
  25. package/dist/esm/fea/frame/index.js +1 -0
  26. package/dist/esm/fea/frame/index.js.map +1 -1
  27. package/dist/esm/fea/frame/post/member-diagram.js +71 -28
  28. package/dist/esm/fea/frame/post/member-diagram.js.map +1 -1
  29. package/dist/esm/fea/frame/solver/analyze-frame.js +19 -11
  30. package/dist/esm/fea/frame/solver/analyze-frame.js.map +1 -1
  31. package/dist/esm/fea/frame/solver/load-case-solver.js +21 -7
  32. package/dist/esm/fea/frame/solver/load-case-solver.js.map +1 -1
  33. package/dist/esm/fea/frame/validation/validate-model.js +103 -6
  34. package/dist/esm/fea/frame/validation/validate-model.js.map +1 -1
  35. package/dist/fea/frame/area/area-geometry.d.ts +56 -0
  36. package/dist/fea/frame/area/area-geometry.js +142 -0
  37. package/dist/fea/frame/area/area-geometry.js.map +1 -0
  38. package/dist/fea/frame/area/distribute-area-loads.d.ts +30 -0
  39. package/dist/fea/frame/area/distribute-area-loads.js +272 -0
  40. package/dist/fea/frame/area/distribute-area-loads.js.map +1 -0
  41. package/dist/fea/frame/area/edge-members.d.ts +25 -0
  42. package/dist/fea/frame/area/edge-members.js +67 -0
  43. package/dist/fea/frame/area/edge-members.js.map +1 -0
  44. package/dist/fea/frame/elements/fixed-end-forces.d.ts +17 -3
  45. package/dist/fea/frame/elements/fixed-end-forces.js +18 -4
  46. package/dist/fea/frame/elements/fixed-end-forces.js.map +1 -1
  47. package/dist/fea/frame/index.d.ts +2 -1
  48. package/dist/fea/frame/index.js +3 -1
  49. package/dist/fea/frame/index.js.map +1 -1
  50. package/dist/fea/frame/post/member-diagram.js +71 -28
  51. package/dist/fea/frame/post/member-diagram.js.map +1 -1
  52. package/dist/fea/frame/solver/analyze-frame.d.ts +7 -4
  53. package/dist/fea/frame/solver/analyze-frame.js +19 -11
  54. package/dist/fea/frame/solver/analyze-frame.js.map +1 -1
  55. package/dist/fea/frame/solver/load-case-solver.js +21 -7
  56. package/dist/fea/frame/solver/load-case-solver.js.map +1 -1
  57. package/dist/fea/frame/types/model.type.d.ts +59 -1
  58. package/dist/fea/frame/validation/validate-model.d.ts +1 -1
  59. package/dist/fea/frame/validation/validate-model.js +103 -6
  60. package/dist/fea/frame/validation/validate-model.js.map +1 -1
  61. package/package.json +9 -3
@@ -0,0 +1,267 @@
1
+ import { AREA_GEOMETRY_TOLERANCE } from "../../../core/constants/frame.constant.js";
2
+ import { throwIssues, validateFrameModel } from "../validation/validate-model.js";
3
+ import { areaPlane, clipPolygon, edgeVector, resolveAreaSupports, } from "./area-geometry.js";
4
+ import { edgeMemberChain, memberAdjacency } from "./edge-members.js";
5
+ const GLOBAL_AXES = [
6
+ ["X", 0],
7
+ ["Y", 1],
8
+ ["Z", 2],
9
+ ];
10
+ const dot2 = (a, b) => a[0] * b[0] + a[1] * b[1];
11
+ /** Linear interpolation of a profile at `s` (0 outside it). */
12
+ const valueAt = (profile, s) => {
13
+ for (let k = 1; k < profile.length; k++) {
14
+ const a = profile[k - 1];
15
+ const b = profile[k];
16
+ if (s >= a.s && s <= b.s)
17
+ return b.s > a.s ? a.w + ((b.w - a.w) * (s - a.s)) / (b.s - a.s) : b.w;
18
+ }
19
+ return 0;
20
+ };
21
+ /**
22
+ * Width of a convex polygon, given in (s, d) coordinates, across the s axis: the extent in d
23
+ * at each vertex position s. Between vertices the width is linear, so this is exact.
24
+ */
25
+ const widthProfile = (polygon, tolerance) => {
26
+ const positions = [];
27
+ for (const s of polygon.map((p) => p[0]).sort((a, b) => a - b)) {
28
+ if (positions.length === 0 || s - positions[positions.length - 1] > tolerance)
29
+ positions.push(s);
30
+ }
31
+ return positions.map((s) => {
32
+ let min = Infinity;
33
+ let max = -Infinity;
34
+ polygon.forEach((p, i) => {
35
+ const q = polygon[(i + 1) % polygon.length];
36
+ const lo = Math.min(p[0], q[0]) - tolerance;
37
+ const hi = Math.max(p[0], q[0]) + tolerance;
38
+ if (s < lo || s > hi)
39
+ return;
40
+ const ds = q[0] - p[0];
41
+ const values = Math.abs(ds) <= tolerance ? [p[1], q[1]] : [p[1] + ((s - p[0]) / ds) * (q[1] - p[1])];
42
+ for (const d of values) {
43
+ min = Math.min(min, d);
44
+ max = Math.max(max, d);
45
+ }
46
+ });
47
+ return { s, w: max - min };
48
+ });
49
+ };
50
+ /** Unit inward normal of edge i of a counter-clockwise polygon (the area is on its left). */
51
+ const inwardNormal = (corners, i) => {
52
+ const e = edgeVector(corners, i);
53
+ const L = Math.hypot(...e);
54
+ return [-e[1] / L, e[0] / L];
55
+ };
56
+ /** A profile pinned to the edge ends: clamped to [0, L], with breakpoints at 0 and L. */
57
+ const pinToEdge = (profile, L) => {
58
+ const inside = profile.filter((p) => p.s > 0 && p.s < L);
59
+ return [{ s: 0, w: valueAt(profile, 0) }, ...inside, { s: L, w: valueAt(profile, L) }];
60
+ };
61
+ /**
62
+ * Two-way: every point of the area goes to the nearest edge line, so edge i takes the area
63
+ * clipped by `dᵢ(p) ≤ dⱼ(p)` for every other edge j (the corner-bisector, or straight-skeleton,
64
+ * split of a convex polygon), carried straight across onto the edge.
65
+ */
66
+ const twoWayProfile = (plane, i, tolerance) => {
67
+ const { corners } = plane;
68
+ const ni = inwardNormal(corners, i);
69
+ let region = corners;
70
+ corners.forEach((cj, j) => {
71
+ if (j === i)
72
+ return;
73
+ const nj = inwardNormal(corners, j);
74
+ // dᵢ(p) ≤ dⱼ(p) ⇔ (nᵢ − nⱼ)·p ≤ nᵢ·cᵢ − nⱼ·cⱼ
75
+ region = clipPolygon(region, [ni[0] - nj[0], ni[1] - nj[1]], dot2(ni, corners[i]) - dot2(nj, cj));
76
+ });
77
+ const e = edgeVector(corners, i);
78
+ const L = Math.hypot(...e);
79
+ const t = [e[0] / L, e[1] / L];
80
+ const local = region.map((p) => {
81
+ const r = [p[0] - corners[i][0], p[1] - corners[i][1]];
82
+ return [dot2(r, t), dot2(r, ni)];
83
+ });
84
+ return pinToEdge(widthProfile(local, tolerance), L);
85
+ };
86
+ /**
87
+ * One-way: strips parallel to `span` run across the area and half of each strip goes to each
88
+ * edge it ends on. A strip of width db meets edge i (at angle θ to the span) over ds = db/sin θ,
89
+ * so the edge takes `chord(b) / 2 · sin θ` per unit length; edges parallel to the span take none.
90
+ */
91
+ const oneWayProfile = (plane, i, span, tolerance) => {
92
+ const { corners } = plane;
93
+ const across = [-span[1], span[0]];
94
+ const chord = widthProfile(corners.map((p) => [dot2(p, across), dot2(p, span)]), tolerance);
95
+ const e = edgeVector(corners, i);
96
+ const L = Math.hypot(...e);
97
+ const sin = Math.abs(e[0] * span[1] - e[1] * span[0]) / L;
98
+ if (sin <= AREA_GEOMETRY_TOLERANCE)
99
+ return null;
100
+ const b0 = dot2(corners[i], across);
101
+ const b1 = b0 + dot2(e, across);
102
+ const at = (b) => (valueAt(chord, b) / 2) * sin;
103
+ const inside = chord
104
+ .filter((p) => (p.s - b0) * (p.s - b1) < 0)
105
+ .map((p) => ({ s: ((p.s - b0) / (b1 - b0)) * L, w: at(p.s) }));
106
+ const profile = [{ s: 0, w: at(b0) }, ...inside, { s: L, w: at(b1) }];
107
+ return profile.sort((a, b) => a.s - b.s);
108
+ };
109
+ /**
110
+ * Cuts an edge profile at the members along the edge and maps each piece onto its member, as
111
+ * positions from the member start. Pieces that carry nothing are dropped.
112
+ */
113
+ const segmentPieces = (profile, segment, memberLength, tolerance) => {
114
+ const { from, to, reversed } = segment;
115
+ const cuts = [
116
+ from,
117
+ ...profile.map((p) => p.s).filter((s) => s > from + tolerance && s < to - tolerance),
118
+ to,
119
+ ];
120
+ const x = (s) => {
121
+ const along = ((s - from) / (to - from)) * memberLength;
122
+ return Math.min(memberLength, Math.max(0, reversed ? memberLength - along : along));
123
+ };
124
+ const peak = Math.max(...profile.map((p) => Math.abs(p.w)));
125
+ const pieces = [];
126
+ for (let k = 1; k < cuts.length; k++) {
127
+ const wa = valueAt(profile, cuts[k - 1]);
128
+ const wb = valueAt(profile, cuts[k]);
129
+ if (Math.max(Math.abs(wa), Math.abs(wb)) <= AREA_GEOMETRY_TOLERANCE * peak)
130
+ continue;
131
+ const [xa, xb] = [x(cuts[k - 1]), x(cuts[k])];
132
+ pieces.push(xa < xb ? { start: xa, end: xb, w1: wa, w2: wb } : { start: xb, end: xa, w1: wb, w2: wa });
133
+ }
134
+ return pieces;
135
+ };
136
+ /**
137
+ * Turns the area loads of a model into member loads, assuming the model is valid (as
138
+ * `validateFrameModel` checks): each area's edge profiles are built once, then scaled for each
139
+ * of its loads and split into global X, Y and Z trapezoidal loads (plus torques for a cantilever).
140
+ * Everything is linear in `q`, so load-case superposition still holds.
141
+ */
142
+ export const areaMemberLoads = (model) => {
143
+ const areas = model.areas ?? [];
144
+ const areaLoads = model.areaLoads ?? [];
145
+ const memberLoads = [];
146
+ const warnings = [];
147
+ if (areas.length === 0 || areaLoads.length === 0)
148
+ return { memberLoads, warnings };
149
+ const nodeById = new Map(model.nodes.map((n) => [n.id, n]));
150
+ const position = (id) => {
151
+ const node = nodeById.get(id);
152
+ return [node.x, node.y, node.z];
153
+ };
154
+ const lengthOf = (member) => {
155
+ const [a, b] = [position(member.startNodeId), position(member.endNodeId)];
156
+ return Math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2]);
157
+ };
158
+ const loadedAreas = new Set(areaLoads.map((l) => l.areaId));
159
+ const adjacency = memberAdjacency(model.members);
160
+ const prepared = new Map();
161
+ for (const area of areas) {
162
+ if (!loadedAreas.has(area.id))
163
+ continue;
164
+ const ids = area.nodeIds;
165
+ const plane = areaPlane(ids.map(position));
166
+ const supports = resolveAreaSupports(plane, area.distribution, area.supportEdges);
167
+ const tolerance = AREA_GEOMETRY_TOLERANCE * plane.size;
168
+ const n = ids.length;
169
+ const edges = [];
170
+ for (const i of supports.loadedEdges) {
171
+ const chain = edgeMemberChain(ids[i], ids[(i + 1) % n], position, adjacency);
172
+ const L = Math.hypot(...edgeVector(plane.corners, i));
173
+ if (area.distribution === "cantilever") {
174
+ const depth = Math.hypot(...edgeVector(plane.corners, (i + 1) % n));
175
+ edges.push({
176
+ chain,
177
+ profile: [
178
+ { s: 0, w: depth },
179
+ { s: L, w: depth },
180
+ ],
181
+ torque: depth ** 2 / 2,
182
+ });
183
+ }
184
+ else if (area.distribution === "twoWay") {
185
+ edges.push({ chain, profile: twoWayProfile(plane, i, tolerance) });
186
+ }
187
+ else {
188
+ const profile = oneWayProfile(plane, i, supports.span, tolerance);
189
+ if (profile)
190
+ edges.push({ chain, profile });
191
+ else {
192
+ warnings.push({
193
+ reference: "Null area, one-way distribution",
194
+ message: `Area "${String(area.id)}": support edge ${i} runs parallel to the span and receives no load.`,
195
+ });
196
+ }
197
+ }
198
+ }
199
+ prepared.set(area.id, { plane, edges });
200
+ }
201
+ for (const load of areaLoads) {
202
+ const area = prepared.get(load.areaId);
203
+ if (!area || load.q === 0)
204
+ continue;
205
+ const { plane, edges } = area;
206
+ const e = load.direction === "3"
207
+ ? plane.normal
208
+ : GLOBAL_AXES.map(([axis]) => (axis === load.direction ? 1 : 0));
209
+ const components = GLOBAL_AXES.filter(([, k]) => Math.abs(e[k]) > AREA_GEOMETRY_TOLERANCE);
210
+ // Lever arm (inward, in plane) × load: only the normal part of the load twists the edge,
211
+ // about +edge direction; validation rejects a load along a cantilever's support edge.
212
+ const normalPart = e[0] * plane.normal[0] + e[1] * plane.normal[1] + e[2] * plane.normal[2];
213
+ const tolerance = AREA_GEOMETRY_TOLERANCE * plane.size;
214
+ for (const { chain, profile, torque } of edges) {
215
+ for (const segment of chain) {
216
+ const { member } = segment;
217
+ const L = lengthOf(member);
218
+ for (const piece of segmentPieces(profile, segment, L, tolerance)) {
219
+ for (const [axis, k] of components) {
220
+ memberLoads.push({
221
+ loadCase: load.loadCase,
222
+ type: "trapezoidal",
223
+ memberId: member.id,
224
+ direction: axis,
225
+ w1: load.q * e[k] * piece.w1 * 1e-3, // kN/m² · mm → kN/m
226
+ w2: load.q * e[k] * piece.w2 * 1e-3,
227
+ start: piece.start,
228
+ end: piece.end,
229
+ });
230
+ }
231
+ }
232
+ if (torque !== undefined && Math.abs(normalPart) > AREA_GEOMETRY_TOLERANCE) {
233
+ // member local 1 is ±edge direction
234
+ const sign = segment.reversed ? -1 : 1;
235
+ memberLoads.push({
236
+ loadCase: load.loadCase,
237
+ type: "torque",
238
+ memberId: member.id,
239
+ t: load.q * normalPart * torque * sign * 1e-6, // kN/m² · mm² → kN·m/m
240
+ });
241
+ }
242
+ }
243
+ }
244
+ }
245
+ return { memberLoads, warnings };
246
+ };
247
+ /**
248
+ * The member loads that a model's null areas send to the members along their edges — what
249
+ * `analyzeFrame` adds to `memberLoads` — so they can be checked or previewed.
250
+ *
251
+ * Two-way areas send each point to the nearest edge (corner-bisector split); one-way areas
252
+ * split strips parallel to their unsupported edges half to each end; cantilever areas send
253
+ * `q · c` and a torque `q · c² / 2` per unit length to their support edge (c = depth). Edges
254
+ * split by intermediate nodes are cut at those nodes. Loads are per unit true area and come
255
+ * out as trapezoidal loads in global X, Y and Z (and torques), each tagged with its load case.
256
+ *
257
+ * @param model - The frame model, validated first
258
+ * @returns `memberLoads` and `warnings` (a one-way support edge parallel to the span)
259
+ * @throws {FrameAnalysisError} 301–317 for an invalid model, with every problem in `issues`
260
+ */
261
+ export const distributeAreaLoads = (model) => {
262
+ const issues = validateFrameModel(model);
263
+ if (issues.length > 0)
264
+ throwIssues(issues);
265
+ return areaMemberLoads(model);
266
+ };
267
+ //# 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,62 @@
1
+ import { AREA_GEOMETRY_TOLERANCE } from "../../../core/constants/frame.constant.js";
2
+ /** Indexes members by the nodes they connect. */
3
+ export const memberAdjacency = (members) => {
4
+ const adjacency = new Map();
5
+ const link = (node, entry) => {
6
+ const list = adjacency.get(node);
7
+ if (list)
8
+ list.push(entry);
9
+ else
10
+ adjacency.set(node, [entry]);
11
+ };
12
+ for (const member of members) {
13
+ link(member.startNodeId, { member, other: member.endNodeId });
14
+ link(member.endNodeId, { member, other: member.startNodeId });
15
+ }
16
+ return adjacency;
17
+ };
18
+ /**
19
+ * The chain of collinear members covering an area edge from `start` to `end`, found by walking
20
+ * the members at each node towards `end`: each step takes the member whose far node lies on the
21
+ * edge nearest ahead, so intermediate nodes (beams framing in) split the edge into segments.
22
+ *
23
+ * @param position - Node coordinates in mm
24
+ * @returns The segments in order along the edge, or `null` if a gap leaves part of it uncovered
25
+ */
26
+ export const edgeMemberChain = (start, end, position, adjacency) => {
27
+ const A = position(start);
28
+ const B = position(end);
29
+ const d = [B[0] - A[0], B[1] - A[1], B[2] - A[2]];
30
+ const L = Math.hypot(...d);
31
+ const t = [d[0] / L, d[1] / L, d[2] / L];
32
+ const tolerance = AREA_GEOMETRY_TOLERANCE * L;
33
+ const segments = [];
34
+ let current = start;
35
+ let s = 0;
36
+ while (current !== end) {
37
+ let next;
38
+ for (const { member, other } of adjacency.get(current) ?? []) {
39
+ const P = position(other);
40
+ const r = [P[0] - A[0], P[1] - A[1], P[2] - A[2]];
41
+ const along = r[0] * t[0] + r[1] * t[1] + r[2] * t[2];
42
+ const off = Math.hypot(r[0] - along * t[0], r[1] - along * t[1], r[2] - along * t[2]);
43
+ if (off > tolerance || along <= s + tolerance || along > L + tolerance)
44
+ continue;
45
+ if (!next || along < next.s)
46
+ next = { member, other, s: along };
47
+ }
48
+ if (!next)
49
+ return null;
50
+ const to = next.other === end ? L : next.s;
51
+ segments.push({
52
+ member: next.member,
53
+ from: s,
54
+ to,
55
+ reversed: next.member.startNodeId !== current,
56
+ });
57
+ current = next.other;
58
+ s = to;
59
+ }
60
+ return segments;
61
+ };
62
+ //# 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":"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"}
@@ -1,5 +1,7 @@
1
1
  import { FrameAnalysisError, FrameErrors } from "../../../core/errors/frame-analysis.error.js";
2
- // 4-point Gauss–Legendre rule, exact for the cubic integrands used here
2
+ /** Intensity of a distributed load at `x` (inside its extent), in N/mm. */
3
+ export const loadIntensity = (load, x) => load.w1 + ((load.w2 - load.w1) * (x - load.start)) / (load.end - load.start);
4
+ // 4-point Gauss–Legendre rule, exact up to degree 7: cubic shape functions × linear loads
3
5
  const GAUSS_POINTS = [
4
6
  -0.8611363115940526, -0.3399810435848563, 0.3399810435848563, 0.8611363115940526,
5
7
  ];
@@ -54,7 +56,17 @@ export const fixedEndForces = (loads, L) => {
54
56
  equivalent[i] += unit[i] * factor;
55
57
  };
56
58
  for (const load of loads) {
57
- if (load.type === "point") {
59
+ if (load.type === "torque") {
60
+ if (!(load.start >= 0 && load.end <= L && load.start < load.end)) {
61
+ throw new FrameAnalysisError(FrameErrors.LOAD_OUTSIDE_MEMBER);
62
+ }
63
+ // linear torsion shape functions 1 − ξ and ξ, integrated over [start, end]
64
+ const resultant = load.t * (load.end - load.start);
65
+ const centroid = (load.start + load.end) / 2;
66
+ equivalent[3] += resultant * (1 - centroid / L);
67
+ equivalent[9] += (resultant * centroid) / L;
68
+ }
69
+ else if (load.type === "point") {
58
70
  if (!(load.a >= 0 && load.a <= L))
59
71
  throw new FrameAnalysisError(FrameErrors.LOAD_OUTSIDE_MEMBER);
60
72
  add(unitEquivalentLoad(load.axis, load.a, L), load.P);
@@ -66,7 +78,8 @@ export const fixedEndForces = (loads, L) => {
66
78
  const half = (load.end - load.start) / 2;
67
79
  const mid = (load.end + load.start) / 2;
68
80
  GAUSS_POINTS.forEach((p, index) => {
69
- add(unitEquivalentLoad(load.axis, mid + half * p, L), load.w * half * GAUSS_WEIGHTS[index]);
81
+ const x = mid + half * p;
82
+ add(unitEquivalentLoad(load.axis, x, L), loadIntensity(load, x) * half * GAUSS_WEIGHTS[index]);
70
83
  });
71
84
  }
72
85
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fixed-end-forces.js","sourceRoot":"","sources":["../../../../../src/fea/frame/elements/fixed-end-forces.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fixed-end-forces.js","sourceRoot":"","sources":["../../../../../src/fea/frame/elements/fixed-end-forces.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  export { analyzeFrame, createFrameAnalysis } from "./solver/analyze-frame.js";
2
2
  export { validateFrameModel } from "./validation/validate-model.js";
3
+ export { distributeAreaLoads } from "./area/distribute-area-loads.js";
3
4
  export { beam3dLocalStiffness, beam3dLocalStiffnessRightHanded, } from "./elements/beam-3d-stiffness.js";
4
5
  export { memberAxes } from "./transformation/coordinate-transform.js";
5
6
  export { memberDemandEnvelope } from "./post/demand-envelope.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/fea/frame/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EACL,oBAAoB,EACpB,+BAA+B,GAChC,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/fea/frame/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EACL,oBAAoB,EACpB,+BAA+B,GAChC,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -7,6 +7,9 @@ const DEFLECTION_GRID_INTERVALS = 40;
7
7
  /** Golden-section steps refining each deflection extreme between its neighbouring grid points. */
8
8
  const REFINE_STEPS = 30;
9
9
  const GOLDEN = (Math.sqrt(5) - 1) / 2;
10
+ // 3-point Gauss–Legendre rule on [−1, 1], exact up to degree 5
11
+ const GAUSS3_POINTS = [-Math.sqrt(3 / 5), 0, Math.sqrt(3 / 5)];
12
+ const GAUSS3_WEIGHTS = [5 / 9, 8 / 9, 5 / 9];
10
13
  const FORCE_DECIMALS = 4;
11
14
  const DISPLACEMENT_DECIMALS = 5;
12
15
  /**
@@ -18,11 +21,17 @@ const DISPLACEMENT_DECIMALS = 5;
18
21
  */
19
22
  const internalForces = (startForce, loads, x, side) => {
20
23
  const [f1, f2, f3, m1, m2, m3] = startForce;
21
- // Q[axis]: resultant of loads in [0, x]; I[axis]: ∫(s − x)·q ds over [0, x]
24
+ // Q[axis]: resultant of loads in [0, x]; I[axis]: ∫(s − x)·q ds over [0, x]; Qt: torque in [0, x]
22
25
  const Q = [0, 0, 0, 0];
23
26
  const I = [0, 0, 0, 0];
27
+ let Qt = 0;
24
28
  for (const load of loads) {
25
- if (load.type === "point") {
29
+ if (load.type === "torque") {
30
+ const m = Math.min(x, load.end);
31
+ if (m > load.start)
32
+ Qt += load.t * (m - load.start);
33
+ }
34
+ else if (load.type === "point") {
26
35
  const included = side === "left" ? load.a < x : load.a <= x;
27
36
  if (included) {
28
37
  Q[load.axis] += load.P;
@@ -32,8 +41,12 @@ const internalForces = (startForce, loads, x, side) => {
32
41
  else {
33
42
  const m = Math.min(x, load.end);
34
43
  if (m > load.start) {
35
- Q[load.axis] += load.w * (m - load.start);
36
- I[load.axis] += (load.w * ((m - x) ** 2 - (load.start - x) ** 2)) / 2;
44
+ // q(s) = w1 + k·(s − start); in u = s − x over [a, b]: q = w1 + k·(u − a)
45
+ const k = (load.w2 - load.w1) / (load.end - load.start);
46
+ const a = load.start - x;
47
+ const b = m - x;
48
+ Q[load.axis] += load.w1 * (b - a) + (k * (b - a) ** 2) / 2;
49
+ I[load.axis] += ((load.w1 - k * a) * (b ** 2 - a ** 2)) / 2 + (k * (b ** 3 - a ** 3)) / 3;
37
50
  }
38
51
  }
39
52
  }
@@ -41,7 +54,7 @@ const internalForces = (startForce, loads, x, side) => {
41
54
  N: -f1 - Q[1],
42
55
  V2: -f2 - Q[2],
43
56
  V3: -f3 - Q[3],
44
- T: -m1,
57
+ T: -m1 - Qt,
45
58
  M2: -m2 - x * f3 + I[3],
46
59
  M3: -m3 + x * f2 - I[2],
47
60
  };
@@ -52,8 +65,8 @@ const internalForces = (startForce, loads, x, side) => {
52
65
  *
53
66
  * Each field is `a + b·x + x·∫₀ˣκ − ∫₀ˣ s·κ`, with the running integrals accumulated once along
54
67
  * the sorted grid. The grid contains every load breakpoint, so each interval lies inside one
55
- * smooth piece where N is at most linear and M at most quadratic, and one Simpson panel per
56
- * interval integrates the (at most cubic) integrands exactly.
68
+ * smooth piece where N is at most quadratic and M at most cubic, and one 3-point Gauss panel per
69
+ * interval integrates the (at most quartic) integrands exactly.
57
70
  *
58
71
  * The constants come from the member's own end displacements: end translations first, an end
59
72
  * rotation only where a translation is released. A released rotation (hinge) never enters, so
@@ -64,22 +77,29 @@ const displacementsOnGrid = (member, startForce, endDisplacements, loads, grid)
64
77
  const L = member.length;
65
78
  const n = grid.length;
66
79
  // integrands: [N/EA, M3/EI33, s·M3/EI33, −M2/EI22, −s·M2/EI22]
67
- const integrands = (s, side) => {
68
- const f = internalForces(startForce, loads, s, side);
80
+ const integrands = (s) => {
81
+ const f = internalForces(startForce, loads, s, "right");
69
82
  const k3 = f.M3 / (E * I33);
70
83
  const k2 = -f.M2 / (E * I22);
71
84
  return [f.N / (E * A), k3, s * k3, k2, s * k2];
72
85
  };
86
+ /** ∫ₐᵇ of every integrand: one 3-point Gauss panel, interior points only (no load side). */
87
+ const panel = (a, b) => {
88
+ const half = (b - a) / 2;
89
+ const mid = (a + b) / 2;
90
+ const out = [0, 0, 0, 0, 0];
91
+ GAUSS3_POINTS.forEach((p, k) => {
92
+ const g = integrands(mid + half * p);
93
+ for (let c = 0; c < 5; c++)
94
+ out[c] += half * GAUSS3_WEIGHTS[k] * g[c];
95
+ });
96
+ return out;
97
+ };
73
98
  const cumulative = Array.from({ length: 5 }, () => new Float64Array(n));
74
99
  for (let i = 1; i < n; i++) {
75
- const a = grid[i - 1];
76
- const b = grid[i];
77
- const ga = integrands(a, "right");
78
- const gm = integrands((a + b) / 2, "right");
79
- const gb = integrands(b, "left");
80
- for (let c = 0; c < 5; c++) {
81
- cumulative[c][i] = cumulative[c][i - 1] + ((b - a) / 6) * (ga[c] + 4 * gm[c] + gb[c]);
82
- }
100
+ const g = panel(grid[i - 1], grid[i]);
101
+ for (let c = 0; c < 5; c++)
102
+ cumulative[c][i] = cumulative[c][i - 1] + g[c];
83
103
  }
84
104
  const [strain, k3, sk3, k2, sk2] = cumulative;
85
105
  const last = n - 1;
@@ -121,7 +141,7 @@ const displacementsOnGrid = (member, startForce, endDisplacements, loads, grid)
121
141
  u2: plane2.a + plane2.b * x + P3(i),
122
142
  u3: plane3.a + plane3.b * x + P2(i),
123
143
  }));
124
- /** Displacement anywhere: the grid value plus one exact Simpson panel to x. */
144
+ /** Displacement anywhere: the grid value plus one exact Gauss panel to x. */
125
145
  const at = (x) => {
126
146
  let lo = 0;
127
147
  let hi = last;
@@ -135,10 +155,8 @@ const displacementsOnGrid = (member, startForce, endDisplacements, loads, grid)
135
155
  const a = grid[lo];
136
156
  if (x - a <= 0)
137
157
  return onGrid[lo];
138
- const ga = integrands(a, "right");
139
- const gm = integrands((a + x) / 2, "right");
140
- const gx = integrands(x, "left");
141
- const c = cumulative.map((col, k) => col[lo] + ((x - a) / 6) * (ga[k] + 4 * gm[k] + gx[k]));
158
+ const g = panel(a, x);
159
+ const c = cumulative.map((col, k) => col[lo] + g[k]);
142
160
  return {
143
161
  u1: axialStart + c[0],
144
162
  u2: plane2.a + plane2.b * x + (x * c[1] - c[2]),
@@ -194,16 +212,40 @@ export const memberDiagram = (member, startForce, endDisplacements, loads, stati
194
212
  out.push(v);
195
213
  return out;
196
214
  };
197
- // Zero-shear points: V is linear inside each piece between breakpoints, so the root is exact
215
+ // Inside each piece between breakpoints N and V are at most quadratic (linear loads), so the
216
+ // quadratic through both ends and the midpoint is exact. Its roots (zero shear: the moment
217
+ // extremes) and its vertex (zero load: the N and V extremes) are added to the grid.
198
218
  const roots = [];
199
219
  for (let i = 0; i < sortedBreaks.length - 1; i++) {
200
220
  const xa = sortedBreaks[i];
201
221
  const xb = sortedBreaks[i + 1];
202
222
  const fa = internalForces(startForce, loads, xa, "right");
223
+ const fm = internalForces(startForce, loads, (xa + xb) / 2, "right");
203
224
  const fb = internalForces(startForce, loads, xb, "left");
204
- for (const key of ["V2", "V3"]) {
205
- if (fa[key] * fb[key] < 0)
206
- roots.push(xa + ((xb - xa) * fa[key]) / (fa[key] - fb[key]));
225
+ const inside = (t) => t > 0 && t < 1 && roots.push(xa + (xb - xa) * t);
226
+ for (const key of ["N", "V2", "V3"]) {
227
+ // f(t) = A·t² + B·t + C on t ∈ [0, 1]
228
+ const C = fa[key];
229
+ const A = 2 * fa[key] - 4 * fm[key] + 2 * fb[key];
230
+ const B = 4 * fm[key] - 3 * fa[key] - fb[key];
231
+ const scale = Math.max(Math.abs(fa[key]), Math.abs(fm[key]), Math.abs(fb[key]));
232
+ const curved = Math.abs(A) > 1e-12 * scale;
233
+ if (curved)
234
+ inside(-B / (2 * A));
235
+ if (key === "N")
236
+ continue;
237
+ if (!curved) {
238
+ if (Math.abs(B) > 1e-12 * scale)
239
+ inside(-C / B);
240
+ }
241
+ else {
242
+ const disc = B * B - 4 * A * C;
243
+ if (disc >= 0) {
244
+ const sq = Math.sqrt(disc);
245
+ inside((-B - sq) / (2 * A));
246
+ inside((-B + sq) / (2 * A));
247
+ }
248
+ }
207
249
  }
208
250
  }
209
251
  const coarse = Array.from({ length: DEFLECTION_GRID_INTERVALS + 1 }, (_, i) => (L * i) / DEFLECTION_GRID_INTERVALS);
@@ -258,8 +300,9 @@ export const memberDiagram = (member, startForce, endDisplacements, loads, stati
258
300
  }
259
301
  }
260
302
  // ---- Extremes -------------------------------------------------------------------
261
- // N, V and T are linear and M quadratic inside each piece, so their extremes lie at a
262
- // breakpoint (either side) or a zero-shear point — all on the grid, so these are exact.
303
+ // N and V are at most quadratic, T linear and M at most cubic inside each piece, so their
304
+ // extremes lie at a breakpoint (either side), a zero-load or a zero-shear point — all on the
305
+ // grid, so these are exact.
263
306
  // Deflections are taken on the grid, then refined by golden-section search.
264
307
  const extremes = {};
265
308
  const best = {};