The values printed in the analysis and design report tables, which are also what the CSV and PDF downloads contain.
How the precision is kept
The report reads the solver's 64-bit results and rounds them only when it writes the text of a cell. The same rounded text goes to the page, the CSV file and the PDF, so the downloads carry two or three decimals in kN, kN·m, mm and mrad, not the full values.
Open item. Offer the CSV download with the unrounded 64-bit values, since it is the file other programs read.
Calculations under this policy
10 calculations in 5 source files. 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.
The value is rounded with Math.round and then written with toFixed. Only the text is rounded; the ratio that decides pass or fail is computed from the full values.
Rounded with Math.round after a multiplication by a power of ten, then written with toFixed. Used for periods (3 decimals), Cs (4), forces in kN (0 or 1) and drifts in mm (1 or 2).
For each slab or wall: its largest deflection, its largest positive and negative moments, twisting moment and shear.
max and min of the plates' center values; Q = √(Qx² + Qy²); w = largest node displacement; kN·m/m = N·mm/mm ÷ 1000, 2 decimals
Moments and shears are the plate center values, not the smoothed node values the colored view shows. They are written with toFixed(2) after one division by 1000.
frame/plate-draw.js
lines 61 to 82
CadCraft 0.8.2
export function plateTables(model, sol, key, t) {
const R = sol?.results?.[key], pl = sol?.prep?.shell?.pl;
if (!R || !pl?.length) return [];
const groups = new Map();
model.plates.forEach((p, k) => { const g = p.from?.ref || p.id.split('.p')[0]; if (!groups.has(g)) groups.set(g, []); groups.get(g).push(k); });
const kNm = (v) => (v / 1e3).toFixed(2), kN = (v) => (v / 1e3).toFixed(2);
const rows = [];
for (const [g, list] of groups) {
let w = 0, mx = [0, 0], my = [0, 0], mxy = 0, q = 0;
for (const k of list) {
const c = plateCentre(sol.prep, R, k);
mx = [Math.max(mx[0], c[3]), Math.min(mx[1], c[3])]; my = [Math.max(my[0], c[4]), Math.min(my[1], c[4])];
mxy = Math.max(mxy, Math.abs(c[5])); q = Math.max(q, Math.hypot(c[6], c[7]));
for (const nd of pl[k].nodes) w = Math.max(w, Math.hypot(R.u[6 * nd], R.u[6 * nd + 1], R.u[6 * nd + 2]));
}
rows.push([g, String(list.length), (model.plates[list[0]].t).toFixed(0), w.toFixed(2), kNm(mx[0]), kNm(mx[1]), kNm(my[0]), kNm(my[1]), kNm(mxy), kN(q)]);
}
/* i18n-ignore-start: column heads that are symbols / units */
return [{ title: t('frame.pl.title'), head: [t('frame.pl.element'), t('frame.pl.n'), 't (mm)', 'w (mm)', 'Mx+ (kN·m/m)', 'Mx− (kN·m/m)', 'My+ (kN·m/m)', 'My− (kN·m/m)', '|Mxy| (kN·m/m)', 'Q (kN/m)'], numeric: [1, 2, 3, 4, 5, 6, 7, 8, 9], rows },
{ title: t('frame.pl.about'), head: [t('frame.rep.item'), t('frame.rep.value')], numeric: [], rows: [[t('frame.pl.method'), t('frame.pl.method-text')], [t('frame.pl.limits'), t('frame.pl.limits-text')]] }];
/* i18n-ignore-end */
}
Unit change by one division (N to kN, N·mm to kN·m, rad to mrad), then fixed decimals.
Number types
64-bit numbers until the text is written.
Tolerances
A value smaller than half of the last printed decimal is written as 0, so no cell reads −0.00.
Limits
Forces 0.01 kN, moments 0.01 kN·m, displacements 0.01 mm, rotations 0.001 mrad, utilization 0.1 %. Section properties are printed in cm units to 1 or 2 decimals.
Approach: 64-bit, direct
Every value is a 64-bit number from input to result. Formulas are closed form or a direct solve, and every comparison uses a stated tolerance.