Skip to main content

Core Concepts

This guide covers the fundamental concepts and domain knowledge required to understand and develop PVTools effectively.

Solar PV System Fundamentals

System Components

Solar Panels

  • Power Rating (kWp): Peak power output under Standard Test Conditions (STC)
  • Efficiency: Percentage of solar energy converted to electricity
  • Degradation Rate: Annual reduction in panel efficiency (typically 0.5-0.8%)
  • Temperature Coefficient: Performance impact of temperature variations

Inverters

  • String Inverters: Central inverter for multiple panel strings
  • Power Optimizers: Panel-level optimization with string inverter
  • Microinverters: Individual inverter per panel
  • Sizing Ratio: Inverter capacity vs panel capacity (typically 1.1-1.3)

Battery Energy Storage Systems (BESS)

  • Capacity (kWh): Total energy storage capability
  • Power Rating (kW): Maximum charge/discharge rate
  • Round-trip Efficiency: Energy lost in charge/discharge cycle
  • Depth of Discharge (DoD): Usable capacity percentage
  • Cycle Life: Number of charge/discharge cycles before degradation

Performance Metrics

Energy Production

# Monthly energy production calculation
monthly_production = panel_capacity * monthly_irradiation * performance_ratio

Performance Ratio (PR)

# System efficiency considering all losses
performance_ratio = actual_output / (panel_capacity * irradiation)

Malaysian Energy Market Context

Regulatory Framework

SARE (Solar Energy Regulatory)

  • Grid connection standards and requirements
  • Safety and technical specifications
  • Installation and commissioning procedures

NOVA (Net Energy Metering)

  • Bi-directional energy metering system
  • Credit mechanism for excess energy exported to grid
  • Capacity limitations based on consumer category

SELCO (Self-Consumption)

  • On-site consumption prioritization
  • No export to grid allowed
  • Simplified approval process

TNB Tariff Structure

Tariff Categories

  • Domestic (B): Residential consumers
  • Commercial (C1-C3): Business consumers by voltage level
  • Industrial (D-F): Large industrial consumers
  • Agricultural (G): Farming and agricultural operations

Billing Components

# Complex tariff calculation example
def calculate_tnb_bill(consumption, peak_demand, tariff_category):
energy_charge = calculate_energy_charge(consumption, tariff_category)
demand_charge = calculate_demand_charge(peak_demand, tariff_category)
service_charge = get_service_charge(tariff_category)
return energy_charge + demand_charge + service_charge

Financial Modeling Concepts

Financing Models

Tokenization

  • Digital Asset Creation: Converting solar assets into tradeable tokens
  • Fractional Ownership: Multiple investors can own portions of a system
  • Revenue Distribution: Automated distribution of energy savings/revenues
  • Liquidity: Token trading on secondary markets
class TokenizedFinancing:
def __init__(self, system_value: float, token_count: int):
self.token_value = system_value / token_count
self.investors = {}

def distribute_returns(self, monthly_savings: float):
"""Distribute returns proportionally to token holders."""
for investor, tokens in self.investors.items():
proportion = tokens / self.token_count
investor_return = monthly_savings * proportion
# Process payment

Term Loan

  • Fixed Interest Rate: Predetermined borrowing cost
  • Amortization Schedule: Principal and interest payment timeline
  • Collateral: Solar system as loan security
  • Prepayment Options: Early repayment terms

Power Purchase Agreement (PPA)

  • Energy Rate: Fixed price per kWh
  • Escalation: Annual price increase mechanism
  • Performance Guarantees: Minimum energy production commitments
  • Term Length: Contract duration (typically 15-25 years)

Financial Metrics

Net Present Value (NPV)

def calculate_npv(cash_flows: List[float], discount_rate: float) -> float:
"""Calculate NPV of cash flow series."""
npv = 0
for year, cash_flow in enumerate(cash_flows):
npv += cash_flow / (1 + discount_rate) ** year
return npv

Internal Rate of Return (IRR)

def calculate_irr(cash_flows: List[float]) -> float:
"""Calculate IRR using numerical methods."""
from scipy.optimize import fsolve

def npv_func(rate):
return sum(cf / (1 + rate) ** i for i, cf in enumerate(cash_flows))

return fsolve(npv_func, 0.1)[0]

Levelized Cost of Energy (LCOE)

def calculate_lcoe(capex: float, opex_annual: float,
production_annual: float, years: int,
discount_rate: float) -> float:
"""Calculate LCOE in RM/kWh."""
# Present value of costs
pv_costs = capex + sum(opex_annual / (1 + discount_rate) ** year
for year in range(1, years + 1))

# Present value of energy production
pv_energy = sum(production_annual / (1 + discount_rate) ** year
for year in range(1, years + 1))

return pv_costs / pv_energy

Optimization Theory

Multi-Objective Optimization

PVTools solves problems with multiple competing objectives:

  1. Maximize Customer Savings: Reduce electricity bills
  2. Maximize Investor Returns: Optimize financial metrics
  3. Minimize System Cost: Reduce capital expenditure
  4. Maximize Energy Production: Optimize system performance

Pareto Optimality

def is_pareto_optimal(solution, solution_set):
"""Check if solution is Pareto optimal."""
for other in solution_set:
if dominates(other, solution):
return False
return True

def dominates(a, b):
"""Check if solution a dominates solution b."""
better_in_all = all(a[i] >= b[i] for i in range(len(a)))
better_in_one = any(a[i] > b[i] for i in range(len(a)))
return better_in_all and better_in_one

Constraint Handling

Technical Constraints

  • Roof Space Limitation: Maximum installable capacity
  • CT Rating Limit: Grid connection capacity constraints
  • Inverter Sizing: Optimal inverter-to-panel ratio
  • Electrical Safety: Code compliance requirements

Financial Constraints

  • Budget Limitations: Maximum available capital
  • Financing Terms: Loan-to-value ratios
  • ROI Requirements: Minimum acceptable returns
  • Regulatory Limits: Government incentive caps

Operational Constraints

  • Peak Demand: Maximum instantaneous power requirement
  • Load Profile: Energy consumption patterns
  • Grid Stability: Power quality requirements
  • Maintenance Access: Physical accessibility

Battery Storage Concepts

Storage Applications

Peak Shaving

def calculate_peak_shaving_benefit(peak_demand_before: float,
peak_demand_after: float,
demand_charge_rate: float) -> float:
"""Calculate monthly savings from peak demand reduction."""
demand_reduction = peak_demand_before - peak_demand_after
return demand_reduction * demand_charge_rate

Load Shifting

def optimize_load_shifting(load_profile: List[float],
tariff_schedule: List[float],
battery_capacity: float) -> List[float]:
"""Optimize battery dispatch for load shifting."""
# Implement time-of-use optimization
# Charge during low-rate periods
# Discharge during high-rate periods

Backup Power

def calculate_backup_duration(battery_capacity: float,
critical_load: float,
efficiency: float) -> float:
"""Calculate backup power duration in hours."""
usable_capacity = battery_capacity * efficiency
return usable_capacity / critical_load

Battery Modeling

State of Charge (SOC)

class BatteryModel:
def __init__(self, capacity: float, efficiency: float):
self.capacity = capacity
self.efficiency = efficiency
self.soc = 0.5 # Start at 50%

def charge(self, power: float, duration: float) -> float:
"""Charge battery and return actual energy stored."""
energy_input = power * duration
energy_stored = energy_input * self.efficiency
new_soc = min(1.0, self.soc + energy_stored / self.capacity)
actual_stored = (new_soc - self.soc) * self.capacity
self.soc = new_soc
return actual_stored

def discharge(self, power: float, duration: float) -> float:
"""Discharge battery and return actual energy delivered."""
energy_requested = power * duration
available_energy = self.soc * self.capacity
energy_delivered = min(energy_requested, available_energy) * self.efficiency
self.soc -= energy_delivered / self.capacity
return energy_delivered

Environmental Impact (ESG)

Carbon Footprint Calculation

def calculate_co2_reduction(annual_production: float,
grid_emission_factor: float) -> float:
"""Calculate annual CO2 reduction in tonnes."""
return annual_production * grid_emission_factor / 1000 # kg to tonnes

Equivalent Environmental Metrics

def trees_equivalent(co2_reduction: float) -> float:
"""Calculate equivalent trees planted."""
co2_per_tree_annual = 21.77 # kg CO2 per tree per year
return co2_reduction * 1000 / co2_per_tree_annual

Data Integration Patterns

External API Integration

PVGIS (Photovoltaic Geographical Information System)

async def fetch_pvgis_data(latitude: float, longitude: float,
system_capacity: float) -> Dict:
"""Fetch solar irradiation data from PVGIS."""
url = f"https://re.jrc.ec.europa.eu/api/PVcalc"
params = {
'lat': latitude,
'lon': longitude,
'peakpower': system_capacity,
'outputformat': 'json'
}
# Implementation with error handling and caching

Real-time Forecasting

async def fetch_forecast_data(latitude: float, longitude: float) -> Dict:
"""Fetch solar forecast from Forecast.Solar."""
url = f"https://api.forecast.solar/estimate/{latitude}/{longitude}/40/0/5"
# Implementation with rate limiting and fallbacks

Data Validation and Processing

Time Series Validation

def validate_time_series(data: pd.DataFrame) -> bool:
"""Validate time series data integrity."""
# Check for missing timestamps
# Validate data ranges
# Detect outliers
# Ensure temporal consistency

Geographic Validation

def validate_coordinates(latitude: float, longitude: float) -> bool:
"""Validate geographic coordinates for Malaysia."""
# Malaysia bounds: approximately 1°-7°N, 99°-119°E
return (1.0 <= latitude <= 7.0 and
99.0 <= longitude <= 119.0)

This foundational knowledge is essential for understanding the codebase, implementing new features, and debugging complex optimization scenarios in PVTools.