@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.
- package/README.md +57 -6
- package/dist/core/constants/frame.constant.d.ts +19 -0
- package/dist/core/constants/frame.constant.js +23 -0
- package/dist/core/constants/frame.constant.js.map +1 -0
- package/dist/core/errors/frame-analysis.error.d.ts +36 -0
- package/dist/core/errors/frame-analysis.error.js +86 -0
- package/dist/core/errors/frame-analysis.error.js.map +1 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.js +13 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/types/section-properties.type.d.ts +13 -0
- package/dist/core/types/section-properties.type.js +3 -0
- package/dist/core/types/section-properties.type.js.map +1 -0
- package/dist/esm/core/constants/frame.constant.js +20 -0
- package/dist/esm/core/constants/frame.constant.js.map +1 -0
- package/dist/esm/core/constants/rc.constant.js +63 -0
- package/dist/esm/core/constants/rc.constant.js.map +1 -0
- package/dist/esm/core/errors/frame-analysis.error.js +82 -0
- package/dist/esm/core/errors/frame-analysis.error.js.map +1 -0
- package/dist/esm/core/errors/rc-design.error.js +64 -0
- package/dist/esm/core/errors/rc-design.error.js.map +1 -0
- package/dist/esm/core/index.js +9 -0
- package/dist/esm/core/index.js.map +1 -0
- package/dist/esm/core/types/output-message.type.js +2 -0
- package/dist/esm/core/types/output-message.type.js.map +1 -0
- package/dist/esm/core/types/plate-jacketing.type.js +18 -0
- package/dist/esm/core/types/plate-jacketing.type.js.map +1 -0
- package/dist/esm/core/types/rc-beam.type.js +11 -0
- package/dist/esm/core/types/rc-beam.type.js.map +1 -0
- package/dist/esm/core/types/section-properties.type.js +2 -0
- package/dist/esm/core/types/section-properties.type.js.map +1 -0
- package/dist/esm/core/types/unit.type.js +2 -0
- package/dist/esm/core/types/unit.type.js.map +1 -0
- package/dist/esm/fea/frame/area/area-geometry.js +132 -0
- package/dist/esm/fea/frame/area/area-geometry.js.map +1 -0
- package/dist/esm/fea/frame/area/distribute-area-loads.js +267 -0
- package/dist/esm/fea/frame/area/distribute-area-loads.js.map +1 -0
- package/dist/esm/fea/frame/area/edge-members.js +62 -0
- package/dist/esm/fea/frame/area/edge-members.js.map +1 -0
- package/dist/esm/fea/frame/elements/beam-3d-stiffness.js +84 -0
- package/dist/esm/fea/frame/elements/beam-3d-stiffness.js.map +1 -0
- package/dist/esm/fea/frame/elements/fixed-end-forces.js +88 -0
- package/dist/esm/fea/frame/elements/fixed-end-forces.js.map +1 -0
- package/dist/esm/fea/frame/elements/static-condensation.js +55 -0
- package/dist/esm/fea/frame/elements/static-condensation.js.map +1 -0
- package/dist/esm/fea/frame/index.js +7 -0
- package/dist/esm/fea/frame/index.js.map +1 -0
- package/dist/esm/fea/frame/post/demand-envelope.js +97 -0
- package/dist/esm/fea/frame/post/demand-envelope.js.map +1 -0
- package/dist/esm/fea/frame/post/envelope.js +59 -0
- package/dist/esm/fea/frame/post/envelope.js.map +1 -0
- package/dist/esm/fea/frame/post/member-diagram.js +375 -0
- package/dist/esm/fea/frame/post/member-diagram.js.map +1 -0
- package/dist/esm/fea/frame/post/present-state.js +106 -0
- package/dist/esm/fea/frame/post/present-state.js.map +1 -0
- package/dist/esm/fea/frame/solver/analyze-frame.js +131 -0
- package/dist/esm/fea/frame/solver/analyze-frame.js.map +1 -0
- package/dist/esm/fea/frame/solver/boundary-conditions.js +33 -0
- package/dist/esm/fea/frame/solver/boundary-conditions.js.map +1 -0
- package/dist/esm/fea/frame/solver/combinations.js +69 -0
- package/dist/esm/fea/frame/solver/combinations.js.map +1 -0
- package/dist/esm/fea/frame/solver/frame-system.js +122 -0
- package/dist/esm/fea/frame/solver/frame-system.js.map +1 -0
- package/dist/esm/fea/frame/solver/global-assembly.js +27 -0
- package/dist/esm/fea/frame/solver/global-assembly.js.map +1 -0
- package/dist/esm/fea/frame/solver/load-case-solver.js +133 -0
- package/dist/esm/fea/frame/solver/load-case-solver.js.map +1 -0
- package/dist/esm/fea/frame/transformation/coordinate-transform.js +71 -0
- package/dist/esm/fea/frame/transformation/coordinate-transform.js.map +1 -0
- package/dist/esm/fea/frame/types/model.type.js +2 -0
- package/dist/esm/fea/frame/types/model.type.js.map +1 -0
- package/dist/esm/fea/frame/types/results.type.js +2 -0
- package/dist/esm/fea/frame/types/results.type.js.map +1 -0
- package/dist/esm/fea/frame/validation/validate-model.js +389 -0
- package/dist/esm/fea/frame/validation/validate-model.js.map +1 -0
- package/dist/esm/fea/index.js +3 -0
- package/dist/esm/fea/index.js.map +1 -0
- package/dist/esm/index.js +10 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/rc/general.js +32 -0
- package/dist/esm/rc/general.js.map +1 -0
- package/dist/esm/rc/index.js +5 -0
- package/dist/esm/rc/index.js.map +1 -0
- package/dist/esm/rc/rc-bar-layout.js +89 -0
- package/dist/esm/rc/rc-bar-layout.js.map +1 -0
- package/dist/esm/rc/rc-beam-design.js +320 -0
- package/dist/esm/rc/rc-beam-design.js.map +1 -0
- package/dist/esm/rc/rc-section-properties.js +55 -0
- package/dist/esm/rc/rc-section-properties.js.map +1 -0
- package/dist/esm/strengthening/index.js +4 -0
- package/dist/esm/strengthening/index.js.map +1 -0
- package/dist/esm/strengthening/rc-beam-plate-interface-bolts.js +338 -0
- package/dist/esm/strengthening/rc-beam-plate-interface-bolts.js.map +1 -0
- package/dist/esm/strengthening/rc-beam-side-plate-shear.js +381 -0
- package/dist/esm/strengthening/rc-beam-side-plate-shear.js.map +1 -0
- package/dist/esm/strengthening/rc-beam-steel-plate-jacketing.js +90 -0
- package/dist/esm/strengthening/rc-beam-steel-plate-jacketing.js.map +1 -0
- package/dist/esm/utils/index.js +5 -0
- package/dist/esm/utils/index.js.map +1 -0
- package/dist/esm/utils/math.js +30 -0
- package/dist/esm/utils/math.js.map +1 -0
- package/dist/esm/utils/matrix.js +145 -0
- package/dist/esm/utils/matrix.js.map +1 -0
- package/dist/esm/utils/merge-warning.js +11 -0
- package/dist/esm/utils/merge-warning.js.map +1 -0
- package/dist/esm/utils/skyline.js +151 -0
- package/dist/esm/utils/skyline.js.map +1 -0
- package/dist/fea/frame/area/area-geometry.d.ts +56 -0
- package/dist/fea/frame/area/area-geometry.js +142 -0
- package/dist/fea/frame/area/area-geometry.js.map +1 -0
- package/dist/fea/frame/area/distribute-area-loads.d.ts +30 -0
- package/dist/fea/frame/area/distribute-area-loads.js +272 -0
- package/dist/fea/frame/area/distribute-area-loads.js.map +1 -0
- package/dist/fea/frame/area/edge-members.d.ts +25 -0
- package/dist/fea/frame/area/edge-members.js +67 -0
- package/dist/fea/frame/area/edge-members.js.map +1 -0
- package/dist/fea/frame/elements/beam-3d-stiffness.d.ts +29 -0
- package/dist/fea/frame/elements/beam-3d-stiffness.js +90 -0
- package/dist/fea/frame/elements/beam-3d-stiffness.js.map +1 -0
- package/dist/fea/frame/elements/fixed-end-forces.d.ts +36 -0
- package/dist/fea/frame/elements/fixed-end-forces.js +93 -0
- package/dist/fea/frame/elements/fixed-end-forces.js.map +1 -0
- package/dist/fea/frame/elements/static-condensation.d.ts +19 -0
- package/dist/fea/frame/elements/static-condensation.js +59 -0
- package/dist/fea/frame/elements/static-condensation.js.map +1 -0
- package/dist/fea/frame/index.d.ts +10 -0
- package/dist/fea/frame/index.js +18 -0
- package/dist/fea/frame/index.js.map +1 -0
- package/dist/fea/frame/post/demand-envelope.d.ts +36 -0
- package/dist/fea/frame/post/demand-envelope.js +101 -0
- package/dist/fea/frame/post/demand-envelope.js.map +1 -0
- package/dist/fea/frame/post/envelope.d.ts +8 -0
- package/dist/fea/frame/post/envelope.js +63 -0
- package/dist/fea/frame/post/envelope.js.map +1 -0
- package/dist/fea/frame/post/member-diagram.d.ts +26 -0
- package/dist/fea/frame/post/member-diagram.js +379 -0
- package/dist/fea/frame/post/member-diagram.js.map +1 -0
- package/dist/fea/frame/post/present-state.d.ts +19 -0
- package/dist/fea/frame/post/present-state.js +111 -0
- package/dist/fea/frame/post/present-state.js.map +1 -0
- package/dist/fea/frame/solver/analyze-frame.d.ts +70 -0
- package/dist/fea/frame/solver/analyze-frame.js +136 -0
- package/dist/fea/frame/solver/analyze-frame.js.map +1 -0
- package/dist/fea/frame/solver/boundary-conditions.d.ts +14 -0
- package/dist/fea/frame/solver/boundary-conditions.js +37 -0
- package/dist/fea/frame/solver/boundary-conditions.js.map +1 -0
- package/dist/fea/frame/solver/combinations.d.ts +11 -0
- package/dist/fea/frame/solver/combinations.js +73 -0
- package/dist/fea/frame/solver/combinations.js.map +1 -0
- package/dist/fea/frame/solver/frame-system.d.ts +42 -0
- package/dist/fea/frame/solver/frame-system.js +126 -0
- package/dist/fea/frame/solver/frame-system.js.map +1 -0
- package/dist/fea/frame/solver/global-assembly.d.ts +17 -0
- package/dist/fea/frame/solver/global-assembly.js +33 -0
- package/dist/fea/frame/solver/global-assembly.js.map +1 -0
- package/dist/fea/frame/solver/load-case-solver.d.ts +34 -0
- package/dist/fea/frame/solver/load-case-solver.js +138 -0
- package/dist/fea/frame/solver/load-case-solver.js.map +1 -0
- package/dist/fea/frame/transformation/coordinate-transform.d.ts +21 -0
- package/dist/fea/frame/transformation/coordinate-transform.js +76 -0
- package/dist/fea/frame/transformation/coordinate-transform.js.map +1 -0
- package/dist/fea/frame/types/model.type.d.ts +170 -0
- package/dist/fea/frame/types/model.type.js +3 -0
- package/dist/fea/frame/types/model.type.js.map +1 -0
- package/dist/fea/frame/types/results.type.d.ts +134 -0
- package/dist/fea/frame/types/results.type.js +3 -0
- package/dist/fea/frame/types/results.type.js.map +1 -0
- package/dist/fea/frame/validation/validate-model.d.ts +18 -0
- package/dist/fea/frame/validation/validate-model.js +395 -0
- package/dist/fea/frame/validation/validate-model.js.map +1 -0
- package/dist/fea/index.d.ts +1 -0
- package/dist/fea/index.js +19 -0
- package/dist/fea/index.js.map +1 -0
- package/dist/index.d.ts +8 -4
- package/dist/index.js +37 -1
- package/dist/index.js.map +1 -1
- package/dist/rc/index.d.ts +2 -0
- package/dist/rc/index.js +3 -1
- package/dist/rc/index.js.map +1 -1
- package/dist/rc/rc-section-properties.d.ts +35 -0
- package/dist/rc/rc-section-properties.js +59 -0
- package/dist/rc/rc-section-properties.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +19 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/matrix.d.ts +45 -0
- package/dist/utils/matrix.js +157 -0
- package/dist/utils/matrix.js.map +1 -0
- package/dist/utils/skyline.d.ts +49 -0
- package/dist/utils/skyline.js +161 -0
- package/dist/utils/skyline.js.map +1 -0
- 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":";;;AAAA,gFAAwF;AACxF,8CAAwD;AACxD,gDAAkD;AAElD,mEAAoF;AAGpF,uDAAoE;AAcpE,MAAM,iBAAiB,GAAsD;IAC3E,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACZ,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACZ,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;CACb,CAAC;AAEF,gEAAgE;AAChE,MAAM,YAAY,GAAG,CAAC,IAAgB,EAAE,MAAc,EAAE,CAAS,EAAqB,EAAE;IACtF,MAAM,UAAU,GAAG,CAAC,SAAwB,EAAyC,EAAE;QACrF,IAAI,SAAS,KAAK,GAAG,IAAI,SAAS,KAAK,GAAG,IAAI,SAAS,KAAK,GAAG,EAAE,CAAC;YAChE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,SAAS,CAAc,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,CAAC,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;QACvC,OAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAW;aACxB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACd,IAAI;YACJ,MAAM,EACJ,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SACvF,CAAC,CAAC;aACF,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC;IAC/C,CAAC,CAAC;IAEF,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC3B,uBAAuB;QACvB,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3F,CAAC;IACD,OAAO,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAmB,EAAE;QAC1E,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO;YAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,MAAM,GAAG,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;QAC/F,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7E,OAAO;YACL,IAAI,EAAE,aAAa;YACnB,IAAI;YACJ,EAAE,EAAE,EAAE,GAAG,MAAM,EAAE,cAAc;YAC/B,EAAE,EAAE,EAAE,GAAG,MAAM;YACf,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,CAAC;YACtB,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC;SACnB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF;;;;;;;;;;GAUG;AACI,MAAM,aAAa,GAAG,CAC3B,MAAmB,EACnB,QAAkB,EAClB,KAA6D,EACnD,EAAE;IACZ,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC;IAC/F,MAAM,CAAC,GAAG,IAAI,KAAK,CAAS,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAE9C,MAAM,aAAa,GAAmB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IAC5D,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACrC,aAAa,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,IAAI,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAwB,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACjE,MAAM,eAAe,GAAG,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;YACrB,MAAM,EAAE,UAAU,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC;YACzC,IAAI,UAAU,KAAK,SAAS;gBAAE,MAAM,IAAI,yCAAkB,CAAC,kCAAW,CAAC,mBAAmB,CAAC,CAAC;YAC5F,oBAAoB;YACpB,MAAM,CAAC,GAAG,CAAC,UAAU,GAAG,UAAU,GAAG,CAAC,GAAG,IAAI,CAAC;YAC9C,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBACZ,eAAe,CAAC,IAAI,CAAC;oBACnB,QAAQ,EAAE,QAAQ,CAAC,EAAE;oBACrB,IAAI,EAAE,KAAK;oBACX,QAAQ,EAAE,MAAM,CAAC,EAAE;oBACnB,SAAS,EAAE,GAAG;oBACd,CAAC;iBACF,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,eAAe,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7F,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACtC,MAAM,SAAS,GAAG,MAAM,CAAC,sBAAsB,CAAC,IAAA,iCAAc,EAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/F,IAAA,qCAAmB,EAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;QAC9C,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC,CAAC;IAEH,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,CAAC,GAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAY,CAAC;QACxD,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QAC/E,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IACrF,CAAC;IAED,MAAM,CAAC,GAAG,IAAI,KAAK,CAAS,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9C,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,QAAQ,GAAG,IAAA,sBAAY,EAC3B,MAAM,EACN,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAC1B,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,qFAAqF;IACrF,MAAM,EAAE,GAAG,IAAI,KAAK,CAAS,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/C,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QAC7C,MAAM,MAAM,GAAG,IAAA,eAAM,EACnB,MAAM,CAAC,CAAC,EACR,IAAA,4BAAU,EAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CACpC,CAAC;QACF,MAAM,OAAO,GAAG,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzC,IAAA,qCAAmB,EAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QAC5C,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEpE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;AAChD,CAAC,CAAC;AArEW,QAAA,aAAa,iBAqExB;AAEF,MAAM,SAAS,GAAG,CAAC,IAAqB,EAAE,MAAc,EAAmB,EAAE;IAC3E,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa;QAAE,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;IAChG,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC;IACnE,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC;AACzC,CAAC,CAAC;AAEF,6FAA6F;AACtF,MAAM,aAAa,GAAG,CAAC,KAA4C,EAAY,EAAE;IACtF,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC7B,MAAM,GAAG,GAAG,CAAC,IAA+B,EAAE,MAAc,EAAE,EAAE;QAC9D,MAAM,GAAG,GAAG,IAAI,KAAK,CAAS,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9C,KAAK,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;YACtC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;IACF,OAAO;QACL,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QAClC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QAClC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QAClC,YAAY,EAAE,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACjF,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAC1C,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAClC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAC1E,CACF;KACF,CAAC;AACJ,CAAC,CAAC;AApBW,QAAA,aAAa,iBAoBxB"}
|
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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[];
|