File size: 4,417 Bytes
dff1ff3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px

# ----------------------------
# Helper functions
# ----------------------------

def calculate_daily_load(appliances):
    return (appliances['Power (W)'] *
            appliances['Qty'] *
            appliances['Hours/day']).sum()

def calculate_panels_needed(daily_load_wh, panel_watt, psh, perf_ratio, coverage):
    energy_per_panel_wh = panel_watt * psh * perf_ratio
    if energy_per_panel_wh == 0:
        return 0
    return int(np.ceil((daily_load_wh / coverage) / energy_per_panel_wh))

def tilt_suggestions(latitude):
    return {
        "Rule of Thumb (year-round)": round(latitude, 1),
        "Summer (lat - 15°)": round(latitude - 15, 1),
        "Winter (lat + 15°)": round(latitude + 15, 1)
    }

def battery_sizing(daily_load_wh, autonomy_days, dod, inverter_eff, battery_capacity_Wh):
    required_storage_Wh = daily_load_wh * autonomy_days
    usable_per_battery = battery_capacity_Wh * dod * inverter_eff
    if usable_per_battery == 0:
        return 0
    return int(np.ceil(required_storage_Wh / usable_per_battery))

def simulate_weekly_monthly(daily_load_wh, daily_prod_wh):
    days = pd.date_range("2025-01-01", periods=365, freq="D")
    df = pd.DataFrame({
        "date": days,
        "load_Wh": daily_load_wh,
        "prod_Wh": daily_prod_wh
    })
    weekly = df.resample("W-MON", on="date").sum()
    monthly = df.resample("M", on="date").sum()
    return weekly, monthly

# ----------------------------
# Streamlit UI
# ----------------------------

st.set_page_config(page_title="☀️ Solar Sizing App", layout="wide")
st.title("☀️ Solar Energy Consumption & Sizing App")

st.sidebar.header("Inputs")

# Location & solar input
latitude = st.sidebar.number_input("Latitude (°)", -90.0, 90.0, 30.0)
psh = st.sidebar.number_input("Peak Sun Hours (hrs/day)", 0.0, 10.0, 5.0)

# Panel specs
panel_watt = st.sidebar.number_input("Panel STC Wattage (W)", 50, 1000, 400)
perf_ratio = st.sidebar.slider("Performance Ratio", 0.5, 0.9, 0.75)
coverage = st.sidebar.slider("System Coverage (%)", 10, 100, 100) / 100

# Battery specs
autonomy_days = st.sidebar.number_input("Battery Autonomy (days)", 0.0, 7.0, 1.0)
dod = st.sidebar.slider("Battery Depth of Discharge (DoD)", 0.1, 1.0, 0.8)
inverter_eff = st.sidebar.slider("Inverter Efficiency", 0.5, 1.0, 0.95)
battery_capacity_Wh = st.sidebar.number_input("Battery Capacity (Wh)", 100, 20000, 5000)

# Appliances table
st.subheader("Appliances")
appliances = st.data_editor(
    pd.DataFrame(columns=["Appliance", "Power (W)", "Qty", "Hours/day"]),
    num_rows="dynamic"
)

if not appliances.empty:
    daily_load_wh = calculate_daily_load(appliances)
    st.write(f"**Total Daily Load:** {daily_load_wh:,.0f} Wh")

    # Panel count
    panels_needed = calculate_panels_needed(daily_load_wh, panel_watt, psh, perf_ratio, coverage)
    daily_prod_wh = panels_needed * panel_watt * psh * perf_ratio

    st.metric("Panels Needed", panels_needed)
    st.metric("Estimated Daily Production (Wh)", f"{daily_prod_wh:,.0f}")

    # Tilt suggestion
    tilts = tilt_suggestions(latitude)
    st.subheader("Tilt Angle Suggestions (°)")
    st.table(pd.DataFrame(list(tilts.items()), columns=["Case", "Tilt"]))

    # Battery sizing
    num_batteries = battery_sizing(daily_load_wh, autonomy_days, dod, inverter_eff, battery_capacity_Wh)
    st.metric("Recommended Batteries", num_batteries)

    # Graphs
    weekly, monthly = simulate_weekly_monthly(daily_load_wh, daily_prod_wh)

    tab1, tab2 = st.tabs(["📅 Weekly", "📆 Monthly"])
    with tab1:
        fig = px.bar(weekly, x=weekly.index, y=["load_Wh", "prod_Wh"],
                     labels={"value":"Energy (Wh)", "date":"Week"},
                     barmode="group", title="Weekly Load vs Production")
        st.plotly_chart(fig, use_container_width=True)
    with tab2:
        fig = px.bar(monthly, x=monthly.index, y=["load_Wh", "prod_Wh"],
                     labels={"value":"Energy (Wh)", "date":"Month"},
                     barmode="group", title="Monthly Load vs Production")
        st.plotly_chart(fig, use_container_width=True)

    # Export
    st.download_button("Download Monthly Data (CSV)", monthly.to_csv().encode("utf-8"),
                       "monthly_results.csv", "text/csv")
else:
    st.info("➕ Add appliances above to calculate system sizing.")