Skip to content

Grid and PCC Subsystem Simulation Model (AI / Code Generation Version)

This document specifies the Grid and PCC simulation model using formal notation for automated code generation. Targets: Python (NumPy), C/C++, MATLAB/Simulink.

Sign convention (shared across BESS, EMS, and Grid models): - P_pcc > 0 → plant exports to grid (generating) - P_pcc < 0 → plant imports from grid (consuming/charging) - P_bess_setpoint > 0 → BESS charging (consuming from AC bus) - P_bess_setpoint < 0 → BESS discharging (injecting to AC bus)


Simulation Loop (Top-Level Pseudocode)

# ─── Initialization ──────────────────────────────────────────────────────
Vg              = 400.0         # V RMS line-to-line (grid source)
f               = 50.0          # Hz
breaker_status  = True          # CLOSED = True
energy_acc      = 0.0           # MWh accumulator
uv_timer        = 0.0           # Under-voltage hold timer (s)
ov_timer        = 0.0
uf_timer        = 0.0
of_timer        = 0.0

# ─── Per-step loop ───────────────────────────────────────────────────────
for k in range(N_steps):

    # 1. Apply any disturbance scenario (FRT test, frequency step, etc.)
    Vg_actual = Vg * Vg_dip_factor[k]           # from test scenario
    f_actual  = f + f_disturbance[k]             # from test scenario

    # 2. Read plant asset currents / powers (from BESS and PV/Wind models)
    P_bess  = bess_model.P_bess_output           # MW, positive=charging
    Q_bess  = bess_model.Q_bess_output           # MVAr
    P_pv    = pv_model.P_pv_output               # MW
    P_wind  = wind_model.P_wind_output           # MW

    # 3. Compute PCC bus voltage and current
    I_plant, Vpcc = compute_pcc_voltage(Vg_actual, P_bess, P_pv, P_wind, Rg, Xg)

    # 4. CT/PT scaling
    V_sec, I_sec = ctpt_model(Vpcc, I_plant, PT_ratio, CT_ratio)

    # 5. PCC Meter: compute measurements
    P_pcc, Q_pcc, V_pcc, energy_acc = pcc_meter_step(
        P_bess, Q_bess, P_pv, P_wind, V_pcc_kV, f_actual, energy_acc, dt
    )

    # 6. Publish to EMS (IF-GM01, IF-GM02)
    emit_to_ems(P_pcc, Q_pcc, V_pcc, f_actual, energy_acc)

    # 7. Breaker IED: check protection conditions
    breaker_status, trip_alarm, trip_cause = ied_protection_step(
        abs(I_plant), Vpcc, f_actual,
        uv_timer, ov_timer, uf_timer, of_timer,
        breaker_status, dt
    )

    # 8. Publish IED status to EMS (IF-BR01)
    emit_to_ems_alarm(breaker_status, trip_alarm, trip_cause)

    # 9. If breaker OPEN: disconnect all assets from grid (P_pcc = 0)
    if not breaker_status:
        P_bess = 0.0; P_pv = 0.0; P_wind = 0.0

1. AC Grid Voltage Source

Thevenin phasor model (scalar, steady-state, per time step):

V_{pcc} \approx V_g - I_{plant} \cdot R_g

(For simulation time scales of 0.5–1 s, the resistive drop dominates. Full complex phasor optionally:)

V_{pcc} = V_g - I_{plant} \cdot (R_g + j X_g)

Plant current from asset power injections:

I_{plant} = \frac{P_{bess} + P_{pv} + P_{wind}}{V_{pcc}} \cdot 10^6 \cdot \frac{1}{\sqrt{3}}
(approximate scalar for balanced three-phase, converting MW to A.)

def compute_pcc_voltage(Vg, P_bess, P_pv, P_wind, Rg, Xg=0.0):
    """
    Vg in V (line-to-line RMS).
    P_* in MW (positive = generation / export).
    Returns I_plant (A, positive = plant generating) and Vpcc (V).
    """
    P_plant_total = P_bess + P_pv + P_wind    # MW, positive = export
    # Scalar approximation: P = V * I * sqrt(3) for three-phase
    if abs(Vg) > 1.0:
        I_plant = (P_plant_total * 1e6) / (Vg * 1.732)
    else:
        I_plant = 0.0
    Vpcc = Vg - I_plant * Rg
    return I_plant, Vpcc

Parameters:

Symbol Description Default
$V_g$ Grid source voltage (V, line-to-line RMS) 400.0
$R_g$ Thevenin resistance ($\Omega$) 0.01
$X_g$ Thevenin reactance ($\Omega$) 0.05
$f_{nom}$ Nominal frequency (Hz) 50.0

2. CT/PT Sensor Model

def ctpt_model(V_bus, I_bus, PT_ratio, CT_ratio,
               V_noise_std=0.001, I_noise_std=0.001):
    """
    Scales high-level bus signals to meter-level secondary values.
    Adds small Gaussian noise to simulate real sensor imperfection.
    """
    import numpy as np
    V_sec = V_bus / PT_ratio + np.random.normal(0, V_noise_std)
    I_sec = I_bus / CT_ratio + np.random.normal(0, I_noise_std)
    return V_sec, I_sec

Parameters:

Symbol Description Default
PT_ratio Potential transformer ratio 100
CT_ratio Current transformer ratio 1000
V_noise_std Voltage noise std dev (V) 0.001
I_noise_std Current noise std dev (A) 0.001

3. PCC Meter

def pcc_meter_step(P_bess, Q_bess, P_pv, P_wind, V_pcc_kV,
                   f, energy_acc, dt, meter_rate=1.0):
    """
    Computes PCC measurements from asset power injections.
    P_* in MW (positive = export to grid).
    Returns P_pcc, Q_pcc, V_pcc, updated energy_acc.
    """
    # Power balance at PCC node
    # Positive P_bess = charging = plant consuming = reduces export
    P_pcc = -P_bess + P_pv + P_wind   # MW; positive = net export to grid
    Q_pcc = -Q_bess                   # MVAr; simplified (PV/Wind unity PF)
    V_pcc = V_pcc_kV                  # kV

    # Energy accumulation (MWh)
    energy_acc += P_pcc * dt / 3600.0

    return P_pcc, Q_pcc, V_pcc, energy_acc

Output signals (IF-GM01 to EMS):

Signal Type Unit Description
P_pcc float MW Active power at PCC (+ = export)
Q_pcc float MVAr Reactive power at PCC
V_pcc float kV PCC voltage magnitude
f float Hz Grid frequency
energy_acc float MWh Accumulated exported energy
quality string "GOOD" / "SUSPECT" / "INVALID"
timestamp datetime UTC Measurement timestamp

Interface note: P_pcc published here is directly consumed by: - EMS PCC Tracking Controller (as feedback in the PI loop: P_error = P_target - P_pcc) - EMS Alarm Manager (for frequency/voltage alarm checks)


4. PCC Breaker + Protection IED

def ied_protection_step(I_mag, Vpcc, f, uv_t, ov_t, uf_t, of_t,
                         breaker_closed, dt):
    """
    Evaluates protection conditions and updates timers.
    Returns (breaker_status, trip_alarm, trip_cause).
    """
    Vnom = 400.0
    trip = False
    cause = None

    # Overcurrent: instantaneous
    if I_mag > I_trip:
        trip = True; cause = "OC"

    # Under-voltage: time-delayed
    if Vpcc < V_uv_trip * Vnom:
        uv_t += dt
        if uv_t >= trip_delay_uv:
            trip = True; cause = "UV"
    else:
        uv_t = 0.0

    # Over-voltage: time-delayed
    if Vpcc > V_ov_trip * Vnom:
        ov_t += dt
        if ov_t >= trip_delay_ov:
            trip = True; cause = "OV"
    else:
        ov_t = 0.0

    # Under-frequency: time-delayed
    if f < f_min_ied:
        uf_t += dt
        if uf_t >= trip_delay_uf:
            trip = True; cause = "UF"
    else:
        uf_t = 0.0

    # Over-frequency: time-delayed
    if f > f_max_ied:
        of_t += dt
        if of_t >= trip_delay_of:
            trip = True; cause = "OF"
    else:
        of_t = 0.0

    if trip:
        breaker_closed = False

    return breaker_closed, trip, cause, uv_t, ov_t, uf_t, of_t

Parameters:

Symbol Description Default
I_trip Instantaneous overcurrent trip (A) 1500.0
V_uv_trip Under-voltage trip fraction of Vnom 0.80
V_ov_trip Over-voltage trip fraction of Vnom 1.10
f_min_ied Under-frequency trip (Hz) 47.5
f_max_ied Over-frequency trip (Hz) 51.5
trip_delay_uv UV hold timer before trip (s) 3.0
trip_delay_ov OV hold timer before trip (s) 0.5
trip_delay_uf UF hold timer before trip (s) 4.0
trip_delay_of OF hold timer before trip (s) 0.5

Output signals (IF-BR01 to EMS Alarm Manager):

Signal Type Description
breaker_status bool True = CLOSED, False = OPEN
trip_alarm bool True = protection trip occurred
trip_cause string "OC", "UV", "OV", "UF", "OF", "Manual"

Interface note: breaker_status is consumed by the EMS Alarm Manager using:

if not breaker_status:
    alarms["critical"] = True
    alarms["source"]   = "Breaker_Open"


5. Complete Interface Signal Table (Cross-System)

All signals defined below are the canonical interface contracts between the three simulation models.

Grid → EMS

Signal IF-ID From To Unit
P_pcc IF-GM01 PCC Meter EMS P_error = P_target - P_pcc MW
Q_pcc IF-GM01 PCC Meter EMS reactive control MVAr
V_pcc IF-GM01 PCC Meter EMS voltage control / alarm kV
f IF-GM01 PCC Meter EMS alarm frequency check Hz
breaker_status IF-BR01 Breaker IED EMS alarm_state["critical"] bool
trip_alarm IF-BR01 Breaker IED EMS Alarm Manager bool

EMS → Grid

Signal IF-ID From To Unit
breaker_open_cmd IF-BR02 EMS Alarm Manager Breaker IED bool

BESS → Grid (AC Bus)

Signal IF-ID From To Unit
P_bess_output IF-BE01 BESS PCS Pout Grid P_pcc computation MW
Q_bess_output IF-BE01 BESS PCS Qout Grid Q_pcc computation MVAr

EMS → BESS

Signal IF-ID From To Unit
P_bess_setpoint IF-BE02 EMS Coordinator BESS PCS Preq MW (+ = charge)
Q_bess_setpoint IF-BE02 EMS Coordinator BESS PCS Qreq MVAr

BESS → EMS

Signal IF-ID From To Unit
SoC IF-BM01 BESS BMS EMS Coordinator 0.0–1.0
P_lim_chg IF-BM01 BESS BMS EMS Ramp Manager + Coordinator MW
P_lim_dis IF-BM01 BESS BMS EMS Ramp Manager + Coordinator MW
bms_critical_alarm IF-BM01 BESS BMS EMS Alarm Manager bool