bgamazay commited on
Commit
d453c25
·
verified ·
1 Parent(s): a1156a3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +118 -95
app.py CHANGED
@@ -20,6 +20,7 @@ st.markdown("""
20
  text-align: center;
21
  margin-bottom: 20px;
22
  border: 1px solid #e0e0e0;
 
23
  }
24
  .big-number {
25
  font-size: 3em;
@@ -30,132 +31,154 @@ st.markdown("""
30
  font-size: 1.2em;
31
  color: #555;
32
  }
 
 
 
 
33
  </style>
34
  """, unsafe_allow_html=True)
35
 
36
  # --- Title ---
37
  st.title("🌍 The Climate Cost of the AI Race ⛽️")
38
  st.markdown("""
39
- **What will the US emissions of AI be in 2030?** Use the sliders to model the variables, focused on natural gas deployment.
40
  """)
41
 
42
  st.divider()
43
 
44
- # Initialize variables to ensure scope safety
45
- ai_demand_gw = 100
46
- gas_share = 90
47
- ocgt_share = 50
48
- capacity_factor = 0.90
49
- ccgt_eff = 0.60
50
- ocgt_eff = 0.33
51
- base_ef = 486
52
- us_baseline_mmt = 6343
53
-
54
- # --- Explanation ---
55
- st.info(f"**Current Scenario:** {gas_share}% of AI power met by Gas, with {ocgt_share}% of that using Open Cycle turbines.")
56
-
57
  # --- Sidebar Inputs ---
58
  st.sidebar.header("⚙️ Scenario Settings")
59
 
60
- # Mode Toggle
61
- mode = st.sidebar.radio("Mode", ["Simple", "Advanced"], horizontal=True)
62
-
63
- if mode == "Simple":
64
- st.sidebar.subheader("Demand Assumptions")
65
- ai_demand_gw = st.sidebar.number_input("AI Power Demand in 2030 (GW)", value=100, key="adv_gw")
66
- gas_share = st.sidebar.slider("Gas Share (%)", 0, 100, 90, key="adv_gas")
67
- capacity_factor = st.sidebar.slider("Capacity Factor", 0.0, 1.0, 0.90, key="adv_cf")
68
-
69
- st.sidebar.subheader("Natural Gas Power Proportion")
70
- gas_share = st.sidebar.slider(
71
- "Percent of AI Power met by Natural Gas (%)",
72
- min_value=0, max_value=100, value=90, step=5,
73
- key="simple_gas_share",
74
- help="How much of the AI load is powered by gas vs clean energy and/or other strategies like demand response."
75
- )
76
-
77
- st.sidebar.subheader("2. Turbine Technology")
78
- ocgt_share = st.sidebar.slider(
79
- "Percent Open Cycle (Speed Scenario) (%)",
80
- min_value=0, max_value=100, value=50, step=10,
81
- key="simple_ocgt_share",
82
- help="0% = All Combined Cycle. 100% = All Open Cycle."
83
- )
84
-
85
- else: # Advanced Mode
86
- st.sidebar.subheader("Technical Specs")
87
- ocgt_share = st.sidebar.slider("Open Cycle Share (%)", 0, 100, 50, key="adv_ocgt")
88
-
89
- ccgt_eff = st.number_input("CCGT Efficiency", value=0.60, key="adv_ccgt_eff")
90
- ocgt_eff = st.number_input("OCGT Efficiency", value=0.33, key="adv_ocgt_eff")
91
- base_ef = st.number_input("CCGT Emissions Factor (gCO2e/kWh)", value=486, key="adv_base_ef")
92
- us_baseline_mmt = st.number_input("US Baseline Emissions (Million tCO2e)", value=6343, key="adv_base_mmt")
93
 
94
  # --- Calculations ---
95
- # 1. Calculate weighted emission factor
96
- ocgt_ef_calc = base_ef * (ccgt_eff / ocgt_eff)
97
- weighted_ef = ((ocgt_share/100) * ocgt_ef_calc) + ((1 - (ocgt_share/100)) * base_ef)
 
 
 
 
98
 
99
  # 2. Calculate Total Energy
100
  gas_gw_capacity = ai_demand_gw * (gas_share/100)
101
- total_gwh = gas_gw_capacity * capacity_factor * 8760
102
 
103
  # 3. Calculate Emissions (MMT CO2e)
104
- ai_emissions_mmt = (total_gwh * weighted_ef) / 1_000_000
 
 
105
 
106
- percent_increase = (ai_emissions_mmt / us_baseline_mmt) * 100
107
 
108
  # --- Dashboard Layout ---
109
 
110
- # 1. The Big Number
111
- col1, col2, col3 = st.columns([1, 2, 1])
112
- with col2:
113
  st.markdown(f"""
114
  <div class="metric-card">
115
- <div class="sub-text">Projected US Emissions Increase in 2030</div>
116
  <div class="big-number">+{percent_increase:.2f}%</div>
117
  <div class="sub-text">({ai_emissions_mmt:.1f} Million tCO2e)</div>
 
 
 
118
  </div>
119
  """, unsafe_allow_html=True)
120
 
121
- # 2. Charts
122
- col_chart1, col_chart2 = st.columns(2)
123
-
124
- with col_chart1:
125
- st.subheader("US Emissions Trajectory")
126
-
127
- # Data Setup
128
- years = [2005, 2010, 2015, 2020, 2023]
129
- emissions_hist = [7200, 6900, 6600, 6000, 6200] # Proxies
130
- target_2030 = 7200 * 0.50
131
- bau_2030 = 5800 # Optimistic decline
132
-
133
- fig1 = go.Figure()
134
-
135
- # History
136
- fig1.add_trace(go.Scatter(x=years, y=emissions_hist, mode='lines', name='Historical', line=dict(color='gray')))
137
-
138
- # Target Path
139
- fig1.add_trace(go.Scatter(x=[2023, 2030], y=[6200, target_2030], mode='lines', name='Paris Goal', line=dict(color='green', dash='dash')))
140
-
141
- # AI Impact Stack
142
- fig1.add_trace(go.Bar(x=[2030], y=[bau_2030], name='US Baseline', marker_color='lightgray'))
143
- fig1.add_trace(go.Bar(x=[2030], y=[ai_emissions_mmt], name='AI Impact', base=bau_2030, marker_color='#ff4b4b'))
144
-
145
- fig1.update_layout(
146
- title="Can we hit the 50% reduction target?",
147
- yaxis_title="Emissions (Million tCO2e)",
148
- barmode='stack',
149
- legend=dict(orientation="h", y=-0.2),
150
- height=400
151
- )
152
- st.plotly_chart(fig1, use_container_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
 
154
  st.markdown("---")
155
  with st.expander("📚 Data Sources & Methodology"):
156
- st.markdown("""
157
- * **Baseline:** Based on EPA Gross GHG Inventory (~6,343 MMT).
158
- * **Efficiency:** Combined Cycle (60%) vs Aeroderivative OCGT (33%).
159
- * **Emission Factors:** Derived from NREL Lifecycle Analysis.
160
- * **Logic:** OCGT is modeled as ~1.8x more carbon intensive per kWh than CCGT due to lower efficiency.
161
- """)
 
 
 
 
 
20
  text-align: center;
21
  margin-bottom: 20px;
22
  border: 1px solid #e0e0e0;
23
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
24
  }
25
  .big-number {
26
  font-size: 3em;
 
31
  font-size: 1.2em;
32
  color: #555;
33
  }
34
+ .stPlotlyChart {
35
+ display: flex;
36
+ justify-content: center;
37
+ }
38
  </style>
39
  """, unsafe_allow_html=True)
40
 
41
  # --- Title ---
42
  st.title("🌍 The Climate Cost of the AI Race ⛽️")
43
  st.markdown("""
44
+ **What will the US emissions of AI be in 2030?** Model the variables below, focused on the efficiency of Natural Gas deployment.
45
  """)
46
 
47
  st.divider()
48
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  # --- Sidebar Inputs ---
50
  st.sidebar.header("⚙️ Scenario Settings")
51
 
52
+ # 1. AI Power Demand
53
+ ai_demand_gw = st.sidebar.number_input(
54
+ "AI Power Demand in 2030 (GW)",
55
+ value=100,
56
+ step=10,
57
+ help="Projected total power load required by AI data centers in 2030."
58
+ )
59
+
60
+ # 2. Gas Share
61
+ gas_share = st.sidebar.slider(
62
+ "Natural Gas Proportion (%)",
63
+ min_value=0, max_value=100, value=90, step=5,
64
+ help="The percentage of AI power demand that will be met specifically by Natural Gas generation (vs. Renewables/Nuclear)."
65
+ )
66
+
67
+ # 3. Turbine Efficiency (The new logic)
68
+ # Range 35% (Aeroderivative) to 60% (H-Class CCGT)
69
+ turbine_eff_percent = st.sidebar.slider(
70
+ "Gas Turbine Average Efficiency (%)",
71
+ min_value=35, max_value=60, value=45, step=1,
72
+ help="Thermal efficiency of the gas fleet. 35-40% = Peakers/Aeroderivative. 50-60% = Modern Combined Cycle (CCGT)."
73
+ )
74
+
75
+ # Constants
76
+ CAPACITY_FACTOR = 0.90 # Fixed as requested
77
+ US_BASELINE_MMT = 6343 # EPA Gross GHG Inventory Proxy
78
+ # Base reference: 486 gCO2e/kWh at 60% efficiency
79
+ # Constant for Carbon Content of Fuel derived from this: 486 * 0.60 = 291.6
80
+ FUEL_CARBON_CONSTANT = 486 * 0.60
 
 
 
 
81
 
82
  # --- Calculations ---
83
+
84
+ # 1. Calculate Emissions Factor based on selected efficiency
85
+ # Formula: EF_output = Constant_Fuel_Carbon / Efficiency
86
+ if turbine_eff_percent > 0:
87
+ calculated_ef = FUEL_CARBON_CONSTANT / (turbine_eff_percent / 100)
88
+ else:
89
+ calculated_ef = 0
90
 
91
  # 2. Calculate Total Energy
92
  gas_gw_capacity = ai_demand_gw * (gas_share/100)
93
+ total_gwh = gas_gw_capacity * CAPACITY_FACTOR * 8760
94
 
95
  # 3. Calculate Emissions (MMT CO2e)
96
+ # (GWh * 1,000,000 -> kWh) * (gCO2 / 1,000,000 -> Tonnes) / 1,000,000 -> Million Tonnes
97
+ # Simplifies to (GWh * EF) / 1,000,000
98
+ ai_emissions_mmt = (total_gwh * calculated_ef) / 1_000_000
99
 
100
+ percent_increase = (ai_emissions_mmt / US_BASELINE_MMT) * 100
101
 
102
  # --- Dashboard Layout ---
103
 
104
+ # 1. The Big Number (Centered)
105
+ c1, c2, c3 = st.columns([1, 2, 1])
106
+ with c2:
107
  st.markdown(f"""
108
  <div class="metric-card">
109
+ <div class="sub-text">Projected US Emissions Increase</div>
110
  <div class="big-number">+{percent_increase:.2f}%</div>
111
  <div class="sub-text">({ai_emissions_mmt:.1f} Million tCO2e)</div>
112
+ <div style="font-size: 0.9em; color: #888; margin-top: 10px;">
113
+ Based on {turbine_eff_percent}% Efficiency & {gas_share}% Gas Share
114
+ </div>
115
  </div>
116
  """, unsafe_allow_html=True)
117
 
118
+ # 2. Charts (Centered / Full Width)
119
+ # Using columns with spacers to center the chart if it feels too wide,
120
+ # or just full width for better visibility.
121
+ st.subheader("US Emissions Trajectory vs. AI Impact")
122
+
123
+ # Data Setup
124
+ years = [2005, 2010, 2015, 2020, 2023]
125
+ emissions_hist = [7200, 6900, 6600, 6000, 6200]
126
+ target_2030 = 7200 * 0.50 # 50% reduction from 2005
127
+ bau_2030 = 5800 # Optimistic business-as-usual decline
128
+
129
+ fig1 = go.Figure()
130
+
131
+ # History Line
132
+ fig1.add_trace(go.Scatter(
133
+ x=years, y=emissions_hist,
134
+ mode='lines+markers',
135
+ name='Historical Emissions',
136
+ line=dict(color='gray', width=2)
137
+ ))
138
+
139
+ # Target Path Line
140
+ fig1.add_trace(go.Scatter(
141
+ x=[2023, 2030], y=[6200, target_2030],
142
+ mode='lines',
143
+ name='2030 Climate Goal (50% Cut)',
144
+ line=dict(color='green', dash='dash', width=2)
145
+ ))
146
+
147
+ # AI Impact Stacked Bar
148
+ fig1.add_trace(go.Bar(
149
+ x=[2030], y=[bau_2030],
150
+ name='2030 Baseline Estimate',
151
+ marker_color='lightgray'
152
+ ))
153
+ fig1.add_trace(go.Bar(
154
+ x=[2030], y=[ai_emissions_mmt],
155
+ name='Additional AI Gas Emissions',
156
+ base=bau_2030,
157
+ marker_color='#ff4b4b'
158
+ ))
159
+
160
+ fig1.update_layout(
161
+ yaxis_title="Emissions (Million tCO2e)",
162
+ barmode='stack',
163
+ legend=dict(orientation="h", y=1.1, x=0.5, xanchor='center'),
164
+ height=500,
165
+ margin=dict(l=40, r=40, t=40, b=40),
166
+ hovermode="x unified"
167
+ )
168
+
169
+ # Centering the chart using container width
170
+ st.plotly_chart(fig1, use_container_width=True)
171
+
172
 
173
  st.markdown("---")
174
  with st.expander("📚 Data Sources & Methodology"):
175
+ st.markdown(f"""
176
+ **Methodology Updates:**
177
+ * **Baseline Emissions:** Compared against approx. {US_BASELINE_MMT} MMT (EPA Gross GHG Inventory).
178
+ * **Efficiency Logic:** Emissions Factor is calculated dynamically based on the **Electrical Efficiency** slider ({turbine_eff_percent}% currently selected).
179
+ * *Formula:* `EF = (Benchmark Carbon Content) / Efficiency %`
180
+ * *Benchmark:* Based on standard NREL data for CCGT (486 gCO2e/kWh @ 60% efficiency).
181
+ * Lower efficiency (e.g., 35% for Aeroderivative/Peakers) results in higher emissions per kWh.
182
+ * **Capacity Factor:** Fixed at **{int(CAPACITY_FACTOR*100)}%** to represent high uptime requirements for AI workloads.
183
+ * **Source Data:** Turbine efficiency ranges (35-60%) derived from industrial comparisons of Aeroderivative GTs vs H-Class CCGTs.
184
+ """)