|
|
""" |
|
|
Internal loads form module for HVAC Load Calculator. |
|
|
This module provides UI components for internal loads input. |
|
|
""" |
|
|
|
|
|
import streamlit as st |
|
|
from models.building import Building, People, Lighting, Equipment |
|
|
|
|
|
def display_internal_loads_form(building: Building = None) -> Building: |
|
|
""" |
|
|
Display form for internal loads input. |
|
|
|
|
|
Args: |
|
|
building: Optional existing building model to edit |
|
|
|
|
|
Returns: |
|
|
Updated building model with user inputs |
|
|
""" |
|
|
if building is None: |
|
|
building = Building() |
|
|
|
|
|
st.header("Internal Loads") |
|
|
|
|
|
|
|
|
st.subheader("People") |
|
|
col1, col2 = st.columns(2) |
|
|
|
|
|
with col1: |
|
|
building.people.count = st.number_input("Number of People", |
|
|
min_value=0, |
|
|
value=building.people.count) |
|
|
|
|
|
|
|
|
activity_levels = { |
|
|
"Seated, resting": {"sensible": 60, "latent": 40}, |
|
|
"Seated, light work": {"sensible": 75, "latent": 55}, |
|
|
"Seated, moderate work": {"sensible": 80, "latent": 80}, |
|
|
"Standing, light work": {"sensible": 80, "latent": 80}, |
|
|
"Standing, moderate work": {"sensible": 90, "latent": 125}, |
|
|
"Walking, light work": {"sensible": 100, "latent": 180}, |
|
|
"Walking, moderate work": {"sensible": 110, "latent": 230}, |
|
|
"Heavy work": {"sensible": 170, "latent": 340} |
|
|
} |
|
|
|
|
|
selected_activity = st.selectbox( |
|
|
"Activity Level", |
|
|
options=list(activity_levels.keys()), |
|
|
index=list(activity_levels.keys()).index(building.people.activity_level) |
|
|
if building.people.activity_level in activity_levels |
|
|
else 1 |
|
|
) |
|
|
|
|
|
building.people.activity_level = selected_activity |
|
|
building.people.sensible_heat = activity_levels[selected_activity]["sensible"] |
|
|
building.people.latent_heat = activity_levels[selected_activity]["latent"] |
|
|
|
|
|
|
|
|
st.info(f"Sensible Heat Gain: {building.people.sensible_heat} W/person\n\n" |
|
|
f"Latent Heat Gain: {building.people.latent_heat} W/person") |
|
|
|
|
|
with col2: |
|
|
building.people.hours_occupancy = st.selectbox( |
|
|
"Hours of Occupancy", |
|
|
options=["8h", "10h", "12h", "14h", "16h", "18h", "24h"], |
|
|
index=["8h", "10h", "12h", "14h", "16h", "18h", "24h"].index(building.people.hours_occupancy) |
|
|
) |
|
|
|
|
|
|
|
|
total_sensible = building.people.count * building.people.sensible_heat |
|
|
total_latent = building.people.count * building.people.latent_heat |
|
|
total_heat = total_sensible + total_latent |
|
|
|
|
|
st.write(f"Total Sensible Heat Gain: {total_sensible:.1f} W") |
|
|
st.write(f"Total Latent Heat Gain: {total_latent:.1f} W") |
|
|
st.write(f"Total Heat Gain: {total_heat:.1f} W") |
|
|
|
|
|
|
|
|
st.subheader("Lighting") |
|
|
col1, col2 = st.columns(2) |
|
|
|
|
|
with col1: |
|
|
building.lighting.power = st.number_input("Lighting Power (W)", |
|
|
min_value=0.0, |
|
|
value=building.lighting.power) |
|
|
|
|
|
|
|
|
lighting_types = { |
|
|
"LED": 0.8, |
|
|
"Fluorescent": 0.85, |
|
|
"Halogen": 0.95, |
|
|
"Incandescent": 0.98 |
|
|
} |
|
|
|
|
|
selected_lighting = st.selectbox( |
|
|
"Lighting Type", |
|
|
options=list(lighting_types.keys()), |
|
|
index=list(lighting_types.keys()).index(building.lighting.type) |
|
|
if building.lighting.type in lighting_types |
|
|
else 0 |
|
|
) |
|
|
|
|
|
building.lighting.type = selected_lighting |
|
|
building.lighting.heat_factor = lighting_types[selected_lighting] |
|
|
|
|
|
|
|
|
st.info(f"Heat Emission Factor: {building.lighting.heat_factor * 100:.0f}% of power is converted to heat") |
|
|
|
|
|
with col2: |
|
|
building.lighting.hours_operation = st.selectbox( |
|
|
"Hours of Operation", |
|
|
options=["8h", "10h", "12h", "14h", "16h", "18h", "24h"], |
|
|
index=["8h", "10h", "12h", "14h", "16h", "18h", "24h"].index(building.lighting.hours_operation) |
|
|
) |
|
|
|
|
|
|
|
|
total_lighting_heat = building.lighting.power * building.lighting.heat_factor |
|
|
|
|
|
st.write(f"Total Heat Gain: {total_lighting_heat:.1f} W") |
|
|
|
|
|
|
|
|
st.subheader("Equipment") |
|
|
col1, col2 = st.columns(2) |
|
|
|
|
|
with col1: |
|
|
building.equipment.power = st.number_input("Equipment Power (W)", |
|
|
min_value=0.0, |
|
|
value=building.equipment.power) |
|
|
|
|
|
|
|
|
equipment_types = { |
|
|
"General": {"sensible": 1.0, "latent": 0.0}, |
|
|
"Computer": {"sensible": 0.95, "latent": 0.05}, |
|
|
"Kitchen": {"sensible": 0.85, "latent": 0.15}, |
|
|
"Medical": {"sensible": 0.9, "latent": 0.1}, |
|
|
"Laboratory": {"sensible": 0.8, "latent": 0.2} |
|
|
} |
|
|
|
|
|
selected_equipment = st.selectbox( |
|
|
"Equipment Type", |
|
|
options=list(equipment_types.keys()), |
|
|
index=list(equipment_types.keys()).index(building.equipment.type) |
|
|
if building.equipment.type in equipment_types |
|
|
else 0 |
|
|
) |
|
|
|
|
|
building.equipment.type = selected_equipment |
|
|
building.equipment.sensible_factor = equipment_types[selected_equipment]["sensible"] |
|
|
building.equipment.latent_factor = equipment_types[selected_equipment]["latent"] |
|
|
|
|
|
|
|
|
st.info(f"Sensible Heat Factor: {building.equipment.sensible_factor * 100:.0f}%\n\n" |
|
|
f"Latent Heat Factor: {building.equipment.latent_factor * 100:.0f}%") |
|
|
|
|
|
with col2: |
|
|
building.equipment.hours_operation = st.selectbox( |
|
|
"Hours of Operation", |
|
|
options=["8h", "10h", "12h", "14h", "16h", "18h", "24h"], |
|
|
index=["8h", "10h", "12h", "14h", "16h", "18h", "24h"].index(building.equipment.hours_operation) |
|
|
) |
|
|
|
|
|
|
|
|
total_sensible_equipment = building.equipment.power * building.equipment.sensible_factor |
|
|
total_latent_equipment = building.equipment.power * building.equipment.latent_factor |
|
|
total_equipment_heat = total_sensible_equipment + total_latent_equipment |
|
|
|
|
|
st.write(f"Sensible Heat Gain: {total_sensible_equipment:.1f} W") |
|
|
st.write(f"Latent Heat Gain: {total_latent_equipment:.1f} W") |
|
|
st.write(f"Total Heat Gain: {total_equipment_heat:.1f} W") |
|
|
|
|
|
|
|
|
st.subheader("Internal Loads Summary") |
|
|
|
|
|
|
|
|
total_sensible = ( |
|
|
building.people.count * building.people.sensible_heat + |
|
|
building.lighting.power * building.lighting.heat_factor + |
|
|
building.equipment.power * building.equipment.sensible_factor |
|
|
) |
|
|
|
|
|
total_latent = ( |
|
|
building.people.count * building.people.latent_heat + |
|
|
building.equipment.power * building.equipment.latent_factor |
|
|
) |
|
|
|
|
|
total_heat = total_sensible + total_latent |
|
|
|
|
|
|
|
|
col1, col2, col3 = st.columns(3) |
|
|
|
|
|
with col1: |
|
|
st.metric("Total Sensible Load", f"{total_sensible:.1f} W") |
|
|
|
|
|
with col2: |
|
|
st.metric("Total Latent Load", f"{total_latent:.1f} W") |
|
|
|
|
|
with col3: |
|
|
st.metric("Total Internal Load", f"{total_heat:.1f} W") |
|
|
|
|
|
return building |
|
|
|