@theerapat-s28/ts-structural-eng-tools 2.3.0 → 3.0.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/CHANGELOG.md +28 -1
- package/README.md +8 -5
- package/dist/core/constants/frame.constant.d.ts +15 -0
- package/dist/core/constants/frame.constant.js +16 -1
- package/dist/core/constants/frame.constant.js.map +1 -1
- package/dist/core/errors/frame-analysis.error.d.ts +1 -0
- package/dist/core/errors/frame-analysis.error.js +18 -2
- package/dist/core/errors/frame-analysis.error.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +2 -1
- package/dist/core/index.js.map +1 -1
- package/dist/esm/core/constants/frame.constant.js +15 -0
- package/dist/esm/core/constants/frame.constant.js.map +1 -1
- package/dist/esm/core/errors/frame-analysis.error.js +18 -2
- package/dist/esm/core/errors/frame-analysis.error.js.map +1 -1
- package/dist/esm/core/index.js +1 -1
- package/dist/esm/core/index.js.map +1 -1
- package/dist/esm/fea/frame/elements/shell/dkq-plate.js +109 -0
- package/dist/esm/fea/frame/elements/shell/dkq-plate.js.map +1 -0
- package/dist/esm/fea/frame/elements/shell/flat-shell.js +111 -0
- package/dist/esm/fea/frame/elements/shell/flat-shell.js.map +1 -0
- package/dist/esm/fea/frame/elements/shell/membrane-quad.js +107 -0
- package/dist/esm/fea/frame/elements/shell/membrane-quad.js.map +1 -0
- package/dist/esm/fea/frame/elements/shell/quad-geometry.js +127 -0
- package/dist/esm/fea/frame/elements/shell/quad-geometry.js.map +1 -0
- package/dist/esm/fea/frame/elements/shell/rigidity.js +19 -0
- package/dist/esm/fea/frame/elements/shell/rigidity.js.map +1 -0
- package/dist/esm/fea/frame/elements/shell/shell-axes.js +97 -0
- package/dist/esm/fea/frame/elements/shell/shell-axes.js.map +1 -0
- package/dist/esm/fea/frame/mesh/expand-model.js +129 -0
- package/dist/esm/fea/frame/mesh/expand-model.js.map +1 -0
- package/dist/esm/fea/frame/mesh/mesh-shells.js +239 -0
- package/dist/esm/fea/frame/mesh/mesh-shells.js.map +1 -0
- package/dist/esm/fea/frame/post/envelope.js +38 -1
- package/dist/esm/fea/frame/post/envelope.js.map +1 -1
- package/dist/esm/fea/frame/post/member-diagram.js +51 -2
- package/dist/esm/fea/frame/post/member-diagram.js.map +1 -1
- package/dist/esm/fea/frame/post/present-state.js +34 -16
- package/dist/esm/fea/frame/post/present-state.js.map +1 -1
- package/dist/esm/fea/frame/post/shell-forces.js +111 -0
- package/dist/esm/fea/frame/post/shell-forces.js.map +1 -0
- package/dist/esm/fea/frame/solver/analyze-frame.js +27 -7
- package/dist/esm/fea/frame/solver/analyze-frame.js.map +1 -1
- package/dist/esm/fea/frame/solver/auto-restraint.js +58 -10
- package/dist/esm/fea/frame/solver/auto-restraint.js.map +1 -1
- package/dist/esm/fea/frame/solver/frame-system.js +148 -40
- package/dist/esm/fea/frame/solver/frame-system.js.map +1 -1
- package/dist/esm/fea/frame/solver/global-assembly.js +5 -3
- package/dist/esm/fea/frame/solver/global-assembly.js.map +1 -1
- package/dist/esm/fea/frame/solver/load-case-solver.js +102 -9
- package/dist/esm/fea/frame/solver/load-case-solver.js.map +1 -1
- package/dist/esm/fea/frame/validation/validate-model.js +120 -3
- package/dist/esm/fea/frame/validation/validate-model.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/fea/frame/elements/shell/dkq-plate.d.ts +50 -0
- package/dist/fea/frame/elements/shell/dkq-plate.js +115 -0
- package/dist/fea/frame/elements/shell/dkq-plate.js.map +1 -0
- package/dist/fea/frame/elements/shell/flat-shell.d.ts +63 -0
- package/dist/fea/frame/elements/shell/flat-shell.js +118 -0
- package/dist/fea/frame/elements/shell/flat-shell.js.map +1 -0
- package/dist/fea/frame/elements/shell/membrane-quad.d.ts +61 -0
- package/dist/fea/frame/elements/shell/membrane-quad.js +113 -0
- package/dist/fea/frame/elements/shell/membrane-quad.js.map +1 -0
- package/dist/fea/frame/elements/shell/quad-geometry.d.ts +71 -0
- package/dist/fea/frame/elements/shell/quad-geometry.js +136 -0
- package/dist/fea/frame/elements/shell/quad-geometry.js.map +1 -0
- package/dist/fea/frame/elements/shell/rigidity.d.ts +14 -0
- package/dist/fea/frame/elements/shell/rigidity.js +23 -0
- package/dist/fea/frame/elements/shell/rigidity.js.map +1 -0
- package/dist/fea/frame/elements/shell/shell-axes.d.ts +43 -0
- package/dist/fea/frame/elements/shell/shell-axes.js +102 -0
- package/dist/fea/frame/elements/shell/shell-axes.js.map +1 -0
- package/dist/fea/frame/index.d.ts +2 -2
- package/dist/fea/frame/mesh/expand-model.d.ts +29 -0
- package/dist/fea/frame/mesh/expand-model.js +133 -0
- package/dist/fea/frame/mesh/expand-model.js.map +1 -0
- package/dist/fea/frame/mesh/mesh-shells.d.ts +38 -0
- package/dist/fea/frame/mesh/mesh-shells.js +244 -0
- package/dist/fea/frame/mesh/mesh-shells.js.map +1 -0
- package/dist/fea/frame/post/envelope.js +38 -1
- package/dist/fea/frame/post/envelope.js.map +1 -1
- package/dist/fea/frame/post/member-diagram.d.ts +21 -1
- package/dist/fea/frame/post/member-diagram.js +53 -3
- package/dist/fea/frame/post/member-diagram.js.map +1 -1
- package/dist/fea/frame/post/present-state.d.ts +3 -2
- package/dist/fea/frame/post/present-state.js +33 -15
- package/dist/fea/frame/post/present-state.js.map +1 -1
- package/dist/fea/frame/post/shell-forces.d.ts +27 -0
- package/dist/fea/frame/post/shell-forces.js +116 -0
- package/dist/fea/frame/post/shell-forces.js.map +1 -0
- package/dist/fea/frame/solver/analyze-frame.d.ts +8 -4
- package/dist/fea/frame/solver/analyze-frame.js +27 -7
- package/dist/fea/frame/solver/analyze-frame.js.map +1 -1
- package/dist/fea/frame/solver/auto-restraint.d.ts +23 -10
- package/dist/fea/frame/solver/auto-restraint.js +60 -11
- package/dist/fea/frame/solver/auto-restraint.js.map +1 -1
- package/dist/fea/frame/solver/frame-system.d.ts +47 -8
- package/dist/fea/frame/solver/frame-system.js +146 -38
- package/dist/fea/frame/solver/frame-system.js.map +1 -1
- package/dist/fea/frame/solver/global-assembly.d.ts +11 -0
- package/dist/fea/frame/solver/global-assembly.js +7 -4
- package/dist/fea/frame/solver/global-assembly.js.map +1 -1
- package/dist/fea/frame/solver/load-case-solver.d.ts +11 -1
- package/dist/fea/frame/solver/load-case-solver.js +100 -7
- package/dist/fea/frame/solver/load-case-solver.js.map +1 -1
- package/dist/fea/frame/types/model.type.d.ts +82 -4
- package/dist/fea/frame/types/results.type.d.ts +61 -1
- package/dist/fea/frame/validation/validate-model.d.ts +3 -2
- package/dist/fea/frame/validation/validate-model.js +120 -3
- package/dist/fea/frame/validation/validate-model.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { roundToDecimalPlaces } from "../../../utils/math.js";
|
|
2
|
+
import { matVec } from "../../../utils/matrix.js";
|
|
3
|
+
import { dkqCurvatureRows, plateRigidity } from "../elements/shell/dkq-plate.js";
|
|
4
|
+
import { membraneRigidity, membraneStrainRows } from "../elements/shell/membrane-quad.js";
|
|
5
|
+
import { bilinearShape, cartesianDerivatives, GAUSS_2X2, quadJacobian, } from "../elements/shell/quad-geometry.js";
|
|
6
|
+
import { elementDofs } from "../solver/global-assembly.js";
|
|
7
|
+
/** Raw components per corner: F11 F22 F12 (N/mm), M11 M22 M12 (N·mm/mm), V13 V23 (N/mm). */
|
|
8
|
+
export const SHELL_FORCE_COMPONENTS = 8;
|
|
9
|
+
const FORCE_DECIMALS = 4;
|
|
10
|
+
const ROOT3 = Math.sqrt(3);
|
|
11
|
+
const CORNERS = [
|
|
12
|
+
[-1, -1],
|
|
13
|
+
[1, -1],
|
|
14
|
+
[1, 1],
|
|
15
|
+
[-1, 1],
|
|
16
|
+
];
|
|
17
|
+
/**
|
|
18
|
+
* Bilinear functions through the 2×2 Gauss points (in `GAUSS_2X2` order), evaluated at each
|
|
19
|
+
* corner: the corner is at ±√3 in the Gauss points' own coordinates, ξ' = √3·ξ.
|
|
20
|
+
*/
|
|
21
|
+
const atCorners = CORNERS.map(([xi, eta]) => bilinearShape(ROOT3 * xi, ROOT3 * eta));
|
|
22
|
+
/**
|
|
23
|
+
* Unrounded forces per unit width at the four corners of a shell, in its local axes 1, 2, from
|
|
24
|
+
* the global displacements `U` (N and mm): 8 values per corner in `nodeIds` order.
|
|
25
|
+
*
|
|
26
|
+
* - Membrane forces `n = D_m·ε` and moments are evaluated at the 2×2 Gauss points and
|
|
27
|
+
* extrapolated bilinearly to the corners.
|
|
28
|
+
* - Moments follow the member convention: M11 is positive when it puts the −3 face in tension
|
|
29
|
+
* (sagging with local 3 up), so M = −∫ z·σ dz.
|
|
30
|
+
* - The plate has no shear strain, so V13, V23 come from moment equilibrium,
|
|
31
|
+
* `V13 = −(∂M11/∂x₁ + ∂M12/∂x₂)` and `V23 = −(∂M12/∂x₁ + ∂M22/∂x₂)` (as V2 = −dM3/dx for a
|
|
32
|
+
* member), on the bilinear field through the Gauss-point moments. They are coarser than the
|
|
33
|
+
* moments.
|
|
34
|
+
*
|
|
35
|
+
* Everything is linear in `U`, so load combinations superpose it.
|
|
36
|
+
*/
|
|
37
|
+
export const shellRawForces = (shell, U) => {
|
|
38
|
+
const { element, type, section, modifiers: m } = shell;
|
|
39
|
+
const dofs = elementDofs(shell.nodeIndices);
|
|
40
|
+
// local DOFs [u₁ u₂ u₃ r₁ r₂ r₃] of each projected corner
|
|
41
|
+
const local = element.transforms.map((T, i) => matVec(T, dofs.slice(6 * i, 6 * i + 6).map((d) => U[d])));
|
|
42
|
+
const { corners } = element.axes;
|
|
43
|
+
const properties = { E: section.E, nu: section.nu, t: section.thickness };
|
|
44
|
+
const out = new Array(4 * SHELL_FORCE_COMPONENTS).fill(0);
|
|
45
|
+
const extrapolate = (atGauss, first) => {
|
|
46
|
+
atCorners.forEach(({ N }, c) => {
|
|
47
|
+
for (let k = 0; k < 3; k++) {
|
|
48
|
+
out[SHELL_FORCE_COMPONENTS * c + first + k] = N.reduce((sum, w, g) => sum + w * atGauss[g][k], 0);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
if (type !== "plate") {
|
|
53
|
+
const D = membraneRigidity({ ...properties, modifiers: [m.f11 ?? 1, m.f22 ?? 1, m.f12 ?? 1] });
|
|
54
|
+
const u = local.flatMap((d) => [d[0], d[1], d[5]]);
|
|
55
|
+
extrapolate(GAUSS_2X2.map(({ xi, eta }) => matVec(D, matVec(membraneStrainRows(corners, xi, eta).B, u))), 0);
|
|
56
|
+
}
|
|
57
|
+
if (type !== "membrane") {
|
|
58
|
+
const D = plateRigidity({ ...properties, modifiers: [m.m11 ?? 1, m.m22 ?? 1, m.m12 ?? 1] });
|
|
59
|
+
const w = local.flatMap((d) => [d[2], d[3], d[4]]);
|
|
60
|
+
const moments = GAUSS_2X2.map(({ xi, eta }) => matVec(D, matVec(dkqCurvatureRows(corners, xi, eta).B, w)).map((v) => -v));
|
|
61
|
+
extrapolate(moments, 3);
|
|
62
|
+
CORNERS.forEach(([xi, eta], c) => {
|
|
63
|
+
const { dXi, dEta } = atCorners[c];
|
|
64
|
+
const { dX, dY } = cartesianDerivatives(quadJacobian(corners, xi, eta), {
|
|
65
|
+
dXi: dXi.map((v) => ROOT3 * v),
|
|
66
|
+
dEta: dEta.map((v) => ROOT3 * v),
|
|
67
|
+
});
|
|
68
|
+
const d = (weights, k) => weights.reduce((sum, v, g) => sum + v * moments[g][k], 0);
|
|
69
|
+
out[SHELL_FORCE_COMPONENTS * c + 6] = -(d(dX, 0) + d(dY, 2));
|
|
70
|
+
out[SHELL_FORCE_COMPONENTS * c + 7] = -(d(dX, 2) + d(dY, 1));
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
};
|
|
75
|
+
const round = (value) => roundToDecimalPlaces(value, FORCE_DECIMALS) + 0; // + 0: no −0
|
|
76
|
+
/**
|
|
77
|
+
* The presented forces of one shell: kN/m, kN·m/m and kN/m per corner, with the face stresses
|
|
78
|
+
* `σ = F/t ∓ 6M/t²` in MPa (top = +3 face).
|
|
79
|
+
*
|
|
80
|
+
* @param raw - From `shellRawForces`, or a factored sum of them
|
|
81
|
+
*/
|
|
82
|
+
export const presentShellForces = (shell, nodeIds, raw) => {
|
|
83
|
+
const t = shell.section.thickness;
|
|
84
|
+
return {
|
|
85
|
+
shellId: shell.id,
|
|
86
|
+
areaId: shell.areaId,
|
|
87
|
+
corners: nodeIds.map((nodeId, c) => {
|
|
88
|
+
const [F11, F22, F12, M11, M22, M12, V13, V23] = raw.slice(SHELL_FORCE_COMPONENTS * c, SHELL_FORCE_COMPONENTS * (c + 1));
|
|
89
|
+
// N/mm ÷ mm and N·mm/mm ÷ mm² are MPa
|
|
90
|
+
const face = (F, M, side) => round(F / t - (side * 6 * M) / t ** 2);
|
|
91
|
+
return {
|
|
92
|
+
nodeId,
|
|
93
|
+
F11: round(F11), // N/mm = kN/m
|
|
94
|
+
F22: round(F22),
|
|
95
|
+
F12: round(F12),
|
|
96
|
+
M11: round(M11 * 1e-3), // N·mm/mm = 10⁻³ kN·m/m
|
|
97
|
+
M22: round(M22 * 1e-3),
|
|
98
|
+
M12: round(M12 * 1e-3),
|
|
99
|
+
V13: round(V13),
|
|
100
|
+
V23: round(V23),
|
|
101
|
+
S11Top: face(F11, M11, 1),
|
|
102
|
+
S22Top: face(F22, M22, 1),
|
|
103
|
+
S12Top: face(F12, M12, 1),
|
|
104
|
+
S11Bot: face(F11, M11, -1),
|
|
105
|
+
S22Bot: face(F22, M22, -1),
|
|
106
|
+
S12Bot: face(F12, M12, -1),
|
|
107
|
+
};
|
|
108
|
+
}),
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
//# sourceMappingURL=shell-forces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell-forces.js","sourceRoot":"","sources":["../../../../../src/fea/frame/post/shell-forces.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { areaMemberLoads } from "../area/distribute-area-loads.js";
|
|
|
3
3
|
import { buildEnvelope } from "../post/envelope.js";
|
|
4
4
|
import { presentMemberDiagram, presentState } from "../post/present-state.js";
|
|
5
5
|
import { throwIssues, validateFrameModel } from "../validation/validate-model.js";
|
|
6
|
+
import { expandModel } from "../mesh/expand-model.js";
|
|
6
7
|
import { resolveCombinations } from "./combinations.js";
|
|
7
8
|
import { prepareFrameSystem } from "./frame-system.js";
|
|
8
9
|
import { combineStates, solveLoadCase } from "./load-case-solver.js";
|
|
@@ -38,14 +39,16 @@ const groupByCase = (loads = []) => {
|
|
|
38
39
|
* null areas, and combinations
|
|
39
40
|
* @param options - Diagram station count and detail
|
|
40
41
|
* @returns `{ result, memberDiagram }`
|
|
41
|
-
* @throws {FrameAnalysisError} 301–317 for an invalid model (with `details` and
|
|
42
|
-
* `issues`),
|
|
42
|
+
* @throws {FrameAnalysisError} 301–317, 326 and 327 for an invalid model (with `details` and
|
|
43
|
+
* every problem in `issues`), 328 for a translation nothing resists at a node connected only
|
|
44
|
+
* to shells, 304 for an unstable structure
|
|
43
45
|
*/
|
|
44
46
|
export const createFrameAnalysis = (model, options = {}) => {
|
|
45
47
|
const issues = validateFrameModel(model);
|
|
46
48
|
if (issues.length > 0)
|
|
47
49
|
throwIssues(issues);
|
|
48
|
-
const
|
|
50
|
+
const expanded = expandModel(model);
|
|
51
|
+
const system = prepareFrameSystem(expanded.model);
|
|
49
52
|
const combinations = model.combinations ?? [];
|
|
50
53
|
const resolved = resolveCombinations(combinations, new Set(model.loadCases.map((c) => c.id)));
|
|
51
54
|
const withStations = (options.diagrams ?? "full") === "full";
|
|
@@ -57,10 +60,13 @@ export const createFrameAnalysis = (model, options = {}) => {
|
|
|
57
60
|
...(model.memberLoads ?? []),
|
|
58
61
|
...fromAreas.memberLoads,
|
|
59
62
|
]);
|
|
63
|
+
// area loads on shells load the shell elements; those on null areas became member loads
|
|
64
|
+
const shellByCase = groupByCase((model.areaLoads ?? []).filter((load) => system.shellsByArea.has(load.areaId)));
|
|
60
65
|
for (const loadCase of model.loadCases) {
|
|
61
66
|
const state = solveLoadCase(system, loadCase, {
|
|
62
67
|
nodalLoads: nodalByCase.get(loadCase.id) ?? [],
|
|
63
68
|
memberLoads: memberByCase.get(loadCase.id) ?? [],
|
|
69
|
+
shellLoads: shellByCase.get(loadCase.id) ?? [],
|
|
64
70
|
});
|
|
65
71
|
states.set(loadCase.id, state);
|
|
66
72
|
cases[loadCase.id] = presentState(system, state, { id: loadCase.id, kind: "case", name: loadCase.name, type: loadCase.type }, { stations: options.stations, withStations });
|
|
@@ -76,6 +82,7 @@ export const createFrameAnalysis = (model, options = {}) => {
|
|
|
76
82
|
}
|
|
77
83
|
const warnings = [
|
|
78
84
|
...fromAreas.warnings,
|
|
85
|
+
...expanded.warnings,
|
|
79
86
|
...[...Object.values(cases), ...Object.values(combinationResults)].flatMap((r) => r.warnings.map((w) => ({
|
|
80
87
|
...w,
|
|
81
88
|
message: `${r.kind === "case" ? "Load case" : "Load combination"} "${r.id}": ${w.message}`,
|
|
@@ -86,9 +93,11 @@ export const createFrameAnalysis = (model, options = {}) => {
|
|
|
86
93
|
cases,
|
|
87
94
|
combinations: combinationResults,
|
|
88
95
|
envelope: combinationList.length > 0 ? buildEnvelope(combinationList) : undefined,
|
|
96
|
+
...(expanded.mesh ? { mesh: expanded.mesh } : {}),
|
|
89
97
|
calculationDetails: {
|
|
90
98
|
nodeCount: system.nodes.length,
|
|
91
|
-
memberCount: system.
|
|
99
|
+
memberCount: system.memberGroups.length,
|
|
100
|
+
shellCount: system.shells.length,
|
|
92
101
|
dofCount: system.dofCount,
|
|
93
102
|
freeDofCount: system.free.length,
|
|
94
103
|
profileSize: system.profileSize,
|
|
@@ -96,7 +105,15 @@ export const createFrameAnalysis = (model, options = {}) => {
|
|
|
96
105
|
combinationCount: combinations.length,
|
|
97
106
|
autoRestrainedDofs: autoRestrainedDofs(system),
|
|
98
107
|
},
|
|
99
|
-
units: {
|
|
108
|
+
units: {
|
|
109
|
+
force: "kN",
|
|
110
|
+
moment: "kN·m",
|
|
111
|
+
length: "mm",
|
|
112
|
+
rotation: "rad",
|
|
113
|
+
forcePerLength: "kN/m",
|
|
114
|
+
momentPerLength: "kN·m/m",
|
|
115
|
+
stress: "MPa",
|
|
116
|
+
},
|
|
100
117
|
warnings,
|
|
101
118
|
};
|
|
102
119
|
return {
|
|
@@ -129,6 +146,8 @@ export const createFrameAnalysis = (model, options = {}) => {
|
|
|
129
146
|
*
|
|
130
147
|
* Area loads on null areas (`areas`, `areaLoads`) are first turned into member loads on the
|
|
131
148
|
* members along each area's edges (see `distributeAreaLoads`); the areas add no stiffness.
|
|
149
|
+
* Shell areas (`shells`) are four-node flat shell elements with their own stiffness; area loads
|
|
150
|
+
* and self-weight on them act as forces at their corners.
|
|
132
151
|
*
|
|
133
152
|
* Model and result are plain data (JSON-serialisable), so the analysis can run in a Web Worker.
|
|
134
153
|
*
|
|
@@ -137,8 +156,9 @@ export const createFrameAnalysis = (model, options = {}) => {
|
|
|
137
156
|
* @param options - Diagram station count and detail
|
|
138
157
|
* @returns `cases` and `combinations` keyed by id, `envelope` over the combinations,
|
|
139
158
|
* `calculationDetails`, `units` and `warnings`
|
|
140
|
-
* @throws {FrameAnalysisError} 301–317 for an invalid model (with `details` and
|
|
141
|
-
* `issues`),
|
|
159
|
+
* @throws {FrameAnalysisError} 301–317, 326 and 327 for an invalid model (with `details` and
|
|
160
|
+
* every problem in `issues`), 328 for a translation nothing resists at a node connected only
|
|
161
|
+
* to shells, 304 for an unstable structure
|
|
142
162
|
*/
|
|
143
163
|
export const analyzeFrame = (model, options = {}) => createFrameAnalysis(model, options).result;
|
|
144
164
|
//# sourceMappingURL=analyze-frame.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze-frame.js","sourceRoot":"","sources":["../../../../../src/fea/frame/solver/analyze-frame.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAQ3E,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAoB,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAiB,MAAM,oBAAoB,CAAC;AA8BjF,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAU,CAAC;AAElD,oEAAoE;AACpE,MAAM,kBAAkB,GAAG,CAAC,MAAmB,EAAuB,EAAE,CACtE,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAA6B,CAAC;IAC5F,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5D,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE;QAC7B,IAAI,EAAE,OAAO;QACb,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACzD,CAAC;AACJ,CAAC,CAAC,CAAC;AAEL,oFAAoF;AACpF,MAAM,WAAW,GAAG,CAAiC,QAAa,EAAE,EAAoB,EAAE;IACxF,MAAM,MAAM,GAAG,IAAI,GAAG,EAAe,CAAC;IACtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;;YACvB,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"analyze-frame.js","sourceRoot":"","sources":["../../../../../src/fea/frame/solver/analyze-frame.ts"],"names":[],"mappings":"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"}
|
|
@@ -52,26 +52,27 @@ const symmetricEigen = (M) => {
|
|
|
52
52
|
* Finds the joint rotations that nothing resists, so they can be held instead of making the
|
|
53
53
|
* stiffness singular — e.g. a truss joint where every member releases its end moments.
|
|
54
54
|
*
|
|
55
|
-
* For each node with
|
|
56
|
-
*
|
|
55
|
+
* For each node with elements, the free rotational block `B` (3×3, global) of the assembled
|
|
56
|
+
* element stiffness plus rotational springs is decomposed; every eigenvector whose eigenvalue
|
|
57
57
|
* is below `SINGULARITY_TOLERANCE` times the block's largest diagonal is a null direction `n`.
|
|
58
|
-
* Each
|
|
58
|
+
* Each element's global stiffness is positive semi-definite, so `nᵀ·B·n = 0` makes the whole
|
|
59
59
|
* stiffness column of `n` zero: the rotation along `n` is decoupled from every other DOF, and a
|
|
60
60
|
* spring `k·n·nᵀ` there carries no force unless a load has a moment component along `n`.
|
|
61
61
|
*
|
|
62
62
|
* @param nodeCount - Number of nodes
|
|
63
|
-
* @param
|
|
63
|
+
* @param elements - Node indices and global stiffness (6 DOFs per node) of every element, members
|
|
64
|
+
* included (N and mm)
|
|
64
65
|
* @param boundary - Fixed DOFs and spring stiffnesses
|
|
65
66
|
*/
|
|
66
|
-
export const findAutoRestraints = (nodeCount,
|
|
67
|
+
export const findAutoRestraints = (nodeCount, elements, boundary) => {
|
|
67
68
|
const blocks = new Array(nodeCount).fill(null);
|
|
68
|
-
for (const
|
|
69
|
-
|
|
69
|
+
for (const element of elements) {
|
|
70
|
+
element.nodes.forEach((node, position) => {
|
|
70
71
|
const block = (blocks[node] ?? (blocks[node] = [0, 1, 2].map(() => [0, 0, 0])));
|
|
71
|
-
const base = 6 *
|
|
72
|
+
const base = 6 * position + 3;
|
|
72
73
|
for (let i = 0; i < 3; i++) {
|
|
73
74
|
for (let j = 0; j < 3; j++)
|
|
74
|
-
block[i][j] +=
|
|
75
|
+
block[i][j] += element.kGlobal[base + i][base + j];
|
|
75
76
|
}
|
|
76
77
|
});
|
|
77
78
|
}
|
|
@@ -80,7 +81,7 @@ export const findAutoRestraints = (nodeCount, members, boundary) => {
|
|
|
80
81
|
const restraints = [];
|
|
81
82
|
blocks.forEach((block, node) => {
|
|
82
83
|
if (!block)
|
|
83
|
-
return; // a node without
|
|
84
|
+
return; // a node without elements is a mechanism, left for the factorisation
|
|
84
85
|
const free = [0, 1, 2].filter((i) => !boundary.fixed[6 * node + 3 + i]);
|
|
85
86
|
if (free.length === 0)
|
|
86
87
|
return;
|
|
@@ -101,4 +102,51 @@ export const findAutoRestraints = (nodeCount, members, boundary) => {
|
|
|
101
102
|
});
|
|
102
103
|
return restraints;
|
|
103
104
|
};
|
|
105
|
+
/**
|
|
106
|
+
* Finds the translations that nothing resists at the given nodes: the null directions of each
|
|
107
|
+
* node's free translational block (3×3, global) of the assembled element stiffness plus
|
|
108
|
+
* translational springs, by the same eigen-decomposition as `findAutoRestraints`. Such a
|
|
109
|
+
* direction is decoupled from every other DOF, so the structure is a mechanism there.
|
|
110
|
+
*
|
|
111
|
+
* @param nodes - Node indices to check, e.g. nodes connected only to shells
|
|
112
|
+
* @param elements - Node indices and global stiffness (6 DOFs per node) of every element
|
|
113
|
+
* @param boundary - Fixed DOFs and spring stiffnesses
|
|
114
|
+
*/
|
|
115
|
+
export const findUnresistedTranslations = (nodes, elements, boundary) => {
|
|
116
|
+
const blocks = new Map();
|
|
117
|
+
for (const node of nodes)
|
|
118
|
+
blocks.set(node, [0, 1, 2].map(() => [0, 0, 0]));
|
|
119
|
+
for (const element of elements) {
|
|
120
|
+
element.nodes.forEach((node, position) => {
|
|
121
|
+
const block = blocks.get(node);
|
|
122
|
+
if (!block)
|
|
123
|
+
return;
|
|
124
|
+
const base = 6 * position;
|
|
125
|
+
for (let i = 0; i < 3; i++) {
|
|
126
|
+
for (let j = 0; j < 3; j++)
|
|
127
|
+
block[i][j] += element.kGlobal[base + i][base + j];
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
const unresisted = [];
|
|
132
|
+
blocks.forEach((block, node) => {
|
|
133
|
+
const free = [0, 1, 2].filter((i) => !boundary.fixed[6 * node + i]);
|
|
134
|
+
if (free.length === 0)
|
|
135
|
+
return;
|
|
136
|
+
const sub = free.map((i) => free.map((j) => block[i][j] + (i === j ? boundary.spring[6 * node + i] : 0)));
|
|
137
|
+
const scale = Math.max(...sub.map((row, i) => Math.abs(row[i])));
|
|
138
|
+
const { values, vectors } = symmetricEigen(sub);
|
|
139
|
+
values.forEach((value, e) => {
|
|
140
|
+
if (scale > 0 && value > SINGULARITY_TOLERANCE * scale)
|
|
141
|
+
return;
|
|
142
|
+
const axis = [0, 0, 0];
|
|
143
|
+
free.forEach((i, k) => (axis[i] = vectors[e][k]));
|
|
144
|
+
const lead = axis.reduce((best, c, i) => (Math.abs(c) > Math.abs(axis[best]) ? i : best), 0);
|
|
145
|
+
if (axis[lead] < 0)
|
|
146
|
+
axis.forEach((c, i) => (axis[i] = -c));
|
|
147
|
+
unresisted.push({ node, axis });
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
return unresisted;
|
|
151
|
+
};
|
|
104
152
|
//# sourceMappingURL=auto-restraint.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auto-restraint.js","sourceRoot":"","sources":["../../../../../src/fea/frame/solver/auto-restraint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"auto-restraint.js","sourceRoot":"","sources":["../../../../../src/fea/frame/solver/auto-restraint.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,54 +3,162 @@ import { FrameErrors } from "../../../core/errors/frame-analysis.error.js";
|
|
|
3
3
|
import { createSkyline, reverseCuthillMcKee, skylineAdd, skylineFactor, skylineSize, } from "../../../utils/skyline.js";
|
|
4
4
|
import { beam3dLocalStiffnessRightHanded } from "../elements/beam-3d-stiffness.js";
|
|
5
5
|
import { memberEndReleases } from "../elements/end-releases.js";
|
|
6
|
+
import { flatShellElement } from "../elements/shell/flat-shell.js";
|
|
7
|
+
import { cornerAreas } from "../elements/shell/quad-geometry.js";
|
|
6
8
|
import { condenseMember } from "../elements/static-condensation.js";
|
|
7
9
|
import { memberAxes, transformationMatrix } from "../transformation/coordinate-transform.js";
|
|
8
10
|
import { frameIssue, throwIssues } from "../validation/validate-model.js";
|
|
9
|
-
import { findAutoRestraints } from "./auto-restraint.js";
|
|
11
|
+
import { findAutoRestraints, findUnresistedTranslations, } from "./auto-restraint.js";
|
|
10
12
|
import { buildBoundaryConditions } from "./boundary-conditions.js";
|
|
11
|
-
import {
|
|
13
|
+
import { elementDofs, memberGlobalStiffness, } from "./global-assembly.js";
|
|
12
14
|
const DOF_NAMES = ["ux", "uy", "uz", "rx", "ry", "rz"];
|
|
13
15
|
/**
|
|
14
|
-
* Builds the member matrices of a model that passed `validateFrameModel`, assembles
|
|
15
|
-
* stiffness in skyline storage with nodes in reverse Cuthill–McKee order, and
|
|
16
|
-
* once for all load cases. Joint rotations that
|
|
17
|
-
* held by a spring along each null direction, which carries no force.
|
|
16
|
+
* Builds the member and shell matrices of a model that passed `validateFrameModel`, assembles
|
|
17
|
+
* the free stiffness in skyline storage with nodes in reverse Cuthill–McKee order, and
|
|
18
|
+
* factorises it once for all load cases. Joint rotations that nothing resists (e.g. at truss
|
|
19
|
+
* joints) are held by a spring along each null direction, which carries no force.
|
|
18
20
|
*
|
|
19
|
-
* @throws {FrameAnalysisError}
|
|
20
|
-
* a
|
|
21
|
+
* @throws {FrameAnalysisError} 328 if a node connected only to shells has a translation that
|
|
22
|
+
* nothing resists (a membrane's out-of-plane or a plate's in-plane direction), with `nodeId`,
|
|
23
|
+
* `shellId` and `dof`; 304 if the structure is a mechanism; `details` names a node and a DOF
|
|
24
|
+
* involved in it
|
|
21
25
|
*/
|
|
22
26
|
export const prepareFrameSystem = (model) => {
|
|
23
27
|
const { nodes, members, restraints } = model;
|
|
28
|
+
// shell elements: after `expandModel` they carry their area's id
|
|
29
|
+
const shells = (model.shells ?? []);
|
|
24
30
|
const nodeIndex = new Map(nodes.map((n, i) => [n.id, i]));
|
|
25
31
|
const memberIndex = new Map(members.map((m, i) => [m.id, i]));
|
|
32
|
+
const shellIndex = new Map(shells.map((sh, i) => [sh.id, i]));
|
|
26
33
|
const dofCount = 6 * nodes.length;
|
|
27
34
|
const boundary = buildBoundaryConditions(restraints, nodeIndex, dofCount);
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
const point = (id) => {
|
|
36
|
+
const n = nodes[nodeIndex.get(id)];
|
|
37
|
+
return [n.x, n.y, n.z];
|
|
38
|
+
};
|
|
39
|
+
const systemMembers = [];
|
|
40
|
+
const memberGroups = members.map((member) => {
|
|
41
|
+
// pieces between the member's ends and the mesh nodes inside it (see `expandModel`)
|
|
42
|
+
const chain = [member.startNodeId, ...(member.through ?? []), member.endNodeId];
|
|
43
|
+
const whole = memberAxes(point(member.startNodeId), point(member.endNodeId), member.angle ?? 0);
|
|
32
44
|
const { E, G, A, I22, I33, J } = member.section;
|
|
33
|
-
const
|
|
34
|
-
|
|
45
|
+
const pieces = [];
|
|
46
|
+
let offset = 0;
|
|
47
|
+
for (let k = 0; k + 1 < chain.length; k++) {
|
|
48
|
+
const { length, lambda } = chain.length === 2
|
|
49
|
+
? whole
|
|
50
|
+
: memberAxes(point(chain[k]), point(chain[k + 1]), member.angle ?? 0);
|
|
51
|
+
// releases only at the member's own ends
|
|
52
|
+
const releases = memberEndReleases({
|
|
53
|
+
start: k === 0 ? member.releases?.start : undefined,
|
|
54
|
+
end: k === chain.length - 2 ? member.releases?.end : undefined,
|
|
55
|
+
});
|
|
56
|
+
const condensed = condenseMember(beam3dLocalStiffnessRightHanded(E, G, A, I22, I33, J, length), releases);
|
|
57
|
+
pieces.push(systemMembers.length);
|
|
58
|
+
systemMembers.push({
|
|
59
|
+
id: member.id,
|
|
60
|
+
offset,
|
|
61
|
+
section: member.section,
|
|
62
|
+
startIndex: nodeIndex.get(chain[k]),
|
|
63
|
+
endIndex: nodeIndex.get(chain[k + 1]),
|
|
64
|
+
T: transformationMatrix(lambda),
|
|
65
|
+
k: condensed.k,
|
|
66
|
+
hasReleases: releases.length > 0,
|
|
67
|
+
condenseFixedEndForces: condensed.condenseFixedEndForces,
|
|
68
|
+
memberEndDisplacements: condensed.memberEndDisplacements,
|
|
69
|
+
length,
|
|
70
|
+
lambda,
|
|
71
|
+
});
|
|
72
|
+
offset += length;
|
|
73
|
+
}
|
|
35
74
|
return {
|
|
36
75
|
id: member.id,
|
|
76
|
+
pieces,
|
|
37
77
|
section: member.section,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
78
|
+
length: whole.length,
|
|
79
|
+
lambda: whole.lambda,
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
const systemShells = shells.map((shell) => {
|
|
83
|
+
const nodeIndices = shell.nodeIds.map((id) => nodeIndex.get(id));
|
|
84
|
+
const points = nodeIndices.map((n) => [nodes[n].x, nodes[n].y, nodes[n].z]);
|
|
85
|
+
const { thickness, E, nu } = shell.section;
|
|
86
|
+
const m = shell.modifiers ?? {};
|
|
87
|
+
const type = shell.type ?? "shell";
|
|
88
|
+
const element = flatShellElement(points, {
|
|
89
|
+
E,
|
|
90
|
+
nu,
|
|
91
|
+
t: thickness,
|
|
92
|
+
type,
|
|
93
|
+
membraneModifiers: [m.f11 ?? 1, m.f22 ?? 1, m.f12 ?? 1],
|
|
94
|
+
bendingModifiers: [m.m11 ?? 1, m.m22 ?? 1, m.m12 ?? 1],
|
|
95
|
+
}, shell.angle ?? 0);
|
|
96
|
+
return {
|
|
97
|
+
id: shell.id,
|
|
98
|
+
areaId: shell.areaId ?? shell.id,
|
|
99
|
+
nodeIndices,
|
|
100
|
+
type,
|
|
101
|
+
section: shell.section,
|
|
102
|
+
modifiers: m,
|
|
103
|
+
element,
|
|
104
|
+
cornerAreas: cornerAreas(element.axes.corners),
|
|
47
105
|
};
|
|
48
106
|
});
|
|
107
|
+
const shellsByArea = new Map();
|
|
108
|
+
systemShells.forEach((sh, s) => {
|
|
109
|
+
const list = shellsByArea.get(sh.areaId);
|
|
110
|
+
if (list)
|
|
111
|
+
list.push(s);
|
|
112
|
+
else
|
|
113
|
+
shellsByArea.set(sh.areaId, [s]);
|
|
114
|
+
});
|
|
115
|
+
// Everything that adds stiffness, as elements over 6 DOFs per node; members have 2 nodes
|
|
116
|
+
const memberElements = systemMembers.map((m) => ({
|
|
117
|
+
nodes: [m.startIndex, m.endIndex],
|
|
118
|
+
kGlobal: memberGlobalStiffness(m),
|
|
119
|
+
}));
|
|
120
|
+
const shellElements = systemShells.map((sh) => ({
|
|
121
|
+
nodes: sh.nodeIndices,
|
|
122
|
+
kGlobal: sh.element.kGlobal,
|
|
123
|
+
}));
|
|
124
|
+
const elements = [...memberElements, ...shellElements];
|
|
125
|
+
// ---- Translations no shell resists at nodes without members (membrane / plate only) --
|
|
126
|
+
const memberNodes = new Set(systemMembers.flatMap((m) => [m.startIndex, m.endIndex]));
|
|
127
|
+
const shellOnlyNodes = new Set(systemShells.flatMap((sh) => sh.nodeIndices).filter((n) => !memberNodes.has(n)));
|
|
128
|
+
const unresisted = findUnresistedTranslations([...shellOnlyNodes].sort((a, b) => a - b), // issues in model order
|
|
129
|
+
shellElements, boundary);
|
|
130
|
+
if (unresisted.length > 0) {
|
|
131
|
+
throwIssues(unresisted.map(({ node, axis }) => {
|
|
132
|
+
const lead = axis.reduce((best, c, i) => (Math.abs(c) > Math.abs(axis[best]) ? i : best), 0);
|
|
133
|
+
return frameIssue(FrameErrors.SHELL_DOF_UNSUPPORTED, {
|
|
134
|
+
nodeId: nodes[node].id,
|
|
135
|
+
shellId: systemShells.find((sh) => sh.nodeIndices.includes(node))?.id,
|
|
136
|
+
dof: DOF_NAMES[lead],
|
|
137
|
+
});
|
|
138
|
+
}));
|
|
139
|
+
}
|
|
49
140
|
// ---- Equation numbering: nodes in RCM order, fixed DOFs skipped ------------------
|
|
50
141
|
const adjacency = nodes.map(() => []);
|
|
51
|
-
for (const
|
|
52
|
-
|
|
53
|
-
|
|
142
|
+
for (const element of memberElements) {
|
|
143
|
+
for (const a of element.nodes) {
|
|
144
|
+
for (const b of element.nodes)
|
|
145
|
+
if (a !== b)
|
|
146
|
+
adjacency[a].push(b);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// shells share edges: add each neighbour once (members keep their own order unchanged)
|
|
150
|
+
if (shellElements.length > 0) {
|
|
151
|
+
const known = adjacency.map((list) => new Set(list));
|
|
152
|
+
for (const element of shellElements) {
|
|
153
|
+
for (const a of element.nodes) {
|
|
154
|
+
for (const b of element.nodes) {
|
|
155
|
+
if (a !== b && !known[a].has(b)) {
|
|
156
|
+
known[a].add(b);
|
|
157
|
+
adjacency[a].push(b);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
54
162
|
}
|
|
55
163
|
const equation = new Int32Array(dofCount).fill(-1);
|
|
56
164
|
const free = [];
|
|
@@ -63,18 +171,13 @@ export const prepareFrameSystem = (model) => {
|
|
|
63
171
|
}
|
|
64
172
|
}
|
|
65
173
|
}
|
|
66
|
-
const
|
|
67
|
-
const autoRestraints = findAutoRestraints(nodes.length, systemMembers.map((m, i) => ({
|
|
68
|
-
startIndex: m.startIndex,
|
|
69
|
-
endIndex: m.endIndex,
|
|
70
|
-
kGlobal: kGlobal[i],
|
|
71
|
-
})), boundary);
|
|
174
|
+
const autoRestraints = findAutoRestraints(nodes.length, elements, boundary);
|
|
72
175
|
// ---- Profile, assembly and factorisation -----------------------------------------
|
|
73
176
|
let factor = null;
|
|
74
177
|
if (free.length > 0) {
|
|
75
178
|
const first = free.map((_, e) => e);
|
|
76
|
-
const
|
|
77
|
-
for (const eqs of
|
|
179
|
+
const elementEquations = elements.map((el) => elementDofs(el.nodes).map((d) => equation[d]));
|
|
180
|
+
for (const eqs of elementEquations) {
|
|
78
181
|
const active = eqs.filter((e) => e >= 0);
|
|
79
182
|
const low = Math.min(...active);
|
|
80
183
|
for (const e of active)
|
|
@@ -82,14 +185,15 @@ export const prepareFrameSystem = (model) => {
|
|
|
82
185
|
first[e] = low;
|
|
83
186
|
}
|
|
84
187
|
const K = createSkyline(first);
|
|
85
|
-
|
|
86
|
-
//
|
|
87
|
-
|
|
188
|
+
elementEquations.forEach((eqs, index) => {
|
|
189
|
+
// an element's nodes, hence its DOFs, are distinct: each pair and diagonal is added once
|
|
190
|
+
const k = elements[index].kGlobal;
|
|
191
|
+
for (let a = 0; a < eqs.length; a++) {
|
|
88
192
|
if (eqs[a] < 0)
|
|
89
193
|
continue;
|
|
90
|
-
for (let b = 0; b <
|
|
194
|
+
for (let b = 0; b < eqs.length; b++) {
|
|
91
195
|
if (eqs[b] >= eqs[a])
|
|
92
|
-
skylineAdd(K, eqs[a], eqs[b],
|
|
196
|
+
skylineAdd(K, eqs[a], eqs[b], k[a][b]);
|
|
93
197
|
}
|
|
94
198
|
}
|
|
95
199
|
});
|
|
@@ -97,7 +201,7 @@ export const prepareFrameSystem = (model) => {
|
|
|
97
201
|
if (boundary.spring[dof] > 0)
|
|
98
202
|
skylineAdd(K, e, e, boundary.spring[dof]);
|
|
99
203
|
});
|
|
100
|
-
// k·n·nᵀ on the node's free rotations, inside the profile: its
|
|
204
|
+
// k·n·nᵀ on the node's free rotations, inside the profile: its elements span all 6 node DOFs
|
|
101
205
|
for (const { node, axis, stiffness } of autoRestraints) {
|
|
102
206
|
for (let i = 0; i < 3; i++) {
|
|
103
207
|
const ei = equation[6 * node + 3 + i];
|
|
@@ -126,7 +230,11 @@ export const prepareFrameSystem = (model) => {
|
|
|
126
230
|
nodes,
|
|
127
231
|
nodeIndex,
|
|
128
232
|
memberIndex,
|
|
233
|
+
memberGroups,
|
|
129
234
|
members: systemMembers,
|
|
235
|
+
shellIndex,
|
|
236
|
+
shellsByArea,
|
|
237
|
+
shells: systemShells,
|
|
130
238
|
dofCount,
|
|
131
239
|
boundary,
|
|
132
240
|
equation,
|