diff --git a/solarfarmer/models/pvsystem/pvsystem.py b/solarfarmer/models/pvsystem/pvsystem.py index 32290c7..9365156 100644 --- a/solarfarmer/models/pvsystem/pvsystem.py +++ b/solarfarmer/models/pvsystem/pvsystem.py @@ -198,6 +198,12 @@ class PVSystem: If True, generates loss tree timeseries output (default is True). enable_spectral_modeling : bool If True, enables spectral modeling in the calculation (default is False). + calculate_dhi_from_ghi : bool + Whether to calculate diffuse horizontal irradiance (DHI) from global + horizontal irradiance (GHI) when the ``DHI`` column is missing from the + meteorological file. If ``False`` and ``DHI`` is missing, the calculation + will fail. Set to ``True`` when using weather files that only provide GHI. + Provided DHI is preferred over engine decomposition (default is False). Methods ------- @@ -271,6 +277,7 @@ class PVSystem: generate_pvsyst_format_timeseries: bool = True generate_loss_tree_timeseries: bool = True enable_spectral_modeling: bool = False + calculate_dhi_from_ghi: bool = False # Auxiliary files _pan_files: dict[str, Path] = field(default_factory=dict, repr=False) @@ -832,6 +839,7 @@ def describe(self, verbose=False) -> None: print("\n--- MODELING OPTIONS ---") print(f"Enable Spectral Modeling: {self.enable_spectral_modeling}") print(f"Module IAM Model Override: {self.module_iam_model_override}") + print(f"Calculate DHI (from GHI in weather file): {self.calculate_dhi_from_ghi}") # Output Options print("\n--- OUTPUT OPTIONS ---") @@ -1105,6 +1113,7 @@ def construct_plant(pvplant: PVSystem) -> str: pvplant.generate_pvsyst_format_timeseries ) calculation_options.apply_spectral_mismatch_modifier = pvplant.enable_spectral_modeling + calculation_options.calculate_dhi = pvplant.calculate_dhi_from_ghi # Build the full inputs model inputs = EnergyCalculationInputs( diff --git a/tests/test_construct_plant.py b/tests/test_construct_plant.py index 149ed7b..8e27e47 100644 --- a/tests/test_construct_plant.py +++ b/tests/test_construct_plant.py @@ -57,6 +57,16 @@ def test_spectral_modeling_on_when_enabled(self, plant): payload = json.loads(construct_plant(plant)) assert payload["energyCalculationOptions"]["applySpectralMismatchModifier"] is True + def test_calculate_dhi_off_by_default(self, plant): + payload = json.loads(construct_plant(plant)) + opts = payload["energyCalculationOptions"] + assert opts.get("calculateDHI", False) is False + + def test_calculate_dhi_on_when_enabled(self, plant): + plant.calculate_dhi_from_ghi = True + payload = json.loads(construct_plant(plant)) + assert payload["energyCalculationOptions"]["calculateDHI"] is True + def test_horizon_keys_absent_when_not_set(self, plant): payload = json.loads(construct_plant(plant)) assert "horizonAzimuths" not in payload