Spaces:
Sleeping
Sleeping
File size: 7,390 Bytes
fe5061b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# app.py
# Busbar sizing Gradio app
# Run locally: pip install -r requirements.txt ; python app.py
# To deploy on Hugging Face Spaces: push this file + requirements.txt to your space repo.
import math
import gradio as gr
import pandas as pd
# Material properties and default current densities (A/mm^2)
# These are conservative engineering defaults — adjust per your standards/practice.
MATERIALS = {
"Copper": {
"resistivity": 1.724e-8, # ohm·m at 20°C
"J_natural": 1.6, # A/mm^2 (natural convection)
"J_forced": 2.5, # A/mm^2 (forced air / ventilated)
},
"Aluminium": {
"resistivity": 2.82e-8, # ohm·m at 20°C
"J_natural": 0.9,
"J_forced": 1.4,
}
}
# Common commercial thicknesses (mm) and widths (mm) to propose (you can extend)
COMMON_THICKNESSES = [3, 5, 6, 8, 10, 12, 15] # mm
COMMON_WIDTHS = [10, 12, 15, 20, 25, 30, 40, 50, 60, 80, 100, 120, 150, 200] # mm
def nearest_busbar_size(required_area_mm2, thicknesss=COMMON_THICKNESSES, widths=COMMON_WIDTHS):
"""
Find the smallest commercial thickness x width combination whose area >= required_area_mm2.
Returns a list of candidate dicts sorted ascending by area.
"""
candidates = []
for t in thicknesss:
for w in widths:
area = t * w # mm^2 for rectangular busbar
if area >= required_area_mm2:
candidates.append({
"thickness_mm": t,
"width_mm": w,
"area_mm2": area
})
# if none found (very large current), return a few top oversized combos
if not candidates:
# create a fallback by scaling up widths
scale = 2
for t in thicknesss:
w = widths[-1] * scale
candidates.append({"thickness_mm": t, "width_mm": w, "area_mm2": t * w})
candidates.sort(key=lambda x: x["area_mm2"])
return candidates[:6]
candidates.sort(key=lambda x: (x["area_mm2"], x["thickness_mm"], x["width_mm"]))
return candidates[:6] # top 6 suggestions
def size_busbar(current_A: float,
material: str = "Copper",
cooling: str = "Natural (no forced ventilation)",
select_thickness: int = None,
prefer_forced: bool = False,
voltage_V: float = 415.0):
"""
Main calculation function for busbar sizing.
"""
# Input validation / fixups
if current_A <= 0:
return "Current must be positive.", None, None
mat = MATERIALS.get(material)
if mat is None:
return f"Unknown material: {material}", None, None
# Choose current density J (A/mm^2)
if "forced" in cooling.lower() or prefer_forced:
J = mat["J_forced"]
cooling_label = "Forced ventilation"
else:
J = mat["J_natural"]
cooling_label = "Natural convection"
required_area_mm2 = current_A / J # mm^2
# If user selected a thickness, compute required width
suggestions = []
if select_thickness in COMMON_THICKNESSES:
t = select_thickness
required_width = math.ceil(required_area_mm2 / t)
# round up to nearest standard width
std_width = next((w for w in COMMON_WIDTHS if w >= required_width), required_width)
area_actual = t * std_width
suggestions.append({
"thickness_mm": t,
"width_mm": std_width,
"area_mm2": area_actual
})
else:
suggestions = nearest_busbar_size(required_area_mm2)
# pick the best suggestion (smallest area)
best = suggestions[0]
# Resistance per meter (DC approximation)
area_m2 = best["area_mm2"] * 1e-6 # mm2 -> m2
resistivity = mat["resistivity"]
R_per_m = resistivity / area_m2 # ohm per meter
voltage_drop_per_m_V = R_per_m * current_A
percent_drop_per_m = (voltage_drop_per_m_V / voltage_V) * 100
# Build outputs
summary = (
f"Design current: {current_A:.1f} A\n"
f"Material: {material}\n"
f"Cooling: {cooling_label}\n"
f"Design current density used: {J:.2f} A/mm²\n"
f"Required cross-sectional area (ideal): {required_area_mm2:.2f} mm²\n\n"
f"Recommended busbar (best match): {best['thickness_mm']} mm thick × {best['width_mm']} mm wide\n"
f" -> Cross-sectional area: {best['area_mm2']:.1f} mm²\n\n"
f"Estimated DC resistance: {R_per_m:.6f} Ω/m\n"
f"Voltage drop at {current_A:.1f} A: {voltage_drop_per_m_V:.3f} V/m ({percent_drop_per_m:.4f}% of {voltage_V} V per meter)\n\n"
"Note: This is a simplified design aid. Verify with thermal/mechanical checks, short-circuit stability, standards (IEC/NEC/IEC 61439 etc.), and local practice."
)
# Prepare a DataFrame of the suggestions for display
df = pd.DataFrame(suggestions)
df = df[["thickness_mm", "width_mm", "area_mm2"]]
df.columns = ["Thickness (mm)", "Width (mm)", "Area (mm²)"]
return summary, df, {
"required_area_mm2": round(required_area_mm2, 2),
"chosen_thickness_mm": best["thickness_mm"],
"chosen_width_mm": best["width_mm"],
"chosen_area_mm2": best["area_mm2"],
"resistance_ohm_per_m": R_per_m,
"voltage_drop_V_per_m": voltage_drop_per_m_V
}
# ---- Gradio UI ----
with gr.Blocks(title="Busbar sizing calculator") as demo:
gr.Markdown("# Busbar sizing — Gradio app\nEnter design current and choices; app suggests rectangular busbar sizes.")
with gr.Row():
with gr.Column():
current_in = gr.Number(label="Design current (A)", value=400, precision=1)
material_in = gr.Radio(choices=list(MATERIALS.keys()), value="Copper", label="Material")
cooling_in = gr.Radio(choices=["Natural (no forced ventilation)", "Forced ventilation"], value="Natural (no forced ventilation)", label="Cooling")
prefer_forced = gr.Checkbox(label="Prefer forced-ventilation values (override cooling)", value=False)
thickness_in = gr.Dropdown(choices=["Auto (choose best)"] + [str(t) for t in COMMON_THICKNESSES], value="Auto (choose best)", label="Prefer thickness (mm) - optional")
voltage_in = gr.Number(label="Nominal system voltage (V) — for % drop calc", value=415)
run_btn = gr.Button("Calculate")
with gr.Column():
output_text = gr.Textbox(label="Summary", interactive=False, lines=10)
output_table = gr.Dataframe(label="Suggested commercial sizes", interactive=False)
output_json = gr.JSON(label="Raw results (for engineering use)")
def on_calculate(current, material, cooling, prefer_forced, thickness_choice, voltage):
sel_thickness = None
if thickness_choice and thickness_choice != "Auto (choose best)":
try:
sel_thickness = int(thickness_choice)
except:
sel_thickness = None
summary, df, raw = size_busbar(current, material, cooling, sel_thickness, prefer_forced, voltage)
return summary, df, raw
run_btn.click(
on_calculate,
inputs=[current_in, material_in, cooling_in, prefer_forced, thickness_in, voltage_in],
outputs=[output_text, output_table, output_json]
)
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860)
|