diff --git a/changelog.md b/changelog.md index 2620487..fc71bad 100644 --- a/changelog.md +++ b/changelog.md @@ -1,7 +1,9 @@ # EAS Python client ## [0.28.0] - UNRELEASED ### Breaking Changes -* None. +* For `CandidateGenerationConfig`, replaced `voltage_delta_avg_threshold` with `average_voltage_spread_threshold`, which serves the same purpose but is + in volts instead of voltage per-unit. + * EAS must support this change in the GraphQL schema (`v2.10.0` and above). ### New Features * None. diff --git a/src/zepben/eas/client/eas_client.py b/src/zepben/eas/client/eas_client.py index 5c93fe1..0709c8b 100644 --- a/src/zepben/eas/client/eas_client.py +++ b/src/zepben/eas/client/eas_client.py @@ -386,11 +386,11 @@ def work_package_config_to_json(self, work_package: WorkPackageConfig) -> dict: "candidateGeneration": work_package.intervention.candidate_generation and { "type": work_package.intervention.candidate_generation.type.name, "interventionCriteriaName": work_package.intervention.candidate_generation.intervention_criteria_name, - "voltageDeltaAvgThreshold": work_package.intervention.candidate_generation.voltage_delta_avg_threshold, + "averageVoltageSpreadThreshold": work_package.intervention.candidate_generation.average_voltage_spread_threshold, "voltageUnderLimitHoursThreshold": work_package.intervention.candidate_generation.voltage_under_limit_hours_threshold, "voltageOverLimitHoursThreshold": work_package.intervention.candidate_generation.voltage_over_limit_hours_threshold, "tapWeightingFactorLowerThreshold": work_package.intervention.candidate_generation.tap_weighting_factor_lower_threshold, - "tapWeightingFactorUpperThreshold": work_package.intervention.candidate_generation.tap_weighting_factor_upper_threshold, + "tapWeightingFactorUpperThreshold": work_package.intervention.candidate_generation.tap_weighting_factor_upper_threshold }, "allocationCriteria": work_package.intervention.allocation_criteria, "specificAllocationInstance": work_package.intervention.specific_allocation_instance, diff --git a/src/zepben/eas/client/work_package.py b/src/zepben/eas/client/work_package.py index caa60e9..6343933 100644 --- a/src/zepben/eas/client/work_package.py +++ b/src/zepben/eas/client/work_package.py @@ -767,9 +767,13 @@ class CandidateGenerationConfig: base work package run. Only used when type is CRITERIA. """ - voltage_delta_avg_threshold: Optional[float] = None + average_voltage_spread_threshold: Optional[int] = None """ - The threshold for average deviation in voltage p.u. across the transformer. Only used when type is TAP_OPTIMIZATION. + The threshold for average line voltage spread under the transformer over the year, in volts. + Voltage spread at each timestep is calculated by taking the difference between the maximum and minimum phase-to-phase voltage over + the nodes under the transformer, for each phase, then taking the maximum of that difference across all phases. + When the average voltage spread exceeds this threshold, it indicates that the transformer is experiencing a + significant voltage swing that may impact system stability. Only used when type is TAP_OPTIMIZATION. """ voltage_under_limit_hours_threshold: Optional[int] = None diff --git a/test/test_eas_client.py b/test/test_eas_client.py index e8b68a3..f2504e2 100644 --- a/test/test_eas_client.py +++ b/test/test_eas_client.py @@ -17,7 +17,7 @@ from werkzeug import Response from zepben.ewb.auth import ZepbenTokenFetcher -from zepben.eas import EasClient, Study, SolveConfig, InterventionConfig, YearRange +from zepben.eas import EasClient, Study, SolveConfig, InterventionConfig, YearRange, CandidateGenerationConfig, CandidateGenerationType from zepben.eas import FeederConfig, ForecastConfig, FixedTimeLoadOverride from zepben.eas.client.ingestor import IngestorConfigInput, IngestorRunsSortCriteriaInput, IngestorRunsFilterInput, \ IngestorRunState, IngestorRuntimeKind @@ -1744,3 +1744,53 @@ def test_work_package_config_to_json_includes_server_defaulted_fields_if_specifi "dvms": None, "allocationLimitPerYear": 5 } + +def test_work_package_config_to_json_for_tap_optimization(httpserver: HTTPServer): + eas_client = EasClient( + LOCALHOST, + httpserver.port, + verify_certificate=False + ) + + wp_config = WorkPackageConfig( + name="wp", + syf_config=FeederConfigs([]), + intervention=InterventionConfig( + base_work_package_id="abc", + year_range=YearRange(2020, 2025), + intervention_type=InterventionClass.DISTRIBUTION_TAP_OPTIMIZATION, + allocation_limit_per_year=5, + candidate_generation=CandidateGenerationConfig( + type=CandidateGenerationType.TAP_OPTIMIZATION, + average_voltage_spread_threshold=40, + voltage_under_limit_hours_threshold=1, + voltage_over_limit_hours_threshold=2, + tap_weighting_factor_lower_threshold=-0.3, + tap_weighting_factor_upper_threshold=0.4 + ) + ) + ) + json_config = eas_client.work_package_config_to_json(wp_config) + + assert json_config["intervention"] == { + "baseWorkPackageId": "abc", + "yearRange": { + "maxYear": 2025, + "minYear": 2020 + }, + "interventionType": "DISTRIBUTION_TAP_OPTIMIZATION", + "candidateGeneration": { + "type": "TAP_OPTIMIZATION", + "interventionCriteriaName": None, + "averageVoltageSpreadThreshold": 40, + "voltageUnderLimitHoursThreshold": 1, + "voltageOverLimitHoursThreshold": 2, + "tapWeightingFactorLowerThreshold": -0.3, + "tapWeightingFactorUpperThreshold": 0.4, + }, + "allocationCriteria": None, + "specificAllocationInstance": None, + "phaseRebalanceProportions": None, + "dvms": None, + "allocationLimitPerYear": 5 + }