dss-extensions / dss-extensions/dss_capi

Lines.R1()/X1()/C1() silently return stale defaults for matrix-defined lines

Open
#137 1 comment 0 reactions 0 assignees View on GitHub
docs lines
Dominant language
Pascal
Stars
39
Forks
19
PR merge metrics
No merged PRs in 30d

Description

## Summary

`Lines.R1()`, `Lines.X1()`, and `Lines.C1()` (and the equivalent `LineCodes.*` properties) are symmetric-component fields. They only reflect reality when a line/LineCode was defined via `r1=`/`x1=`/`c1=`. Once a line/LineCode is switched to a matrix definition (`rmatrix=`/`xmatrix=`/`cmatrix=`), those fields are never cleared or recomputed -- they silently hold whatever they were constructed with (`R1 := 0.0580`, `X1 := 0.1206`, per `TLineObj`/`TLineCodeObj` construction in the original Pascal source), and the direct numeric getters return that stale value with no indication anything is wrong.

This is distinct from #36 (which is about a scaling inconsistency between the `RMatrix`/`XMatrix` getter and setter) -- this is about `R1`/`X1`/`C1` becoming meaningless, not mis-scaled, once matrix mode is active.

## Reproduction

```
New Circuit.test basekv=0.4 pu=1.0 phases=3
New LineCode.lc1 nphases=3 baseFreq=50 units=km
~ rmatrix=[0.868 | 0.1 0.868 | 0.1 0.1 0.868]
~ xmatrix=[0.077 | 0.01 0.077 | 0.01 0.01 0.077]
New Line.l1 bus1=a.1.2.3 bus2=b.1.2.3 phases=3 linecode=lc1 length=1 units=km
```

```python
import opendssdirect as dss
dss.Command("...redirect the above...")
dss.Lines.Name("l1")
dss.Lines.R1(), dss.Lines.X1()
# -> (0.058, 0.1206) -- the hard-coded construction default, not 0.868/0.077 -- or
# anything derivable from the declared matrix.
```

Confirmed via the Pascal source that the text-based property interface handles this correctly -- querying the `R1` property by name returns `'----'` once `SymComponentsModel` is `False` (see `LineCode.pas`: `If SymComponentsModel Then Result := Format(...) else Result := '----'`). The direct numeric getter used by the C-API/OpenDSSDirect.py doesn't perform the same check, so there is no way to tell, from the numeric API alone, that the returned value is meaningless.

## Impact

Any matrix-defined line, any conductor count -- not neutral- or phase-count-specific. We hit this while validating a pandapower OpenDSS importer against a real utility network (an explicit-neutral 4-conductor European LineCode looked like a Kron-reduction issue at first; a plain 3-conductor matrix LineCode with no neutral at all reproduced the identical stale value), which is what led us to check the Pascal source. Any tool that reads `Lines.R1()/X1()/C1()` directly (rather than going through the text/property-name interface, or manually deriving from `RMatrix()`/`XMatrix()`/`CMatrix()`) on a matrix-defined line will silently get wrong data with no error, warning, or way to detect it via the numeric API.

## Suggested fix

Given #36 was closed as not-planned (presumably to avoid changing numeric behavior that might already be relied upon / for EPRI-COM-compatibility reasons), I'd guess changing what `R1()`/`X1()`/`C1()` themselves return is a similarly hard sell. Two lower-risk options that don't touch existing behavior:

1. **Document it** on the `Lines.R1`/`X1`/`C1` (and `LineCode.R1`/`X1`/`C1`) properties: "meaningless once the line/LineCode has been defined via a matrix; check `SymComponentsModel`" (or equivalent) -- currently there's no hint of this anywhere a numeric-API user would see it.
2. **Expose `SymComponentsModel`** as a new read-only boolean getter (e.g. `Lines.SymComponentsModel()` / `LineCodes.SymComponentsModel()`). Purely additive, no behavior change, and it would let API consumers detect the unsafe case themselves and fall back to `RMatrix()`/`XMatrix()`/`CMatrix()`.

Happy to help test either, or just to have this documented if that's the preferred resolution.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the Lines.R1(), X1(), and C1() entry points and compare their direct numeric behavior with the text-property handling in LineCode.pas, especially the SymComponentsModel check. Reproduce the matrix-defined line example, then determine whether the issue is resolved by documenting the limitation or exposing a read-only model-status getter so callers can detect it.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.