Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .claude/Sienna.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Sienna Programming Practices — psy6 / Sienna 1.0 line

General practices and cross-package architecture for the **psy6 (Sienna 1.0) development line**. This file is intended to be **identical across every repo under `/home/jdlara/Sienna_work/psy6/`** — package-specific guidance belongs in that repo's `.claude/CLAUDE.md`, and workspace wiring/policy in `/home/jdlara/Sienna_work/psy6/CLAUDE.md`. The psy5 (released) line at the workspace top level has its own copy of this file; never mix checkouts between the two lines.
General practices and cross-package architecture for the **psy6 (Sienna 1.0) development line**. This file is intended to be **identical across every repo in the psy6 workspace** — package-specific guidance belongs in that repo's `.claude/CLAUDE.md`, and workspace wiring/policy in the psy6 workspace root `CLAUDE.md`. The psy5 (released) line at the workspace top level has its own copy of this file; never mix checkouts between the two lines.

## Start here (fresh-session reading order)

1. This file — shared practices, the stack, and the vocabulary (glossary at the end).
2. The current repo's `.claude/CLAUDE.md` — package specifics, verified commands, gotchas.
3. `/home/jdlara/Sienna_work/psy6/CLAUDE.md` — workspace architecture, design decisions, seams, and the knowledge index (audit, active plans).
4. `/home/jdlara/Sienna_work/CLAUDE.md` — the two-line workspace layout and git/test policy.
3. the psy6 workspace root `CLAUDE.md` — workspace architecture, design decisions, seams, and the knowledge index (audit, active plans).
4. the workspace top-level `CLAUDE.md` (one level above the psy6 root) — the two-line workspace layout and git/test policy.
Comment on lines +9 to +10

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these files tracked anywhere?


If you are porting anything from the psy5 line (or reading psy5-era docs/PRs), read the psy5 → psy6 translation map below first — many psy5 facts are actively wrong here.

Expand Down Expand Up @@ -46,7 +46,7 @@ Blast-radius quick reference — after changing:
Downstream smoke check after upstream edits:

```sh
julia --project=/home/jdlara/Sienna_work/psy6 -e 'using PowerNetworkMatrices, PowerFlows, PowerOperationsModels, PowerSystemCaseBuilder'
julia --project=<psy6-workspace-root> -e 'using PowerNetworkMatrices, PowerFlows, PowerOperationsModels, PowerSystemCaseBuilder'
```

## The data/schema pipeline (SiennaSchemas → OpenAPI models → SiennaGridDB)
Expand Down Expand Up @@ -108,11 +108,11 @@ These exist in the codebase and are flagged for removal; new code must error lou

## Environments and testing in the psy6 workspace

- **Shared dev env:** `julia --project=/home/jdlara/Sienna_work/psy6` dev-wires all co-developed packages (rebuild with `psy6/wire_psy6.jl`). A dev'd dependency's own `[sources]` pins are ignored by the parent env — only the active project's count; that is why the shared env exists.
- **Shared dev env:** `julia --project=<psy6-workspace-root>` dev-wires all co-developed packages (rebuild with the workspace's `wire_psy6.jl`). A dev'd dependency's own `[sources]` pins are ignored by the parent env — only the active project's count; that is why the shared env exists.
- **Per-package `Pkg.test()` honors that package's own `[sources]` git pins**, not the shared env. To test against local checkouts, temporarily repoint that repo's `test/Project.toml` `[sources]` to local paths (restore before finishing).
- **No version/compat bumps in any Project.toml until release** (PSY reads 5.10.0, IS 3.6.0 despite being the 6.0/4.0 lines). Bumps have reappeared spontaneously mid-session — revert them.
- PSB cache: no version-aware invalidation — clear `data/serialized_system/` after PSY changes; the CaseData artifact download can flake (retry once).
- Python tooling: use `python3` (never `python`); the units venv is `/home/jdlara/Sienna_work/psy6/.venv-units`; **`just` is not installed** — run the underlying commands from the `.justfile` directly.
- Python tooling: use `python3` (never `python`); the units venv is `.venv-units` at the psy6 workspace root; **`just` is not installed** — run the underlying commands from the `.justfile` directly.

## Performance Requirements

Expand Down
58 changes: 42 additions & 16 deletions src/pm_io/psse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -738,8 +738,12 @@ function _psse2pm_shunt!(pm_data::Dict, pti_data::Dict, import_all::Bool)
sub_data["step_number"] = [step_numbers[k] for k in step_numbers_sorted]
sub_data["step_number"] = sub_data["step_number"][sub_data["step_number"] .!= 0]

sub_data["control_mode"] = switched_shunt["MODSW"]
# pti.jl names the regulated-bus column "SWREM" for every source version,
# including v35 where the PSS/E spec itself calls it SWREG.
sub_data["regulated_bus_number"] = switched_shunt["SWREM"]

sub_data["ext"] = Dict{String, Any}(
"MODSW" => switched_shunt["MODSW"],
"ADJM" => switched_shunt["ADJM"],
"RMPCT" => switched_shunt["RMPCT"],
"RMIDNT" => switched_shunt["RMIDNT"],
Expand Down Expand Up @@ -770,7 +774,6 @@ function _psse2pm_shunt!(pm_data::Dict, pti_data::Dict, import_all::Bool)

sub_data["ext"]["NREG"] = pop!(switched_shunt, "NREG")
elseif pm_data["source_version"] ∈ ("30", "32", "33")
sub_data["ext"]["SWREM"] = switched_shunt["SWREM"]
sub_data["initial_status"] = ones(Int, length(sub_data["y_increment"]))
else
error("Unsupported PSS(R)E source version: $(pm_data["source_version"])")
Expand Down Expand Up @@ -1858,8 +1861,38 @@ function _psse2pm_dcline!(pm_data::Dict, pti_data::Dict, import_all::Bool)
sub_data["ac_voltage_control_from"] = from_bus["MODE"] == 1 ? true : false
sub_data["ac_voltage_control_to"] = to_bus["MODE"] == 1 ? true : false

sub_data["dc_setpoint_from"] = from_bus["DCSET"]
sub_data["dc_setpoint_to"] = to_bus["DCSET"]
if sub_data["dc_voltage_control_from"] && !sub_data["dc_voltage_control_to"]
base_voltage = from_bus["DCSET"]
flow_setpoint = to_bus["DCSET"]
elseif !sub_data["dc_voltage_control_from"] && sub_data["dc_voltage_control_to"]
base_voltage = to_bus["DCSET"]
flow_setpoint = -from_bus["DCSET"]
elseif !sub_data["dc_voltage_control_from"] &&
!sub_data["dc_voltage_control_to"]
error(
"At least one converter in converter $(sub_data["name"]) must set a voltage control.",
)
else
error(
"Exactly one converter in converter $(sub_data["name"]) must control DC voltage (TYPE = 1).",
)
end

# PSY documents dc_setpoint_from/to as p.u. of rated_dc_voltage for the
# DC-voltage-controlling side (TYPE = 1), and p.u. of baseMVA otherwise.
sub_data["rated_dc_voltage"] = base_voltage
sub_data["dc_setpoint_from"] =
if from_bus["TYPE"] == 1
from_bus["DCSET"] / base_voltage
else
from_bus["DCSET"] / baseMVA
end
sub_data["dc_setpoint_to"] =
if to_bus["TYPE"] == 1
to_bus["DCSET"] / base_voltage
else
to_bus["DCSET"] / baseMVA
end
sub_data["ac_setpoint_from"] = from_bus["ACSET"]
sub_data["ac_setpoint_to"] = to_bus["ACSET"]

Expand Down Expand Up @@ -1903,17 +1936,6 @@ function _psse2pm_dcline!(pm_data::Dict, pti_data::Dict, import_all::Bool)
sub_data["pminf"] = -sub_data["pmaxf"]
sub_data["pmint"] = -sub_data["pmaxt"]

if sub_data["dc_voltage_control_from"] && !sub_data["dc_voltage_control_to"]
base_voltage = sub_data["dc_setpoint_from"]
flow_setpoint = sub_data["dc_setpoint_to"]
elseif !sub_data["dc_voltage_control_from"] && sub_data["dc_voltage_control_to"]
base_voltage = sub_data["dc_setpoint_to"]
flow_setpoint = -sub_data["dc_setpoint_from"]
else
error(
"At least one converter in converter $(sub_data["name"]) must set a voltage control.",
)
end
Zbase = base_voltage^2 / baseMVA
sub_data["r"] = dcline["RDC"] / Zbase
sub_data["pf"] = flow_setpoint / baseMVA
Expand Down Expand Up @@ -1991,15 +2013,19 @@ function _psse2pm_facts!(pm_data::Dict, pti_data::Dict, import_all::Bool)
@warn "% MVAr required must me positive."
end

sub_data["reactive_power_required"] = facts["RMPCT"]
sub_data["ext"] = Dict{String, Any}()

if pm_data["source_version"] == "35"
sub_data["regulated_bus_number"] = facts["FCREG"]
sub_data["ext"]["NREG"] = facts["NREG"]
sub_data["ext"]["MNAME"] = facts["MNAME"]
sub_data["ext"]["RMPCT"] = facts["RMPCT"]
elseif pm_data["source_version"] ∈ ("30", "32", "33")
# REMOT is absent from the v30 FACTS record layout (_FACTS_dtypes_v30)
sub_data["regulated_bus_number"] = get(facts, "REMOT", 0)
sub_data["ext"] = Dict{String, Any}(
"J" => facts["J"],
"RMPCT" => facts["RMPCT"],
)
else
error("Unsupported PSS(R)E source version: $(pm_data["source_version"])")
Expand Down
9 changes: 0 additions & 9 deletions src/pm_io/pti.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1523,15 +1523,6 @@ const _default_switched_shunt = Dict(
"S8" => 1, "N8" => 0, "B8" => 0.0,
)

const _default_switched_shunt_v35 = merge(
Dict(k => v for (k, v) in pairs(_default_switched_shunt) if k != "SWREM"),
Dict(
"SWREG" => 0,
"ID" => "1",
"NAME" => "",
),
)

const _default_gne_device = Dict(
"NTERM" => 1,
"NREAL" => 0,
Expand Down
Loading