Collection of engineering calculation projects (Python + Typst), each with input, calc script, tests, results, and generated PDF where available.
132 lines
4.2 KiB
Python
132 lines
4.2 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
import math
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
try:
|
|
import yaml
|
|
except ImportError:
|
|
raise SystemExit("Install PyYAML: python -m pip install pyyaml")
|
|
|
|
|
|
HERE = Path(__file__).resolve().parent
|
|
|
|
|
|
def _require_positive(name: str, value: float) -> float:
|
|
if value <= 0:
|
|
raise ValueError(f"{name} must be positive")
|
|
return value
|
|
|
|
|
|
def compute(inp: dict) -> dict:
|
|
span_ft = _require_positive("span_ft", float(inp["span_ft"]))
|
|
tributary_ft = _require_positive("tributary_ft", float(inp["tributary_ft"]))
|
|
D_psf = _require_positive("D_psf", float(inp["D_psf"]))
|
|
L_psf = _require_positive("L_psf", float(inp["L_psf"]))
|
|
bw_in = _require_positive("bw_in", float(inp["bw_in"]))
|
|
h_in = _require_positive("h_in", float(inp["h_in"]))
|
|
d_in = _require_positive("d_in", float(inp["d_in"]))
|
|
fc_ksi = _require_positive("fc_ksi", float(inp["fc_ksi"]))
|
|
fy_ksi = _require_positive("fy_ksi", float(inp["fy_ksi"]))
|
|
As_in2 = _require_positive("As_in2", float(inp["As_in2"]))
|
|
concrete_pcf = _require_positive("concrete_pcf", float(inp["concrete_pcf"]))
|
|
|
|
self_weight_klf = (bw_in * h_in / 144.0) * concrete_pcf / 1000.0
|
|
wD_klf = D_psf * tributary_ft / 1000.0 + self_weight_klf
|
|
wL_klf = L_psf * tributary_ft / 1000.0
|
|
wu_klf = 1.2 * wD_klf + 1.6 * wL_klf
|
|
Mu_kipft = wu_klf * span_ft**2 / 8.0
|
|
Vu_kip = wu_klf * span_ft / 2.0
|
|
|
|
fc_psi = fc_ksi * 1000.0
|
|
fy_psi = fy_ksi * 1000.0
|
|
a_in = As_in2 * fy_ksi / (0.85 * fc_ksi * bw_in)
|
|
beta1 = max(0.65, min(0.85, 0.85 - 0.05 * max(0.0, (fc_psi - 4000.0) / 1000.0)))
|
|
c_in = a_in / beta1
|
|
et = 0.003 * (d_in - c_in) / c_in if c_in > 0 else 0.0
|
|
if et >= 0.005:
|
|
phi = 0.90
|
|
else:
|
|
phi = max(0.65, min(0.90, 0.65 + (et - 0.002) * 250.0 / 3.0))
|
|
Mn_kipft = As_in2 * fy_ksi * (d_in - a_in / 2.0) / 12.0
|
|
phiMn_kipft = phi * Mn_kipft
|
|
|
|
rho_min = max(3.0 * math.sqrt(fc_psi) / fy_psi, 200.0 / fy_psi)
|
|
As_min_in2 = rho_min * bw_in * d_in
|
|
|
|
Vc_kip = 2.0 * math.sqrt(fc_psi) * bw_in * d_in / 1000.0
|
|
phiVc_kip = 0.75 * Vc_kip
|
|
|
|
def q(value: float) -> float:
|
|
return round(value, 6)
|
|
|
|
return {
|
|
"tool": "concrete_beam",
|
|
"version": "0.1",
|
|
"project": inp.get("project", ""),
|
|
"prepared_by": inp.get("prepared_by", ""),
|
|
"values": {
|
|
"span_ft": q(span_ft),
|
|
"tributary_ft": q(tributary_ft),
|
|
"D_psf": q(D_psf),
|
|
"L_psf": q(L_psf),
|
|
"self_weight_klf": q(self_weight_klf),
|
|
"wD_klf": q(wD_klf),
|
|
"wL_klf": q(wL_klf),
|
|
"wu_klf": q(wu_klf),
|
|
"Mu_kipft": q(Mu_kipft),
|
|
"Vu_kip": q(Vu_kip),
|
|
"bw_in": q(bw_in),
|
|
"h_in": q(h_in),
|
|
"d_in": q(d_in),
|
|
"fc_ksi": q(fc_ksi),
|
|
"fy_ksi": q(fy_ksi),
|
|
"As_in2": q(As_in2),
|
|
"a_in": q(a_in),
|
|
"et": q(et),
|
|
"phi": q(phi),
|
|
"Mn_kipft": q(Mn_kipft),
|
|
"phiMn_kipft": q(phiMn_kipft),
|
|
"As_min_in2": q(As_min_in2),
|
|
"Vc_kip": q(Vc_kip),
|
|
"phiVc_kip": q(phiVc_kip),
|
|
},
|
|
"checks": {
|
|
"flexure": {
|
|
"demand": q(Mu_kipft),
|
|
"capacity": q(phiMn_kipft),
|
|
"ok": Mu_kipft <= phiMn_kipft,
|
|
},
|
|
"minimum_steel": {
|
|
"demand": q(As_min_in2),
|
|
"capacity": q(As_in2),
|
|
"ok": As_in2 >= As_min_in2,
|
|
},
|
|
"shear": {
|
|
"demand": q(Vu_kip),
|
|
"capacity": q(phiVc_kip),
|
|
"ok": Vu_kip <= phiVc_kip,
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
def write_results(result: dict, path: Path) -> None:
|
|
path.write_text(json.dumps(result, indent=2) + "\n", encoding="utf-8")
|
|
|
|
|
|
def main() -> int:
|
|
input_path = Path(sys.argv[1]) if len(sys.argv) > 1 else HERE / "input.yaml"
|
|
output_path = Path(sys.argv[2]) if len(sys.argv) > 2 else input_path.with_name("results.json")
|
|
with input_path.open(encoding="utf-8") as handle:
|
|
inp = yaml.safe_load(handle)
|
|
result = compute(inp)
|
|
write_results(result, output_path)
|
|
print(output_path)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|