PRO SECTIONFREE plan — full report is locked. The multi-cable trench editor is free on this calculator; the full .docx report requires a licence — an admin invitation unlocks it for your account.
Calculator #004 IEC 60287 series IEC 60228 / 60502 IEC 60949 SC UAE · GCC · UK · EU

Cable Ampacity — continuous current rating

Continuous current rating Iz of power cables per IEC 60287-1-1, -1-2, -1-3, -2-1, -2-2 and -3-1. Skin and proximity effects, dielectric losses, sheath and armour loss factors, thermal resistances T1…T4, conductor-temperature back-calculation at user load, thermal short-circuit withstand per IEC 60949. Direct-buried and in-air installations, regional defaults for UAE / GCC / UK / EU.
Developed by the ieccalc.com engineering team
← All calculators
PRO Multi-cable trench cross-section CAD — free · full report is PRO. The graphical layout editor below (soil layer stack with drag-to-reorder, mutual heating, λ₁ screen-loss, two-zone backfill T₄, conductor-temperature heatmap) is open to everyone. A licence adds the full .docx report: IEC 60502-2 Annex B cross-validation grid, distances matrix, per-cable derivation and the embedded canvas snapshot.
Cable Ampacity — Trench CAD multi-cable cross-section · IEC 60287 · Neher-McGrath
45%
Trench
Add
IEC 60502-2 Annex B
Buried direct, screens bonded both ends
Demo example. Editing of cables, layers and IEC presets is locked for the showcase. Calculate works on the example below; Download PRO below produces a watermarked EXAMPLE report. Upgrade to a paid licence to unlock editing and clean reports.
LMB: pan/drag · Shift: box · Scroll: zoom · Del: delete · Click layer · Drag boundary to swap
Click cable or layer
LMB empty: pan
Shift: box select
Scroll: zoom · Del: delete
FREE Single cable, parametric input. IEC 60287 closed-form ampacity, conductor-temperature back-calc at user load, IEC 60949 short-circuit withstand, compact .docx report. Always visible — every visitor of ieccalc.com sees this section.

1 — Cable construction

2 — Installation

3 — Operating conditions

4 — Advanced overrides (optional)
By default all dimensions are estimated from IEC 60228 + IEC 60502 typical values. Override here if you have a specific cable datasheet.

A — Steady-state ampacity Iz

Continuous current rating Iz A
Active power transferable (3-φ)
Conductor max temperature θc,max
Reference ambient θamb
Allowed temperature rise Δθ
Number of load-carrying cores n

B — Loss components (per metre, per phase)

DC resistance R20 @ 20 °C
DC resistance R' @ θc,max
Skin-effect factor ys
Proximity-effect factor yp
AC resistance R
Dielectric capacitance C
Dielectric loss Wd
Sheath loss factor λ₁
Armour loss factor λ₂
Conductor loss Wc at Iz
Sheath loss Ws at Iz
Armour loss Wa at Iz
Total losses Wt at Iz

C — Thermal resistances

T₁ insulation [K·m/W]
T₂ bedding (sheath ↔ armour) [K·m/W]
T₃ outer covering [K·m/W]
T₄ external [K·m/W]
Estimated cable diameter De [mm]
Conductor diameter dc [mm]
Insulation thickness t₁ [mm]
Sheath ext. dia D's [mm]
Geometric u = 2L/De

D — Conductor temperature at user load

θc at Iload °C
Conductor loss Wc(Iload)
Sheath loss Ws(Iload)
Total losses Wt(Iload)
Margin to limit θc,max
Verdict

E — Thermal short-circuit withstand (IEC 60949)

k constant (initial→final, material/insulation)
Permissible adiabatic I·√t [kA·√s]
Permissible ISC for given tSC
Permissible time at given I"k
Verdict

F — Project completeness & overall verdict

ItemStatus
Formulas & methodology — IEC 60287 / IEC 60949
I = √( (Δθ − Wd·[½T₁ + n·(T₂+T₃+T₄)]) / (R·T₁ + n·R·(1+λ₁)·T₂ + n·R·(1+λ₁+λ₂)·(T₃+T₄)) )
Continuous current rating per IEC 60287-1-1 Eq. 1 (100 % load factor).
θc = θamb + Wd·(½T₁ + n(T₂+T₃+T₄)) + I²R·(T₁ + n(1+λ₁)T₂ + n(1+λ₁+λ₂)(T₃+T₄))
Conductor temperature back-calculation at user load — same Eq. 1 solved for θc at given I.
ISC,perm = k · S / √tSC
Adiabatic thermal short-circuit withstand per IEC 60949 §3.1; k constant is material/insulation specific.
Validation tests (IEC 60287 worked examples + reciprocal checks)
Click "Run validation" below to execute the test suite.
"); w.document.close();} } // === PUBLIC SNAPSHOT for PRO .docx === function getSnapshot(){ if(!S.result) return null; const canvas=cvRef; let pngDataUrl=null; if(canvas){try{pngDataUrl=canvas.toDataURL("image/png");}catch(e){pngDataUrl=null;}} const distRows=[]; const pw=S.result.pw; for(let i=0;i new Paragraph({ children:[ new TextRun({ text:txt, bold: !!opts.bold, italics: !!opts.italic, size: opts.size || 20 }) ], heading: opts.heading, spacing: { after: opts.after ?? 80 }, alignment: opts.align }); const subhead = (txt) => para(txt, { bold:true, size:22, after:120 }); const cellBorder = {style:BorderStyle.SINGLE, size:4, color:"888888"}; const cellBorders = {top:cellBorder,bottom:cellBorder,left:cellBorder,right:cellBorder,insideHorizontal:cellBorder,insideVertical:cellBorder}; const tableRow = (k, v) => new TableRow({ children:[ new TableCell({ width:{size:55,type:WidthType.PERCENTAGE}, children:[new Paragraph({children:[new TextRun({text:k, size:18})]})] }), new TableCell({ width:{size:45,type:WidthType.PERCENTAGE}, children:[new Paragraph({children:[new TextRun({text:String(v), size:18, bold:true})]})] }) ] }); const T = (rows) => new Table({width:{size:100,type:WidthType.PERCENTAGE}, rows, borders:cellBorders}); const headerRow = (cells) => new TableRow({tableHeader:true, children:cells.map(c=> new TableCell({children:[new Paragraph({children:[new TextRun({text:c, size:16, bold:true})]})]}))}); const dataRow = (cells) => new TableRow({children:cells.map(c=> new TableCell({children:[new Paragraph({children:[new TextRun({text:String(c), size:16})]})]}))}); const wideTable = (header, rows) => new Table({width:{size:100,type:WidthType.PERCENTAGE}, rows:[headerRow(header), ...rows.map(dataRow)], borders:cellBorders}); // === Sections 1–6: same as FREE === const inputsRows = [ tableRow("Conductor", MAT[I.material].name + " " + I.S + " mm² (" + I.design + ")"), tableRow("Cores", I.cores.toString()), tableRow("Insulation", INS[I.insulation].name + ", U₀/U = " + I.U0 + "/" + (I.U0===0.6?1:Math.round(I.U0/0.6)) + " kV"), tableRow("Construction", I.construct.replace(/_/g," ")), tableRow("Sheath / screen",I.sheath.replace(/_/g," ")), tableRow("Armour", I.armour.toUpperCase()), tableRow("Outer jacket", I.jacket), tableRow("Installation", I.instMethod.replace(/_/g," ") + (I.instMethod==="buried" ? ", L = "+I.depth_m+" m" : "")), tableRow("Formation", I.formation.replace(/_/g," ")), tableRow("Circuits", I.nCircuits + " (spacing "+I.circuitSpacing_mm+" mm)"), tableRow("Soil ρ_T", I.soilRho + " K·m/W"), tableRow("Reference ambient temp", I.ambTemp + " °C"), tableRow("System frequency", I.freq + " Hz"), tableRow("Bonding", I.bonding), tableRow("Conductor max temp", r.theta_c + " °C") ]; const geomRows = [ tableRow("Conductor diameter d_c", r.geo.d_c.toFixed(2) + " mm"), tableRow("Insulation thickness t₁", r.geo.t_1.toFixed(2) + " mm"), tableRow("Diameter over insulation",r.geo.D_over_ins.toFixed(2) + " mm"), tableRow("Sheath thickness t_s", r.geo.t_s.toFixed(2) + " mm"), tableRow("Diameter over sheath", r.geo.D_over_sh.toFixed(2) + " mm"), tableRow("Armour wire ⌀", r.geo.t_a ? r.geo.t_a.toFixed(2) + " mm" : "—"), tableRow("Diameter over armour", r.geo.D_over_armour.toFixed(2) + " mm"), tableRow("Outer jacket t₃", r.geo.t_3.toFixed(2) + " mm"), tableRow("External diameter D_e", r.geo.D_e.toFixed(2) + " mm") ]; const lossRows = [ tableRow("R₂₀ (DC)", (r.R20_per_km).toExponential(3) + " Ω/km"), tableRow("R' DC at θ_c", (r.R_dc_per_m_theta*1000).toExponential(3) + " Ω/km"), tableRow("Skin factor y_s", r.ys.toFixed(4)), tableRow("Proximity factor y_p", r.yp.toFixed(4)), tableRow("R AC at θ_c", (r.R_ac*1000).toExponential(3) + " Ω/km"), tableRow("Capacitance C", (r.C*1e9).toFixed(3) + " nF/m"), tableRow("Dielectric loss W_d", r.Wd.toExponential(3) + " W/m/φ"), tableRow("λ₁ sheath loss factor", r.lam1.toFixed(4)), tableRow("λ₂ armour loss factor", r.lam2.toFixed(4)), tableRow("T₁ insulation", r.T1.toFixed(4) + " K·m/W"), tableRow("T₂ bedding", r.T2.toFixed(4) + " K·m/W"), tableRow("T₃ outer jacket", r.T3.toFixed(4) + " K·m/W"), tableRow("T₄ external", r.T4.toFixed(4) + " K·m/W") ]; const resultsRows = [ tableRow("Continuous ampacity I_z", Math.round(r.I_z) + " A"), tableRow("Conductor losses W_c at I_z",r.Wc_z.toFixed(2) + " W/m/φ"), tableRow("Sheath losses W_s at I_z", r.Ws_z.toFixed(3) + " W/m/φ"), tableRow("Armour losses W_a at I_z", r.Wa_z.toFixed(3) + " W/m/φ"), tableRow("Total losses W_t at I_z", r.Wt_z.toFixed(2) + " W/m/φ") ]; const exampleBanner = isExample ? [ new Paragraph({ alignment: AlignmentType.CENTER, shading: { type: ShadingType.SOLID, color: "FFE0E0", fill: "FFE0E0" }, children:[new TextRun({ text:"⚠ EXAMPLE — DEMO MODE — NOT FOR ENGINEERING USE ⚠", bold:true, color:"C00000", size:36 })], spacing:{after:120} }), para("This report was generated from the showcase example shipped with the calculator. Cable layout, layer stack and IEC presets were not user-edited. Do not use the values below for any real project. Purchase a PRO licence to unlock editing and to download a clean (non-watermarked) report.", {italic:true, align:AlignmentType.CENTER, after:240, size:18}) ] : []; const children = [ ...exampleBanner, new Paragraph({ heading:HeadingLevel.TITLE, children:[new TextRun({text:"Cable Ampacity — PRO Report" + (isExample?" (EXAMPLE)":""), bold:true, size:32, color: isExample?"C00000":"000000"})], alignment:AlignmentType.CENTER }), para("Per IEC 60287-1-1, -1-2, -2-1, -2-2 and -3-1; IEC 60228 conductor data; IEC 60949 short-circuit withstand; IEC 60502-2 Annex B reference cross-validation.", { italic:true, align:AlignmentType.CENTER, after:300 }), para("Date: " + new Date().toISOString().slice(0,10), { after:100 }), para("Calculator: ieccalc.com/004 — Cable Ampacity (PRO tier — full report with trench layout, distance matrix, per-cable derivation, IEC reference cross-validation).", { italic:true, after:200 }), subhead("1. Cable construction & site parameters"), T(inputsRows), para(" "), subhead("2. Estimated cable geometry (IEC 60228 / IEC 60502 typical)"), T(geomRows), para(" "), subhead("3. Electrical and thermal parameters"), T(lossRows), para(" "), subhead("4. Steady-state ampacity I_z"), T(resultsRows), para(" ", {after:60}), para("I_z = √( (Δθ − W_d·[½T₁ + n·(T₂+T₃+T₄)]) / (R·T₁ + n·R·(1+λ₁)·T₂ + n·R·(1+λ₁+λ₂)·(T₃+T₄)) )", { italic:true, after:80 }), para("(IEC 60287-1-1 Eq. 1; n = "+r.n+" load-carrying conductors)", { italic:true, after:200 }) ]; if(I.iLoad > 0){ children.push(subhead("5. Conductor temperature at user load")); children.push(T([ tableRow("User load I_load", I.iLoad + " A"), tableRow("Conductor losses W_c(I_load)",r.Wc_load.toFixed(2) + " W/m/φ"), tableRow("Total losses W_t(I_load)", r.Wt_load.toFixed(2) + " W/m/φ"), tableRow("Conductor temperature θ_c", r.theta_at_load.toFixed(1) + " °C"), tableRow("Limit θ_c,max", r.theta_c + " °C"), tableRow("Ratio θ_c,max / θ_c", (r.theta_c/r.theta_at_load).toFixed(3)), tableRow("Verdict", r.theta_at_load <= r.theta_c ? "PASS" : "FAIL") ])); children.push(para(" ")); } if(r.sc){ children.push(subhead("6. Thermal short-circuit withstand (IEC 60949)")); children.push(T([ tableRow("k constant ("+I.material+"/"+I.insulation+")", r.k_sc.toString()), tableRow("S × k = adiabatic I·√t", (r.k_sc * I.S / 1000).toFixed(2) + " kA·√s"), tableRow("User I\"_k", I.iScKa + " kA"), tableRow("User t_SC", I.tScSec + " s"), tableRow("Permissible I_SC for given t_SC", (r.sc.Iperm_A/1000).toFixed(2) + " kA"), tableRow("Permissible time at user I\"_k", r.sc.tperm_s.toFixed(3) + " s"), tableRow("Verdict", ((r.sc.Iperm_A/1000)>=I.iScKa) ? "PASS" : "FAIL") ])); children.push(para("I_SC,perm = k · S / √t (IEC 60949 §3.1, adiabatic).", { italic:true, after:200 })); } // === Sections 7+: PRO-only — trench CAD data === const snap = (typeof Trench !== "undefined") ? Trench.getSnapshot() : null; if(snap){ children.push(subhead("7. Trench cross-section — geometry")); children.push(T([ tableRow("Trench width", snap.trench.effW + " mm (left "+snap.trench.trL+" → right "+snap.trench.trR+")"), tableRow("Trench depth", snap.trench.effD + " mm"), tableRow("System frequency", snap.trench.freq + " Hz"), tableRow("Number of cables (any type)", snap.cables.length), tableRow("Number of power cables", snap.result.pw.length) ])); children.push(para(" ")); if(snap.pngDataUrl){ try{ const base64=snap.pngDataUrl.split(",")[1]; const bin=atob(base64); const len=bin.length; const bytes=new Uint8Array(len); for(let i=0;i[i+1, ly.soilIdx, ly.from, ly.to, ly.rho, (ly.temp!=null?ly.temp:25)]); children.push(wideTable(soilHeader, soilRows)); children.push(para(" ")); children.push(subhead("9. Cable layout")); const cabHeader=["Label","Type","S, mm²","Mat","Ins","V class","Constr.","Screen","X, mm","Depth, mm","D_e, mm","Tmax, °C","I_w, A"]; const cabRows = snap.result.pw.map(c=>[ c.label, c.type, c.size, c.mat, c.ins, c.vc, c.con, c.screen?"Yes":"No", c.x, c.y, snap.getDe(c).toFixed(1), c.maxT||90, c.Iw||"—" ]); children.push(wideTable(cabHeader, cabRows)); children.push(para(" ")); children.push(subhead("10. Cable-to-cable distances (m)")); const distHdr=[""].concat(snap.result.pw.map(c=>c.label)); const distRows = snap.result.pw.map((c,i)=>[c.label].concat(snap.distRows[i])); children.push(wideTable(distHdr, distRows)); children.push(para(" ")); children.push(subhead("11. Per-cable derivation (Trench CAD)")); snap.result.pw.forEach((c,i)=>{ const ri=snap.result.gr[i]; const isi=snap.result.iso[i]; if(!ri||!ri.conv) return; const ce = (function(){for(let li=0;li=snap.layers[li].from&&c.y0 ? isi.I.toFixed(1)+" A" : "—"), tableRow("Mutual-heating reduction df", isi&&isi.I>0 ? (ri.I/isi.I).toFixed(3) : "—"), tableRow("θ_c at I_w = "+((c.Iw>0)?c.Iw.toFixed(0):ri.I.toFixed(0))+" A", ri.TcWork.toFixed(1)+" °C"), tableRow("Verdict (θ_c ≤ θ_max="+ (c.maxT||90)+" °C)", ri.TcWork <= (c.maxT||90) ? "PASS" : "FAIL") ])); children.push(para(" ")); }); if(snap.iec.refValue){ children.push(subhead("12. IEC 60502-2 Annex B cross-validation")); const iecHdr=["Cable","IEC ref, A","Calculated, A","Δ, %","Verdict"]; const iecRows = snap.result.pw.map((c,i)=>{ const ri=snap.result.gr[i]; if(!ri||!ri.conv) return null; const dPct = ((ri.I-snap.iec.refValue)/snap.iec.refValue*100); return [c.label, snap.iec.refValue, ri.I.toFixed(0), dPct.toFixed(1), Math.abs(dPct)<10?"OK":"REVIEW"]; }).filter(Boolean); children.push(wideTable(iecHdr, iecRows)); children.push(para("IEC reference conditions: Table "+snap.iec.table+", "+snap.iec.size+" mm², "+snap.iec.arrange+(snap.iec.circuits>1?", "+snap.iec.circuits+" circuits ×B.19":"")+", buried "+snap.iec.depth+" mm, ρ="+snap.iec.rho+" K·m/W, ground "+snap.iec.envT+" °C, screens bonded both ends.", {italic:true, after:200})); } } children.push(subhead("Standards & methodology — PRO tier")); children.push(para("This PRO report includes: parametric IEC 60287 cable rating, full trench layout with multi-cable mutual heating, per-cable conductor-temperature back-calc, distance matrix, IEC 60502-2 Annex B cross-validation, and a colour heatmap of the steady-state temperature field.")); children.push(para("• Skin and proximity per IEC 60287-1-1 §2.1 (k_s, k_p as per design class).")); children.push(para("• Sheath loss factor λ₁ for both-ends bonded systems via the simplified Eq. 32 reduced form (cross-bonding eddy term λ₁\" of IEC 60287-1-2 not modelled).")); children.push(para("• Thermal resistances T₁, T₃ per IEC 60287-2-1 closed form; T₄ uses the two-zone backfill model per IEC 60287-2-1 §2.2.7.2 with native-soil mutual heating (image method).")); children.push(para("• Conductor-temperature at user load uses I²R quadratic scaling: θ_c(I_w) = θ_env + (I_w/I_z)²·Δθ + ΔT_d.")); children.push(para("• Heatmap is computed from the same image-method potential field; intended for visual comparison of competing layouts.")); children.push(para("• Cyclic ratings per IEC 60853, full magnetic-armour modelling for arbitrary geometry, in-duct configurations, and Heidler-pulse transient ratings remain open development items.")); // Header / footer with EXAMPLE marker on every page when isExample const sectionProps = isExample ? { properties:{}, headers:{ default: new Header({ children:[new Paragraph({alignment:AlignmentType.CENTER, children:[new TextRun({text:"EXAMPLE — DEMO MODE — NOT FOR ENGINEERING USE", bold:true, color:"C00000", size:18})]})]}) }, footers:{ default: new Footer({ children:[new Paragraph({alignment:AlignmentType.CENTER, children:[new TextRun({text:"EXAMPLE report from ieccalc.com showcase — do not use for engineering decisions.", italics:true, color:"C00000", size:16})]})]}) }, children } : { properties:{}, children }; const doc = new Document({ creator:"ieccalc.com", title:"Cable Ampacity PRO Report" + (isExample?" (EXAMPLE)":""), sections:[sectionProps] }); const blob = await Packer.toBlob(doc); const fname = (isExample?"EXAMPLE_":"") + "cable_ampacity_PRO_" + I.material + I.S + "_U0_" + I.U0 + "kV_Iz" + Math.round(r.I_z||0) + "A.docx"; saveAs(blob, fname); } /* ============================================================ Tier state: paints the page for whatever this account is entitled to. Called on load and whenever the licence changes. ============================================================ */ function tdbApplyState(){ // Real entitlement: License resolves admin rights and granted licences // (see _lib/license.js). The dev hash still works for local testing. const isPro = (window.License && License.canUseFeature("trench_cad")) || /dev=(day|month|year|lifetime)/.test(location.hash || ""); // The trench cross-section editor is open to everyone on this calculator; only the // full .docx report stays licence-gated. const TRENCH_FREE = true; const trenchOpen = isPro || TRENCH_FREE; const stateEl = document.getElementById("tdbState"); const btnEl = document.getElementById("tdbToggle"); const trEl = document.getElementById("trenchCAD"); const proSec = document.querySelector("details.tier-section.pro"); const freeSec = document.querySelector("details.tier-section.free"); const proBtns = ["btnDocxPro"]; if(stateEl){ stateEl.textContent = isPro ? "PRO features unlocked for this account" : "FREE plan — full report is locked"; stateEl.className = isPro ? "tdb-state-pro" : "tdb-state-free"; } if(btnEl) btnEl.hidden = true; // no self-service switch any more // Entitled: the trench editor is fully live. Otherwise it stays visible // but inert, so the engineer can see what the licence buys. if(trEl){ if(trenchOpen){ trEl.classList.remove("demo-locked"); trEl.classList.remove("locked"); trEl.style.opacity="1"; trEl.style.pointerEvents="auto"; } else { trEl.classList.remove("demo-locked"); trEl.classList.add("locked"); trEl.style.opacity="0.55"; trEl.style.pointerEvents="none"; } } if(proSec){ // The trench editor inside this section is free, so keep it open and fully legible; // the licence-gated pieces (full report) signal themselves via their disabled buttons. proSec.open = true; proSec.style.opacity = "1"; } if(freeSec){ // FREE block stays closed by default in PRO view, opens automatically when toggling to FREE if(!isPro){freeSec.open = true;} } proBtns.forEach(id=>{const el=document.getElementById(id); if(el){el.disabled = !isPro; el.title = isPro?"":"PRO feature — toggle Demo PRO above to test";}}); } function tdbBindToggle(){ const btn = document.getElementById("tdbToggle"); if(!btn) return; btn.addEventListener("click", () => { const isPro = !location.hash.match(/dev=free/); if(isPro){ // switch to FREE: clear dev hash, force License.refresh location.hash = "dev=free"; } else { location.hash = "dev=lifetime"; } location.reload(); }); // No default hash: the page opens on whatever the account is entitled to. } /* ============================================================ INIT ============================================================ */ // ── Reference data ───────────────────────────────────────────────── // IEC 60228, IEC 60287 and IEC 60502 tables live in the IEC Tables // sub-base of the shared ieccalc database (see _lib/refdata.js). The // shapes rebuilt below are the shapes this file used when the numbers // were hard-coded, so the engine is unchanged. // Map the shared tables onto the shapes the Trench module expects. Everything, // including the conductor diameter, now comes from the same tables the rest of // the page uses — the module no longer holds a second opinion about anything. function applyTrenchReference() { if (typeof Trench === "undefined" || !Trench.setReference) return; const ref = {}; const tm = RefData.tableSync("iec60287.metal-properties"); if (tm && tm.rows.length) { const o = {}; tm.rows.forEach(r => { // Trench works in Ω·mm²/m; the table is in Ω·m. if (r._key === "Cu" || r._key === "Al") o[r._key] = { n: r.name, r: r.rho20 * 1e6, a: r.alpha }; }); if (Object.keys(o).length) ref.metals = o; } const ti = RefData.tableSync("iec60287.insulation-properties"); if (ti && ti.rows.length) { const o = {}; ti.rows.forEach(r => { if (!["XLPE", "PVC", "EPR"].includes(r._key)) return; o[r._key] = { n: r.name, mt: r.th_max, rt: r.rho_T != null ? r.rho_T : r.rho_T_lo, ep: r.eps_r, td: r.tan_d != null ? r.tan_d : r.tan_d_lo }; }); if (Object.keys(o).length) ref.insulation = o; } // Conductor diameter comes from IEC 60228 Table 2, the same table the main // calculation on this page uses. The module used to carry its own figures, // all of them above the maximum the standard allows for a class 2 conductor; // they had no recorded source and made the insulation thermal resistance // read low, so the trench came out cooler than it is. They were removed // rather than kept: no calculation was ever issued with them. // // The offered cross-sections are unchanged — the sizes this editor has // always listed — so a saved trench still resolves every cable it holds. const TRENCH_SIZES = [10, 16, 25, 35, 50, 70, 95, 120, 150, 185, 240, 300, 400, 500, 630]; const t228 = RefData.tableSync("iec60228.conductor-resistance"); if (t228 && t228.rows.length) { const rows = t228.rows .filter(r => TRENCH_SIZES.indexOf(r.S) !== -1 && r.dc > 0) .map(r => ({ s: r.S, cu: r.Cu, al: r.Al, d: r.dc })); if (rows.length) ref.sections = rows; } const tv = RefData.tableSync("iec60502.insulation-thickness-by-material"); if (tv && tv.rows.length) ref.classes = tv.rows.map(r => ({ l: r.label, u: r.U0, x: r.XLPE, p: r.PVC, e: r.EPR })); const tc = RefData.tableSync("practice.cable-outer-diameter"); if (tc && tc.rows.length) { ref.cables = tc.rows.map(r => ({ mfr: r.manufacturer, vc: r.voltage_class, ins: r.insulation, sizes: Object.fromEntries(Object.entries(r.diameters || {}).map(([s, De]) => [s, { De: De }])), })); } Trench.setReference(ref); } function stepFn(breaks) { // breaks: [[S_max | null, value], …] ascending. A null bound means // "every larger cross-section" and is therefore always last. return function (S) { for (const b of breaks) if (b[0] === null || S <= b[0]) return b[1]; return breaks[breaks.length - 1][1]; }; } function applyIecTables() { applyTrenchReference(); const rg = RefData.tableSync("presets.regions-ampacity"); if (rg && rg.rows.length) { const o = {}; rg.rows.forEach(r => { const v = Object.assign({}, r); delete v._key; delete v.region; o[r.region] = v; }); REGION_PRESETS = o; } const t228 = RefData.tableSync("iec60228.conductor-resistance"); if (t228 && t228.rows.length) IEC60228 = t228.rows.map(r => ({ S: r.S, dc: r.dc, Cu: r.Cu, Al: r.Al })); const tm = RefData.tableSync("iec60287.metal-properties"); if (tm && tm.rows.length) { const o = {}; tm.rows.forEach(r => { o[r._key] = { alpha: r.alpha, rho20: r.rho20, name: r.name }; }); MAT = o; } const ti = RefData.tableSync("iec60287.insulation-properties"); if (ti && ti.rows.length) { const o = {}; ti.rows.forEach(r => { const v = Object.assign({}, r); delete v._key; o[r._key] = v; }); INS = o; } const tj = RefData.tableSync("iec60287.jacket-thermal-resistivity"); if (tj && tj.rows.length) { const o = {}; tj.rows.forEach(r => { o[r.material] = r.rho_T; }); JACKET_RHO = o; } const tt = RefData.tableSync("iec60502.insulation-thickness"); if (tt && tt.rows.length) { const o = {}; tt.rows.forEach(r => { o[r.U0] = stepFn(r.breaks); }); INS_THK_XLPE_EPR = o; } } window.addEventListener("DOMContentLoaded", () => { // Nothing is computed until the reference tables are in hand. RefData.preload({ tables: ["iec60228.conductor-resistance", "iec60287.metal-properties", "iec60287.insulation-properties", "iec60287.jacket-thermal-resistivity", "iec60502.insulation-thickness", "presets.regions-ampacity", "iec60502.insulation-thickness-by-material", "practice.cable-outer-diameter"], }).then(() => { applyIecTables(); boot004(); // Late answer from the database: re-apply and recompute. window.addEventListener("refdata:updated", () => { applyIecTables(); if (typeof recalc === "function") recalc(); }, { once: true }); }); }); function boot004() { tdbBindToggle(); // TEMP-DEMO tdbApplyState(); // TEMP-DEMO populateCrossSections(); applyTypicalDefaults(); // also calls recalc() // Init Trench CAD module — always. const Trench is module-scoped, NOT on window — call directly. if(typeof Trench !== "undefined") Trench.init(); document.getElementById("btnRecalc").addEventListener("click", recalc); document.getElementById("btnReset").addEventListener("click", applyTypicalDefaults); document.getElementById("btnDocx").addEventListener("click", downloadDocx); document.getElementById("btnDocxPro").addEventListener("click", () => { // TEMP-DEMO: in dev (#dev=lifetime / #dev=free) the licence is "isDev:true" — let download proceed // but stamp the report with EXAMPLE watermark so it's clearly not for engineering use. const lic = (window.License && License.getSync) ? License.getSync() : null; const isDemoExample = lic && lic.isDev === true; if(isDemoExample){ downloadDocxPro({example:true}); return; } if(window.License && License.gate){ License.gate("full_report", { onAllowed: () => downloadDocxPro({example:false}) }); } else { downloadDocxPro({example:false}); } }); document.getElementById("btnTrenchCAD").addEventListener("click", () => { Trench.show(); // trench editor is free on this calculator (full report stays PRO) }); document.getElementById("btnValidate").addEventListener("click", runValidation); document.getElementById("regionPreset").addEventListener("change", applyRegionPreset); document.getElementById("insulation").addEventListener("change", () => { autoSetThetaMax(); recalc(); }); // recalc on every input change (only main form, not trench CAD inputs) document.querySelectorAll(".container > .layout input, .container > .layout select, .container > .toolbar input, .container > .toolbar select").forEach(el => { el.addEventListener("change", recalc); }); } // ── Shared project documents ────────────────────────────────────── // Contract consumed by _lib/calc-nav.js. This calculator holds its // inputs in the DOM, so the document is every named control plus the // trench model — enough to reproduce the run exactly. window.IecCalcDoc = { slug: "004", title: "Cable Ampacity", _fields() { return [...document.querySelectorAll(".container input[id], .container select[id], .container textarea[id]")] .filter(el => el.type !== "file" && el.type !== "button" && el.type !== "submit"); }, serialize() { const fields = {}; for (const el of this._fields()) { fields[el.id] = (el.type === "checkbox" || el.type === "radio") ? el.checked : el.value; } let trench = null; try { trench = (typeof Trench !== "undefined" && Trench.getState) ? Trench.getState() : null; } catch (e) {} return { v: 1, slug: "004", fields, trench }; }, restore(d) { if (!d || d.slug !== "004" || !d.fields) { throw new Error("This document belongs to another calculator."); } for (const el of this._fields()) { if (!(el.id in d.fields)) continue; const v = d.fields[el.id]; if (el.type === "checkbox" || el.type === "radio") el.checked = !!v; else el.value = v; el.dispatchEvent(new Event("change", { bubbles: true })); } if (d.trench) { try { Trench.setState(d.trench); } catch (e) {} } if (typeof recalc === "function") recalc(); }, };