# Input Formats

CommmonOPF provides three ways to construct the Network Model model:

- YAML file(s)
- JSON file(s)
- Julia code (manual)

Only `Network`

and `Conductor`

are required to build the `Network`

. Note that the input keys are, singular, CamelCase words to align with the data type names. For example a single phase, single time step model looks like:

```
Network:
substation_bus: b1
Conductor:
- name: cond1
busses:
- b1
- b2
r1: 0.301 # impedance has units of ohm/per-unit-length
x1: 0.627
length: 100
- busses:
- b2
- b3
template: cond1 # <- reuse impedance of cond1
length: 200
Load:
- bus: b2
kws1:
- 5.6 # you can specify more loads at each bus to add time steps
kvars1:
- 1.2
- bus: b3
kws1:
- 5.6
kvars1:
- 1.2
```

The `Network(fp::String)`

constructor excepts a path to a yaml file.

## Conductor

`CommonOPF.Conductor`

— Type`struct Conductor <: AbstractEdge`

Interface for conductors in a Network. Fieldnames can be provided via a YAML file, JSON file, or populated manually. Conductors are specified via two busses, the **impedance in ohms per-unit length**, and a length value.

**Single phase models**

The minimum inputs for a single phase conductor look like:

```
Conductor:
- busses:
- b1
- b2
r1: 0.1
x1: 0.1
length: 100
```

Note that the order of the items in the YAML file does not matter.

A conductor can also leverage a `template`

, i.e. another conductor with a `name`

that matches the `template`

value so that we can re-use the impedance values:

```
Conductor:
- name: cond1
busses:
- b1
- b2
r1: 0.1
x1: 0.1
length: 100
- busses:
- b2
- b3
template: cond1
length: 200
```

The second conductor in the `conductors`

above will use the `r0`

and `x0`

values from `cond1`

, scaled by the `length`

of 200 and normalized by `Zbase`

.

The `name`

field is optional unless a `conductor.name`

is also the `template`

of another conductor.

If any `phases`

properties are set in the `conductors`

then it is assumed that the model is multi-phase.

**Multi-phase models**

Multi-phase conductors can be modeled as symmetrical or asymmetrical components. Similar to OpenDSS, line impedances can be specified via the zero and positive sequence impedances, `(r0, x0)`

and `(r1, x1)`

respectively; or via the lower-diagaonal portion of the phase-impedance matrix.

Using the Multi-phase models require specifing `phases`

(and the zero and positive sequence impedances) like:

```
Conductor:
- busses:
- b1
- b2
phases:
- 2
- 3
r0: 0.766
x0: 1.944
r1: 0.301
x1: 0.627
length: 100
```

When the sequence impedances are provided the phase-impedance matrix is determined using the math in Symmetrical Mutliphase Conductors.

Alternatively one can specify the `rmatrix`

and `xmatrix`

like:

```
Conductor:
- busses:
- b1
- b2
phases:
- 1
- 3
rmatrix:
- [0.31]
- [0.15, 0.32]
xmatrix:
- [1.01]
- [0.5, 1.05]
length: 100
```

The order of the `phases`

is assumed to match the order of the `rmatrix`

and `xmatrix`

. For example using the example just above the 3x3 `rmatrix`

looks like $[0.31, 0, 0.15; 0, 0, 0; 0.15, 0, 0.32]$

Conductors also have a `cmatrix`

attribute that is used when parsing OpenDSS models. The `cmatrix`

is used to define `ShuntAdmittance`

values for busses.

## Load

`CommonOPF.Load`

— Type`@with_kw mutable struct Load <: AbstractBus`

A Load input specifier, mapped from YAML, JSON, or manually populated.

The minimum required inputs include several options. All require a `bus`

to place the load. For single phase models provide one of the following sets of values:

`bus`

,`kws1`

`bus`

,`kws1`

,`kvars1`

`bus`

,`kws1`

,`q_to_p`

`bus`

,`csv`

where `csv`

is a path to a two column CSV file with a single line header like "kws1,kvars1". If only `bus`

and `kws1`

are provided then the reactive load will be zero in the power flow model.

For unbalanced multiphase models one must provide one of:

`bus`

, [`kws1`

,`kvars1`

], [`kws2`

,`kvars2`

], [`kws3`

,`kvars3`

] <– brackets imply optional pairs, depending on the phases at the load bus`bus`

,`csv`

where the `csv`

has 2, 4, or 6 columns with a single line header like "kws1,kvars1,kws2,kvars2,kws3,kvars3" or "kws2,kvars2,kws3,kvars3".

The `kws`

and `kvars`

inputs are plural because we always put the loads in vectors, even with one timestep. We do this so that the modeling packages that build on CommonOPF do not have to account for both scalar values and vector values.

Once the `net::Network`

is defined a load can be accessed like:

```
ld_busses = collect(load_busses(net))
lb = ld_busses[1] # bus keys are strings in the network
net[lb, :kws, 1] # last index is phase integer
```

`Base.getindex`

— Method`function Base.getindex(net::Network, bus::String, kws_kvars::Symbol, phase::Int)`

Load getter for `Network`

. Use like:

```
net["busname", :kws, 2]
net["busname", :kvars, 3]
```

The second argument must be one of `:kws`

or `:kvars`

. The third arbument must be one of `[1,2,3]`

. If the `"busname"`

exists and has a `:Load`

dict, but the load (e.g. `:kvars2`

) is not defined then `zeros(net.Ntimesteps)`

is returned.

## ShuntAdmittance

`CommonOPF.ShuntAdmittance`

— Type`struct ShuntAdmittance <: AbstractBus`

Required fields:

`bus::String`

`g::Real`

conductance in siemens`b::Real`

susceptance in siemens

## Transformer

`CommonOPF.Transformer`

— Type```
@with_kw mutable struct Transformer <: AbstractEdge
# required values
busses::Tuple{String, String}
# optional values
high_kv::Real = 1.0
low_kv::Real = 1.0
phases::Union{Vector{Int}, Missing} = missing
reactance::Real = 0.0
resistance::Real = 0.0
end
```

For now the `high_kv`

and `low_kv`

values are only for reference. Throughout the modules that use CommonOPF we model in per-unit voltage. In the future we may add capability for scaling to absolute voltage in the future (in Results for example).

When `phases`

are not provided the model is assumed to be single phase.

Series impedance defaults to zero.

## VoltageRegulator

`CommonOPF.VoltageRegulator`

— Type```
struct VoltageRegulator <: AbstractEdge
# required values
busses::Tuple{String, String}
# optional values
high_kv::Real = 1.0
low_kv::Real = 1.0
phases::Union{Vector{Int}, Missing} = missing
reactance::Real = 0.0
resistance::Real = 0.0
vreg_pu::Union{Real, AbstractVector{<:Number}, Missing} = missing
turn_ratio::Union{Real, Missing} = missing
end
```

Required fields:

`busses::Tuple{String, String}`

- either
`vreg_pu::Real`

or`turn_ratio::Real`

If `vreg_pu`

is specified then the regulator is "perfect" and the second bus in `busses`

is fixed to the value provided for `vreg_pu`

.

If `turn_ratio`

is provided then the voltage across the regulator is scaled by the `turn_ratio`

.

**Examples:**

**Julia Dict**

```
netdict = Dict(
:network => Dict(:substation_bus => "1", :Sbase => 1),
:conductors => [
...
],
:voltage_regulators => [
Dict(
:busses => ("2", "3")
:vreg_pu => 1.05
)
]
)
```

**YAML file**

```
Network:
substation_bus: 0
Sbase: 1
Conductor:
...
VoltageRegulator:
busses:
- 2
- 3
vreg_pu: 1.05
```