surge-network 0.1.1

Surge network — canonical power-system domain model
Documentation
// SPDX-License-Identifier: LicenseRef-PolyForm-Noncommercial-1.0.0
//! Two-terminal LCC-HVDC line data structures.
//!
//! A two-terminal DC line connects a rectifier bus (AC → DC) and an
//! inverter bus (DC → AC) through a DC circuit with resistance `resistance_ohm`.
//! PSS/E RAW section: "TWO-TERMINAL DC DATA".

use serde::{Deserialize, Serialize};

/// Control mode for a two-terminal LCC-HVDC link.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
pub enum LccHvdcControlMode {
    /// Line is blocked (out of service).
    Blocked = 0,
    /// Power control: SETVL is scheduled MW.
    #[default]
    PowerControl = 1,
    /// Current control: SETVL is scheduled kA.
    CurrentControl = 2,
}

impl LccHvdcControlMode {
    /// Convert a PSS/E MDC integer to a `LccHvdcControlMode`. Out-of-range values map to `Blocked`.
    pub fn from_u32(v: u32) -> Self {
        match v {
            1 => Self::PowerControl,
            2 => Self::CurrentControl,
            _ => Self::Blocked,
        }
    }
}

/// One converter terminal (rectifier or inverter) of a two-terminal LCC-HVDC link.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LccConverterTerminal {
    /// AC bus number this converter is connected to.
    pub bus: u32,
    /// Number of 6-pulse converter bridges (NBR / NBI).
    #[serde(alias = "num_bridges")]
    pub n_bridges: u32,
    /// Maximum firing/extinction angle in degrees (ALFMX / GAMMX).
    pub alpha_max: f64,
    /// Minimum firing/extinction angle in degrees (ALFMN / GAMMN).
    pub alpha_min: f64,
    /// Commutating resistance per bridge in ohms (RCR / RCI).
    pub commutation_resistance_ohm: f64,
    /// Commutating reactance per bridge in ohms (XCR / XCI).
    pub commutation_reactance_ohm: f64,
    /// Converter transformer rated AC voltage (line-to-line kV) on the network side (EBASR / EBASI).
    pub base_voltage_kv: f64,
    /// Transformer turns ratio (EBASR/EBASI side to converter side) (TRR / TRI).
    pub turns_ratio: f64,
    /// Off-nominal tap ratio (TAPR / TAPI), default 1.0.
    pub tap: f64,
    /// Maximum tap ratio (TMXR / TMXI).
    pub tap_max: f64,
    /// Minimum tap ratio (TMNR / TMNI).
    pub tap_min: f64,
    /// Tap step size (STPR / STPI), 0 = continuous.
    pub tap_step: f64,
    /// Converter in-service flag (ICR / ICI == 1).
    pub in_service: bool,
}

impl Default for LccConverterTerminal {
    fn default() -> Self {
        Self {
            bus: 0,
            n_bridges: 1,
            alpha_max: 90.0,
            alpha_min: 5.0,
            commutation_resistance_ohm: 0.0,
            commutation_reactance_ohm: 0.0,
            base_voltage_kv: 0.0,
            turns_ratio: 1.0,
            tap: 1.0,
            tap_max: 1.1,
            tap_min: 0.9,
            tap_step: 0.00625,
            in_service: true,
        }
    }
}

/// Two-terminal LCC-HVDC link (PSS/E TWO-TERMINAL DC DATA section).
///
/// Models a point-to-point high-voltage DC link with line-commutated
/// converters (thyristor bridges). The rectifier converts AC power to DC;
/// the inverter converts DC power back to AC.
///
/// For power flow with `FixedSchedule` DC model the converter power is
/// computed from `setvl`/`vschd` and injected as constant PQ at the
/// converter buses. With `SequentialAcDc`, the AC/DC operating point is
/// iterated to convergence.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LccHvdcLink {
    /// Name / identifier of the DC link.
    pub name: String,
    /// Control mode (0 = blocked, 1 = power control, 2 = current control).
    pub mode: LccHvdcControlMode,
    /// DC circuit resistance in ohms.
    pub resistance_ohm: f64,
    /// Scheduled DC power (MW) for MDC=1, or scheduled current (kA) for MDC=2.
    pub scheduled_setpoint: f64,
    /// Scheduled DC voltage in kV.
    pub scheduled_voltage_kv: f64,
    /// Max DC voltage for mode switching in kV (VCMOD).
    pub voltage_mode_switch_kv: f64,
    /// Compounding resistance in ohms (RCOMP).
    pub compounding_resistance_ohm: f64,
    /// Current margin in kA (DELTI).
    pub current_margin_ka: f64,
    /// Metering end: `'R'` = rectifier-metered, `'I'` = inverter-metered.
    pub meter: char,
    /// Minimum DC voltage in kV (DCVMIN).
    pub voltage_min_kv: f64,
    /// Maximum AC/DC outer-loop iterations (CCCITMX).
    pub ac_dc_iteration_max: u32,
    /// Acceleration factor for AC/DC iteration (CCCACC).
    pub ac_dc_iteration_acceleration: f64,
    /// Rectifier terminal (AC bus → DC).
    pub rectifier: LccConverterTerminal,
    /// Inverter terminal (DC → AC bus).
    pub inverter: LccConverterTerminal,
}

impl Default for LccHvdcLink {
    fn default() -> Self {
        Self {
            name: String::new(),
            mode: LccHvdcControlMode::PowerControl,
            resistance_ohm: 0.0,
            scheduled_setpoint: 0.0,
            scheduled_voltage_kv: 500.0,
            voltage_mode_switch_kv: 0.0,
            compounding_resistance_ohm: 0.0,
            current_margin_ka: 0.0,
            meter: 'I',
            voltage_min_kv: 0.0,
            ac_dc_iteration_max: 20,
            ac_dc_iteration_acceleration: 1.0,
            rectifier: LccConverterTerminal::default(),
            inverter: LccConverterTerminal::default(),
        }
    }
}