Files
SITER-Solar/solar-analysis/solar_optimized.py
Charles N Wyble 400764a9ff feat: initial project setup with bash-based NREL analysis
- Add bash script (siter-solar-analysis.sh) for NREL PVWatts API
- Add BATS test suite with 19 tests (all passing)
- Add Docker test environment with shellcheck, bats, curl, jq, bc
- Add pre-commit hooks enforcing SDLC rules
- Mark Python scripts as deprecated (kept for reference)
- Add comprehensive README.md and AGENTS.md documentation
- Add .env.example for configuration template
- Add .gitignore excluding private data (base-bill/, .env)
- Add SVG diagrams for presentation
- Redact all private location data (use SITER placeholder)

All work done following SDLC: Docker-only development, TDD approach,
conventional commits, code/docs/tests synchronized.

Generated with Crush

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-02-27 16:45:41 -05:00

62 lines
2.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# DEPRECATED: This script is deprecated. Use siter-solar-analysis.sh instead.
# This file is kept for reference only.
"""Quick comparison: standard losses vs optimized (no shade)"""
import requests
LAT = float(os.environ.get("SITER_LAT", "30.44")) # Central Texas
LON = float(os.environ.get("SITER_LON", "-97.62")) # Central Texas
import os
API_URL = "https://developer.nrel.gov/api/pvwatts/v6.json"
def query(capacity, losses):
params = {
"api_key": os.environ.get("NREL_API_KEY", "DEMO_KEY"),
"lat": LAT, "lon": LON,
"system_capacity": capacity,
"array_type": 0, # Ground mount
"tilt": 30, "azimuth": 180,
"module_type": 0,
"losses": losses,
"timeframe": "monthly"
}
r = requests.get(API_URL, params=params, timeout=30)
return r.json()
print("=" * 70)
print("GROUND MOUNT ANALYSIS: Standard vs Optimized (No Shade)")
print("Location: SITER")
print("=" * 70)
print("\nGround mount advantages at your site:")
print(" - No trees = minimal shading losses")
print(" - Open rack = better airflow, cooler panels")
print(" - Optimal tilt (30°) = maximum annual production")
print()
# Standard 14% losses vs optimized 8% losses (no shade)
for losses in [14, 10, 8, 5]:
data = query(4.0, losses)
if data and not data.get("errors"):
annual = data["outputs"]["ac_annual"]
monthly = annual / 12
value = (annual * 0.60 * 0.085) + (annual * 0.40 * 0.04)
payback = 4100 / (value / 12)
print(f"Losses @ {losses}%: {annual:,.0f} kWh/yr | ${value/12:.2f}/mo | Payback: {payback/12:.1f} yrs")
print()
print("=" * 70)
print("PANEL WATTAGE COMPARISON (Optimized @ 8% losses)")
print("=" * 70)
for watts in [250, 300, 350, 400, 450]:
capacity = (16 * watts) / 1000
data = query(capacity, 8) # Optimized losses
if data and not data.get("errors"):
annual = data["outputs"]["ac_annual"]
value = (annual * 0.60 * 0.085) + (annual * 0.40 * 0.04)
payback = 4100 / (value / 12)
offset = (value / 12 / 301.08) * 100
print(f"16 × {watts}W ({capacity:.1f}kW): {annual:,.0f} kWh/yr | ${value/12:.2f}/mo | {offset:.0f}% offset | {payback/12:.1f} yr payback")