#!/usr/bin/env python3 # # SITER Solar Analysis - NREL PVWatts Solar Production Estimator # Copyright (C) 2026 Known Element # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # DEPRECATED: This script is deprecated. Use siter-solar-analysis.sh instead. # This file is kept for reference only. """Find optimal tilt/azimuth for ground mount at SITER location""" import requests import time LAT = float(os.environ.get("SITER_LAT", "30.44")) # Central Texas import os LON = float(os.environ.get("SITER_LON", "-97.62")) # Central Texas API_URL = "https://developer.nrel.gov/api/pvwatts/v6.json" def query(capacity, tilt, azimuth, losses=8): params = { "api_key": os.environ.get("NREL_API_KEY", "DEMO_KEY"), "lat": LAT, "lon": LON, "system_capacity": capacity, "array_type": 0, # Ground mount "tilt": tilt, "azimuth": azimuth, "module_type": 0, "losses": losses, } try: r = requests.get(API_URL, params=params, timeout=30) data = r.json() return data.get("outputs", {}).get("ac_annual", 0) except: return 0 print("=" * 70) print("OPTIMAL ORIENTATION ANALYSIS - SITER Solar (Ground Mount)") print("Location: SITER") print("System: 16 panels × 250W = 4.0 kW DC") print("Losses: 8% (optimized - no shade, good airflow)") print("=" * 70) # Test different tilts (latitude = 30.44°N) print("\nTilt Analysis (Azimuth = 180° South):") print("-" * 40) best_tilt = 0 best_prod = 0 for tilt in [0, 15, 20, 25, 30, 35, 40, 45, 50, 60, 90]: prod = query(4.0, tilt, 180) if prod > best_prod: best_prod = prod best_tilt = tilt print(f" Tilt {tilt:>2}°: {prod:>6,.0f} kWh/yr") time.sleep(0.5) print(f"\n Best tilt: {best_tilt}° ({best_prod:,.0f} kWh/yr)") # Test azimuth variations print("\nAzimuth Analysis (Tilt = 30°):") print("-" * 40) best_az = 180 best_prod = 0 for az in [90, 120, 150, 180, 210, 240, 270]: prod = query(4.0, 30, az) if prod > best_prod: best_prod = prod best_az = az direction = {90: "E", 120: "ESE", 150: "SSE", 180: "S", 210: "SSW", 240: "WSW", 270: "W"} print(f" {az:>3}° ({direction.get(az, ''):<3}): {prod:>6,.0f} kWh/yr") time.sleep(0.5) print(f"\n Best azimuth: {best_az}° ({best_prod:,.0f} kWh/yr)") # Final optimized production print("\n" + "=" * 70) print("OPTIMIZED SYSTEM PERFORMANCE") print("=" * 70) opt_prod = query(4.0, best_tilt, best_az) value = (opt_prod * 0.60 * 0.085) + (opt_prod * 0.40 * 0.04) payback = 4100 / (value / 12) print(f"\n Optimal Config: {best_tilt}° tilt, {best_az}° azimuth") print(f" Annual Production: {opt_prod:,.0f} kWh") print(f" Monthly Average: {opt_prod/12:,.0f} kWh") print(f" Monthly Value: ${value/12:.2f}") print(f" Bill Offset: {(value/12/301.08)*100:.1f}%") print(f" Payback: {payback/12:.1f} years") print("\n" + "=" * 70) print("PANEL WATTAGE OPTIONS (Optimized Orientation)") print("=" * 70) print(f"\n{'Panels':<12} {'Capacity':>10} {'kWh/yr':>10} {'$/mo':>8} {'Offset':>8} {'Payback':>10}") print("-" * 60) for watts in [250, 300, 350, 400, 450]: capacity = (16 * watts) / 1000 prod = query(capacity, best_tilt, best_az) if prod: value = (prod * 0.60 * 0.085) + (prod * 0.40 * 0.04) payback = 4100 / (value / 12) offset = (value / 12 / 301.08) * 100 print(f"16 × {watts}W {capacity:>8.1f}kW {prod:>10,.0f} ${value/12:>6.2f} {offset:>6.1f}% {payback/12:>8.1f} yrs") time.sleep(0.5)