ACI 318 Concrete Column Design Calculator

Design-check reinforced concrete columns per ACI 318 using a clear, mobile-first tool. Enter geometry, materials, reinforcement, and factored loads. The calculator estimates axial and biaxial capacity using a simplified Bresler interaction and reports pass/fail with utilization.

Calculator Inputs

Units
Section shape
Transverse reinforcement
in
in
psi
ksi
Longitudinal steel input mode
%
in
in
kip
kip-ft
kip-ft

Results

Gross area Ag
Steel area As
Strength reduction factor φ
Concentric capacity φP0
Pure-bending φMnx0
Pure-bending φMny0
Bresler exponent r
Utilization ratio U
Status

Note: This is a preliminary design check using simplified assumptions. Slenderness, second-order (P-Δ/P-δ), load duration, and detailed bar placement are not included.

Data Source and Methodology

Authoritative source: ACI Committee 318. “Building Code Requirements for Structural Concrete (ACI 318-19) and Commentary.” American Concrete Institute, 2019. Official reference.

Tutti i calcoli si basano rigorosamente sulle formule e sui dati forniti da questa fonte.

The Formula Explained

Gross area:

Rectangular: Ag = b · h

Circular: Ag = \(\frac{\pi D^2}{4}\)

Steel area (percentage mode): \(A_s = \rho \cdot A_g\), where \(\rho = \frac{\text{percent}}{100}\)

Concentric nominal axial strength:

\(P_{0n} = 0.85\,f'_c\,(A_g - A_s) + f_y A_s\)

Strength reduction factor (compression-controlled):

\(\phi = 0.65\) (tied), \(\phi = 0.75\) (spiral)

Pure bending nominal strength (rectangular approximation, symmetric layout, half steel in tension):

\(a = \dfrac{A_{s,t} f_y}{0.85 f'_c\, b}\),   \(M_n = A_{s,t} f_y \left( d - \tfrac{a}{2} \right)\)

For bending about x: use width \(b_x = b\), effective depth \(d_x = h - d'\).

For bending about y: use width \(b_y = h\), effective depth \(d_y = b - d'\).

For circular sections (approximation): use \(b_{\text{eff}} = 0.85 D\) and \(d = D - d'\).

Biaxial (Bresler-type) interaction:

\(\left(\dfrac{M_{ux}}{\phi M_{nx0}}\right)^r + \left(\dfrac{M_{uy}}{\phi M_{ny0}}\right)^r \le \left(1 - \dfrac{P_u}{\phi P_{0n}}\right)^r\), where \(1 \le r \le 2\) and \(r = 2 - \dfrac{P_u}{\phi P_{0n}}\)

Glossary of Variables

How It Works: A Step-by-Step Example

  1. Select Units = US, Shape = Rectangular, Ties = Tied (φ = 0.65).
  2. Enter b = 16 in, h = 20 in; f'c = 4000 psi; fy = 60 ksi.
  3. Steel mode = As %, ρ = 2.0%; cover c = 1.5 in; bar diameter db = 1.0 in.
  4. Loads: Pu = 400 kip; Mux = 150 kip-ft; Muy = 80 kip-ft.
  5. The tool computes:
    • Ag = 320 in²; As = 6.4 in²; φ = 0.65.
    • φP0 = φ[0.85·4000(320 − 6.4) + 60,000·6.4] ≈ reported in Results.
    • d' = 1.5 + 0.5 = 2.0 in; d_x = 20 − 2 = 18 in; d_y = 16 − 2 = 14 in.
    • Assuming As,t = As/2 = 3.2 in²: a_x = (3.2·60,000)/(0.85·4000·16), and Mn_x0 = As,t·fy(d_x − a_x/2). Similarly for y with b_y = 20 and d_y = 14.
    • Compute r = 2 − Pu/(φP0) clamped [1,2].
    • Check (Mux/φMnx0)^r + (Muy/φMny0)^r ≤ (1 − Pu/φP0)^r; report U and pass/fail.
    Compare with the Results panel for the exact numbers.

Frequently Asked Questions (FAQ)

Does this calculator include slenderness and second-order effects?

No. Slenderness and P-Δ/P-δ effects per ACI 318 (including moment magnifiers) are not included. Use this tool for preliminary checks and apply full code procedures for final design.

How accurate is the pure-bending approximation?

It is conservative for symmetric reinforcement because it neglects compression steel contribution and assumes half of As acts in tension. For final design, use full strain compatibility analysis with your exact bar layout.

Can I input different steel on each face?

Not in this version. Total As is assumed symmetric. Future updates may allow per-face bar counts and positions.

What if U is slightly above 1.0?

Consider increasing member size, raising steel ratio, improving material strengths (within code limits), or reducing loads. Always re-check with full code procedures.

Why is φ different for tied vs. spiral columns?

Spiral confinement generally improves ductility and strength, allowing a higher φ per ACI 318.

How do I choose b and h vs. x and y axes?

In this tool, Mux uses b as the compression block width and h as the effective depth; for Muy, they swap. Ensure your axis convention matches the input geometry.


Audit: Complete
Formula (LaTeX) + variables + units
This section shows the formulas used by the calculator engine, plus variable definitions and units.
Formula (extracted LaTeX)
\[','\]
','
Formula (extracted LaTeX)
\[= (sel, root=document) => Array.from(root.querySelectorAll(sel)); const clamp = (v,min,max)=> Math.max(min, Math.min(max, v)); // Elements const state = { units: 'us', shape: 'rect', tieType: 'tied', steelMode: 'pct' }; const el = { // groups dimRect1: $('#dim-rect'), dimRect2: $('#dim-rect-2'), dimCirc: $('#dim-circ'), groupRho: $('#group-rho'), groupAs: $('#group-As'), // inputs b: $('#b'), h: $('#h'), D: $('#D'), fc: $('#fc'), fy: $('#fy'), rho: $('#rho'), As: $('#As'), cover: $('#cover'), db: $('#db'), Pu: $('#Pu'), Mux: $('#Mux'), Muy: $('#Muy'), // units spans u: { b: $('#unit-b'), h: $('#unit-h'), D: $('#unit-D'), fc: $('#unit-fc'), fy: $('#unit-fy'), As: $('#unit-As'), cover: $('#unit-cover'), db: $('#unit-db'), Pu: $('#unit-Pu'), Mu: $('#unit-Mu'), Mu2: $('#unit-Mu2') }, // results resAg: $('#resAg'), resAs: $('#resAs'), resPhi: $('#resPhi'), resPhiP0: $('#resPhiP0'), resPhiMnx0: $('#resPhiMnx0'), resPhiMny0: $('#resPhiMny0'), resR: $('#resR'), resU: $('#resU'), resStatus: $('#resStatus'), // buttons calcBtn: $('#calcBtn'), resetBtn: $('#resetBtn') }; // Accessible tooltips\]
= (sel, root=document) => Array.from(root.querySelectorAll(sel)); const clamp = (v,min,max)=> Math.max(min, Math.min(max, v)); // Elements const state = { units: 'us', shape: 'rect', tieType: 'tied', steelMode: 'pct' }; const el = { // groups dimRect1: $('#dim-rect'), dimRect2: $('#dim-rect-2'), dimCirc: $('#dim-circ'), groupRho: $('#group-rho'), groupAs: $('#group-As'), // inputs b: $('#b'), h: $('#h'), D: $('#D'), fc: $('#fc'), fy: $('#fy'), rho: $('#rho'), As: $('#As'), cover: $('#cover'), db: $('#db'), Pu: $('#Pu'), Mux: $('#Mux'), Muy: $('#Muy'), // units spans u: { b: $('#unit-b'), h: $('#unit-h'), D: $('#unit-D'), fc: $('#unit-fc'), fy: $('#unit-fy'), As: $('#unit-As'), cover: $('#unit-cover'), db: $('#unit-db'), Pu: $('#unit-Pu'), Mu: $('#unit-Mu'), Mu2: $('#unit-Mu2') }, // results resAg: $('#resAg'), resAs: $('#resAs'), resPhi: $('#resPhi'), resPhiP0: $('#resPhiP0'), resPhiMnx0: $('#resPhiMnx0'), resPhiMny0: $('#resPhiMny0'), resR: $('#resR'), resU: $('#resU'), resStatus: $('#resStatus'), // buttons calcBtn: $('#calcBtn'), resetBtn: $('#resetBtn') }; // Accessible tooltips
Formula (extracted LaTeX)
\[('input[name="units"]').forEach(r=> r.addEventListener('change', e=>{ state.units = e.target.value; applyUnits(); validateAll(false); }));\]
('input[name="units"]').forEach(r=> r.addEventListener('change', e=>{ state.units = e.target.value; applyUnits(); validateAll(false); }));
Formula (extracted LaTeX)
\[('input[name="tieType"]').forEach(r=> r.addEventListener('change', e=>{ state.tieType = e.target.value; }));\]
('input[name="tieType"]').forEach(r=> r.addEventListener('change', e=>{ state.tieType = e.target.value; }));
Formula (extracted LaTeX)
\[('input, select').forEach(inp=>{ inp.addEventListener('blur', ()=> validateField(inp)); }); // Conversions const conv = { // Return consistent internal units: // US: in, kip, psi; Metric: mm, kN, MPa lenToIn: (x) => state.units==='us' ? x : x * 0.0393700787, inToLen: (x) => state.units==='us' ? x : x / 0.0393700787, areaToIn2: (x) => state.units==='us' ? x : x * (0.0393700787**2), // Forces: kip vs kN forceToKip: (x) => state.units==='us' ? x : x * 0.22480894387, // kN to kip // Moments: kip-ft vs kN-m momentToKipFt: (x) => state.units==='us' ? x : x * 0.737562149, // kN-m to kip-ft // Stresses: psi vs MPa fcToPsi: (x) => state.units==='us' ? x : x * 145.0377377, // MPa to psi fyToPsi: (x) => state.units==='us' ? x*1000 : x * 145.0377377 // ksi to psi if US; MPa to psi if metric }; // Calculation core function compute(){ if(!validateAll(true)) return; // Read inputs (convert to internal US units: in, psi, kip, kip-ft) const shape = state.shape; const tied = state.tieType === 'tied'; const b_in = shape==='rect' ? conv.lenToIn(Number(el.b.value)) : null; const h_in = shape==='rect' ? conv.lenToIn(Number(el.h.value)) : null; const D_in = shape==='circ' ? conv.lenToIn(Number(el.D.value)) : null; const fc_psi = conv.fcToPsi(Number(el.fc.value)); const fy_psi = conv.fyToPsi(Number(el.fy.value)); // psi const cover_in = conv.lenToIn(Number(el.cover.value)); const db_in = conv.lenToIn(Number(el.db.value)); const dPrime = cover_in + db_in/2; const Pu_kip = conv.forceToKip(Number(el.Pu.value)); const Mux_kipft = conv.momentToKipFt(Number(el.Mux.value)); const Muy_kipft = conv.momentToKipFt(Number(el.Muy.value)); let Ag_in2 = 0; if(shape==='rect'){ Ag_in2 = b_in * h_in; } else { Ag_in2 = Math.PI * (D_in**2) / 4; } let As_in2 = 0; if(state.steelMode === 'pct'){ const rho = Number(el.rho.value)/100; As_in2 = rho * Ag_in2; } else { As_in2 = state.units==='us' ? Number(el.As.value) : conv.areaToIn2(Number(el.As.value)); } // Strength reduction factor const phi = tied ? 0.65 : 0.75; // Concentric nominal axial strength const P0n_kip = (0.85*fc_psi*(Ag_in2 - As_in2) + fy_psi*As_in2) / 1000.0; // psi*in^2 -> pounds -> /1000 = kips const phiP0 = phi * P0n_kip; // Pure bending nominal strengths (approximate) // Use As,t = As/2 (symmetric), singly reinforced approximation const As_t = As_in2 / 2; let Mnx0_kipin = 0; let Mny0_kipin = 0; if(shape==='rect'){ // About x: compression width b, depth h const bx = b_in, hx = h_in; const dx = hx - dPrime; const ax = (As_t * fy_psi) / (0.85 * fc_psi * Math.max(bx, 1e-9)); Mnx0_kipin = As_t * fy_psi * Math.max(dx - ax/2, 0) / 1000; // kip-in // About y: compression width h, depth b const by = h_in, hy = b_in; const dy = hy - dPrime; const ay = (As_t * fy_psi) / (0.85 * fc_psi * Math.max(by, 1e-9)); Mny0_kipin = As_t * fy_psi * Math.max(dy - ay/2, 0) / 1000; // kip-in } else { // Circular: equivalent rectangular width 0.85D; depth D const beff = 0.85 * D_in; const d = D_in - dPrime; const a = (As_t * fy_psi) / (0.85 * fc_psi * Math.max(beff, 1e-9)); const Mn = As_t * fy_psi * Math.max(d - a/2, 0) / 1000; // kip-in Mnx0_kipin = Mn; Mny0_kipin = Mn; } // Convert nominal moments to kip-ft const Mnx0_kipft = Mnx0_kipin / 12; const Mny0_kipft = Mny0_kipin / 12; const phiMnx0 = phi * Mnx0_kipft; const phiMny0 = phi * Mny0_kipft; // Bresler exponent const n = phiP0 > 0 ? Pu_kip / phiP0 : 1; const r = clamp(2 - n, 1, 2); // Interaction sides const left = Math.pow(phiMnx0>0 ? (Mux_kipft/phiMnx0) : Infinity, r) + Math.pow(phiMny0>0 ? (Muy_kipft/phiMny0) : Infinity, r); const right = Math.pow(Math.max(1 - (phiP0>0 ? Pu_kip/phiP0 : 1), 0), r); let U = left / (right>0 ? right : 1e-9); if(!isFinite(U)) U = 999; // Present results in chosen units for user function fmt(val, unit){ if(!isFinite(val)) return '—'; const abs = Math.abs(val); const digits = abs >= 1000 ? 0 : abs >= 100 ? 1 : 2; return `${val.toFixed(digits)} ${unit}`; } // Output conversions back to UI units // Areas const Ag_disp = state.units==='us' ? Ag_in2 : Ag_in2 / (0.0393700787**2); const As_disp = state.units==='us' ? As_in2 : As_in2 / (0.0393700787**2); el.resAg.textContent = fmt(Ag_disp, state.units==='us' ? 'in²' : 'mm²'); el.resAs.textContent = fmt(As_disp, state.units==='us' ? 'in²' : 'mm²'); el.resPhi.textContent = phi.toFixed(2); // Axial capacity const phiP0_disp = state.units==='us' ? phiP0 : phiP0 / 0.22480894387; // kip -> kN el.resPhiP0.textContent = fmt(phiP0_disp, state.units==='us' ? 'kip' : 'kN'); // Moments const phiMnx0_disp = state.units==='us' ? phiMnx0 : phiMnx0 / 0.737562149; // kip-ft -> kN-m const phiMny0_disp = state.units==='us' ? phiMny0 : phiMny0 / 0.737562149; el.resPhiMnx0.textContent = fmt(phiMnx0_disp, state.units==='us' ? 'kip-ft' : 'kN-m'); el.resPhiMny0.textContent = fmt(phiMny0_disp, state.units==='us' ? 'kip-ft' : 'kN-m'); el.resR.textContent = isFinite(r) ? r.toFixed(2) : '—'; el.resU.textContent = isFinite(U) ? (U>100 ? '>100' : U.toFixed(2)) : '—'; // Status badge const badge = document.createElement('span'); badge.className = `badge ${U <= 1 ? 'pass' : 'fail'}`; badge.textContent = U <= 1 ? 'PASS (U ≤ 1.0)' : 'FAIL (U > 1.0)'; el.resStatus.innerHTML = ''; el.resStatus.appendChild(badge); } // Reset function reset(){ // Clear only numeric inputs; keep toggles [el.b, el.h, el.D, el.fc, el.fy, el.rho, el.As, el.cover, el.db, el.Pu, el.Mux, el.Muy].forEach(inp=>{ if(!inp) return; if(inp === el.rho) { inp.value = 2.0; return; } if(inp === el.cover) { inp.value = state.units==='us' ? 1.5 : 40; return; } if(inp === el.db) { inp.value = state.units==='us' ? 1.0 : 25; return; } inp.value = ''; clearError(inp); }); // Clear results [el.resAg, el.resAs, el.resPhi, el.resPhiP0, el.resPhiMnx0, el.resPhiMny0, el.resR, el.resU].forEach(n=> n.textContent='—'); el.resStatus.innerHTML = '<span class="badge">—</span>'; } // Attach el.calcBtn.addEventListener('click', compute); el.resetBtn.addEventListener('click', reset); // Recompute on change for responsiveness (without spamming errors)\]
('input, select').forEach(inp=>{ inp.addEventListener('blur', ()=> validateField(inp)); }); // Conversions const conv = { // Return consistent internal units: // US: in, kip, psi; Metric: mm, kN, MPa lenToIn: (x) => state.units==='us' ? x : x * 0.0393700787, inToLen: (x) => state.units==='us' ? x : x / 0.0393700787, areaToIn2: (x) => state.units==='us' ? x : x * (0.0393700787**2), // Forces: kip vs kN forceToKip: (x) => state.units==='us' ? x : x * 0.22480894387, // kN to kip // Moments: kip-ft vs kN-m momentToKipFt: (x) => state.units==='us' ? x : x * 0.737562149, // kN-m to kip-ft // Stresses: psi vs MPa fcToPsi: (x) => state.units==='us' ? x : x * 145.0377377, // MPa to psi fyToPsi: (x) => state.units==='us' ? x*1000 : x * 145.0377377 // ksi to psi if US; MPa to psi if metric }; // Calculation core function compute(){ if(!validateAll(true)) return; // Read inputs (convert to internal US units: in, psi, kip, kip-ft) const shape = state.shape; const tied = state.tieType === 'tied'; const b_in = shape==='rect' ? conv.lenToIn(Number(el.b.value)) : null; const h_in = shape==='rect' ? conv.lenToIn(Number(el.h.value)) : null; const D_in = shape==='circ' ? conv.lenToIn(Number(el.D.value)) : null; const fc_psi = conv.fcToPsi(Number(el.fc.value)); const fy_psi = conv.fyToPsi(Number(el.fy.value)); // psi const cover_in = conv.lenToIn(Number(el.cover.value)); const db_in = conv.lenToIn(Number(el.db.value)); const dPrime = cover_in + db_in/2; const Pu_kip = conv.forceToKip(Number(el.Pu.value)); const Mux_kipft = conv.momentToKipFt(Number(el.Mux.value)); const Muy_kipft = conv.momentToKipFt(Number(el.Muy.value)); let Ag_in2 = 0; if(shape==='rect'){ Ag_in2 = b_in * h_in; } else { Ag_in2 = Math.PI * (D_in**2) / 4; } let As_in2 = 0; if(state.steelMode === 'pct'){ const rho = Number(el.rho.value)/100; As_in2 = rho * Ag_in2; } else { As_in2 = state.units==='us' ? Number(el.As.value) : conv.areaToIn2(Number(el.As.value)); } // Strength reduction factor const phi = tied ? 0.65 : 0.75; // Concentric nominal axial strength const P0n_kip = (0.85*fc_psi*(Ag_in2 - As_in2) + fy_psi*As_in2) / 1000.0; // psi*in^2 -> pounds -> /1000 = kips const phiP0 = phi * P0n_kip; // Pure bending nominal strengths (approximate) // Use As,t = As/2 (symmetric), singly reinforced approximation const As_t = As_in2 / 2; let Mnx0_kipin = 0; let Mny0_kipin = 0; if(shape==='rect'){ // About x: compression width b, depth h const bx = b_in, hx = h_in; const dx = hx - dPrime; const ax = (As_t * fy_psi) / (0.85 * fc_psi * Math.max(bx, 1e-9)); Mnx0_kipin = As_t * fy_psi * Math.max(dx - ax/2, 0) / 1000; // kip-in // About y: compression width h, depth b const by = h_in, hy = b_in; const dy = hy - dPrime; const ay = (As_t * fy_psi) / (0.85 * fc_psi * Math.max(by, 1e-9)); Mny0_kipin = As_t * fy_psi * Math.max(dy - ay/2, 0) / 1000; // kip-in } else { // Circular: equivalent rectangular width 0.85D; depth D const beff = 0.85 * D_in; const d = D_in - dPrime; const a = (As_t * fy_psi) / (0.85 * fc_psi * Math.max(beff, 1e-9)); const Mn = As_t * fy_psi * Math.max(d - a/2, 0) / 1000; // kip-in Mnx0_kipin = Mn; Mny0_kipin = Mn; } // Convert nominal moments to kip-ft const Mnx0_kipft = Mnx0_kipin / 12; const Mny0_kipft = Mny0_kipin / 12; const phiMnx0 = phi * Mnx0_kipft; const phiMny0 = phi * Mny0_kipft; // Bresler exponent const n = phiP0 > 0 ? Pu_kip / phiP0 : 1; const r = clamp(2 - n, 1, 2); // Interaction sides const left = Math.pow(phiMnx0>0 ? (Mux_kipft/phiMnx0) : Infinity, r) + Math.pow(phiMny0>0 ? (Muy_kipft/phiMny0) : Infinity, r); const right = Math.pow(Math.max(1 - (phiP0>0 ? Pu_kip/phiP0 : 1), 0), r); let U = left / (right>0 ? right : 1e-9); if(!isFinite(U)) U = 999; // Present results in chosen units for user function fmt(val, unit){ if(!isFinite(val)) return '—'; const abs = Math.abs(val); const digits = abs >= 1000 ? 0 : abs >= 100 ? 1 : 2; return `${val.toFixed(digits)} ${unit}`; } // Output conversions back to UI units // Areas const Ag_disp = state.units==='us' ? Ag_in2 : Ag_in2 / (0.0393700787**2); const As_disp = state.units==='us' ? As_in2 : As_in2 / (0.0393700787**2); el.resAg.textContent = fmt(Ag_disp, state.units==='us' ? 'in²' : 'mm²'); el.resAs.textContent = fmt(As_disp, state.units==='us' ? 'in²' : 'mm²'); el.resPhi.textContent = phi.toFixed(2); // Axial capacity const phiP0_disp = state.units==='us' ? phiP0 : phiP0 / 0.22480894387; // kip -> kN el.resPhiP0.textContent = fmt(phiP0_disp, state.units==='us' ? 'kip' : 'kN'); // Moments const phiMnx0_disp = state.units==='us' ? phiMnx0 : phiMnx0 / 0.737562149; // kip-ft -> kN-m const phiMny0_disp = state.units==='us' ? phiMny0 : phiMny0 / 0.737562149; el.resPhiMnx0.textContent = fmt(phiMnx0_disp, state.units==='us' ? 'kip-ft' : 'kN-m'); el.resPhiMny0.textContent = fmt(phiMny0_disp, state.units==='us' ? 'kip-ft' : 'kN-m'); el.resR.textContent = isFinite(r) ? r.toFixed(2) : '—'; el.resU.textContent = isFinite(U) ? (U>100 ? '>100' : U.toFixed(2)) : '—'; // Status badge const badge = document.createElement('span'); badge.className = `badge ${U <= 1 ? 'pass' : 'fail'}`; badge.textContent = U <= 1 ? 'PASS (U ≤ 1.0)' : 'FAIL (U > 1.0)'; el.resStatus.innerHTML = ''; el.resStatus.appendChild(badge); } // Reset function reset(){ // Clear only numeric inputs; keep toggles [el.b, el.h, el.D, el.fc, el.fy, el.rho, el.As, el.cover, el.db, el.Pu, el.Mux, el.Muy].forEach(inp=>{ if(!inp) return; if(inp === el.rho) { inp.value = 2.0; return; } if(inp === el.cover) { inp.value = state.units==='us' ? 1.5 : 40; return; } if(inp === el.db) { inp.value = state.units==='us' ? 1.0 : 25; return; } inp.value = ''; clearError(inp); }); // Clear results [el.resAg, el.resAs, el.resPhi, el.resPhiP0, el.resPhiMnx0, el.resPhiMny0, el.resR, el.resU].forEach(n=> n.textContent='—'); el.resStatus.innerHTML = '<span class="badge">—</span>'; } // Attach el.calcBtn.addEventListener('click', compute); el.resetBtn.addEventListener('click', reset); // Recompute on change for responsiveness (without spamming errors)
Formula (extracted text)
Gross area: Rectangular: Ag = b · h Circular: Ag = \(\frac{\pi D^2}{4}\) Steel area (percentage mode): \(A_s = \rho \cdot A_g\), where \(\rho = \frac{\text{percent}}{100}\) Concentric nominal axial strength: \(P_{0n} = 0.85\,f'_c\,(A_g - A_s) + f_y A_s\) Strength reduction factor (compression-controlled): \(\phi = 0.65\) (tied), \(\phi = 0.75\) (spiral) Pure bending nominal strength (rectangular approximation, symmetric layout, half steel in tension): \(a = \dfrac{A_{s,t} f_y}{0.85 f'_c\, b}\), \(M_n = A_{s,t} f_y \left( d - \tfrac{a}{2} \right)\) For bending about x: use width \(b_x = b\), effective depth \(d_x = h - d'\). For bending about y: use width \(b_y = h\), effective depth \(d_y = b - d'\). For circular sections (approximation): use \(b_{\text{eff}} = 0.85 D\) and \(d = D - d'\). Biaxial (Bresler-type) interaction: \(\left(\dfrac{M_{ux}}{\phi M_{nx0}}\right)^r + \left(\dfrac{M_{uy}}{\phi M_{ny0}}\right)^r \le \left(1 - \dfrac{P_u}{\phi P_{0n}}\right)^r\), where \(1 \le r \le 2\) and \(r = 2 - \dfrac{P_u}{\phi P_{0n}}\)
Variables and units
  • No variables provided in audit spec.
Sources (authoritative):
Changelog
Version: 0.1.0-draft
Last code update: 2026-01-19
0.1.0-draft · 2026-01-19
  • Initial audit spec draft generated from HTML extraction (review required).
  • Verify formulas match the calculator engine and convert any text-only formulas to LaTeX.
  • Confirm sources are authoritative and relevant to the calculator methodology.
Verified by Ugo Candido on 2026-01-19
Profile · LinkedIn
, ', svg: { fontCache: 'global' } };

ACI 318 Concrete Column Design Calculator

Design-check reinforced concrete columns per ACI 318 using a clear, mobile-first tool. Enter geometry, materials, reinforcement, and factored loads. The calculator estimates axial and biaxial capacity using a simplified Bresler interaction and reports pass/fail with utilization.

Calculator Inputs

Units
Section shape
Transverse reinforcement
in
in
psi
ksi
Longitudinal steel input mode
%
in
in
kip
kip-ft
kip-ft

Results

Gross area Ag
Steel area As
Strength reduction factor φ
Concentric capacity φP0
Pure-bending φMnx0
Pure-bending φMny0
Bresler exponent r
Utilization ratio U
Status

Note: This is a preliminary design check using simplified assumptions. Slenderness, second-order (P-Δ/P-δ), load duration, and detailed bar placement are not included.

Data Source and Methodology

Authoritative source: ACI Committee 318. “Building Code Requirements for Structural Concrete (ACI 318-19) and Commentary.” American Concrete Institute, 2019. Official reference.

Tutti i calcoli si basano rigorosamente sulle formule e sui dati forniti da questa fonte.

The Formula Explained

Gross area:

Rectangular: Ag = b · h

Circular: Ag = \(\frac{\pi D^2}{4}\)

Steel area (percentage mode): \(A_s = \rho \cdot A_g\), where \(\rho = \frac{\text{percent}}{100}\)

Concentric nominal axial strength:

\(P_{0n} = 0.85\,f'_c\,(A_g - A_s) + f_y A_s\)

Strength reduction factor (compression-controlled):

\(\phi = 0.65\) (tied), \(\phi = 0.75\) (spiral)

Pure bending nominal strength (rectangular approximation, symmetric layout, half steel in tension):

\(a = \dfrac{A_{s,t} f_y}{0.85 f'_c\, b}\),   \(M_n = A_{s,t} f_y \left( d - \tfrac{a}{2} \right)\)

For bending about x: use width \(b_x = b\), effective depth \(d_x = h - d'\).

For bending about y: use width \(b_y = h\), effective depth \(d_y = b - d'\).

For circular sections (approximation): use \(b_{\text{eff}} = 0.85 D\) and \(d = D - d'\).

Biaxial (Bresler-type) interaction:

\(\left(\dfrac{M_{ux}}{\phi M_{nx0}}\right)^r + \left(\dfrac{M_{uy}}{\phi M_{ny0}}\right)^r \le \left(1 - \dfrac{P_u}{\phi P_{0n}}\right)^r\), where \(1 \le r \le 2\) and \(r = 2 - \dfrac{P_u}{\phi P_{0n}}\)

Glossary of Variables

How It Works: A Step-by-Step Example

  1. Select Units = US, Shape = Rectangular, Ties = Tied (φ = 0.65).
  2. Enter b = 16 in, h = 20 in; f'c = 4000 psi; fy = 60 ksi.
  3. Steel mode = As %, ρ = 2.0%; cover c = 1.5 in; bar diameter db = 1.0 in.
  4. Loads: Pu = 400 kip; Mux = 150 kip-ft; Muy = 80 kip-ft.
  5. The tool computes:
    • Ag = 320 in²; As = 6.4 in²; φ = 0.65.
    • φP0 = φ[0.85·4000(320 − 6.4) + 60,000·6.4] ≈ reported in Results.
    • d' = 1.5 + 0.5 = 2.0 in; d_x = 20 − 2 = 18 in; d_y = 16 − 2 = 14 in.
    • Assuming As,t = As/2 = 3.2 in²: a_x = (3.2·60,000)/(0.85·4000·16), and Mn_x0 = As,t·fy(d_x − a_x/2). Similarly for y with b_y = 20 and d_y = 14.
    • Compute r = 2 − Pu/(φP0) clamped [1,2].
    • Check (Mux/φMnx0)^r + (Muy/φMny0)^r ≤ (1 − Pu/φP0)^r; report U and pass/fail.
    Compare with the Results panel for the exact numbers.

Frequently Asked Questions (FAQ)

Does this calculator include slenderness and second-order effects?

No. Slenderness and P-Δ/P-δ effects per ACI 318 (including moment magnifiers) are not included. Use this tool for preliminary checks and apply full code procedures for final design.

How accurate is the pure-bending approximation?

It is conservative for symmetric reinforcement because it neglects compression steel contribution and assumes half of As acts in tension. For final design, use full strain compatibility analysis with your exact bar layout.

Can I input different steel on each face?

Not in this version. Total As is assumed symmetric. Future updates may allow per-face bar counts and positions.

What if U is slightly above 1.0?

Consider increasing member size, raising steel ratio, improving material strengths (within code limits), or reducing loads. Always re-check with full code procedures.

Why is φ different for tied vs. spiral columns?

Spiral confinement generally improves ductility and strength, allowing a higher φ per ACI 318.

How do I choose b and h vs. x and y axes?

In this tool, Mux uses b as the compression block width and h as the effective depth; for Muy, they swap. Ensure your axis convention matches the input geometry.


Audit: Complete
Formula (LaTeX) + variables + units
This section shows the formulas used by the calculator engine, plus variable definitions and units.
Formula (extracted LaTeX)
\[','\]
','
Formula (extracted LaTeX)
\[= (sel, root=document) => Array.from(root.querySelectorAll(sel)); const clamp = (v,min,max)=> Math.max(min, Math.min(max, v)); // Elements const state = { units: 'us', shape: 'rect', tieType: 'tied', steelMode: 'pct' }; const el = { // groups dimRect1: $('#dim-rect'), dimRect2: $('#dim-rect-2'), dimCirc: $('#dim-circ'), groupRho: $('#group-rho'), groupAs: $('#group-As'), // inputs b: $('#b'), h: $('#h'), D: $('#D'), fc: $('#fc'), fy: $('#fy'), rho: $('#rho'), As: $('#As'), cover: $('#cover'), db: $('#db'), Pu: $('#Pu'), Mux: $('#Mux'), Muy: $('#Muy'), // units spans u: { b: $('#unit-b'), h: $('#unit-h'), D: $('#unit-D'), fc: $('#unit-fc'), fy: $('#unit-fy'), As: $('#unit-As'), cover: $('#unit-cover'), db: $('#unit-db'), Pu: $('#unit-Pu'), Mu: $('#unit-Mu'), Mu2: $('#unit-Mu2') }, // results resAg: $('#resAg'), resAs: $('#resAs'), resPhi: $('#resPhi'), resPhiP0: $('#resPhiP0'), resPhiMnx0: $('#resPhiMnx0'), resPhiMny0: $('#resPhiMny0'), resR: $('#resR'), resU: $('#resU'), resStatus: $('#resStatus'), // buttons calcBtn: $('#calcBtn'), resetBtn: $('#resetBtn') }; // Accessible tooltips\]
= (sel, root=document) => Array.from(root.querySelectorAll(sel)); const clamp = (v,min,max)=> Math.max(min, Math.min(max, v)); // Elements const state = { units: 'us', shape: 'rect', tieType: 'tied', steelMode: 'pct' }; const el = { // groups dimRect1: $('#dim-rect'), dimRect2: $('#dim-rect-2'), dimCirc: $('#dim-circ'), groupRho: $('#group-rho'), groupAs: $('#group-As'), // inputs b: $('#b'), h: $('#h'), D: $('#D'), fc: $('#fc'), fy: $('#fy'), rho: $('#rho'), As: $('#As'), cover: $('#cover'), db: $('#db'), Pu: $('#Pu'), Mux: $('#Mux'), Muy: $('#Muy'), // units spans u: { b: $('#unit-b'), h: $('#unit-h'), D: $('#unit-D'), fc: $('#unit-fc'), fy: $('#unit-fy'), As: $('#unit-As'), cover: $('#unit-cover'), db: $('#unit-db'), Pu: $('#unit-Pu'), Mu: $('#unit-Mu'), Mu2: $('#unit-Mu2') }, // results resAg: $('#resAg'), resAs: $('#resAs'), resPhi: $('#resPhi'), resPhiP0: $('#resPhiP0'), resPhiMnx0: $('#resPhiMnx0'), resPhiMny0: $('#resPhiMny0'), resR: $('#resR'), resU: $('#resU'), resStatus: $('#resStatus'), // buttons calcBtn: $('#calcBtn'), resetBtn: $('#resetBtn') }; // Accessible tooltips
Formula (extracted LaTeX)
\[('input[name="units"]').forEach(r=> r.addEventListener('change', e=>{ state.units = e.target.value; applyUnits(); validateAll(false); }));\]
('input[name="units"]').forEach(r=> r.addEventListener('change', e=>{ state.units = e.target.value; applyUnits(); validateAll(false); }));
Formula (extracted LaTeX)
\[('input[name="tieType"]').forEach(r=> r.addEventListener('change', e=>{ state.tieType = e.target.value; }));\]
('input[name="tieType"]').forEach(r=> r.addEventListener('change', e=>{ state.tieType = e.target.value; }));
Formula (extracted LaTeX)
\[('input, select').forEach(inp=>{ inp.addEventListener('blur', ()=> validateField(inp)); }); // Conversions const conv = { // Return consistent internal units: // US: in, kip, psi; Metric: mm, kN, MPa lenToIn: (x) => state.units==='us' ? x : x * 0.0393700787, inToLen: (x) => state.units==='us' ? x : x / 0.0393700787, areaToIn2: (x) => state.units==='us' ? x : x * (0.0393700787**2), // Forces: kip vs kN forceToKip: (x) => state.units==='us' ? x : x * 0.22480894387, // kN to kip // Moments: kip-ft vs kN-m momentToKipFt: (x) => state.units==='us' ? x : x * 0.737562149, // kN-m to kip-ft // Stresses: psi vs MPa fcToPsi: (x) => state.units==='us' ? x : x * 145.0377377, // MPa to psi fyToPsi: (x) => state.units==='us' ? x*1000 : x * 145.0377377 // ksi to psi if US; MPa to psi if metric }; // Calculation core function compute(){ if(!validateAll(true)) return; // Read inputs (convert to internal US units: in, psi, kip, kip-ft) const shape = state.shape; const tied = state.tieType === 'tied'; const b_in = shape==='rect' ? conv.lenToIn(Number(el.b.value)) : null; const h_in = shape==='rect' ? conv.lenToIn(Number(el.h.value)) : null; const D_in = shape==='circ' ? conv.lenToIn(Number(el.D.value)) : null; const fc_psi = conv.fcToPsi(Number(el.fc.value)); const fy_psi = conv.fyToPsi(Number(el.fy.value)); // psi const cover_in = conv.lenToIn(Number(el.cover.value)); const db_in = conv.lenToIn(Number(el.db.value)); const dPrime = cover_in + db_in/2; const Pu_kip = conv.forceToKip(Number(el.Pu.value)); const Mux_kipft = conv.momentToKipFt(Number(el.Mux.value)); const Muy_kipft = conv.momentToKipFt(Number(el.Muy.value)); let Ag_in2 = 0; if(shape==='rect'){ Ag_in2 = b_in * h_in; } else { Ag_in2 = Math.PI * (D_in**2) / 4; } let As_in2 = 0; if(state.steelMode === 'pct'){ const rho = Number(el.rho.value)/100; As_in2 = rho * Ag_in2; } else { As_in2 = state.units==='us' ? Number(el.As.value) : conv.areaToIn2(Number(el.As.value)); } // Strength reduction factor const phi = tied ? 0.65 : 0.75; // Concentric nominal axial strength const P0n_kip = (0.85*fc_psi*(Ag_in2 - As_in2) + fy_psi*As_in2) / 1000.0; // psi*in^2 -> pounds -> /1000 = kips const phiP0 = phi * P0n_kip; // Pure bending nominal strengths (approximate) // Use As,t = As/2 (symmetric), singly reinforced approximation const As_t = As_in2 / 2; let Mnx0_kipin = 0; let Mny0_kipin = 0; if(shape==='rect'){ // About x: compression width b, depth h const bx = b_in, hx = h_in; const dx = hx - dPrime; const ax = (As_t * fy_psi) / (0.85 * fc_psi * Math.max(bx, 1e-9)); Mnx0_kipin = As_t * fy_psi * Math.max(dx - ax/2, 0) / 1000; // kip-in // About y: compression width h, depth b const by = h_in, hy = b_in; const dy = hy - dPrime; const ay = (As_t * fy_psi) / (0.85 * fc_psi * Math.max(by, 1e-9)); Mny0_kipin = As_t * fy_psi * Math.max(dy - ay/2, 0) / 1000; // kip-in } else { // Circular: equivalent rectangular width 0.85D; depth D const beff = 0.85 * D_in; const d = D_in - dPrime; const a = (As_t * fy_psi) / (0.85 * fc_psi * Math.max(beff, 1e-9)); const Mn = As_t * fy_psi * Math.max(d - a/2, 0) / 1000; // kip-in Mnx0_kipin = Mn; Mny0_kipin = Mn; } // Convert nominal moments to kip-ft const Mnx0_kipft = Mnx0_kipin / 12; const Mny0_kipft = Mny0_kipin / 12; const phiMnx0 = phi * Mnx0_kipft; const phiMny0 = phi * Mny0_kipft; // Bresler exponent const n = phiP0 > 0 ? Pu_kip / phiP0 : 1; const r = clamp(2 - n, 1, 2); // Interaction sides const left = Math.pow(phiMnx0>0 ? (Mux_kipft/phiMnx0) : Infinity, r) + Math.pow(phiMny0>0 ? (Muy_kipft/phiMny0) : Infinity, r); const right = Math.pow(Math.max(1 - (phiP0>0 ? Pu_kip/phiP0 : 1), 0), r); let U = left / (right>0 ? right : 1e-9); if(!isFinite(U)) U = 999; // Present results in chosen units for user function fmt(val, unit){ if(!isFinite(val)) return '—'; const abs = Math.abs(val); const digits = abs >= 1000 ? 0 : abs >= 100 ? 1 : 2; return `${val.toFixed(digits)} ${unit}`; } // Output conversions back to UI units // Areas const Ag_disp = state.units==='us' ? Ag_in2 : Ag_in2 / (0.0393700787**2); const As_disp = state.units==='us' ? As_in2 : As_in2 / (0.0393700787**2); el.resAg.textContent = fmt(Ag_disp, state.units==='us' ? 'in²' : 'mm²'); el.resAs.textContent = fmt(As_disp, state.units==='us' ? 'in²' : 'mm²'); el.resPhi.textContent = phi.toFixed(2); // Axial capacity const phiP0_disp = state.units==='us' ? phiP0 : phiP0 / 0.22480894387; // kip -> kN el.resPhiP0.textContent = fmt(phiP0_disp, state.units==='us' ? 'kip' : 'kN'); // Moments const phiMnx0_disp = state.units==='us' ? phiMnx0 : phiMnx0 / 0.737562149; // kip-ft -> kN-m const phiMny0_disp = state.units==='us' ? phiMny0 : phiMny0 / 0.737562149; el.resPhiMnx0.textContent = fmt(phiMnx0_disp, state.units==='us' ? 'kip-ft' : 'kN-m'); el.resPhiMny0.textContent = fmt(phiMny0_disp, state.units==='us' ? 'kip-ft' : 'kN-m'); el.resR.textContent = isFinite(r) ? r.toFixed(2) : '—'; el.resU.textContent = isFinite(U) ? (U>100 ? '>100' : U.toFixed(2)) : '—'; // Status badge const badge = document.createElement('span'); badge.className = `badge ${U <= 1 ? 'pass' : 'fail'}`; badge.textContent = U <= 1 ? 'PASS (U ≤ 1.0)' : 'FAIL (U > 1.0)'; el.resStatus.innerHTML = ''; el.resStatus.appendChild(badge); } // Reset function reset(){ // Clear only numeric inputs; keep toggles [el.b, el.h, el.D, el.fc, el.fy, el.rho, el.As, el.cover, el.db, el.Pu, el.Mux, el.Muy].forEach(inp=>{ if(!inp) return; if(inp === el.rho) { inp.value = 2.0; return; } if(inp === el.cover) { inp.value = state.units==='us' ? 1.5 : 40; return; } if(inp === el.db) { inp.value = state.units==='us' ? 1.0 : 25; return; } inp.value = ''; clearError(inp); }); // Clear results [el.resAg, el.resAs, el.resPhi, el.resPhiP0, el.resPhiMnx0, el.resPhiMny0, el.resR, el.resU].forEach(n=> n.textContent='—'); el.resStatus.innerHTML = '<span class="badge">—</span>'; } // Attach el.calcBtn.addEventListener('click', compute); el.resetBtn.addEventListener('click', reset); // Recompute on change for responsiveness (without spamming errors)\]
('input, select').forEach(inp=>{ inp.addEventListener('blur', ()=> validateField(inp)); }); // Conversions const conv = { // Return consistent internal units: // US: in, kip, psi; Metric: mm, kN, MPa lenToIn: (x) => state.units==='us' ? x : x * 0.0393700787, inToLen: (x) => state.units==='us' ? x : x / 0.0393700787, areaToIn2: (x) => state.units==='us' ? x : x * (0.0393700787**2), // Forces: kip vs kN forceToKip: (x) => state.units==='us' ? x : x * 0.22480894387, // kN to kip // Moments: kip-ft vs kN-m momentToKipFt: (x) => state.units==='us' ? x : x * 0.737562149, // kN-m to kip-ft // Stresses: psi vs MPa fcToPsi: (x) => state.units==='us' ? x : x * 145.0377377, // MPa to psi fyToPsi: (x) => state.units==='us' ? x*1000 : x * 145.0377377 // ksi to psi if US; MPa to psi if metric }; // Calculation core function compute(){ if(!validateAll(true)) return; // Read inputs (convert to internal US units: in, psi, kip, kip-ft) const shape = state.shape; const tied = state.tieType === 'tied'; const b_in = shape==='rect' ? conv.lenToIn(Number(el.b.value)) : null; const h_in = shape==='rect' ? conv.lenToIn(Number(el.h.value)) : null; const D_in = shape==='circ' ? conv.lenToIn(Number(el.D.value)) : null; const fc_psi = conv.fcToPsi(Number(el.fc.value)); const fy_psi = conv.fyToPsi(Number(el.fy.value)); // psi const cover_in = conv.lenToIn(Number(el.cover.value)); const db_in = conv.lenToIn(Number(el.db.value)); const dPrime = cover_in + db_in/2; const Pu_kip = conv.forceToKip(Number(el.Pu.value)); const Mux_kipft = conv.momentToKipFt(Number(el.Mux.value)); const Muy_kipft = conv.momentToKipFt(Number(el.Muy.value)); let Ag_in2 = 0; if(shape==='rect'){ Ag_in2 = b_in * h_in; } else { Ag_in2 = Math.PI * (D_in**2) / 4; } let As_in2 = 0; if(state.steelMode === 'pct'){ const rho = Number(el.rho.value)/100; As_in2 = rho * Ag_in2; } else { As_in2 = state.units==='us' ? Number(el.As.value) : conv.areaToIn2(Number(el.As.value)); } // Strength reduction factor const phi = tied ? 0.65 : 0.75; // Concentric nominal axial strength const P0n_kip = (0.85*fc_psi*(Ag_in2 - As_in2) + fy_psi*As_in2) / 1000.0; // psi*in^2 -> pounds -> /1000 = kips const phiP0 = phi * P0n_kip; // Pure bending nominal strengths (approximate) // Use As,t = As/2 (symmetric), singly reinforced approximation const As_t = As_in2 / 2; let Mnx0_kipin = 0; let Mny0_kipin = 0; if(shape==='rect'){ // About x: compression width b, depth h const bx = b_in, hx = h_in; const dx = hx - dPrime; const ax = (As_t * fy_psi) / (0.85 * fc_psi * Math.max(bx, 1e-9)); Mnx0_kipin = As_t * fy_psi * Math.max(dx - ax/2, 0) / 1000; // kip-in // About y: compression width h, depth b const by = h_in, hy = b_in; const dy = hy - dPrime; const ay = (As_t * fy_psi) / (0.85 * fc_psi * Math.max(by, 1e-9)); Mny0_kipin = As_t * fy_psi * Math.max(dy - ay/2, 0) / 1000; // kip-in } else { // Circular: equivalent rectangular width 0.85D; depth D const beff = 0.85 * D_in; const d = D_in - dPrime; const a = (As_t * fy_psi) / (0.85 * fc_psi * Math.max(beff, 1e-9)); const Mn = As_t * fy_psi * Math.max(d - a/2, 0) / 1000; // kip-in Mnx0_kipin = Mn; Mny0_kipin = Mn; } // Convert nominal moments to kip-ft const Mnx0_kipft = Mnx0_kipin / 12; const Mny0_kipft = Mny0_kipin / 12; const phiMnx0 = phi * Mnx0_kipft; const phiMny0 = phi * Mny0_kipft; // Bresler exponent const n = phiP0 > 0 ? Pu_kip / phiP0 : 1; const r = clamp(2 - n, 1, 2); // Interaction sides const left = Math.pow(phiMnx0>0 ? (Mux_kipft/phiMnx0) : Infinity, r) + Math.pow(phiMny0>0 ? (Muy_kipft/phiMny0) : Infinity, r); const right = Math.pow(Math.max(1 - (phiP0>0 ? Pu_kip/phiP0 : 1), 0), r); let U = left / (right>0 ? right : 1e-9); if(!isFinite(U)) U = 999; // Present results in chosen units for user function fmt(val, unit){ if(!isFinite(val)) return '—'; const abs = Math.abs(val); const digits = abs >= 1000 ? 0 : abs >= 100 ? 1 : 2; return `${val.toFixed(digits)} ${unit}`; } // Output conversions back to UI units // Areas const Ag_disp = state.units==='us' ? Ag_in2 : Ag_in2 / (0.0393700787**2); const As_disp = state.units==='us' ? As_in2 : As_in2 / (0.0393700787**2); el.resAg.textContent = fmt(Ag_disp, state.units==='us' ? 'in²' : 'mm²'); el.resAs.textContent = fmt(As_disp, state.units==='us' ? 'in²' : 'mm²'); el.resPhi.textContent = phi.toFixed(2); // Axial capacity const phiP0_disp = state.units==='us' ? phiP0 : phiP0 / 0.22480894387; // kip -> kN el.resPhiP0.textContent = fmt(phiP0_disp, state.units==='us' ? 'kip' : 'kN'); // Moments const phiMnx0_disp = state.units==='us' ? phiMnx0 : phiMnx0 / 0.737562149; // kip-ft -> kN-m const phiMny0_disp = state.units==='us' ? phiMny0 : phiMny0 / 0.737562149; el.resPhiMnx0.textContent = fmt(phiMnx0_disp, state.units==='us' ? 'kip-ft' : 'kN-m'); el.resPhiMny0.textContent = fmt(phiMny0_disp, state.units==='us' ? 'kip-ft' : 'kN-m'); el.resR.textContent = isFinite(r) ? r.toFixed(2) : '—'; el.resU.textContent = isFinite(U) ? (U>100 ? '>100' : U.toFixed(2)) : '—'; // Status badge const badge = document.createElement('span'); badge.className = `badge ${U <= 1 ? 'pass' : 'fail'}`; badge.textContent = U <= 1 ? 'PASS (U ≤ 1.0)' : 'FAIL (U > 1.0)'; el.resStatus.innerHTML = ''; el.resStatus.appendChild(badge); } // Reset function reset(){ // Clear only numeric inputs; keep toggles [el.b, el.h, el.D, el.fc, el.fy, el.rho, el.As, el.cover, el.db, el.Pu, el.Mux, el.Muy].forEach(inp=>{ if(!inp) return; if(inp === el.rho) { inp.value = 2.0; return; } if(inp === el.cover) { inp.value = state.units==='us' ? 1.5 : 40; return; } if(inp === el.db) { inp.value = state.units==='us' ? 1.0 : 25; return; } inp.value = ''; clearError(inp); }); // Clear results [el.resAg, el.resAs, el.resPhi, el.resPhiP0, el.resPhiMnx0, el.resPhiMny0, el.resR, el.resU].forEach(n=> n.textContent='—'); el.resStatus.innerHTML = '<span class="badge">—</span>'; } // Attach el.calcBtn.addEventListener('click', compute); el.resetBtn.addEventListener('click', reset); // Recompute on change for responsiveness (without spamming errors)
Formula (extracted text)
Gross area: Rectangular: Ag = b · h Circular: Ag = \(\frac{\pi D^2}{4}\) Steel area (percentage mode): \(A_s = \rho \cdot A_g\), where \(\rho = \frac{\text{percent}}{100}\) Concentric nominal axial strength: \(P_{0n} = 0.85\,f'_c\,(A_g - A_s) + f_y A_s\) Strength reduction factor (compression-controlled): \(\phi = 0.65\) (tied), \(\phi = 0.75\) (spiral) Pure bending nominal strength (rectangular approximation, symmetric layout, half steel in tension): \(a = \dfrac{A_{s,t} f_y}{0.85 f'_c\, b}\), \(M_n = A_{s,t} f_y \left( d - \tfrac{a}{2} \right)\) For bending about x: use width \(b_x = b\), effective depth \(d_x = h - d'\). For bending about y: use width \(b_y = h\), effective depth \(d_y = b - d'\). For circular sections (approximation): use \(b_{\text{eff}} = 0.85 D\) and \(d = D - d'\). Biaxial (Bresler-type) interaction: \(\left(\dfrac{M_{ux}}{\phi M_{nx0}}\right)^r + \left(\dfrac{M_{uy}}{\phi M_{ny0}}\right)^r \le \left(1 - \dfrac{P_u}{\phi P_{0n}}\right)^r\), where \(1 \le r \le 2\) and \(r = 2 - \dfrac{P_u}{\phi P_{0n}}\)
Variables and units
  • No variables provided in audit spec.
Sources (authoritative):
Changelog
Version: 0.1.0-draft
Last code update: 2026-01-19
0.1.0-draft · 2026-01-19
  • Initial audit spec draft generated from HTML extraction (review required).
  • Verify formulas match the calculator engine and convert any text-only formulas to LaTeX.
  • Confirm sources are authoritative and relevant to the calculator methodology.
Verified by Ugo Candido on 2026-01-19
Profile · LinkedIn
]], displayMath: [['\\[','\\]']] }, svg: { fontCache: 'global' } };, svg: { fontCache: 'global' } };

ACI 318 Concrete Column Design Calculator

Design-check reinforced concrete columns per ACI 318 using a clear, mobile-first tool. Enter geometry, materials, reinforcement, and factored loads. The calculator estimates axial and biaxial capacity using a simplified Bresler interaction and reports pass/fail with utilization.

Calculator Inputs

Units
Section shape
Transverse reinforcement
in
in
psi
ksi
Longitudinal steel input mode
%
in
in
kip
kip-ft
kip-ft

Results

Gross area Ag
Steel area As
Strength reduction factor φ
Concentric capacity φP0
Pure-bending φMnx0
Pure-bending φMny0
Bresler exponent r
Utilization ratio U
Status

Note: This is a preliminary design check using simplified assumptions. Slenderness, second-order (P-Δ/P-δ), load duration, and detailed bar placement are not included.

Data Source and Methodology

Authoritative source: ACI Committee 318. “Building Code Requirements for Structural Concrete (ACI 318-19) and Commentary.” American Concrete Institute, 2019. Official reference.

Tutti i calcoli si basano rigorosamente sulle formule e sui dati forniti da questa fonte.

The Formula Explained

Gross area:

Rectangular: Ag = b · h

Circular: Ag = \(\frac{\pi D^2}{4}\)

Steel area (percentage mode): \(A_s = \rho \cdot A_g\), where \(\rho = \frac{\text{percent}}{100}\)

Concentric nominal axial strength:

\(P_{0n} = 0.85\,f'_c\,(A_g - A_s) + f_y A_s\)

Strength reduction factor (compression-controlled):

\(\phi = 0.65\) (tied), \(\phi = 0.75\) (spiral)

Pure bending nominal strength (rectangular approximation, symmetric layout, half steel in tension):

\(a = \dfrac{A_{s,t} f_y}{0.85 f'_c\, b}\),   \(M_n = A_{s,t} f_y \left( d - \tfrac{a}{2} \right)\)

For bending about x: use width \(b_x = b\), effective depth \(d_x = h - d'\).

For bending about y: use width \(b_y = h\), effective depth \(d_y = b - d'\).

For circular sections (approximation): use \(b_{\text{eff}} = 0.85 D\) and \(d = D - d'\).

Biaxial (Bresler-type) interaction:

\(\left(\dfrac{M_{ux}}{\phi M_{nx0}}\right)^r + \left(\dfrac{M_{uy}}{\phi M_{ny0}}\right)^r \le \left(1 - \dfrac{P_u}{\phi P_{0n}}\right)^r\), where \(1 \le r \le 2\) and \(r = 2 - \dfrac{P_u}{\phi P_{0n}}\)

Glossary of Variables

How It Works: A Step-by-Step Example

  1. Select Units = US, Shape = Rectangular, Ties = Tied (φ = 0.65).
  2. Enter b = 16 in, h = 20 in; f'c = 4000 psi; fy = 60 ksi.
  3. Steel mode = As %, ρ = 2.0%; cover c = 1.5 in; bar diameter db = 1.0 in.
  4. Loads: Pu = 400 kip; Mux = 150 kip-ft; Muy = 80 kip-ft.
  5. The tool computes:
    • Ag = 320 in²; As = 6.4 in²; φ = 0.65.
    • φP0 = φ[0.85·4000(320 − 6.4) + 60,000·6.4] ≈ reported in Results.
    • d' = 1.5 + 0.5 = 2.0 in; d_x = 20 − 2 = 18 in; d_y = 16 − 2 = 14 in.
    • Assuming As,t = As/2 = 3.2 in²: a_x = (3.2·60,000)/(0.85·4000·16), and Mn_x0 = As,t·fy(d_x − a_x/2). Similarly for y with b_y = 20 and d_y = 14.
    • Compute r = 2 − Pu/(φP0) clamped [1,2].
    • Check (Mux/φMnx0)^r + (Muy/φMny0)^r ≤ (1 − Pu/φP0)^r; report U and pass/fail.
    Compare with the Results panel for the exact numbers.

Frequently Asked Questions (FAQ)

Does this calculator include slenderness and second-order effects?

No. Slenderness and P-Δ/P-δ effects per ACI 318 (including moment magnifiers) are not included. Use this tool for preliminary checks and apply full code procedures for final design.

How accurate is the pure-bending approximation?

It is conservative for symmetric reinforcement because it neglects compression steel contribution and assumes half of As acts in tension. For final design, use full strain compatibility analysis with your exact bar layout.

Can I input different steel on each face?

Not in this version. Total As is assumed symmetric. Future updates may allow per-face bar counts and positions.

What if U is slightly above 1.0?

Consider increasing member size, raising steel ratio, improving material strengths (within code limits), or reducing loads. Always re-check with full code procedures.

Why is φ different for tied vs. spiral columns?

Spiral confinement generally improves ductility and strength, allowing a higher φ per ACI 318.

How do I choose b and h vs. x and y axes?

In this tool, Mux uses b as the compression block width and h as the effective depth; for Muy, they swap. Ensure your axis convention matches the input geometry.


Audit: Complete
Formula (LaTeX) + variables + units
This section shows the formulas used by the calculator engine, plus variable definitions and units.
Formula (extracted LaTeX)
\[','\]
','
Formula (extracted LaTeX)
\[= (sel, root=document) => Array.from(root.querySelectorAll(sel)); const clamp = (v,min,max)=> Math.max(min, Math.min(max, v)); // Elements const state = { units: 'us', shape: 'rect', tieType: 'tied', steelMode: 'pct' }; const el = { // groups dimRect1: $('#dim-rect'), dimRect2: $('#dim-rect-2'), dimCirc: $('#dim-circ'), groupRho: $('#group-rho'), groupAs: $('#group-As'), // inputs b: $('#b'), h: $('#h'), D: $('#D'), fc: $('#fc'), fy: $('#fy'), rho: $('#rho'), As: $('#As'), cover: $('#cover'), db: $('#db'), Pu: $('#Pu'), Mux: $('#Mux'), Muy: $('#Muy'), // units spans u: { b: $('#unit-b'), h: $('#unit-h'), D: $('#unit-D'), fc: $('#unit-fc'), fy: $('#unit-fy'), As: $('#unit-As'), cover: $('#unit-cover'), db: $('#unit-db'), Pu: $('#unit-Pu'), Mu: $('#unit-Mu'), Mu2: $('#unit-Mu2') }, // results resAg: $('#resAg'), resAs: $('#resAs'), resPhi: $('#resPhi'), resPhiP0: $('#resPhiP0'), resPhiMnx0: $('#resPhiMnx0'), resPhiMny0: $('#resPhiMny0'), resR: $('#resR'), resU: $('#resU'), resStatus: $('#resStatus'), // buttons calcBtn: $('#calcBtn'), resetBtn: $('#resetBtn') }; // Accessible tooltips\]
= (sel, root=document) => Array.from(root.querySelectorAll(sel)); const clamp = (v,min,max)=> Math.max(min, Math.min(max, v)); // Elements const state = { units: 'us', shape: 'rect', tieType: 'tied', steelMode: 'pct' }; const el = { // groups dimRect1: $('#dim-rect'), dimRect2: $('#dim-rect-2'), dimCirc: $('#dim-circ'), groupRho: $('#group-rho'), groupAs: $('#group-As'), // inputs b: $('#b'), h: $('#h'), D: $('#D'), fc: $('#fc'), fy: $('#fy'), rho: $('#rho'), As: $('#As'), cover: $('#cover'), db: $('#db'), Pu: $('#Pu'), Mux: $('#Mux'), Muy: $('#Muy'), // units spans u: { b: $('#unit-b'), h: $('#unit-h'), D: $('#unit-D'), fc: $('#unit-fc'), fy: $('#unit-fy'), As: $('#unit-As'), cover: $('#unit-cover'), db: $('#unit-db'), Pu: $('#unit-Pu'), Mu: $('#unit-Mu'), Mu2: $('#unit-Mu2') }, // results resAg: $('#resAg'), resAs: $('#resAs'), resPhi: $('#resPhi'), resPhiP0: $('#resPhiP0'), resPhiMnx0: $('#resPhiMnx0'), resPhiMny0: $('#resPhiMny0'), resR: $('#resR'), resU: $('#resU'), resStatus: $('#resStatus'), // buttons calcBtn: $('#calcBtn'), resetBtn: $('#resetBtn') }; // Accessible tooltips
Formula (extracted LaTeX)
\[('input[name="units"]').forEach(r=> r.addEventListener('change', e=>{ state.units = e.target.value; applyUnits(); validateAll(false); }));\]
('input[name="units"]').forEach(r=> r.addEventListener('change', e=>{ state.units = e.target.value; applyUnits(); validateAll(false); }));
Formula (extracted LaTeX)
\[('input[name="tieType"]').forEach(r=> r.addEventListener('change', e=>{ state.tieType = e.target.value; }));\]
('input[name="tieType"]').forEach(r=> r.addEventListener('change', e=>{ state.tieType = e.target.value; }));
Formula (extracted LaTeX)
\[('input, select').forEach(inp=>{ inp.addEventListener('blur', ()=> validateField(inp)); }); // Conversions const conv = { // Return consistent internal units: // US: in, kip, psi; Metric: mm, kN, MPa lenToIn: (x) => state.units==='us' ? x : x * 0.0393700787, inToLen: (x) => state.units==='us' ? x : x / 0.0393700787, areaToIn2: (x) => state.units==='us' ? x : x * (0.0393700787**2), // Forces: kip vs kN forceToKip: (x) => state.units==='us' ? x : x * 0.22480894387, // kN to kip // Moments: kip-ft vs kN-m momentToKipFt: (x) => state.units==='us' ? x : x * 0.737562149, // kN-m to kip-ft // Stresses: psi vs MPa fcToPsi: (x) => state.units==='us' ? x : x * 145.0377377, // MPa to psi fyToPsi: (x) => state.units==='us' ? x*1000 : x * 145.0377377 // ksi to psi if US; MPa to psi if metric }; // Calculation core function compute(){ if(!validateAll(true)) return; // Read inputs (convert to internal US units: in, psi, kip, kip-ft) const shape = state.shape; const tied = state.tieType === 'tied'; const b_in = shape==='rect' ? conv.lenToIn(Number(el.b.value)) : null; const h_in = shape==='rect' ? conv.lenToIn(Number(el.h.value)) : null; const D_in = shape==='circ' ? conv.lenToIn(Number(el.D.value)) : null; const fc_psi = conv.fcToPsi(Number(el.fc.value)); const fy_psi = conv.fyToPsi(Number(el.fy.value)); // psi const cover_in = conv.lenToIn(Number(el.cover.value)); const db_in = conv.lenToIn(Number(el.db.value)); const dPrime = cover_in + db_in/2; const Pu_kip = conv.forceToKip(Number(el.Pu.value)); const Mux_kipft = conv.momentToKipFt(Number(el.Mux.value)); const Muy_kipft = conv.momentToKipFt(Number(el.Muy.value)); let Ag_in2 = 0; if(shape==='rect'){ Ag_in2 = b_in * h_in; } else { Ag_in2 = Math.PI * (D_in**2) / 4; } let As_in2 = 0; if(state.steelMode === 'pct'){ const rho = Number(el.rho.value)/100; As_in2 = rho * Ag_in2; } else { As_in2 = state.units==='us' ? Number(el.As.value) : conv.areaToIn2(Number(el.As.value)); } // Strength reduction factor const phi = tied ? 0.65 : 0.75; // Concentric nominal axial strength const P0n_kip = (0.85*fc_psi*(Ag_in2 - As_in2) + fy_psi*As_in2) / 1000.0; // psi*in^2 -> pounds -> /1000 = kips const phiP0 = phi * P0n_kip; // Pure bending nominal strengths (approximate) // Use As,t = As/2 (symmetric), singly reinforced approximation const As_t = As_in2 / 2; let Mnx0_kipin = 0; let Mny0_kipin = 0; if(shape==='rect'){ // About x: compression width b, depth h const bx = b_in, hx = h_in; const dx = hx - dPrime; const ax = (As_t * fy_psi) / (0.85 * fc_psi * Math.max(bx, 1e-9)); Mnx0_kipin = As_t * fy_psi * Math.max(dx - ax/2, 0) / 1000; // kip-in // About y: compression width h, depth b const by = h_in, hy = b_in; const dy = hy - dPrime; const ay = (As_t * fy_psi) / (0.85 * fc_psi * Math.max(by, 1e-9)); Mny0_kipin = As_t * fy_psi * Math.max(dy - ay/2, 0) / 1000; // kip-in } else { // Circular: equivalent rectangular width 0.85D; depth D const beff = 0.85 * D_in; const d = D_in - dPrime; const a = (As_t * fy_psi) / (0.85 * fc_psi * Math.max(beff, 1e-9)); const Mn = As_t * fy_psi * Math.max(d - a/2, 0) / 1000; // kip-in Mnx0_kipin = Mn; Mny0_kipin = Mn; } // Convert nominal moments to kip-ft const Mnx0_kipft = Mnx0_kipin / 12; const Mny0_kipft = Mny0_kipin / 12; const phiMnx0 = phi * Mnx0_kipft; const phiMny0 = phi * Mny0_kipft; // Bresler exponent const n = phiP0 > 0 ? Pu_kip / phiP0 : 1; const r = clamp(2 - n, 1, 2); // Interaction sides const left = Math.pow(phiMnx0>0 ? (Mux_kipft/phiMnx0) : Infinity, r) + Math.pow(phiMny0>0 ? (Muy_kipft/phiMny0) : Infinity, r); const right = Math.pow(Math.max(1 - (phiP0>0 ? Pu_kip/phiP0 : 1), 0), r); let U = left / (right>0 ? right : 1e-9); if(!isFinite(U)) U = 999; // Present results in chosen units for user function fmt(val, unit){ if(!isFinite(val)) return '—'; const abs = Math.abs(val); const digits = abs >= 1000 ? 0 : abs >= 100 ? 1 : 2; return `${val.toFixed(digits)} ${unit}`; } // Output conversions back to UI units // Areas const Ag_disp = state.units==='us' ? Ag_in2 : Ag_in2 / (0.0393700787**2); const As_disp = state.units==='us' ? As_in2 : As_in2 / (0.0393700787**2); el.resAg.textContent = fmt(Ag_disp, state.units==='us' ? 'in²' : 'mm²'); el.resAs.textContent = fmt(As_disp, state.units==='us' ? 'in²' : 'mm²'); el.resPhi.textContent = phi.toFixed(2); // Axial capacity const phiP0_disp = state.units==='us' ? phiP0 : phiP0 / 0.22480894387; // kip -> kN el.resPhiP0.textContent = fmt(phiP0_disp, state.units==='us' ? 'kip' : 'kN'); // Moments const phiMnx0_disp = state.units==='us' ? phiMnx0 : phiMnx0 / 0.737562149; // kip-ft -> kN-m const phiMny0_disp = state.units==='us' ? phiMny0 : phiMny0 / 0.737562149; el.resPhiMnx0.textContent = fmt(phiMnx0_disp, state.units==='us' ? 'kip-ft' : 'kN-m'); el.resPhiMny0.textContent = fmt(phiMny0_disp, state.units==='us' ? 'kip-ft' : 'kN-m'); el.resR.textContent = isFinite(r) ? r.toFixed(2) : '—'; el.resU.textContent = isFinite(U) ? (U>100 ? '>100' : U.toFixed(2)) : '—'; // Status badge const badge = document.createElement('span'); badge.className = `badge ${U <= 1 ? 'pass' : 'fail'}`; badge.textContent = U <= 1 ? 'PASS (U ≤ 1.0)' : 'FAIL (U > 1.0)'; el.resStatus.innerHTML = ''; el.resStatus.appendChild(badge); } // Reset function reset(){ // Clear only numeric inputs; keep toggles [el.b, el.h, el.D, el.fc, el.fy, el.rho, el.As, el.cover, el.db, el.Pu, el.Mux, el.Muy].forEach(inp=>{ if(!inp) return; if(inp === el.rho) { inp.value = 2.0; return; } if(inp === el.cover) { inp.value = state.units==='us' ? 1.5 : 40; return; } if(inp === el.db) { inp.value = state.units==='us' ? 1.0 : 25; return; } inp.value = ''; clearError(inp); }); // Clear results [el.resAg, el.resAs, el.resPhi, el.resPhiP0, el.resPhiMnx0, el.resPhiMny0, el.resR, el.resU].forEach(n=> n.textContent='—'); el.resStatus.innerHTML = '<span class="badge">—</span>'; } // Attach el.calcBtn.addEventListener('click', compute); el.resetBtn.addEventListener('click', reset); // Recompute on change for responsiveness (without spamming errors)\]
('input, select').forEach(inp=>{ inp.addEventListener('blur', ()=> validateField(inp)); }); // Conversions const conv = { // Return consistent internal units: // US: in, kip, psi; Metric: mm, kN, MPa lenToIn: (x) => state.units==='us' ? x : x * 0.0393700787, inToLen: (x) => state.units==='us' ? x : x / 0.0393700787, areaToIn2: (x) => state.units==='us' ? x : x * (0.0393700787**2), // Forces: kip vs kN forceToKip: (x) => state.units==='us' ? x : x * 0.22480894387, // kN to kip // Moments: kip-ft vs kN-m momentToKipFt: (x) => state.units==='us' ? x : x * 0.737562149, // kN-m to kip-ft // Stresses: psi vs MPa fcToPsi: (x) => state.units==='us' ? x : x * 145.0377377, // MPa to psi fyToPsi: (x) => state.units==='us' ? x*1000 : x * 145.0377377 // ksi to psi if US; MPa to psi if metric }; // Calculation core function compute(){ if(!validateAll(true)) return; // Read inputs (convert to internal US units: in, psi, kip, kip-ft) const shape = state.shape; const tied = state.tieType === 'tied'; const b_in = shape==='rect' ? conv.lenToIn(Number(el.b.value)) : null; const h_in = shape==='rect' ? conv.lenToIn(Number(el.h.value)) : null; const D_in = shape==='circ' ? conv.lenToIn(Number(el.D.value)) : null; const fc_psi = conv.fcToPsi(Number(el.fc.value)); const fy_psi = conv.fyToPsi(Number(el.fy.value)); // psi const cover_in = conv.lenToIn(Number(el.cover.value)); const db_in = conv.lenToIn(Number(el.db.value)); const dPrime = cover_in + db_in/2; const Pu_kip = conv.forceToKip(Number(el.Pu.value)); const Mux_kipft = conv.momentToKipFt(Number(el.Mux.value)); const Muy_kipft = conv.momentToKipFt(Number(el.Muy.value)); let Ag_in2 = 0; if(shape==='rect'){ Ag_in2 = b_in * h_in; } else { Ag_in2 = Math.PI * (D_in**2) / 4; } let As_in2 = 0; if(state.steelMode === 'pct'){ const rho = Number(el.rho.value)/100; As_in2 = rho * Ag_in2; } else { As_in2 = state.units==='us' ? Number(el.As.value) : conv.areaToIn2(Number(el.As.value)); } // Strength reduction factor const phi = tied ? 0.65 : 0.75; // Concentric nominal axial strength const P0n_kip = (0.85*fc_psi*(Ag_in2 - As_in2) + fy_psi*As_in2) / 1000.0; // psi*in^2 -> pounds -> /1000 = kips const phiP0 = phi * P0n_kip; // Pure bending nominal strengths (approximate) // Use As,t = As/2 (symmetric), singly reinforced approximation const As_t = As_in2 / 2; let Mnx0_kipin = 0; let Mny0_kipin = 0; if(shape==='rect'){ // About x: compression width b, depth h const bx = b_in, hx = h_in; const dx = hx - dPrime; const ax = (As_t * fy_psi) / (0.85 * fc_psi * Math.max(bx, 1e-9)); Mnx0_kipin = As_t * fy_psi * Math.max(dx - ax/2, 0) / 1000; // kip-in // About y: compression width h, depth b const by = h_in, hy = b_in; const dy = hy - dPrime; const ay = (As_t * fy_psi) / (0.85 * fc_psi * Math.max(by, 1e-9)); Mny0_kipin = As_t * fy_psi * Math.max(dy - ay/2, 0) / 1000; // kip-in } else { // Circular: equivalent rectangular width 0.85D; depth D const beff = 0.85 * D_in; const d = D_in - dPrime; const a = (As_t * fy_psi) / (0.85 * fc_psi * Math.max(beff, 1e-9)); const Mn = As_t * fy_psi * Math.max(d - a/2, 0) / 1000; // kip-in Mnx0_kipin = Mn; Mny0_kipin = Mn; } // Convert nominal moments to kip-ft const Mnx0_kipft = Mnx0_kipin / 12; const Mny0_kipft = Mny0_kipin / 12; const phiMnx0 = phi * Mnx0_kipft; const phiMny0 = phi * Mny0_kipft; // Bresler exponent const n = phiP0 > 0 ? Pu_kip / phiP0 : 1; const r = clamp(2 - n, 1, 2); // Interaction sides const left = Math.pow(phiMnx0>0 ? (Mux_kipft/phiMnx0) : Infinity, r) + Math.pow(phiMny0>0 ? (Muy_kipft/phiMny0) : Infinity, r); const right = Math.pow(Math.max(1 - (phiP0>0 ? Pu_kip/phiP0 : 1), 0), r); let U = left / (right>0 ? right : 1e-9); if(!isFinite(U)) U = 999; // Present results in chosen units for user function fmt(val, unit){ if(!isFinite(val)) return '—'; const abs = Math.abs(val); const digits = abs >= 1000 ? 0 : abs >= 100 ? 1 : 2; return `${val.toFixed(digits)} ${unit}`; } // Output conversions back to UI units // Areas const Ag_disp = state.units==='us' ? Ag_in2 : Ag_in2 / (0.0393700787**2); const As_disp = state.units==='us' ? As_in2 : As_in2 / (0.0393700787**2); el.resAg.textContent = fmt(Ag_disp, state.units==='us' ? 'in²' : 'mm²'); el.resAs.textContent = fmt(As_disp, state.units==='us' ? 'in²' : 'mm²'); el.resPhi.textContent = phi.toFixed(2); // Axial capacity const phiP0_disp = state.units==='us' ? phiP0 : phiP0 / 0.22480894387; // kip -> kN el.resPhiP0.textContent = fmt(phiP0_disp, state.units==='us' ? 'kip' : 'kN'); // Moments const phiMnx0_disp = state.units==='us' ? phiMnx0 : phiMnx0 / 0.737562149; // kip-ft -> kN-m const phiMny0_disp = state.units==='us' ? phiMny0 : phiMny0 / 0.737562149; el.resPhiMnx0.textContent = fmt(phiMnx0_disp, state.units==='us' ? 'kip-ft' : 'kN-m'); el.resPhiMny0.textContent = fmt(phiMny0_disp, state.units==='us' ? 'kip-ft' : 'kN-m'); el.resR.textContent = isFinite(r) ? r.toFixed(2) : '—'; el.resU.textContent = isFinite(U) ? (U>100 ? '>100' : U.toFixed(2)) : '—'; // Status badge const badge = document.createElement('span'); badge.className = `badge ${U <= 1 ? 'pass' : 'fail'}`; badge.textContent = U <= 1 ? 'PASS (U ≤ 1.0)' : 'FAIL (U > 1.0)'; el.resStatus.innerHTML = ''; el.resStatus.appendChild(badge); } // Reset function reset(){ // Clear only numeric inputs; keep toggles [el.b, el.h, el.D, el.fc, el.fy, el.rho, el.As, el.cover, el.db, el.Pu, el.Mux, el.Muy].forEach(inp=>{ if(!inp) return; if(inp === el.rho) { inp.value = 2.0; return; } if(inp === el.cover) { inp.value = state.units==='us' ? 1.5 : 40; return; } if(inp === el.db) { inp.value = state.units==='us' ? 1.0 : 25; return; } inp.value = ''; clearError(inp); }); // Clear results [el.resAg, el.resAs, el.resPhi, el.resPhiP0, el.resPhiMnx0, el.resPhiMny0, el.resR, el.resU].forEach(n=> n.textContent='—'); el.resStatus.innerHTML = '<span class="badge">—</span>'; } // Attach el.calcBtn.addEventListener('click', compute); el.resetBtn.addEventListener('click', reset); // Recompute on change for responsiveness (without spamming errors)
Formula (extracted text)
Gross area: Rectangular: Ag = b · h Circular: Ag = \(\frac{\pi D^2}{4}\) Steel area (percentage mode): \(A_s = \rho \cdot A_g\), where \(\rho = \frac{\text{percent}}{100}\) Concentric nominal axial strength: \(P_{0n} = 0.85\,f'_c\,(A_g - A_s) + f_y A_s\) Strength reduction factor (compression-controlled): \(\phi = 0.65\) (tied), \(\phi = 0.75\) (spiral) Pure bending nominal strength (rectangular approximation, symmetric layout, half steel in tension): \(a = \dfrac{A_{s,t} f_y}{0.85 f'_c\, b}\), \(M_n = A_{s,t} f_y \left( d - \tfrac{a}{2} \right)\) For bending about x: use width \(b_x = b\), effective depth \(d_x = h - d'\). For bending about y: use width \(b_y = h\), effective depth \(d_y = b - d'\). For circular sections (approximation): use \(b_{\text{eff}} = 0.85 D\) and \(d = D - d'\). Biaxial (Bresler-type) interaction: \(\left(\dfrac{M_{ux}}{\phi M_{nx0}}\right)^r + \left(\dfrac{M_{uy}}{\phi M_{ny0}}\right)^r \le \left(1 - \dfrac{P_u}{\phi P_{0n}}\right)^r\), where \(1 \le r \le 2\) and \(r = 2 - \dfrac{P_u}{\phi P_{0n}}\)
Variables and units
  • No variables provided in audit spec.
Sources (authoritative):
Changelog
Version: 0.1.0-draft
Last code update: 2026-01-19
0.1.0-draft · 2026-01-19
  • Initial audit spec draft generated from HTML extraction (review required).
  • Verify formulas match the calculator engine and convert any text-only formulas to LaTeX.
  • Confirm sources are authoritative and relevant to the calculator methodology.
Verified by Ugo Candido on 2026-01-19
Profile · LinkedIn