How to run an HV Intrinsic Hosting Capacity Work Package
This guide shows a basic Python example for starting an HV node headroom work package through the Energy Workbench Python client.
An HV node headroom work package estimates headroom at selected HV node locations. It uses the same feeder/year/scenario scope, initial load state, injection resource, constraints, model configuration, and solve configuration patterns as an intrinsic work package. For a conceptual overview of how both modes work, see What is Intrinsic Hosting Capacity Mode?.
In this mode, HCM finds every HV node in the selected feeders that matches the configured nodeLocationSelector types. It tests those HV nodes one at a time by injecting additional load or generation at that point in the network until that node's headroom is found. That additional load or generation is then removed before the next HV node is tested.
Minimal Example
Create an EasClient, build an HvNodeHeadroomWorkPackageInput, then submit it using Mutation.run_hv_node_headroom_work_package.
from zepben.eas.client.eas_client import EasClient
from zepben.eas.lib.custom_mutations import Mutation
from zepben.eas.lib import (
HvNodeHeadroomWorkPackageInput,
IntrinsicInitialLoadStateConfigInput,
IntrinsicInitialStateSelectorMode,
IntrinsicSyfConfigInput,
)
client = EasClient(
host=eas_server_host,
port=eas_server_port,
protocol=eas_server_protocol,
client_id=eas_server_client_id,
username=eas_server_username,
password=eas_server_password,
client_secret=eas_server_client_secret,
verify_certificate=eas_server_verify_certificate,
ca_filename=eas_server_ca_filename,
)
work_package = HvNodeHeadroomWorkPackageInput(
syf=IntrinsicSyfConfigInput(
feeders=["feeder-mrid-1"],
year=2030,
scenario="base",
),
initial_state_selector=IntrinsicInitialLoadStateConfigInput(
selector_mode=IntrinsicInitialStateSelectorMode.FIXED_TIME,
start_time="2030-01-01T12:00:00",
include_loads=True,
include_existing_der=True,
load_scaling_factor=1.0,
der_scaling_factor=1.0,
),
)
result = client.mutation(
Mutation.run_hv_node_headroom_work_package(
input=work_package,
work_package_name="Example HV node headroom work package",
)
)
print(result)
The mutation returns the new work package ID if the request is accepted.
Shared Configuration
HV node headroom work packages reuse these inputs from intrinsic work packages:
| Field | Notes |
|---|---|
syf | Same feeder, year, and scenario input as intrinsic work packages. See SYF Config. |
initial_state_selector | Same initial load state selector as intrinsic work packages. See Initial State Selector Config. |
injection_resource | Same injection resource input as intrinsic work packages. See Injection Resource Config. |
constraints | Same voltage and thermal constraint input as intrinsic work packages. See Constraints Config. |
model | Uses the same model configuration input as a normal hosting capacity work package. |
solve | Uses the same solve configuration input as the intrinsic and normal hosting capacity work package inputs. |
HV-Specific Configuration
Search Config
Use search to control the HV node headroom search.
from zepben.eas.lib import HvNodeHeadroomSearchConfigInput
work_package.search = HvNodeHeadroomSearchConfigInput(
step_kw_per_node=5.0,
max_steps_per_node=1000,
)
| Field | Default | Restriction |
|---|---|---|
step_kw_per_node | 1.0 | Optional search increment in kW per node. |
max_steps_per_node | 1000 | Must be 1000 or less. |
HV Node Location Selector Config
Use nodeLocationSelector to choose which HV node locations are included in the headroom calculation.
from zepben.eas.lib import HvNodeLocationKind, HvNodeLocationSelectorInput
work_package.node_location_selector = HvNodeLocationSelectorInput(
location_kinds=[
HvNodeLocationKind.DTX_HV_TERMINAL,
HvNodeLocationKind.LINE_TEE,
],
)
| Field | Default | Notes |
|---|---|---|
location_kinds | [DTX_HV_TERMINAL] | Optional list of HV node location kinds to include. |
Supported location_kinds values:
DTX_HV_TERMINALSWITCH_UPSTREAM_TERMINALLINE_TEE
Full Example
from zepben.eas.client.eas_client import EasClient
from zepben.eas.lib.custom_mutations import Mutation
from zepben.eas.lib import (
HvNodeHeadroomSearchConfigInput,
HvNodeHeadroomWorkPackageInput,
HvNodeLocationKind,
HvNodeLocationSelectorInput,
IntrinsicConstraintsConfigInput,
IntrinsicHvVoltageConstraintInput,
IntrinsicInitialLoadStateConfigInput,
IntrinsicInitialStateSelectorMode,
IntrinsicInjectionResourceConfigInput,
IntrinsicInjectionResourceMethod,
IntrinsicLoadModelType,
IntrinsicLvVoltageConstraintInput,
IntrinsicRatingBasis,
IntrinsicSyfConfigInput,
IntrinsicThermalConstraintInput,
IntrinsicThermalConstraintsInput,
IntrinsicVoltageConstraintsInput,
)
client = EasClient(...)
work_package = HvNodeHeadroomWorkPackageInput(
syf=IntrinsicSyfConfigInput(
feeders=["feeder-mrid-1"],
year=2030,
scenario="base",
),
initial_state_selector=IntrinsicInitialLoadStateConfigInput(
selector_mode=IntrinsicInitialStateSelectorMode.FIXED_TIME,
start_time="2030-01-01T12:00:00",
include_loads=True,
include_existing_der=True,
load_scaling_factor=1.0,
der_scaling_factor=1.0,
),
search=HvNodeHeadroomSearchConfigInput(
step_kw_per_node=5.0,
max_steps_per_node=1000,
),
node_location_selector=HvNodeLocationSelectorInput(
location_kinds=[
HvNodeLocationKind.DTX_HV_TERMINAL,
HvNodeLocationKind.LINE_TEE,
],
),
injection_resource=IntrinsicInjectionResourceConfigInput(
method=IntrinsicInjectionResourceMethod.EXPORT_GENERATION,
load_model_type=IntrinsicLoadModelType.NEGATIVE_LOAD,
power_factor=0.95,
),
constraints=IntrinsicConstraintsConfigInput(
voltage=IntrinsicVoltageConstraintsInput(
hv=IntrinsicHvVoltageConstraintInput(min_pu=0.95, max_pu=1.05),
lv=IntrinsicLvVoltageConstraintInput(min=216.0, max=253.0),
),
thermal=IntrinsicThermalConstraintsInput(
hv=IntrinsicThermalConstraintInput(
percent_of_rating=100.0,
rating_basis=IntrinsicRatingBasis.NORMAL,
),
lv=IntrinsicThermalConstraintInput(
percent_of_rating=100.0,
rating_basis=IntrinsicRatingBasis.NORMAL,
),
),
),
)
result = client.mutation(
Mutation.run_hv_node_headroom_work_package(
input=work_package,
work_package_name="2030 HV node headroom",
)
)
Monitoring The Run
After the mutation returns a work package ID, use the standard work package manager or progress APIs described in How to run a work package and How to manage work packages.
Understanding the Results
Once the work package completes, results are written to the Intrinsic Hosting Capacity output tables. HV node headroom runs produce the hv_node_headroom, binding_constraints, and constraint_violations tables. Note that lv_group_hosting_capacity and customer_allocations are not produced by HV node headroom runs.
Where to start: hv_node_headroom
The hv_node_headroom table is your primary result. Each row is one HV node that was tested and reports the maximum additional kW that can be injected at that point before a network constraint is breached.
The key columns:
available_headroom_kw- the additional kW of load or generation that can connect at this HV node before any configured voltage or thermal limit is hit.headroom_direction- whether this isexport(generation connecting to the HV network) orimport(load connecting).location_type- the type of HV node (DTX_HV_TERMINAL,LINE_TEE, orSWITCH_UPSTREAM_TERMINAL).asset_name- human-readable name of the asset at this location, useful for cross-referencing with network maps or GIS data.
Unlike the LV intrinsic mode, HV nodes are tested one at a time in isolation. The headroom figure represents the capacity at that point assuming only that one injection is added, with the rest of the network in its initial state.
Understanding what constrained each node: constraint_violations
For any node where you want to understand the limiting factor, join through binding_constraints to constraint_violations:
The metric column tells you whether the search stopped on a voltage limit or a thermal current limit. The conducting_equipment_mrid identifies the specific asset - a transformer, line segment, or cable - that was the binding constraint.