Topology pre-processing#

merge_zero_z(case, threshold, *, xfmr_threshold=None)#

Merge zero-impedance bus pairs in case in place.

Parameters:
  • case -- Parsed case. Mutated in place.

  • threshold -- |Z| cutoff in pu on system base. Applied to AC branches and v34 system switching devices below this. Set to 0 or negative to disable. Read from the GENERAL THRSHZ header (default 1e-4).

  • xfmr_threshold -- |Z| cutoff applied separately to 2W transformers. If None, falls back to threshold (legacy behavior). Set to 0 so the threshold does NOT apply to 2W transformer windings, and merging here silently truncates the voltage step across small-|Z| transformers.

Returns:

MergeZeroZStats with counts of what changed.

class MergeZeroZStats(zero_z_branches_disabled=0, diff_baskv_low_z_branches_inflated=0, zero_z_sysswd_disabled=0, diff_baskv_low_z_sysswd_inflated=0, low_z_xfmrs_merged=0, low_z_xfmrs_inflated=0, low_z_3w_xfmrs_skipped=0, merge_groups=0, buses_merged_into_reps=0, non_rep_buses_isolated=0, rep_seeds_reweighted=0, self_loops_dropped=0, device_endpoints_redirected=<factory>, remote_ctrl_fields_redirected=<factory>, ids_renamed_to_dedupe=<factory>, area_swing_buses_redirected=0, rep_of_non_rep=<factory>)#

Bases: object

Counts of what the merge actually changed.

scale_loads(case, *, areas=None, zones=None, owners=None, buses=None, bus_type=None, interruptible='both', target_load_mw=None, multiplier=None, percent=None, increment_mw=None, q_mode='scale', q_target_mvar=None, q_percent=None, q_target_pf=None, q_increment_mvar=None)#

Scale in-service LOAD records in place; return the applied alpha.

P-side method (exactly one of):

target_load_mw=X — subsystem total reaches X. alpha = (X - fixed)/scaleable. multiplier=k — alpha = k. percent=p — alpha = 1 + p/100. increment_mw=d — alpha = (sum_scaleable + d) / sum_scaleable.

Q-side q_mode (and its companion kwarg when applicable):

"scale" (default) — Q multiplied by alpha. "preserve" — Q left at pre-scale values. "zero" — Q set to zero. "target" + q_target_mvar — Q scaled to subsystem total. "percent" + q_percent — Q *= 1 + q_percent/100. "pf" + q_target_pf — Q = sign(Q) * |P_new| * tan(acos(|PF|)). "increment" + q_increment_mvar — Q_i += d * Q_i / sum_Q.

Filters:

areas/zones/owners/buses intersect (AND) and narrow the subsystem. bus_type='pq' or 'pv_slack' further narrows by bus ide code. interruptible='non_interruptible' or 'interruptible' filters scaleable records; the excluded flavor still contributes to the fixed portion of target_load_mw.

Loads with stat=0 are skipped. Loads with scale=0 contribute to the fixed portion of the target but are not mutated.

scale_generators(case, *, areas=None, zones=None, owners=None, buses=None, target_pg_mw=None, multiplier=None, enforce_pt_pb=False)#

Scale in-service generator PG in place; return the applied alpha.

Proportional-dispatch (SCAL_2 dispatch flag = 1): every in-service machine in the subsystem has its PG multiplied by the same alpha = target_pg_mw / sum_PG (or by multiplier directly). Generator area/zone are inherited from the bus record at gen.ibus; owners= filters on the machine's primary owner (o1).

When enforce_pt_pb=True (mirrors SCAL_2 STATUS(3)=1), non-slack machines that would exceed PT or fall below PB are clamped to the rail; the residual (target minus clamped-non-slack-sum) is distributed across slack-bus machines proportionally to their pre-scale PG. Requires target_pg_mw (the multiplier form has no residual to spill since no fixed total is targeted).

Machines with stat=0 are skipped. QG / PT / PB / QT / QB are not altered (they stay as the record's headroom).

scale_shunts(case, *, areas=None, zones=None, owners=None, buses=None, target_g_mw=None, multiplier_g=None, target_cap_mvar=None, target_reactor_mvar=None)#

Scale in-service FIXED SHUNT records in place.

Three independent axes (skip each by passing None):

  • G (active shunt MW). With target_g_mw or multiplier_g, every in-service shunt's GL gets multiplied by the uniform alpha target_g_mw / sum_GL (or the multiplier).

  • B (reactive shunt Mvar). Cap and reactor targets are joint: both target_cap_mvar and target_reactor_mvar must be given together. The new BL is computed via the reference's joint formula and is non-negative; original reactors (BL<0) become capacitive after scaling, matching the reference's behavior.

Per-shunt B formula (with ct = target_cap_mvar, rt = target_reactor_mvar, S_c = sum |BL| over BL>0, S_r = sum |BL| over BL<0):

cap_i: BL_new = ct * ct * |BL_orig| / (S_c * (ct + rt)) rx_i: BL_new = ct * rt * |BL_orig| / (S_r * (ct + rt))

Shunts with BL=0 are not touched on the B axis. Shunts outside the subsystem or with stat=0 are not touched at all. Shunt area/zone/owner are inherited from the bus record at sh.ibus; buses= filters on sh.ibus directly.

Returns None. (Unlike scale_loads / scale_generators there is no single alpha to return: the G side has its own multiplier, and the B side uses the joint cap+reactor formula rather than a per-category alpha.)