Script result fields and meshes shown in the window
The scalar a script's field plot colors by, its range, and the outer surface of a result mesh.
How the precision is kept
A field value is turned into one 64-bit number per node or element (a component, a magnitude or von Mises). The range comes from those numbers. The surface positions handed to the view are 32-bit.
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.
One number per node or element from a vector or stress field.
|u| = √(ux² + uy² + uz²); σvm as above
The result array is a Float64Array and the formula runs in 64-bit arithmetic. Math.hypot is used for the vector magnitude. The 6-component case squares the differences and shears in the order written.
cs-ui.js
lines 305 to 318
PartCraft 0.8.1
/** One number per node or element: { values: Float64Array, label }. */
export function fieldScalar(field, comp) {
const c = field.comps || 1, d = field.data, n = Math.floor(d.length / c), out = new Float64Array(n);
if (!(c === 1 || c === 3 || c === 6) || d.length % c) throw new Error(t('script.ui.field.comps'));
if (c === 1) { out.set(d.subarray ? d.subarray(0, n) : d.slice(0, n)); return { values: out, label: '' }; }
const comps = componentsOf(field), key = comps.some(([k]) => k === comp) ? comp : comps[0][0], k = comps.findIndex(([q]) => q === key) - 1;
for (let i = 0; i < n; i++) {
const o = i * c;
if (c === 3) out[i] = key === 'mag' ? Math.hypot(d[o], d[o + 1], d[o + 2]) : d[o + k];
else if (key === 'vm') { const [sx, sy, sz, txy, tyz, tzx] = [d[o], d[o + 1], d[o + 2], d[o + 3], d[o + 4], d[o + 5]]; out[i] = Math.sqrt(0.5 * ((sx - sy) ** 2 + (sy - sz) ** 2 + (sz - sx) ** 2) + 3 * (txy * txy + tyz * tyz + tzx * tzx)); }
else out[i] = d[o + k];
}
return { values: out, label: comps.find(([q]) => q === key)[1] };
}
Range of the plotted values
64-bit
The lowest and highest value that set the color scale.
hi ≤ lo → hi = lo + max(|lo|, 1) × 1e-6
A plain loop over the values; a flat field is widened by a relative 1e-6 so the scale is not zero wide.
cs-ui.js
lines 319 to 325
PartCraft 0.8.1
export function rangeOf(values) {
let lo = Infinity, hi = -Infinity;
for (let i = 0; i < values.length; i++) { const x = values[i]; if (x < lo) lo = x; if (x > hi) hi = x; }
if (!Number.isFinite(lo)) return { lo: 0, hi: 1 };
if (!(hi > lo)) hi = lo + (Math.abs(lo) || 1) * 1e-6;
return { lo, hi };
}
Deformation scale
32-bit, display only
A round scale that makes the largest displacement about 8 percent of the model size.
raw = 0.08 × diagonal ÷ max |u|, rounded up to 1, 2, 5 or 10 × 10ᵉ
The model size is taken from the surface positions, which are 32-bit. The result is only the exaggeration applied when drawing, not a reported number.
cs-ui.js
lines 326 to 336
PartCraft 0.8.1
/** A round deformation scale making the largest displacement about 8 % of the model's size. */
export function autoScale(positions, u, vertNode) {
let lo = [Infinity, Infinity, Infinity], hi = [-Infinity, -Infinity, -Infinity];
for (let i = 0; i < positions.length; i += 3) for (let a = 0; a < 3; a++) { lo[a] = Math.min(lo[a], positions[i + a]); hi[a] = Math.max(hi[a], positions[i + a]); }
const diag = Math.hypot(hi[0] - lo[0], hi[1] - lo[1], hi[2] - lo[2]) || 1;
let m = 0;
for (let v = 0; v < vertNode.length; v++) { const n = vertNode[v]; m = Math.max(m, Math.hypot(u[3 * n], u[3 * n + 1], u[3 * n + 2])); }
if (!(m > 0)) return 1;
const raw = 0.08 * diag / m, e = Math.floor(Math.log10(raw)), b = raw / 10 ** e;
return +(([1, 2, 5, 10].find((s) => s >= b) || 10) * 10 ** e).toPrecision(2);
}
Outer surface of a mesh
32-bit, display only
The outer surface of a solid or surface mesh as triangles for the view.
Positions are copied with Float32Array.from for the view; the node coordinates in the source mesh are not changed. Tetrahedron faces are oriented by the sign of a 64-bit triple product.
cs-ui.js
lines 248 to 249
PartCraft 0.8.1
return build((n) => [N[3 * n], N[3 * n + 1], N[3 * n + 2]], polys, maxLines, m);
}
In detail
Method
Magnitude = hypot of the components; von Mises = √(½((σx−σy)² + (σy−σz)² + (σz−σx)²) + 3(τxy² + τyz² + τzx²)).
Number types
Output Float64Array. The input field data keeps whatever type the script gave it. surfaceOf returns positions as a Float32Array.
Tolerances
A range with no width is widened by 1e-6 of its size (or of 1 if the value is 0). The deformation scale is rounded to 2 significant digits of 1, 2, 5 or 10 times a power of ten.
Limits
The surface positions are 32-bit copies of the mesh nodes and are for drawing.
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.