import type { PileCapGeometry, MaterialProperties, PileReaction, LoadCombinationResult } from '../types/pileCap'; export interface BearingResults { columnBearing: { demand: number; capacity: number; ratio: number; pass: boolean; requiredDowels: number; }; pileBearing: { demand: number; capacity: number; ratio: number; pass: boolean; }; } export function performBearingChecks( geometry: PileCapGeometry, pileReactions: PileReaction[], materials: MaterialProperties, governingLoad: LoadCombinationResult ): BearingResults { const columnBearing = checkColumnBearing(geometry, materials, governingLoad); const pileBearing = checkPileBearing(geometry, pileReactions, materials); return { columnBearing, pileBearing }; } function checkColumnBearing( geometry: PileCapGeometry, materials: MaterialProperties, load: LoadCombinationResult ): { demand: number; capacity: number; ratio: number; pass: boolean; requiredDowels: number } { // Demand is the factored axial load from the column const demand = load.axialLoad; // kips // Area of column (A1) const A1 = geometry.columnLength * geometry.columnWidth; // in^2 // Supporting area of pile cap (A2) // Geometrically similar area concentric with A1 // Limited by edge of pile cap // Distance to edges: const distLeft = geometry.length * 12 / 2 + geometry.columnOffsetX * 12 - geometry.columnLength / 2; const distRight = geometry.length * 12 / 2 - geometry.columnOffsetX * 12 - geometry.columnLength / 2; const distTop = geometry.width * 12 / 2 - geometry.columnOffsetZ * 12 - geometry.columnWidth / 2; const distBottom = geometry.width * 12 / 2 + geometry.columnOffsetZ * 12 - geometry.columnWidth / 2; const expandX = Math.min(distLeft, distRight); const expandZ = Math.min(distTop, distBottom); const maxExpandX = geometry.columnLength + 2 * expandX; const maxExpandZ = geometry.columnWidth + 2 * expandZ; const A2 = maxExpandX * maxExpandZ; const confinementFactor = Math.min(Math.sqrt(A2 / A1), 2); // Nominal Bearing Strength // Bn = 0.85 * fc * A1 * confinementFactor const Bn = 0.85 * materials.fc * A1 * confinementFactor / 1000; // kips // Design Strength const phiBn = materials.phiBearing * Bn; const ratio = demand / phiBn; const pass = ratio <= 1.0; // Required Dowels let requiredDowels = 0.005 * A1; // Minimum if (!pass) { const excessLoad = demand - phiBn; // fy is in psi. excessLoad is kips. // required = excessLoad * 1000 / (phi * fy) const strengthDowels = (excessLoad * 1000) / (materials.phiBearing * materials.fy); requiredDowels = Math.max(requiredDowels, strengthDowels); } return { demand, capacity: phiBn, ratio, pass, requiredDowels }; } function checkPileBearing( geometry: PileCapGeometry, pileReactions: PileReaction[], materials: MaterialProperties ): { demand: number; capacity: number; ratio: number; pass: boolean } { // Check the pile with the maximum reaction const maxReaction = Math.max(...pileReactions.map(p => p.reaction)); const demand = maxReaction; // kips // Bearing area on pile cap // Assuming pile bears on the cap concrete // Area = Pile Area let A1 = 0; if (geometry.pileType === 'Round') { A1 = Math.PI * Math.pow(geometry.pileSize / 2, 2); } else { A1 = Math.pow(geometry.pileSize, 2); } // Confinement? // Let's assume full confinement (factor = 2) for standard pile caps unless edge distance is tiny. const confinementFactor = 2; const Bn = 0.85 * materials.fc * A1 * confinementFactor / 1000; // kips const phiBn = materials.phiBearing * Bn; return { demand, capacity: phiBn, ratio: demand / phiBn, pass: demand <= phiBn }; }