Resources Numerical accuracy Calculation policy

Material packs: property curves by temperature

Returns a material property at a temperature from a pack's fitted curve, with its unit, valid range and fit error.

How the precision is kept

The value is a published curve fit evaluated in 64-bit; the fit's own error, a fraction stored with each curve, sets the accuracy rather than the arithmetic. Polynomials are evaluated by Horner's rule. A temperature outside the curve's range is refused, never extrapolated.

Calculations under this policy

3 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.

engineer/material-pack.js PartCraft 0.8.1 64-bit 3 calculations Reviewed

Tests tools/engineer-test/materials.mjs

Power and logarithm used

64-bit

Which power and logarithm functions the curves are evaluated with.

When the host object F provides dpow and dlog10 they are used; otherwise the engine's Math.pow and Math.log10.

  • engineer/material-pack.js
  • lines 21 to 22
  • PartCraft 0.8.1
const pow10 = (x) => (F.dpow ? F.dpow(10, x) : Math.pow(10, x));
const log10 = (x) => (F.dlog10 ? F.dlog10(x) : Math.log10(x));

One curve segment

64-bit

The fitted curve's value at a temperature.

y = 10^(Σ cᵢ Lⁱ), L = log10 T; or y = c₀ + T(c₁ + T(c₂ + T(c₃ + T c₄)))

Horner's rule from the highest coefficient down. In the first form the result is 10 raised to the polynomial, so a rounding error δ in the exponent becomes a relative error of about 2.3 × δ in the value. Below tlow the second form returns the stored constant.

  • engineer/material-pack.js
  • lines 64 to 69
  • PartCraft 0.8.1
function evalSeg(s, T) {
  const c = s.coeffs;
  if (s.form === 'log10poly') { const L = log10(T); let a = 0; for (let i = c.length - 1; i >= 0; i--) a = a * L + c[i]; return pow10(a); }
  if (s.tlow != null && T < s.tlow) return s.below;
  return c[0] + T * (c[1] + T * (c[2] + T * (c[3] + T * c[4])));
}

Property at a temperature

64-bit

The property value with its unit, range, fit error and source.

value = curve(T) × scale

T must lie between the first segment's lower limit and the last segment's upper limit, or the call is refused. The segment is the first whose range contains T, so at a shared limit the lower segment is used. The value is the curve times scale, one multiplication.

  • engineer/material-pack.js
  • lines 71 to 85
  • PartCraft 0.8.1
export function materialAt(pack, id, prop, T) {
  const m = pack && pack.materials && pack.materials[id];
  if (!m) throw new EngError('material', { what: 'material', id });
  const p = m.properties[prop];
  if (!p) throw new EngError('material', { what: 'property ' + prop + ' of ' + id, id, prop });
  const lo = p.segments[0].range[0], hi = p.segments[p.segments.length - 1].range[1];
  if (!isNum(T) || T < lo || T > hi) throw new EngError('range', { what: m.name + ' ' + p.name + ' temperature (K)', value: T, lo, hi });
  const s = p.segments.find((g) => T >= g.range[0] && T <= g.range[1]);
  return {
    value: evalSeg(s, T) * p.scale, unit: p.unit, T,
    fitError: p.fitError, range: [lo, hi],
    ref: 'NIST Cryogenics Technologies Group, ' + m.page + ' (' + p.name + ', ' + s.form + ' fit, ' + (p.fitError * 100) + '% vs data, accessed ' + pack.source.accessed + ')',
    pack: { id: pack.id, version: pack.packVersion },
  };
}

In detail

Method
log10poly: y = 10^(a + bL + … + iL⁸) with L = log10 T. poly4: y = a + bT + cT² + dT³ + eT⁴, with a constant below tlow. Value = y × scale.
Number types
64-bit numbers. Power and logarithm come from the host's dpow and dlog10 when it provides them, otherwise Math.pow and Math.log10.
Tolerances
Range limits are compared exactly: T below the lowest limit or above the highest is refused.
Limits
The fit error stored in the pack is returned with every value.

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.

Every policy that takes this approach