Spaces:
Sleeping
Sleeping
File size: 26,024 Bytes
eada9ac 6abf4f4 eada9ac e78af4d eada9ac 81a65c3 ec68136 81a65c3 ec68136 eada9ac 81a65c3 eada9ac ec68136 81a65c3 eada9ac 81a65c3 eada9ac ec68136 eada9ac ec68136 eada9ac ec68136 eada9ac |
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 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 |
# app.py
import streamlit as st
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import requests
import json
import os
from groq import Groq
from dotenv import load_dotenv
import plotly.express as px
import plotly.graph_objects as go
from datetime import datetime
# Load environment variables
load_dotenv()
GROQ_API_KEY = os.getenv('GROQ_API_KEY')
# Page configuration
st.set_page_config(
page_title="Hydrogen Production Optimizer",
page_icon="⚡",
layout="wide",
initial_sidebar_state="expanded"
)
# Custom CSS
st.markdown("""
<style>
.main {
padding: 1rem;
}
.stButton>button {
width: 100%;
background-color: #4CAF50;
color: white;
}
.stTabs [data-baseweb="tab-list"] {
gap: 10px;
}
.stTabs [data-baseweb="tab"] {
padding: 10px;
border-radius: 4px 4px 0px 0px;
}
h1, h2, h3 {
color: #1E88E5;
}
.highlight {
background-color: #f0f8ff;
padding: 1rem;
border-radius: 0.5rem;
border-left: 5px solid #1E88E5;
}
</style>
""", unsafe_allow_html=True)
# Helper functions for calculations
def calculate_h2_production(method, water_quantity, energy_input, current_density, voltage):
"""Calculate hydrogen production based on input parameters"""
# Conversion factors and efficiencies for different methods
method_efficiencies = {
"Alkaline Electrolysis": 0.65,
"PEM Electrolysis": 0.75,
"SOEC": 0.85
}
# Basic Faraday's law calculation (simplified)
# Assuming ideal conditions and standard molar volume
faraday_constant = 96485 # C/mol
molar_mass_h2 = 2.02 # g/mol
# Adjusting efficiency based on method
efficiency = method_efficiencies[method]
# Calculate total charge (Q = I * t)
# Assuming current_density is in A/cm² and we convert water_quantity to surface area
surface_area = water_quantity * 0.1 # Simplified conversion
current = current_density * surface_area # Total current in A
# Assuming energy_input helps determine operation time
time_hours = energy_input / (voltage * current) # Time in hours
# Calculate hydrogen production using Faraday's Law
moles_h2 = (current * time_hours * 3600 * efficiency) / (2 * faraday_constant)
mass_h2 = moles_h2 * molar_mass_h2 # grams
volume_h2 = moles_h2 * 22.4 # Standard liters
return {
"production_rate_g_per_hour": mass_h2 / time_hours,
"total_production_g": mass_h2,
"total_production_L": volume_h2,
"efficiency": efficiency,
"operation_time_hours": time_hours
}
def calculate_cost(method, water_cost, water_purification_cost, energy_source, energy_input, h2_production):
"""Calculate the cost of hydrogen production"""
# Energy costs by source ($/kWh)
energy_costs = {
"Grid Electricity": 0.12,
"Solar": 0.08,
"Wind": 0.06,
"Nuclear": 0.10,
"Hydroelectric": 0.07
}
# Operational costs by method ($/kg H2)
operational_costs = {
"Alkaline Electrolysis": 1.2,
"PEM Electrolysis": 1.5,
"SOEC": 1.8
}
# Calculate water cost
total_water_cost = water_cost * (h2_production["total_production_g"] / 1000) # $/kg
# Calculate purification cost
total_purification_cost = water_purification_cost * (h2_production["total_production_g"] / 1000) # $/kg
# Calculate energy cost
energy_cost_rate = energy_costs[energy_source]
total_energy_cost = energy_cost_rate * energy_input # $
# Calculate operational cost
operational_cost_rate = operational_costs[method]
total_operational_cost = operational_cost_rate * (h2_production["total_production_g"] / 1000) # $
# Calculate total cost
total_cost = total_water_cost + total_purification_cost + total_energy_cost + total_operational_cost
# Calculate cost per kg of H2
cost_per_kg = total_cost / (h2_production["total_production_g"] / 1000) if h2_production["total_production_g"] > 0 else 0
return {
"water_cost": total_water_cost,
"purification_cost": total_purification_cost,
"energy_cost": total_energy_cost,
"operational_cost": total_operational_cost,
"total_cost": total_cost,
"cost_per_kg": cost_per_kg
}
def call_groq_api(user_inputs, production_data, cost_data):
"""Call Groq API with Llama 3 to analyze production parameters and provide recommendations"""
# Initialize Groq client
try:
client = Groq(api_key=os.environ.get("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"))
except Exception as e:
return {"error": f"Failed to initialize Groq client: {str(e)}"}
# Prepare the prompt without f-string for the JSON schema part
prompt_part1 = f"""
As a hydrogen production expert, analyze the following electrolysis parameters and provide recommendations for optimization:
Input Parameters:
- Water Source: {user_inputs['water_source']}
- Production Method: {user_inputs['production_method']}
- Energy Source: {user_inputs['energy_source']}
- Current Density: {user_inputs['current_density']} A/cm²
- Voltage: {user_inputs['voltage']} V
- Membrane Material: {user_inputs['membrane']}
- Electrode Materials: {user_inputs['electrodes']}
Production Results:
- Production Rate: {production_data['production_rate_g_per_hour']:.2f} g/hour
- Total Production: {production_data['total_production_g']:.2f} g
- Efficiency: {production_data['efficiency'] * 100:.1f}%
- Operation Time: {production_data['operation_time_hours']:.2f} hours
Cost Analysis:
- Water Cost: ${cost_data['water_cost']:.2f}
- Purification Cost: ${cost_data['purification_cost']:.2f}
- Energy Cost: ${cost_data['energy_cost']:.2f}
- Operational Cost: ${cost_data['operational_cost']:.2f}
- Total Cost: ${cost_data['total_cost']:.2f}
- Cost per kg H₂: ${cost_data['cost_per_kg']:.2f}
Please provide:
1. An efficiency assessment of the current setup
2. Three specific recommendations to improve efficiency
3. Three specific recommendations to reduce costs
4. An ideal parameter configuration based on the provided inputs
Format your response as a structured JSON with these fields:
"""
# The JSON schema part without using f-string
prompt_part2 = """
{
"efficiency_assessment": "text analysis",
"efficiency_recommendations": ["recommendation1", "recommendation2", "recommendation3"],
"cost_recommendations": ["recommendation1", "recommendation2", "recommendation3"],
"ideal_parameters": {
"current_density": value,
"voltage": value,
"membrane": "recommendation",
"electrodes": "recommendation",
"energy_source": "recommendation"
},
"estimated_improvement": {
"efficiency_increase": "percentage",
"cost_reduction": "percentage"
}
}
"""
# Combine the parts
prompt = prompt_part1 + prompt_part2
try:
# Call Groq API using the client
chat_completion = client.chat.completions.create(
messages=[
{
"role": "user",
"content": prompt,
}
],
model="llama-3.3-70b-versatile",
temperature=0.5,
max_tokens=1024,
response_format={"type": "json_object"}
)
# Extract the response content
response_content = chat_completion.choices[0].message.content
# Parse the JSON response
try:
recommendations_json = json.loads(response_content)
return recommendations_json
except json.JSONDecodeError:
return {"error": "Failed to parse API response as JSON"}
except Exception as e:
return {"error": f"Error calling Groq API: {str(e)}"}
# Main application
def main():
# Sidebar for inputs
st.sidebar.image("https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Creative-Tail-Objects-flask.svg/256px-Creative-Tail-Objects-flask.svg.png", width=100)
st.sidebar.title("H₂ Production Parameters")
# Water parameters
st.sidebar.subheader("Water Parameters")
water_source = st.sidebar.selectbox("Water Source", ["Tap Water", "Deionized Water", "Seawater", "Wastewater", "Ultrapure Water"])
water_cost = st.sidebar.number_input("Water Cost ($/m³)", min_value=0.1, max_value=50.0, value=2.0, step=0.1)
water_purification_cost = st.sidebar.number_input("Water Purification Cost ($/m³)", min_value=0.0, max_value=100.0, value=5.0, step=0.5)
water_quantity = st.sidebar.number_input("Water Quantity (L)", min_value=1.0, max_value=10000.0, value=100.0, step=10.0)
# Electrolysis parameters
st.sidebar.subheader("Electrolysis Parameters")
production_method = st.sidebar.selectbox("Production Method", ["Alkaline Electrolysis", "PEM Electrolysis", "SOEC"])
current_density = st.sidebar.slider("Current Density (A/cm²)", min_value=0.1, max_value=2.0, value=0.5, step=0.1)
voltage = st.sidebar.slider("Voltage (V)", min_value=1.4, max_value=5.0, value=2.0, step=0.1)
# Materials
membrane = st.sidebar.selectbox("Membrane Material", ["Nafion", "Zirfon", "Ceramic", "PBI", "SPEEK"])
electrodes = st.sidebar.selectbox("Electrode Materials", ["Platinum", "Nickel", "Iridium Oxide", "Stainless Steel", "Carbon-based"])
# Energy parameters
st.sidebar.subheader("Energy Parameters")
energy_source = st.sidebar.selectbox("Energy Source", ["Grid Electricity", "Solar", "Wind", "Nuclear", "Hydroelectric"])
energy_input = st.sidebar.number_input("Energy Input (kWh)", min_value=1.0, max_value=10000.0, value=100.0, step=10.0)
# Collect user inputs
user_inputs = {
"water_source": water_source,
"water_cost": water_cost,
"water_purification_cost": water_purification_cost,
"water_quantity": water_quantity,
"production_method": production_method,
"current_density": current_density,
"voltage": voltage,
"membrane": membrane,
"electrodes": electrodes,
"energy_source": energy_source,
"energy_input": energy_input
}
# Main content area
st.title("Hydrogen Production Analysis & Optimization")
st.markdown("Analyze and optimize your hydrogen production process with AI-driven recommendations")
# Process button
analyze_button = st.button("Analyze Production Parameters")
if analyze_button:
with st.spinner("Calculating production parameters and generating AI recommendations..."):
# Calculate production
production_data = calculate_h2_production(
production_method,
water_quantity,
energy_input,
current_density,
voltage
)
# Calculate cost
cost_data = calculate_cost(
production_method,
water_cost,
water_purification_cost,
energy_source,
energy_input,
production_data
)
# Get AI recommendations
ai_recommendations = call_groq_api(user_inputs, production_data, cost_data)
# Display results in tabs
tabs = st.tabs(["Production Analysis", "Cost Analysis", "AI Recommendations", "Visualization"])
# Tab 1: Production Analysis
with tabs[0]:
st.header("Hydrogen Production Analysis")
# Key metrics in columns
col1, col2, col3 = st.columns(3)
with col1:
st.metric("Production Rate", f"{production_data['production_rate_g_per_hour']:.2f} g/hour")
st.metric("Total H₂ Produced", f"{production_data['total_production_g']:.2f} g")
with col2:
st.metric("Volume of H₂", f"{production_data['total_production_L']:.2f} L")
st.metric("Operation Time", f"{production_data['operation_time_hours']:.2f} hours")
with col3:
st.metric("System Efficiency", f"{production_data['efficiency']*100:.1f}%")
energy_consumption = energy_input / (production_data['total_production_g']/1000)
st.metric("Energy Consumption", f"{energy_consumption:.2f} kWh/kg H₂")
# Detailed production information
st.subheader("Process Details")
process_df = pd.DataFrame({
"Parameter": ["Production Method", "Current Density", "Voltage", "Membrane", "Electrodes",
"Water Source", "Water Quantity", "Energy Source", "Energy Input"],
"Value": [production_method, f"{current_density} A/cm²", f"{voltage} V", membrane, electrodes,
water_source, f"{water_quantity} L", energy_source, f"{energy_input} kWh"]
})
st.table(process_df)
# Tab 2: Cost Analysis
with tabs[1]:
st.header("Cost Analysis")
# Key metrics
col1, col2 = st.columns(2)
with col1:
st.metric("Total Production Cost", f"${cost_data['total_cost']:.2f}")
st.metric("Cost per kg H₂", f"${cost_data['cost_per_kg']:.2f}")
# Cost breakdown
st.subheader("Cost Breakdown")
cost_data_viz = {
"Category": ["Water", "Purification", "Energy", "Operation"],
"Cost ($)": [
cost_data["water_cost"],
cost_data["purification_cost"],
cost_data["energy_cost"],
cost_data["operational_cost"]
]
}
cost_df = pd.DataFrame(cost_data_viz)
# Create cost breakdown chart
fig = px.pie(
cost_df,
values="Cost ($)",
names="Category",
title="Cost Distribution",
color_discrete_sequence=px.colors.sequential.Blues_r
)
st.plotly_chart(fig, use_container_width=True)
# Detailed cost table
st.subheader("Detailed Cost Breakdown")
detailed_cost_df = pd.DataFrame({
"Cost Component": ["Water Cost", "Water Purification", "Energy Cost", "Operational Cost", "Total Cost"],
"Amount ($)": [
f"${cost_data['water_cost']:.2f}",
f"${cost_data['purification_cost']:.2f}",
f"${cost_data['energy_cost']:.2f}",
f"${cost_data['operational_cost']:.2f}",
f"${cost_data['total_cost']:.2f}"
],
"Percentage": [
f"{cost_data['water_cost']/cost_data['total_cost']*100:.1f}%",
f"{cost_data['purification_cost']/cost_data['total_cost']*100:.1f}%",
f"{cost_data['energy_cost']/cost_data['total_cost']*100:.1f}%",
f"{cost_data['operational_cost']/cost_data['total_cost']*100:.1f}%",
"100%"
]
})
st.table(detailed_cost_df)
# Tab 3: AI Recommendations
with tabs[2]:
st.header("AI-Driven Recommendations")
if "error" in ai_recommendations:
st.error(f"Error getting AI recommendations: {ai_recommendations['error']}")
else:
# Efficiency Assessment
st.subheader("Efficiency Assessment")
st.markdown(f"<div class='highlight'>{ai_recommendations['efficiency_assessment']}</div>", unsafe_allow_html=True)
# Recommendations
col1, col2 = st.columns(2)
with col1:
st.subheader("Efficiency Recommendations")
for i, rec in enumerate(ai_recommendations['efficiency_recommendations'], 1):
st.markdown(f"**{i}.** {rec}")
with col2:
st.subheader("Cost Reduction Recommendations")
for i, rec in enumerate(ai_recommendations['cost_recommendations'], 1):
st.markdown(f"**{i}.** {rec}")
# Ideal parameters
st.subheader("Ideal Parameter Configuration")
ideal_params = ai_recommendations['ideal_parameters']
param_comparison = pd.DataFrame({
"Parameter": ["Current Density (A/cm²)", "Voltage (V)", "Membrane", "Electrodes", "Energy Source"],
"Current Value": [
current_density,
voltage,
membrane,
electrodes,
energy_source
],
"Recommended Value": [
ideal_params['current_density'],
ideal_params['voltage'],
ideal_params['membrane'],
ideal_params['electrodes'],
ideal_params['energy_source']
]
})
st.table(param_comparison)
# Estimated improvements
st.subheader("Estimated Improvements")
col1, col2 = st.columns(2)
with col1:
st.metric("Efficiency Increase", ai_recommendations['estimated_improvement']['efficiency_increase'])
with col2:
st.metric("Cost Reduction", ai_recommendations['estimated_improvement']['cost_reduction'])
# Tab 4: Visualization
with tabs[3]:
st.header("Production Visualization")
# Create comparison data
methods = ["Alkaline Electrolysis", "PEM Electrolysis", "SOEC"]
production_rates = []
costs_per_kg = []
for method in methods:
# Calculate for each method
prod_data = calculate_h2_production(
method,
water_quantity,
energy_input,
current_density,
voltage
)
cost_result = calculate_cost(
method,
water_cost,
water_purification_cost,
energy_source,
energy_input,
prod_data
)
production_rates.append(prod_data['production_rate_g_per_hour'])
costs_per_kg.append(cost_result['cost_per_kg'])
# Create comparison charts
col1, col2 = st.columns(2)
with col1:
# Production rate comparison
fig1 = px.bar(
x=methods,
y=production_rates,
title="Production Rate Comparison",
labels={"x": "Production Method", "y": "Production Rate (g/hour)"},
color=production_rates,
color_continuous_scale="Blues"
)
st.plotly_chart(fig1, use_container_width=True)
with col2:
# Cost comparison
fig2 = px.bar(
x=methods,
y=costs_per_kg,
title="Cost per kg Comparison",
labels={"x": "Production Method", "y": "Cost ($/kg)"},
color=costs_per_kg,
color_continuous_scale="Reds_r"
)
st.plotly_chart(fig2, use_container_width=True)
# Efficiency vs Cost scatter plot
efficiencies = [0.65, 0.75, 0.85] # Method efficiencies
fig3 = px.scatter(
x=efficiencies,
y=costs_per_kg,
size=production_rates,
text=methods,
title="Efficiency vs Cost Trade-off",
labels={"x": "Efficiency", "y": "Cost ($/kg)"},
color=methods
)
# Add a vertical line for current efficiency
current_efficiency = production_data['efficiency']
fig3.add_shape(
type="line",
x0=current_efficiency,
y0=0,
x1=current_efficiency,
y1=max(costs_per_kg) * 1.1,
line=dict(color="red", width=2, dash="dash")
)
# Add annotation for current efficiency
fig3.add_annotation(
x=current_efficiency,
y=max(costs_per_kg) * 0.9,
text="Current Efficiency",
showarrow=True,
arrowhead=1
)
st.plotly_chart(fig3, use_container_width=True)
# Current density vs production rate
current_densities = np.linspace(0.1, 2.0, 10)
production_results = []
for cd in current_densities:
prod_data = calculate_h2_production(
production_method,
water_quantity,
energy_input,
cd,
voltage
)
production_results.append(prod_data['production_rate_g_per_hour'])
fig4 = px.line(
x=current_densities,
y=production_results,
title=f"Impact of Current Density on {production_method} Production Rate",
labels={"x": "Current Density (A/cm²)", "y": "Production Rate (g/hour)"},
markers=True
)
# Add a vertical line for current current density
fig4.add_shape(
type="line",
x0=current_density,
y0=0,
x1=current_density,
y1=max(production_results) * 1.1,
line=dict(color="green", width=2, dash="dash")
)
st.plotly_chart(fig4, use_container_width=True)
# Add a simulation over time
st.subheader("Production Simulation Over Time")
# Create time series data
hours = list(range(0, int(production_data['operation_time_hours']) + 1))
if len(hours) > 1:
production_over_time = [h * production_data['production_rate_g_per_hour'] for h in hours]
fig5 = px.line(
x=hours,
y=production_over_time,
title="Cumulative Hydrogen Production Over Time",
labels={"x": "Time (hours)", "y": "Cumulative Production (g)"},
markers=True
)
st.plotly_chart(fig5, use_container_width=True)
else:
st.info("Operation time too short for meaningful time series visualization.")
# Export results button
st.download_button(
label="Export Results as CSV",
data=pd.DataFrame({
"Parameter": ["Production Method", "Water Source", "Current Density (A/cm²)", "Voltage (V)",
"Production Rate (g/h)", "Total Production (g)", "Efficiency (%)",
"Total Cost ($)", "Cost per kg ($/kg)"],
"Value": [production_method, water_source, current_density, voltage,
production_data['production_rate_g_per_hour'], production_data['total_production_g'],
production_data['efficiency']*100, cost_data['total_cost'], cost_data['cost_per_kg']]
}).to_csv(index=False),
file_name=f"hydrogen_production_analysis_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv",
mime="text/csv"
)
# Run the app
if __name__ == "__main__":
main() |