The axial force, shears, torque, bending moments and deflected shape along each member, and the largest values the report and the design checks read.
How the precision is kept
Internal forces at a cut are exact statics from the member's end forces and the loads up to the cut, in 64-bit numbers. The deflection is the curvature integrated twice by the trapezoid rule on a grid 16 times finer than the stations. Largest values are the largest of the station values, so the number of stations sets how closely a peak between two stations is caught.
Open item. Add the points of zero shear and the point load positions to the stations, so the reported maximum moment is the true one and not the largest station value.
Calculations under this policy
4 calculations in 1 source file. The code is read from the released app when this page loads. It is the calculation people run, not a copy kept for this page.
N, Vy, Vz, T, My and Mz at a distance x from the member's start.
S = −(F_i + ∫₀ˣ q); M = −(M_i + r × F_i + Σ r × q)
The distributed part is integrated by four Gauss points from the load's start to the cut each time; the integrand is at most quadratic, so the rule is exact up to rounding. A point load is counted when it lies more than 1e-9 mm before the cut, or within 1e-9 mm of it at the member's far end.
frame/frame-solve.js
lines 481 to 498
CadCraft 0.8.2
const at = (x) => {
const S = [-end[0], -end[1], -end[2]];
const Ms = [-end[3], -(end[4] + x * end[2]), -(end[5] - x * end[1])];
for (const pz of loads) {
const c = pz.comp;
const force = (s, q) => { // q along local axis c at s ≤ x; r = (s − x, 0, 0)
S[c] -= q;
if (c === 1) Ms[2] -= (s - x) * q;
else if (c === 2) Ms[1] += (s - x) * q;
};
if (pz.kind === 'point') { if (pz.a < x - 1e-9 || (pz.a <= x + 1e-9 && x >= L - 1e-9)) force(pz.a, pz.P); continue; }
const a = pz.a, b = Math.min(pz.b, x);
if (b <= a) continue;
const h = (b - a) / 2;
for (const [g, wt] of GAUSS4) { const s = a + h * (g + 1); force(s, (pz.w1 + (pz.w2 - pz.w1) * (s - pz.a) / (pz.b - pz.a)) * wt * h); }
}
return { N: S[0], Vy: S[1], Vz: S[2], T: Ms[0], My: -Ms[1], Mz: Ms[2], MSy: Ms[1], MSz: Ms[2] };
};
Deflection along the member
64-bit
The member's displacement between its ends, from its curvature.
v″ = M_z ÷ (E I_z); w″ = −M_y ÷ (E I_y); u′ = N ÷ (E A); trapezoids, twice
The grid has max(8, n) × 16 intervals, so 640 for the report's 40 stations. The trapezoid rule is not exact for the curved moment diagram of a loaded member; its error falls with the square of the grid spacing. The integration constants are fixed by making both ends match the node displacements.
The values kept at each station, and how far the member bows from the straight line between its ends.
rel = √(v_rel² + w_rel²); v_rel = v − v_end × x ÷ L
Every sixteenth grid point is kept. The bow is one Math.hypot of the two transverse parts after the end value's straight line is taken off.
frame/frame-solve.js
lines 517 to 523
CadCraft 0.8.2
for (let k = 0; k <= nf; k += nf / n) {
const a = acts[k], x = xs[k];
out.x.push(x); out.N.push(a.N); out.Vy.push(a.Vy); out.Vz.push(a.Vz); out.T.push(a.T); out.My.push(a.My); out.Mz.push(a.Mz);
out.dx.push(uF(k)); out.dy.push(vF(k)); out.dz.push(wF(k));
const rv = dv[k] - dv[nf] * x / L, rw = dw[k] - dw[nf] * x / L;
out.rel.push(Math.hypot(rv, rw));
}
Largest and smallest values along a member
64-bit
The maximum and minimum of each internal force, where they occur, and the largest deflection with its span ratio.
max and min over the stations; ratio = L ÷ deflection
The extremes are the largest and smallest station values, 41 stations by default; a peak between two stations is not searched for. The ratio L ÷ deflection is given when the deflection exceeds 1e-12 mm, an absolute limit.
frame/frame-solve.js
lines 527 to 541
CadCraft 0.8.2
/** Largest and smallest of each action along a member, and its largest deflection off the chord. */
export function memberExtremes(prep, R, m, n = 40) {
const d = diagram(prep, R, m, n);
const ext = {};
for (const key of ['N', 'Vy', 'Vz', 'T', 'My', 'Mz']) {
let max = -Infinity, min = Infinity, xMax = 0, xMin = 0;
d[key].forEach((v, k) => { if (v > max) { max = v; xMax = d.x[k]; } if (v < min) { min = v; xMin = d.x[k]; } });
ext[key] = { max, min, xMax, xMin, abs: Math.max(Math.abs(max), Math.abs(min)) };
}
let v = 0, xv = 0;
d.rel.forEach((r, k) => { if (r > v) { v = r; xv = d.x[k]; } });
const L = prep.mem[m].ax.L;
ext.defl = { value: v, x: xv, ratio: v > 1e-12 ? L / v : Infinity };
return ext;
}
In detail
Method
Statics from the i end with 4-point Gauss–Legendre quadrature for distributed loads; trapezoid rule twice for the deflection, then a straight-line correction so both ends match the node displacements.
Number types
64-bit numbers in plain arrays; end forces and displacements read from Float64Array.
Tolerances
A point load counts at a cut when it lies more than 1e-9 mm before it (absolute). The span-to-deflection ratio is given only when the deflection exceeds 1e-12 mm.
Limits
Extremes are taken at the stations only: 41 for the report, 49 for the steel checks, 25 for the concrete checks. The deflection grid has 16 intervals per station interval.
Approach: 64-bit, stated limit
The arithmetic is 64-bit, but the method or the data sets the accuracy: a solver tolerance, a mesh, a step size, a datum shift, a table. The limit is stated where the result is shown.