Section Study
Overview
SectionStudy is the main user-facing facade that bundles all engines needed to study a power-line section.
It wraps BalanceEngine, PositionEngine, PlotEngine, ThermalEngine, and Guying into a single object,
providing a simplified workflow with additional safety features:
- Automatic rollback on solver errors — the engine state is restored to the snapshot taken before the solve attempt.
- Intermediate warm-start — before solving extreme weather conditions, a preliminary solve at default conditions (\(T = 15\,°C\), wind = 0, ice = 0) improves convergence.
- State save / restore — take snapshots and roll back to any previous state using the Memento pattern.
Quick start
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Creating a SectionStudy
A SectionStudy requires the same inputs as a BalanceEngine: a CableArray and a SectionArray.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
Custom span and deformation models can be passed at construction:
1 2 3 4 5 6 7 8 9 | |
Solving
Adjustment
The adjustment solve computes the reference length \(L_{ref}\) from sagging conditions (no wind, no ice, sagging temperature).
1 | |
Change of state
The change-of-state solve computes insulator chain positions for given weather conditions.
1 2 3 4 5 6 | |
Important
solve_adjustment() must be called before solve_change_state(). If it has not been called, SectionStudy will trigger it automatically with a warning.
Intermediate warm-start
When the requested conditions differ from the defaults (\(T = 15\,°C\), wind = 0, ice = 0), SectionStudy automatically performs an intermediate solve at the default conditions first.
This provides a better starting point for the solver, improving convergence for extreme conditions.
The intermediate result is accessible via the intermediate_memento property:
1 2 3 4 5 | |
Note
When the requested conditions match the defaults, the intermediate step is skipped and intermediate_memento is None.
Automatic rollback
If the solver fails during solve_change_state(), the engine state is automatically restored to the snapshot taken before the solve was attempted. A SolverError is still raised so you can handle it:
1 2 3 4 5 6 7 | |
For solve_adjustment() without manipulations, the same rollback applies. When manipulations are active, solve_adjustment() first runs on a temporary clean engine (leaving the current engine untouched), so the state is naturally safe if the solver fails.
State management
SectionStudy exposes manual save / restore methods using the Memento pattern.
Save and restore
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
Important
restore_state() automatically notifies downstream engines (PositionEngine, PlotEngine) so their data stays consistent.
Using the Caretaker directly
For advanced use cases, you can also use the BalanceEngineCaretaker directly with any BalanceEngine:
1 2 3 4 5 6 7 8 9 10 | |
Warning
When using BalanceEngineCaretaker directly, observer notification is not automatic. Call engine.notify() manually if a PositionEngine or PlotEngine is attached.
Accessing sub-engines
SectionStudy provides access to all sub-engines through properties:
| Property | Type | Creation |
|---|---|---|
balance_engine |
BalanceEngine |
Eager (at construction) |
position_engine |
PositionEngine |
Eager (at construction) |
plot_engine |
PlotEngine |
Lazy (on first access) |
thermal_engine |
ThermalEngine |
Lazy (on first access) |
guying |
Guying |
Lazy (on first access) |
1 2 3 4 5 6 | |
Retrieving results
Support points
1 | |
Span points
1 | |
Span data
1 2 3 | |
Adding loads
1 2 3 4 5 6 | |
Plotting
Since PlotEngine is lazily created, you can use it directly from SectionStudy:
1 2 3 4 5 6 7 8 | |
Manipulations
SectionStudy provides methods to alter the geometry and insulator properties of supports as overlays, without modifying the original SectionArray. Manipulations are registered on the study object and are applied when solve_adjustment() is called: a clean adjustment is first solved on the original geometry, then a new engine is built from the manipulated copy and receives the injected \(L_{ref}\).
Important
Manipulations must be registered before calling solve_adjustment(). After solve_adjustment() with active manipulations, plot_engine and guying are reset and recreated lazily on next access.
Support Manipulation
modify_support applies additive offsets to conductor_attachment_altitude and/or crossarm_length for specified supports. Internally the Manipulation object produces a new SectionArray with the offsets baked in; the original section array is never modified.
The input is a dictionary where keys are support indices (0-based) and values are dicts with optional keys "y" (crossarm length offset) and "z" (altitude offset), both in meters.
1 2 3 4 5 6 7 8 9 10 11 | |
Note
Manipulations are additive: calling modify_support multiple times stacks the offsets.
reset_support clears all accumulated offsets and restores the original geometry.
For each affected support, counterweight_mass is set to 0; unaffected supports keep their original value.
Rope Manipulation
add_rope replaces the insulator length and mass for specified supports with rope values. Internally the Manipulation object produces a new SectionArray with the rope values baked in; the original section array is never modified.
The input is a dictionary where keys are support indices (0-based) and values are the rope length in meters. An optional rope_lineic_mass parameter (kg/m, default 0.01) controls the mass per unit length.
1 2 3 4 5 6 7 8 9 10 11 | |
Note
The rope overlay only affects insulator_length and insulator_mass (and the derived insulator_weight) for the listed supports.
Unlisted supports keep their original insulator values.
For each affected support, counterweight_mass is set to 0; unaffected supports keep their original value.
The default linear mass can be changed globally via options.data.rope_lineic_mass_default.
Virtual Support
add_virtual_support inserts intermediate supports into a line section. Internally the Manipulation object produces a new SectionArray with the virtual support rows inserted; the original section array is never modified. Each virtual support splits a given span at a specified horizontal distance from the left support. Because the number of supports changes, the full internal model is rebuilt while preserving observer bindings.
The input is a dictionary where keys are left-support indices (0-based, must not be the last support) and values are dicts with the following required keys:
| Key | Description |
|---|---|
"x" |
Distance from the left support (m) — must be strictly in (-abs(crossarm_length[left_support]), abs(span_length) + abs(crossarm_length[right_support])) |
"y" |
Lateral offset (m) — sets line_angle = atan2(y, x) on the left support |
"z" |
conductor_attachment_altitude of the virtual support (m) |
"insulator_length" |
Insulator length on the virtual support (m) |
"insulator_mass" |
Insulator mass on the virtual support (kg) |
"hanging_cable_point_from_left_support" |
Distance from the left support to the cable hanging point (m) — must be strictly in (-abs(crossarm_length[left_support]), abs(span_length) + abs(crossarm_length[right_support])). Not used for computation currently. |
1 2 3 4 5 6 7 8 9 10 11 12 | |
Multiple spans can be provided in one call, or via successive calls (overlays accumulate):
1 2 3 4 5 6 | |
Note
Virtual supports have crossarm_length = 0 and suspension = True.
counterweight_mass is set to 0 for each virtual row.
All changes are reversible with reset_virtual_support; the original section array is never modified.
Cable Shifting
modify_cable applies horizontal support shifting and span length modifications to the cable geometry. This is applied at solve time alongside the other manipulations.
shift_support: dictionary mapping support index (0-based) to horizontal offset (m); first and last supports are forced to 0. Unspecified supports default to 0.shorten_span: dictionary mapping span index (0-based) to span length reduction (m); positive values shorten the span. Unspecified spans default to 0.
1 2 3 4 5 6 7 8 9 10 11 | |
Note
Cable shifting modifies the effective \(L_{ref}\) passed to the manipulated engine; it does not alter the geometry of supports.