Skip to content

Implement SolarCalibrator mirroring WindCalibrator #47

Description

@imharrisonking

Please provide a high level description of the feature.
Implement a SolarCalibrator class under rencal/calibration/solar/ that mirrors the structure and workflow of WindCalibrator, adapting the calibration pipeline for solar PV generators. The ERA5 downloader and data loader already support solar variables (ssrd, t2m), so the core data infrastructure is in place. What's needed is the solar-specific calibrator and supporting constants.

Describe the proposed solution and/or implementation in more detail

New files / directories:

  • rencal/calibration/solar/__init__.py
  • rencal/calibration/solar/solar_calibrator.py — SolarCalibrator(Calibrator) implementing all abstract methods

Changes to existing files:

  • rencal/utils/constants.py — add:
    • SOLAR_TECHNOLOGY_TYPES (analogous to WIND_TECHNOLOGY_TYPES)
    • Solar-specific constants (irradiance bounds, curve-fitting params)
    • SOLAR_NPY_BASEPATH / SOLAR_NPY_HISTOGRAMS_BASEPATH
  • rencal/core/data_loader.py — extend check_historical_weather(), get_historical_weather(), and get_prefix_histograms() to handle solar NPY paths alongside wind

Key implementation differences from WindCalibrator:

  1. Resource variable: Use ssrd (surface solar radiation downwards) as the primary resource proxy instead of wind speed. Note: ssrd is in J/m² (accumulated over the hour) and will need a unit conversion to W/m² (divide by 3600) in extract_resource_timeseries_for_plants().

  2. Optional temperature correction: t2m (2m temperature) is also available and could be used to model temperature-dependent efficiency losses.

  3. Power curve shape: The wind calibrator uses a generalised logistic (sigmoid) function. Solar load factor is more linearly related to irradiance rather than sigmoidal — curve fitting approach to be determined from internal reference script.

  4. Distribution fitting: The wind calibrator fits a Weibull distribution to historical wind speeds. Solar irradiance has a large mass at zero (night-time), making a standard Weibull a poor fit — distribution approach to be determined from internal reference script.

  5. NPY output: WindCalibrator has a stream_npy_output flag for writing .npy alongside .parquet. Whether SolarCalibrator should mirror this is left to the implementer.

Describe alternatives you've considered
No alternatives have been formally considered yet. The assumption is the Calibrator abstract base class and LocalDataLoader infrastructure are reused as-is, with only solar-specific logic added.

Additional context (Optional)
The ERA5DataDownloader already downloads ssrd and t2m as part of its solar request and merges them into the same NetCDF as the wind variables. The LocalDataLoader._filter_dataset_variables() already includes DEFAULT_SOLAR_VARIABLES when loading ERA5 data. No changes to the downloader or ERA5 loading pipeline should be required.

Implementation should be modelled from an internal calibration script. The following design questions should be resolved by reference to that script before or during implementation:

  • Power curve shape: Should the solar curve use a piecewise-linear / clipped linear fit, or keep the generalised logistic function with different initial parameter bounds? This affects estimate_load_factors_for_resource() and the constants to add to rencal/utils/constants.py.
  • Distribution fitting: Should night-time (zero-irradiance) periods be filtered before fitting, and if so, which distribution should be used (e.g., beta, truncated normal)? Or should a different integration approach be used in estimate_load_factors_for_resource()?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions