From 366c16367e388158607383cf8e2c06e8dca2090f Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Thu, 17 Oct 2024 12:43:54 +0000 Subject: [PATCH] build based on c844efb --- stable | 2 +- v0.2 | 1 + v0.2.0/.documenter-siteinfo.json | 1 + v0.2.0/api/analysis/index.html | 166 +++ v0.2.0/api/measurementModel/index.html | 435 +++++++ v0.2.0/api/optimalPowerFlow/index.html | 53 + v0.2.0/api/powerFlow/index.html | 112 ++ v0.2.0/api/powerSystemModel/index.html | 97 ++ v0.2.0/api/setupPrint/index.html | 284 +++++ v0.2.0/api/stateEstimation/index.html | 121 ++ v0.2.0/assets/citations.css | 17 + v0.2.0/assets/cost_function.svg | 452 +++++++ v0.2.0/assets/cost_function_dc.svg | 329 +++++ v0.2.0/assets/cost_function_piecewise.svg | 645 ++++++++++ v0.2.0/assets/cost_function_piecewise_dc.svg | 429 +++++++ v0.2.0/assets/dc_model.svg | 201 ++++ v0.2.0/assets/documenter.js | 1064 +++++++++++++++++ v0.2.0/assets/logo.svg | 1 + v0.2.0/assets/logo2.svg | 1 + v0.2.0/assets/pi_model.svg | 335 ++++++ v0.2.0/assets/pi_model_example.svg | 258 ++++ v0.2.0/assets/pq_curve.svg | 307 +++++ v0.2.0/assets/pq_curve_sloped.svg | 408 +++++++ v0.2.0/assets/tablestyle.css | 7 + v0.2.0/assets/themes/catppuccin-frappe.css | 1 + v0.2.0/assets/themes/catppuccin-latte.css | 1 + v0.2.0/assets/themes/catppuccin-macchiato.css | 1 + v0.2.0/assets/themes/catppuccin-mocha.css | 1 + v0.2.0/assets/themes/documenter-dark.css | 7 + v0.2.0/assets/themes/documenter-light.css | 9 + v0.2.0/assets/themeswap.js | 84 ++ v0.2.0/assets/warner.js | 52 + v0.2.0/background/bibliography/index.html | 2 + v0.2.0/background/installation/index.html | 4 + v0.2.0/background/references.bib | 214 ++++ v0.2.0/index.html | 91 ++ v0.2.0/manual/acOptimalPowerFlow/index.html | 141 +++ v0.2.0/manual/acPowerFlow/index.html | 337 ++++++ v0.2.0/manual/acStateEstimation/index.html | 333 ++++++ v0.2.0/manual/dcOptimalPowerFlow/index.html | 143 +++ v0.2.0/manual/dcPowerFlow/index.html | 130 ++ v0.2.0/manual/dcStateEstimation/index.html | 142 +++ v0.2.0/manual/measurementModel/index.html | 383 ++++++ v0.2.0/manual/pmuStateEstimation/index.html | 221 ++++ v0.2.0/manual/powerSystemModel/index.html | 199 +++ v0.2.0/objects.inv | Bin 0 -> 5166 bytes v0.2.0/search_index.js | 3 + v0.2.0/siteinfo.js | 1 + .../tutorials/acOptimalPowerFlow/index.html | 158 +++ v0.2.0/tutorials/acPowerFlow/index.html | 457 +++++++ v0.2.0/tutorials/acStateEstimation/index.html | 561 +++++++++ .../tutorials/dcOptimalPowerFlow/index.html | 99 ++ v0.2.0/tutorials/dcPowerFlow/index.html | 49 + v0.2.0/tutorials/dcStateEstimation/index.html | 100 ++ v0.2.0/tutorials/measurementModel/index.html | 67 ++ .../tutorials/pmuStateEstimation/index.html | 289 +++++ v0.2.0/tutorials/powerSystemModel/index.html | 204 ++++ versions.js | 3 +- 58 files changed, 10211 insertions(+), 2 deletions(-) create mode 120000 v0.2 create mode 100644 v0.2.0/.documenter-siteinfo.json create mode 100644 v0.2.0/api/analysis/index.html create mode 100644 v0.2.0/api/measurementModel/index.html create mode 100644 v0.2.0/api/optimalPowerFlow/index.html create mode 100644 v0.2.0/api/powerFlow/index.html create mode 100644 v0.2.0/api/powerSystemModel/index.html create mode 100644 v0.2.0/api/setupPrint/index.html create mode 100644 v0.2.0/api/stateEstimation/index.html create mode 100644 v0.2.0/assets/citations.css create mode 100644 v0.2.0/assets/cost_function.svg create mode 100644 v0.2.0/assets/cost_function_dc.svg create mode 100644 v0.2.0/assets/cost_function_piecewise.svg create mode 100644 v0.2.0/assets/cost_function_piecewise_dc.svg create mode 100644 v0.2.0/assets/dc_model.svg create mode 100644 v0.2.0/assets/documenter.js create mode 100644 v0.2.0/assets/logo.svg create mode 100644 v0.2.0/assets/logo2.svg create mode 100644 v0.2.0/assets/pi_model.svg create mode 100644 v0.2.0/assets/pi_model_example.svg create mode 100644 v0.2.0/assets/pq_curve.svg create mode 100644 v0.2.0/assets/pq_curve_sloped.svg create mode 100644 v0.2.0/assets/tablestyle.css create mode 100644 v0.2.0/assets/themes/catppuccin-frappe.css create mode 100644 v0.2.0/assets/themes/catppuccin-latte.css create mode 100644 v0.2.0/assets/themes/catppuccin-macchiato.css create mode 100644 v0.2.0/assets/themes/catppuccin-mocha.css create mode 100644 v0.2.0/assets/themes/documenter-dark.css create mode 100644 v0.2.0/assets/themes/documenter-light.css create mode 100644 v0.2.0/assets/themeswap.js create mode 100644 v0.2.0/assets/warner.js create mode 100644 v0.2.0/background/bibliography/index.html create mode 100644 v0.2.0/background/installation/index.html create mode 100644 v0.2.0/background/references.bib create mode 100644 v0.2.0/index.html create mode 100644 v0.2.0/manual/acOptimalPowerFlow/index.html create mode 100644 v0.2.0/manual/acPowerFlow/index.html create mode 100644 v0.2.0/manual/acStateEstimation/index.html create mode 100644 v0.2.0/manual/dcOptimalPowerFlow/index.html create mode 100644 v0.2.0/manual/dcPowerFlow/index.html create mode 100644 v0.2.0/manual/dcStateEstimation/index.html create mode 100644 v0.2.0/manual/measurementModel/index.html create mode 100644 v0.2.0/manual/pmuStateEstimation/index.html create mode 100644 v0.2.0/manual/powerSystemModel/index.html create mode 100644 v0.2.0/objects.inv create mode 100644 v0.2.0/search_index.js create mode 100644 v0.2.0/siteinfo.js create mode 100644 v0.2.0/tutorials/acOptimalPowerFlow/index.html create mode 100644 v0.2.0/tutorials/acPowerFlow/index.html create mode 100644 v0.2.0/tutorials/acStateEstimation/index.html create mode 100644 v0.2.0/tutorials/dcOptimalPowerFlow/index.html create mode 100644 v0.2.0/tutorials/dcPowerFlow/index.html create mode 100644 v0.2.0/tutorials/dcStateEstimation/index.html create mode 100644 v0.2.0/tutorials/measurementModel/index.html create mode 100644 v0.2.0/tutorials/pmuStateEstimation/index.html create mode 100644 v0.2.0/tutorials/powerSystemModel/index.html diff --git a/stable b/stable index ddd91642f..81fd7ba08 120000 --- a/stable +++ b/stable @@ -1 +1 @@ -v0.1.9 \ No newline at end of file +v0.2.0 \ No newline at end of file diff --git a/v0.2 b/v0.2 new file mode 120000 index 000000000..81fd7ba08 --- /dev/null +++ b/v0.2 @@ -0,0 +1 @@ +v0.2.0 \ No newline at end of file diff --git a/v0.2.0/.documenter-siteinfo.json b/v0.2.0/.documenter-siteinfo.json new file mode 100644 index 000000000..e094e1407 --- /dev/null +++ b/v0.2.0/.documenter-siteinfo.json @@ -0,0 +1 @@ +{"documenter":{"julia_version":"1.11.1","generation_timestamp":"2024-10-17T12:43:46","documenter_version":"1.7.0"}} \ No newline at end of file diff --git a/v0.2.0/api/analysis/index.html b/v0.2.0/api/analysis/index.html new file mode 100644 index 000000000..c1ca07e6e --- /dev/null +++ b/v0.2.0/api/analysis/index.html @@ -0,0 +1,166 @@ + +Power and Current Analysis · JuliaGrid

Power and Current Analysis

In the following section, we have provided a list of functions that can be utilized for post-processing analysis. Once the voltage values are obtained through power flow analysis, optimal power flow analysis, or state estimation, these functions can be used to calculate power or current values. The specific procedures for computing these values depend on the chosen analysis, which are described in separate manuals for further information.

To load power system model API functionalities into the current scope, utilize the following command:

using JuliaGrid

AC Power Analysis
AC Current Analysis
DC Power Analysis

AC Power Analysis

JuliaGrid.power!Method
power!(system::PowerSystem, analysis::AC)

The function computes the active and reactive powers associated with buses, branches, and generators for AC analysis.

Updates

This function updates the power field of the AC abstract type by computing the following electrical quantities:

  • injection: Active and reactive power bus injections.
  • supply: Active and reactive power bus injections from the generators.
  • shunt: Active and reactive power values associated with shunt element at each bus.
  • from: Active and reactive power flows at the from-bus end of each branch.
  • to: Active and reactive power flows at the to-bus end of each branch.
  • charging: Active and reactive power values linked with branch charging admittances for each branch.
  • series Active and reactive power losses through each branch series impedance.
  • generator: Produced active and reactive power outputs of each generator (not for state estimation).

Example

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+power!(system, analysis)
source
JuliaGrid.injectionPowerMethod
injectionPower(system::PowerSystem, analysis::AC, label)

The function returns the active and reactive power injections associated with a specific bus in the AC framework. The label keyword argument must match an existing bus label.

Example

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+active, reactive = injectionPower(system, analysis; label = 1)
source
JuliaGrid.supplyPowerMethod
supplyPower(system::PowerSystem, analysis::AC, label)

The function returns the active and reactive power injections from the generators associated with a specific bus in the AC framework. The label keyword argument must match an existing bus label.

Example

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+active, reactive = supplyPower(system, analysis; label = 1)
source
JuliaGrid.shuntPowerMethod
shuntPower(system::PowerSystem, analysis::AC, label)

The function returns the active and reactive power values of the shunt element associated with a specific bus in the AC framework. The label keyword argument must match an existing bus label.

Example

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+active, reactive = shuntPower(system, analysis; label = 9)

```

source
JuliaGrid.fromPowerMethod
fromPower(system::PowerSystem, analysis::AC; label)

The function returns the active and reactive power flows at the from-bus end associated with a specific branch in the AC framework. The label keyword argument must match an existing branch label.

Example

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+active, reactive = fromPower(system, analysis; label = 2)
source
JuliaGrid.toPowerMethod
toPower(system::PowerSystem, analysis::AC; label)

The function returns the active and reactive power flows at the to-bus end associated with a specific branch in the AC framework. The label keyword argument must match an existing branch label.

Example

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+active, reactive = toPower(system, analysis; label = 2)
source
JuliaGrid.seriesPowerMethod
seriesPower(system::PowerSystem, analysis::AC; label)

The function returns the active and reactive power losses across the series impedance of a specific branch within the AC framework. The label keyword argument should correspond to an existing branch label.

Example

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+active, reactive = seriesPower(system, analysis; label = 2)
source
JuliaGrid.chargingPowerMethod
chargingPower(system::PowerSystem, analysis::AC; label)

The function returns the active and reactive power values associated with the charging admittances of a specific branch in the AC framework. The label keyword argument must correspond to an existing branch label.

Example

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+active, reactive = chargingPower(system, analysis; label = 2)
source
JuliaGrid.generatorPowerMethod
generatorPower(system::PowerSystem, analysis::AC)

The function returns the active and reactive powers associated with a specific generator in the AC framework. The label keyword argument must match an existing generator label.

Example

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+active, reactive = generatorPower(system, analysis; label = 1)
source

AC Current Analysis

JuliaGrid.current!Method
current!(system::PowerSystem, analysis::AC)

The function computes the currents in the polar coordinate system associated with buses and branches in the AC framework.

Updates

This function calculates various electrical quantities in the polar coordinate system:

  • injection: Current injections at each bus.
  • from: Current flows at each from-bus end of the branch.
  • to: Current flows at each to-bus end of the branch.
  • series: Current flows through the series impedance of the branch in the direction from the from-bus end to the to-bus end of the branch.

Example

using Ipopt
+
+system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
+solve!(system, analysis)
+current!(system, analysis)
source
JuliaGrid.injectionCurrentMethod
injectionCurrent(system::PowerSystem, analysis::AC; label)

The function returns the current injection in the polar coordinate system associated with a specific bus in the AC framework. The label keyword argument must match an existing bus label.

Example

using Ipopt
+
+system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
+solve!(system, analysis)
+magnitude, angle = injectionCurrent(system, analysis; label = 1)
source
JuliaGrid.fromCurrentMethod
fromCurrent(system::PowerSystem, analysis::AC; label)

The function returns the current in the polar coordinate system at the from-bus end associated with a specific branch in the AC framework. The label keyword argument must match an existing branch label.

Example

using Ipopt
+
+system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
+solve!(system, analysis)
+magnitude, angle = fromCurrent(system, analysis; label = 2)
source
JuliaGrid.toCurrentMethod
toCurrent(system::PowerSystem, analysis::AC; label)

The function returns the current in the polar coordinate system at the to-bus end associated with a specific branch in the AC framework. The label keyword argument must match an existing branch label.

Example

using Ipopt
+
+system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
+solve!(system, analysis)
+magnitude, angle = toCurrent(system, analysis; label = 2)
source
JuliaGrid.seriesCurrentMethod
seriesCurrent(system::PowerSystem, analysis::AC; label)

The function returns the current in the polar coordinate system through series impedance associated with a specific branch in the direction from the from-bus end to the to-bus end of the branch within the AC framework. The label keyword argument must match an existing branch label.

Example

using Ipopt
+
+system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
+solve!(system, analysis)
+magnitude, angle = seriesCurrent(system, analysis; label = 2)
source

DC Power Analysis

JuliaGrid.power!Method
power!(system::PowerSystem, analysis::DC)

The function calculates the active power values related to buses, branches, and generators within the DC analysis framework.

Updates

This function updates the power field of the DC abstract type by computing the following electrical quantities:

  • injection: Active power injections at each bus.
  • supply: Active power injections from the generators at each bus.
  • from: Active power flows at each from-bus end of the branch.
  • to: Active power flows at each to-bus end of the branch.
  • generator: Output active powers of each generator (excluding for state estimation).

Example

system = powerSystem("case14.h5")
+dcModel!(system)
+
+analysis = dcPowerFlow(system)
+solve!(system, analysis)
+power!(system, analysis)
source
JuliaGrid.injectionPowerMethod
injectionPower(system::PowerSystem, analysis::DC; label)

The function returns the active power injection associated with a specific bus in the DC framework. The label keyword argument must match an existing bus label.

Example

system = powerSystem("case14.h5")
+dcModel!(system)
+
+analysis = dcPowerFlow(system)
+solve!(system, analysis)
+injection = injectionPower(system, analysis; label = 2)
source
JuliaGrid.supplyPowerMethod
supplyPower(system::PowerSystem, analysis::DC; label)

The function returns the active power injection from the generators associated with a specific bus in the DC framework. The label keyword argument must match an existing bus label.

Example

system = powerSystem("case14.h5")
+dcModel!(system)
+
+analysis = dcPowerFlow(system)
+solve!(system, analysis)
+supply = supplyPower(system, analysis; label = 2)
source
JuliaGrid.fromPowerMethod
fromPower(system::PowerSystem, analysis::DC; label)

The function returns the active power flow at the from-bus end associated with a specific branch in the DC framework. The label keyword argument must match an existing branch label.

Example

system = powerSystem("case14.h5")
+dcModel!(system)
+
+analysis = dcPowerFlow(system)
+solve!(system, analysis)
+from = fromPower(system, analysis; label = 2)
source
JuliaGrid.toPowerMethod
toPower(system::PowerSystem, analysis::DC; label)

The function returns the active power flow at the to-bus end associated with a specific branch in the DC framework. The label keyword argument must match an existing branch label.

Example

system = powerSystem("case14.h5")
+dcModel!(system)
+
+analysis = dcPowerFlow(system)
+solve!(system, analysis)
+to = toPower(system, analysis; label = 2)
source
JuliaGrid.generatorPowerMethod
generatorPower(system::PowerSystem, analysis::DC; label)

This function returns the output active power associated with a specific generator in the DC framework. The label keyword argument must match an existing generator label.

Example

system = powerSystem("case14.h5")
+dcModel!(system)
+
+analysis = dcPowerFlow(system)
+solve!(system, analysis)
+generator = generatorPower(system, analysis; label = 1)
source
diff --git a/v0.2.0/api/measurementModel/index.html b/v0.2.0/api/measurementModel/index.html new file mode 100644 index 000000000..ffbe4499d --- /dev/null +++ b/v0.2.0/api/measurementModel/index.html @@ -0,0 +1,435 @@ + +Measurement Model · JuliaGrid

Measurement Model

For further information on this topic, please see the Measurement Model section of the Manual. Below, we have provided a list of functions that can be used to create, save, and manipulate with measurement devices.

To load measurement model API functionalities into the current scope, utilize the following command:

using JuliaGrid

Measurement Data
Voltmeter
Ammeter
Wattmeter
Varmeter
PMU

Measurement Data

JuliaGrid.measurementFunction
measurement(file::String)

The function builds the composite type Measurement and populates voltmeter, ammeter, wattmeter, varmeter, and pmu fields. In general, once the composite type Measurement has been created, it is possible to add new measurement devices, or modify the parameters of existing ones.

Argument

It requires a string path to the HDF5 file with the .h5 extension.

Returns

The Measurement composite type with the following fields:

  • voltmeter: Bus voltage magnitude measurements.
  • ammeter: Branch current magnitude measurements.
  • wattmeter: Active power injection and active power flow measurements.
  • varmeter: Reactive power injection and reactive power flow measurements.
  • pmu: Bus voltage and branch current phasor measurements.

Units

JuliaGrid stores all data in per-units and radians format.

Example

device = measurement("measurement14.h5")
source
measurement()

Alternatively, the Measurement composite type can be initialized by calling the function without any arguments. This allows the model to be built from scratch and modified as needed.

Example

device = measurement()
source
JuliaGrid.saveMeasurementFunction
saveMeasurement(device::Measurement; path::String, reference::String, note::String)

The function saves the measurement's data in the HDF5 file using the fields voltmeter, ammeter, wattmeter, varmeter, and pmu from the Measurement composite type.

Keywords

The location and file name of the HDF5 file is specified by the mandatory keyword path in the format of "path/name.h5". Additional information can be provided by the optional keywords reference and note, which can be saved along with the power system data.

View HDF5 File

To view the saved HDF5 file, you can use the HDFView software.

Example

using Ipopt
+
+system = powerSystem("case14.m")
+device = measurement()
+
+acModel!(system)
+analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
+solve!(system, analysis)
+power!(system, analysis)
+
+addVoltmeter!(system, device, analysis)
+addWattmeter!(system, device, analysis)
+
+saveMeasurement(device; path = "D:/measurement14.h5")
source
JuliaGrid.status!Function
status!(system::PowerSystem, device::Measurement; inservice, outservice, redundancy)

The function generates a set of measurements, assigning measurement devices randomly to either in-service or out-of-service states based on specified keywords.

Keywords

Only one of the following keywords can be used at a time to configure the measurement set:

  • inservice: Sets the number of in-service devices.
  • outservice: Sets the number of out-of-service devices.
  • redundancy: Determines in-service devices based on redundancy.

Updates

The function updates all the status fields within the Measurement type.

Examples

Creating a measurement set with a specific number of in-service devices:

system = powerSystem("case14.h5")
+device = measurement()
+
+acModel!(system)
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+power!(system, analysis)
+
+addVoltmeter!(system, device, analysis)
+addWattmeter!(system, device, analysis)
+
+status!(system, device; inservice = 30)

Creating a measurement set using redundancy:

system = powerSystem("case14.h5")
+device = measurement()
+
+acModel!(system)
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+power!(system, analysis)
+
+addVoltmeter!(system, device, analysis)
+addWattmeter!(system, device, analysis)
+addVarmeter!(system, device, analysis)
+
+status!(system, device; redundancy = 2.5)
source

Voltmeter

JuliaGrid.addVoltmeter!Method
addVoltmeter!(system::PowerSystem, device::Measurement; label, bus, magnitude, variance,
+    noise, status)

The function adds a new voltmeter that measures bus voltage magnitude to the Measurement type within a given PowerSystem type. The voltmeter can be added to an already defined bus.

Keywords

The voltmeter is defined with the following keywords:

  • label: Unique label for the voltmeter.
  • bus: Label of the bus to which the voltmeter is connected.
  • magnitude (pu or V): Bus voltage magnitude value.
  • variance (pu or V): Variance of the bus voltage magnitude measurement.
  • noise: Specifies how to generate the measurement mean:
    • noise = true: adds white Gaussian noise with the variance to the magnitude,
    • noise = false: uses the magnitude value only.
  • status: Operating status of the voltmeter:
    • status = 1: in-service,
    • status = 0: out-of-service.

Updates

The function updates the voltmeter field of the Measurement composite type.

Default Settings

Default settings for certain keywords are as follows: variance = 1e-2, noise = false, status = 1, and users can modify these default settings using the @voltmeter macro.

Units

The default units for the magnitude and variance keywords are per-units (pu). However, users can choose to use volts (V) as the units by applying the @voltage macro.

Examples

Adding a voltmeter using the default unit system:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 132e3)
+
+addVoltmeter!(system, device; label = "Voltmeter 1", bus = "Bus 1", magnitude = 1.1)

Adding a voltmeter using a custom unit system:

@voltage(kV, rad, kV)
+system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 132.0)
+
+addVoltmeter!(system, device; label = "Voltmeter 1", bus = "Bus 1", magnitude = 145.2)
source
JuliaGrid.addVoltmeter!Method
addVoltmeter!(system::PowerSystem, device::Measurement, analysis::AC; variance, noise,
+    status)

The function incorporates voltmeters into the Measurement composite type for every bus within the PowerSystem type. These measurements are derived from the exact bus voltage magnitudes defined in the AC type.

Keywords

Users have the option to configure the following keywords:

  • variance (pu or V): Variance of bus voltage magnitude measurements.
  • noise: Specifies how to generate the measurement mean:
    • noise = true: adds white Gaussian noise with the variance to the voltage magnitudes,
    • noise = false: uses the exact voltage magnitude values.
  • status: Operating status of the voltmeters:
    • status = 1: in-service,
    • status = 0: out-of-service.

Updates

The function updates the voltmeter field of the Measurement composite type.

Default Settings

Default settings for keywords are as follows: variance = 1e-2, noise = false, and status = 1, and users can modify these default settings using the @voltmeter macro.

Units

By default, the unit for variance is per-unit (pu). However, users can choose to use volts (V) as the units by applying the @voltage macro.

Example

system = powerSystem("case14.h5")
+device = measurement()
+
+acModel!(system)
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+
+@voltmeter(label = "Voltmeter ?")
+addVoltmeter!(system, device, analysis; variance = 1e-3, noise = true)
source
JuliaGrid.updateVoltmeter!Function
updateVoltmeter!(system::PowerSystem, device::Measurement, [analysis::Analysis];
+    kwargs...)

The function allows for the alteration of parameters for a voltmeter.

Arguments

If the Analysis type is omitted, the function applies changes to the Measurement composite type only. However, when including the Analysis type, it updates both the Measurement and Analysis types. This streamlined process avoids the need to completely rebuild vectors and matrices when adjusting these parameters.

Keywords

To update a specific voltmeter, provide the necessary kwargs input arguments in accordance with the keywords specified in the addVoltmeter! function, along with their respective values. Ensure that the label keyword matches the label of the existing voltmeter you want to modify. If any keywords are omitted, their corresponding values will remain unchanged.

Updates

The function updates the voltmeter field within the Measurement composite type. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.

Units

Units for input parameters can be changed using the same method as described for the addVoltmeter! function.

Example

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 132e3)
+
+addVoltmeter!(system, device; label = "Voltmeter 1", bus = "Bus 1", magnitude = 1.1)
+updateVoltmeter!(system, device; label = "Voltmeter 1", magnitude = 0.9)
source
JuliaGrid.statusVoltmeter!Function
statusVoltmeter!(system::PowerSystem, device::Measurement; inservice, outservice,
+    redundancy)

The function generates a set of voltmeters, assigning voltmeters randomly to either in-service or out-of-service states based on specified keywords.

Keywords

Only one of the following keywords can be used at a time to configure the measurement set:

  • inservice: Sets the number of in-service voltmeters.
  • outservice: Sets the number of out-of-service voltmeters.
  • redundancy: Determines in-service voltmeters based on redundancy.

Updates

The function updates the status field within the Voltmeter type.

Example

system = powerSystem("case14.h5")
+device = measurement()
+
+acModel!(system)
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+
+addVoltmeter!(system, device, analysis)
+statusVoltmeter!(system, device; inservice = 10)
source
JuliaGrid.@voltmeterMacro
@voltmeter(label, variance, noise, status)

The macro generates a template for a voltmeter, which can be utilized to define a voltmeter using the addVoltmeter! function.

Keywords

To establish the voltmeter template, users can specify default values for the variance, noise, and status keywords, along with pattern for labels using the label keyword.

Units

By default, the unit for variance is per-unit (pu). However, users can choose to use volts (V) as the units by applying the @voltage macro.

Examples

Adding a voltmeter using the default unit system:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 132e3)
+
+@voltmeter(label = "Voltmeter ?", variance = 1e-5)
+addVoltmeter!(system, device; bus = "Bus 1", magnitude = 1.1)

Adding a voltmeter using a custom unit system:

@voltage(kV, rad, kV)
+system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 132.0)
+
+@voltmeter(label = "Voltmeter ?", variance = 0.00132)
+addVoltmeter!(system, device; bus = "Bus 1", magnitude = 145.2)
source

Ammeter

JuliaGrid.addAmmeter!Method
addAmmeter!(system::PowerSystem, device::Measurement; label, from, to, magnitude,
+    variance, noise, status)

The function adds a new ammeter that measures branch current magnitude to the Measurement type within a given PowerSystem type. The ammeter can be added to an already defined branch.

Keywords

The ammeter is defined with the following keywords:

  • label: Unique label for the ammeter.
  • from: Label of the branch if the ammeter is located at the from-bus end.
  • to: Label of the branch if the ammeter is located at the to-bus end.
  • magnitude (pu or A): Branch current magnitude value.
  • variance (pu or A): Variance of the branch current magnitude measurement.
  • noise: Specifies how to generate the measurement mean:
    • noise = true: adds white Gaussian noise with the variance to the magnitude,
    • noise = false: uses the magnitude value only.
  • status: Operating status of the ammeter:
    • status = 1: in-service,
    • status = 0: out-of-service.

Updates

The function updates the ammeter field of the Measurement composite type.

Default Settings

Default settings for certain keywords are as follows: variance = 1e-2, noise = false, status = 1, which apply to ammeters located at both the from-bus and to-bus ends. Users can fine-tune these settings by explicitly specifying the variance and status for ammeters positioned on either the from-bus or to-bus ends of branches using the @ammeter macro.

Units

The default units for the magnitude and variance keywords are per-units (pu). However, users can choose to use amperes (A) as the units by applying the @current macro.

Examples

Adding ammeters using the default unit system:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 132e3)
+addBus!(system; label = "Bus 2", base = 132e3)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.2)
+
+addAmmeter!(system, device; label = "Ammeter 1", from = "Branch 1", magnitude = 1.1)
+addAmmeter!(system, device; label = "Ammeter 2", to = "Branch 1", magnitude = 1.0)

Adding ammeters using a custom unit system:

@current(A, rad)
+system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 132e3)
+addBus!(system; label = "Bus 2", base = 132e3)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.2)
+
+addAmmeter!(system, device; label = "Ammeter 1", from = "Branch 1", magnitude = 481.125)
+addAmmeter!(system, device; label = "Ammeter 2", to = "Branch 1", magnitude = 437.386)
source
JuliaGrid.addAmmeter!Method
addAmmeter!(system::PowerSystem, device::Measurement, analysis::AC; varianceFrom,
+    statusFrom, varianceTo, statusTo, noise)

The function incorporates ammeters into the Measurement type for every branch within the PowerSystem type. These measurements are derived from the exact branch current magnitudes defined in the AC type.

Keywords

Users have the option to configure the following keywords:

  • varianceFrom (pu or A): Measurement variance for ammeters at the from-bus ends.
  • statusFrom: Operating status of the ammeters at the from-bus ends:
    • statusFrom = 1: in-service,
    • statusFrom = 0: out-of-service.
  • varianceTo (pu or A): Measurement variance for ammeters at the to-bus ends.
  • statusTo: Operating status of the ammeters at the to-bus ends:
    • statusTo = 1: in-service,
    • statusTo = 0: out-of-service.
  • noise: Specifies how to generate the measurement mean:
    • noise = true: adds white Gaussian noise with the variance to the current magnitudes,
    • noise = false: uses the exact current magnitude values.

Updates

The function updates the ammeter field of the Measurement composite type.

Default Settings

Default settings for keywords are as follows: varianceFrom = 1e-2, statusFrom = 1, varianceTo = 1e-2, statusTo = 1, and noise = false. Users can change these default settings using the @ammeter macro.

Units

The default units for the varianceFrom and varianceTo keywords are per-units (pu). However, users can choose to use amperes (A) as the units by applying the @current macro.

Example

system = powerSystem("case14.h5")
+device = measurement()
+
+acModel!(system)
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+current!(system, analysis)
+
+@ammeter(label = "Ammeter ?")
+addAmmeter!(system, device, analysis; varianceFrom = 1e-3, statusTo = 0)
source
JuliaGrid.updateAmmeter!Function
updateAmmeter!(system::PowerSystem, device::Measurement, [analysis::Analysis];
+    kwargs...)

The function allows for the alteration of parameters for an ammeter.

Arguments

If the Analysis type is omitted, the function applies changes to the Measurement composite type only. However, when including the Analysis type, it updates both the Measurement and Analysis types. This streamlined process avoids the need to completely rebuild vectors and matrices when adjusting these parameters.

Keywords

To update a specific ammeter, provide the necessary kwargs input arguments in accordance with the keywords specified in the addAmmeter! function, along with their respective values. Ensure that the label keyword matches the label of the existing ammeter you want to modify. If any keywords are omitted, their corresponding values will remain unchanged.

Updates

The function updates the ammeter field within the Measurement composite type. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.

Units

Units for input parameters can be changed using the same method as described for the addAmmeter! function.

Example

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 132e3)
+addBus!(system; label = "Bus 2", base = 132e3)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.2)
+
+addAmmeter!(system, device; label = "Ammeter 1", from = "Branch 1", magnitude = 1.1)
+updateAmmeter!(system, device; label = "Ammeter 1", magnitude = 1.2, variance = 1e-4)
source
JuliaGrid.statusAmmeter!Function
statusAmmeter!(system::PowerSystem, ammeter::Ammeter; inservice, inserviceFrom,
+    inserviceTo, outservice, outserviceFrom, outserviceTo, redundancy, redundancyFrom,
+    redundancyTo)

The function generates a set of ammeters, assigning ammeters randomly to either in-service or out-of-service states based on specified keywords.

Keywords

Users may use either one main keyword or two fine-tuning keywords that specify distinct locations per function call:

  • inservice: Sets the number of in-service ammeters or allows fine-tuning:
    • inserviceFrom: sets only ammeters loacted at the from-bus end,
    • inserviceTo: sets only ammeters loacted at the to-bus end.
  • outservice: Sets the number of out-of-service ammeters or allows fine-tuning:
    • outserviceFrom: sets only ammeters loacted at the from-bus end,
    • outserviceTo: sets only ammeters loacted at the to-bus end.
  • redundancy: Determines in-service ammeters based on redundancy or allows fine-tuning:
    • redundancyFrom: determines only ammeters loacted at the from-bus end,
    • redundancyTo: determines only ammeters loacted at the to-bus end.

Updates

The function updates the status field within the Ammeter type.

Example

system = powerSystem("case14.h5")
+device = measurement()
+
+acModel!(system)
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+current!(system, analysis)
+
+addAmmeter!(system, device, analysis)
+statusAmmeter!(system, device; inserviceFrom = 5, inserviceTo = 10)
source
JuliaGrid.@ammeterMacro
@ammeter(label, varianceFrom, statusFrom, varianceTo, statusTo, noise)

The macro generates a template for an ammeter, which can be utilized to define an ammeter using the addAmmeter! function.

Keywords

To establish the ammeter template, users can set default variance and status values for ammeters at both the from-bus and to-bus ends of branches, using varianceFrom and statusFrom for the former and varianceTo and statusTo for the latter. Users can also configure label patterns with the label keyword, as well as specify the noise type.

Units

The default units for the varianceFrom and varianceTo keywords are per-units (pu). However, users can choose to use amperes (A) as the units by applying the @current macro.

Examples

Adding an ammeter using the default unit system:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 132e3)
+addBus!(system; label = "Bus 2", base = 132e3)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.2)
+
+@ammeter(label = "Ammeter ?", varianceTo = 1e-3, statusTo = 0)
+addAmmeter!(system, device; to = "Branch 1", magnitude = 1.1)

Adding an ammeter using a custom unit system:

@current(A, rad)
+system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 132e3)
+addBus!(system; label = "Bus 2", base = 132e3)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.2)
+
+@ammeter(label = "Ammeter ?", varianceTo = 0.004374, statusTo = 0)
+addAmmeter!(system, device; label = "Ammeter 1", to = "Branch 1", magnitude = 481.125)
source

Wattmeter

JuliaGrid.addWattmeter!Method
addWattmeter!(system::PowerSystem, device::Measurement; label, bus, from, to, active,
+    variance, noise, status)

The function adds a new wattmeter that measures active power injection or active power flow to the Measurement type within a given PowerSystem type. The wattmeter can be added to an already defined bus or branch.

Keywords

The wattmeter is defined with the following keywords:

  • label: Unique label for the wattmeter.
  • bus: Label of the bus if the wattmeter is located at the bus.
  • from: Label of the branch if the wattmeter is located at the from-bus end.
  • to: Label of the branch if the wattmeter is located at the to-bus end.
  • active (pu or W): Active power value.
  • variance (pu or W): Variance of the active power measurement.
  • noise: Specifies how to generate the measurement mean:
    • noise = true: adds white Gaussian noise with the variance to the active,
    • noise = false: uses the active value only.
  • status: Operating status of the wattmeter:
    • status = 1: in-service,
    • status = 0: out-of-service.

Updates

The function updates the wattmeter field of the Measurement composite type.

Default Settings

Default settings for certain keywords are as follows: variance = 1e-2, noise = false, and status = 1, which apply to wattmeters located at the bus, as well as at both the from-bus and to-bus ends. Users can fine-tune these settings by explicitly specifying the variance and status for wattmeters positioned at the buses, from-bus ends, or to-bus ends of branches using the @wattmeter macro.

Units

The default units for the active and variance keywords are per-units (pu). However, users can choose to use watts (W) as the units by applying the @power macro.

Examples

Adding wattmeters using the default unit system:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.2)
+
+addWattmeter!(system, device; label = "Wattmeter 1", bus = "Bus 2", active = 0.4)
+addWattmeter!(system, device; label = "Wattmeter 2", from = "Branch 1", active = 0.1)

Adding wattmeters using a custom unit system:

@power(MW, pu, pu)
+system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.2)
+
+addWattmeter!(system, device; label = "Wattmeter 1", bus = "Bus 2", active = 40.0)
+addWattmeter!(system, device; label = "Wattmeter 2", from = "Branch 1", active = 10.0)
source
JuliaGrid.addWattmeter!Method
addWattmeter!(system::PowerSystem, device::Measurement, analysis::AC;
+    varianceBus, statusBus, varianceFrom, statusFrom, varianceTo, statusTo, noise)

The function incorporates wattmeters into the Measurement composite type for every bus and branch within the PowerSystem type. These measurements are derived from the exact active power injections at buses and active power flows in branches defined in the AC type.

Keywords

Users have the option to configure the following keywords:

  • varianceBus (pu or W): Measurement variance for wattmeters at the buses.
  • statusBus: Operating status of the wattmeters at the buses:
    • statusBus = 1: in-service,
    • statusBus = 0: out-of-service.
  • varianceFrom (pu or W): Measurement variance for wattmeters at the from-bus ends.
  • statusFrom: Operating status of the wattmeters at the from-bus ends:
    • statusFrom = 1: in-service,
    • statusFrom = 0: out-of-service.
  • varianceTo (pu or W): Measurement variance for wattmeters at the to-bus ends.
  • statusTo: Operating status of the wattmeters at the to-bus ends:
    • statusTo = 1: in-service,
    • statusTo = 0: out-of-service.
  • noise: Specifies how to generate the measurement mean:
    • noise = true: adds white Gaussian noise with the variance to the active powers,
    • noise = false: uses the exact active power values.

Updates

The function updates the wattmeter field of the Measurement composite type.

Default Settings

Default settings for keywords are as follows: varianceBus = 1e-2, statusBus = 1, varianceFrom = 1e-2, statusFrom = 1, varianceTo = 1e-2, statusTo = 1, and noise = false. Users can change these default settings using the @wattmeter macro.

Units

The default units for the varianceBus, varianceFrom, and varianceTo keywords are per-units (pu). However, users can choose to use watts (W) as the units by applying the @power macro.

Example

system = powerSystem("case14.h5")
+device = measurement()
+
+acModel!(system)
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+power!(system, analysis)
+
+@wattmeter(label = "Wattmeter ?")
+addWattmeter!(system, device, analysis; varianceBus = 1e-3, statusFrom = 0)
source
JuliaGrid.updateWattmeter!Function
updateWattmeter!(system::PowerSystem, device::Measurement, [analysis::Analysis];
+    kwargs...)

The function allows for the alteration of parameters for a wattmeter.

Arguments

If the Analysis type is omitted, the function applies changes to the Measurement composite type only. However, when including the Analysis type, it updates both the Measurement and Analysis types. This streamlined process avoids the need to completely rebuild vectors and matrices when adjusting these parameters.

Keywords

To update a specific wattmeter, provide the necessary kwargs input arguments in accordance with the keywords specified in the addWattmeter! function, along with their respective values. Ensure that the label keyword matches the label of the existing wattmeter you want to modify. If any keywords are omitted, their corresponding values will remain unchanged.

Updates

The function updates the wattmeter field within the Measurement composite type. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.

Units

Units for input parameters can be changed using the same method as described for the addWattmeter! function.

Example

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 132e3)
+addBus!(system; label = "Bus 2", base = 132e3)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.2)
+
+addWattmeter!(system, device; label = "Wattmeter 1", from = "Branch 1", active = 1.1)
+updateWattmeter!(system, device; label = "Wattmeter 1", active = 1.2, variance = 1e-4)
source
JuliaGrid.statusWattmeter!Function
statusWattmeter!(system::PowerSystem, device::Measurement; inservice, inserviceBus,
+    inserviceFrom, inserviceTo, outservice, outserviceBus outserviceFrom, outserviceTo,
+    redundancy, redundancyBus, redundancyFrom, redundancyTo)

The function generates a set of wattmeters, assigning wattmeters randomly to either in-service or out-of-service states based on specified keywords.

Keywords

Users may use either one main keyword or three fine-tuning keywords that specify distinct locations per function call:

  • inservice: Sets the number of in-service wattmeters or allows fine-tuning:
    • inserviceBus: sets only wattmeters loacted at the bus,
    • inserviceFrom: sets only wattmeters loacted at the from-bus end,
    • inserviceTo: sets only wattmeters loacted at the to-bus end.
  • outservice: Sets the number of out-of-service wattmeters or allows fine-tuning:
    • outserviceBus: sets only wattmeters loacted at the bus,
    • outserviceFrom: sets only wattmeters loacted at the from-bus end,
    • outserviceTo: sets only wattmeters loacted at the to-bus end.
  • redundancy: Determines in-service wattmeters based on redundancy or allows fine-tuning:
    • redundancyBus: determines only wattmeters loacted at the bus,
    • redundancyFrom: determines only wattmeters loacted at the from-bus end,
    • redundancyTo: determines only wattmeters loacted at the to-bus end.

Updates

The function updates the status field within the Wattmeter type.

Example

system = powerSystem("case14.h5")
+device = measurement()
+
+acModel!(system)
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+power!(system, analysis)
+
+addWattmeter!(system, device, analysis)
+statusWattmeter!(system, device; outserviceBus = 14, inserviceFrom = 10, outserviceTo = 2)
source
JuliaGrid.@wattmeterMacro
@wattmeter(label, varianceBus, statusBus, varianceFrom, statusFrom, varianceTo, statusTo,
+    noise)

The macro generates a template for a wattmeter, which can be utilized to define a wattmeter using the addWattmeter! function.

Keywords

To establish the wattmeter template, users can set default variance and status values for wattmeters at buses using varianceBus and statusBus, and at both the from-bus and to-bus ends of branches using varianceFrom and statusFrom for the former and varianceTo and statusTo for the latter. Users can also configure label patterns with the label keyword, as well as specify the noise type.

Units

The default units for the varianceBus, varianceFrom, and varianceTo keywords are per-units (pu). However, users can choose to use watts (W) as the units by applying the @power macro.

Examples

Adding wattmeters using the default unit system:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.2)
+
+@wattmeter(label = "Wattmeter ?", varianceBus = 1e-3, varianceFrom = 1e-4)
+addWattmeter!(system, device; bus = "Bus 2", active = 0.4)
+addWattmeter!(system, device; from = "Branch 1", active = 0.1)

Adding wattmeters using a custom unit system:

@power(MW, pu, pu)
+system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.2)
+
+@wattmeter(label = "Wattmeter ?", varianceBus = 1e-1, varianceFrom = 1e-2)
+addWattmeter!(system, device; bus = "Bus 2", active = 40.0)
+addWattmeter!(system, device; from = "Branch 1", active = 10.0)
source

Varmeter

JuliaGrid.addVarmeter!Method
addVarmeter!(system::PowerSystem, device::Measurement; label, bus, from, to, reactive,
+    variance, noise, status)

The function adds a new varmeter that measures reactive power injection or reactive power flow to the Measurement type within a given PowerSystem type. The varmeter can be added to an already defined bus or branch.

Keywords

The varmeter is defined with the following keywords:

  • label: Unique label for the varmeter.
  • bus: Label of the bus if the varmeter is located at the bus.
  • from: Label of the branch if the varmeter is located at the from-bus end.
  • to: Label of the branch if the varmeter is located at the to-bus end.
  • reactive (pu or VAr): Reactive power value.
  • variance (pu or VAr): Variance of the reactive power measurement.
  • noise: Specifies how to generate the measurement mean:
    • noise = true: adds white Gaussian noise with the variance to the reactive,
    • noise = false: uses the reactive value only.
  • status: Operating status of the varmeter:
    • status = 1: in-service,
    • status = 0: out-of-service.

Updates

The function updates the varmeter field of the Measurement composite type.

Default Settings

Default settings for certain keywords are as follows: variance = 1e-2, noise = false, and status = 1, which apply to varmeters located at the bus, as well as at both the from-bus and to-bus ends. Users can fine-tune these settings by explicitly specifying the variance and status for varmeters positioned at the buses, from-bus ends, or to-bus ends of branches using the @varmeter macro.

Units

The default units for the reactive and variance keywords are per-units (pu). However, users can choose to use volt-amperes reactive (VAr) as the units by applying the @power macro.

Examples

Adding varmeters using the default unit system:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.2)
+
+addVarmeter!(system, device; label = "Varmeter 1", bus = "Bus 2", reactive = 0.4)
+addVarmeter!(system, device; label = "Varmeter 2", from = "Branch 1", reactive = 0.1)

Adding varmeters using a custom unit system:

@power(MW, pu, pu)
+system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.2)
+
+addVarmeter!(system, device; label = "Varmeter 1", bus = "Bus 2", reactive = 40.0)
+addVarmeter!(system, device; label = "Varmeter 2", from = "Branch 1", reactive = 10.0)
source
JuliaGrid.addVarmeter!Method
addVarmeter!(system::PowerSystem, device::Measurement, analysis::AC;
+    varianceBus, statusBus, varianceFrom, statusFrom, varianceTo, statusTo, noise)

The function incorporates varmeters into the Measurement composite type for every bus and branch within the PowerSystem type. These measurements are derived from the exact reactive power injections at buses and reactive power flows in branches defined in the AC type.

Keywords

  • varianceBus (pu or VAr): Measurement variance for varmeters at the buses.
  • statusBus: Operating status of the varmeters at the buses:
    • statusBus = 1: in-service,
    • statusBus = 0: out-of-service.
  • varianceFrom (pu or VAr): Measurement variance for varmeters at the from-bus ends.
  • statusFrom: Operating status of the varmeters at the from-bus ends:
    • statusFrom = 1: in-service,
    • statusFrom = 0: out-of-service.
  • varianceTo (pu or VAr): Measurement variance for varmeters at the to-bus ends.
  • statusTo: Operating status of the varmeters at the to-bus ends:
    • statusTo = 1: in-service,
    • statusTo = 0: out-of-service.
  • noise: Specifies how to generate the measurement mean:
    • noise = true: adds white Gaussian noise with the variance to the reactive powers,
    • noise = false: uses the exact reactive power values.

Updates

The function updates the varmeter field of the Measurement composite type.

Default Settings

Default settings for keywords are as follows: varianceBus = 1e-2, statusBus = 1, varianceFrom = 1e-2, statusFrom = 1, varianceTo = 1e-2, statusTo = 1, and noise = false. Users can change these default settings using the @varmeter macro.

Units

The default units for the varianceBus, varianceFrom, and varianceTo keywords are per-units (pu). However, users can choose to use volt-amperes reactive (VAr) as the units by applying the @power macro.

Example

system = powerSystem("case14.h5")
+device = measurement()
+
+acModel!(system)
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+power!(system, analysis)
+
+@varmeter(label = "Varmeter ?")
+addVarmeter!(system, device, analysis; varianceFrom = 1e-3, statusBus = 0)
source
JuliaGrid.updateVarmeter!Function
updateVarmeter!(system::PowerSystem, device::Measurement, [analysis::Analysis];
+    kwargs...)

The function allows for the alteration of parameters for a varmeter.

Arguments

If the Analysis type is omitted, the function applies changes to the Measurement composite type only. However, when including the Analysis type, it updates both the Measurement and Analysis types. This streamlined process avoids the need to completely rebuild vectors and matrices when adjusting these parameters.

Keywords

To update a specific varmeter, provide the necessary kwargs input arguments in accordance with the keywords specified in the addVarmeter! function, along with their respective values. Ensure that the label keyword matches the label of the existing varmeter you want to modify. If any keywords are omitted, their corresponding values will remain unchanged.

Updates

The function updates the varmeter field within the Measurement composite type. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.

Units

Units for input parameters can be changed using the same method as described for the addVarmeter! function.

Example

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 132e3)
+addBus!(system; label = "Bus 2", base = 132e3)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.2)
+
+addVarmeter!(system, device; label = "Varmeter 1", from = "Branch 1", reactive = 1.1)
+updateVarmeter!(system, device; label = "Varmeter 1", reactive = 1.2, variance = 1e-4)
source
JuliaGrid.statusVarmeter!Function
statusVarmeter!(system::PowerSystem, device::Measurement; inservice, inserviceBus,
+    inserviceFrom, inserviceTo, outservice, outserviceBus outserviceFrom, outserviceTo,
+    redundancy, redundancyBus, redundancyFrom, redundancyTo)

The function generates a set of varmeters, assigning varmeters randomly to either in-service or out-of-service states based on specified keywords.

Keywords

Users may use either one main keyword or three fine-tuning keywords that specify distinct locations per function call:

  • inservice: Sets the number of in-service varmeters or allows fine-tuning:
    • inserviceBus: sets only varmeters loacted at the bus,
    • inserviceFrom: sets only varmeters loacted at the from-bus end,
    • inserviceTo: sets only varmeters loacted at the to-bus end.
  • outservice: Sets the number of out-of-service varmeters or allows fine-tuning:
    • outserviceBus: sets only varmeters loacted at the bus,
    • outserviceFrom: sets only varmeters loacted at the from-bus end,
    • outserviceTo: sets only varmeters loacted at the to-bus end.
  • redundancy: Determines in-service varmeters based on redundancy or allows fine-tuning:
    • redundancyBus: determines only varmeters loacted at the bus,
    • redundancyFrom: determines only varmeters loacted at the from-bus end,
    • redundancyTo: determines only varmeters loacted at the to-bus end.

Updates

The function updates the status field within the Varmeter type.

Example

system = powerSystem("case14.h5")
+device = measurement()
+
+acModel!(system)
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+power!(system, analysis)
+
+addVarmeter!(system, device, analysis)
+statusVarmeter!(system, device; inserviceFrom = 20)
source
JuliaGrid.@varmeterMacro
@varmeter(label, varinaceBus, varianceFrom, varianceTo, statusBus, statusFrom, statusTo,
+    noise)

The macro generates a template for a varmeter, which can be utilized to define a varmeter using the addVarmeter! function.

Keywords

To establish the varmeter template, users can set default variance and status values for varmeters at buses using varianceBus and statusBus, and at both the from-bus and to-bus ends of branches using varianceFrom and statusFrom for the former and varianceTo and statusTo for the latter. Users can also configure label patterns with the label keyword, as well as specify the noise type.

Units

The default units for the varianceBus, varianceFrom, and varianceTo keywords are per-units (pu). However, users can choose to usevolt-amperes reactive (VAr) as the units by applying the @power macro.

Examples

Adding varmeters using the default unit system:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.2)
+
+@varmeter(label = "Varmeter ?", varianceBus = 1e-3, varianceFrom = 1e-4)
+addVarmeter!(system, device; bus = "Bus 2", reactive = 0.4)
+addVarmeter!(system, device; from = "Branch 1", reactive = 0.1)

Adding varmeters using a custom unit system:

@power(MW, pu, pu)
+system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.2)
+
+@varmeter(label = "Varmeter ?", varianceBus = 1e-1, varianceFrom = 1e-2)
+addVarmeter!(system, device; bus = "Bus 2", reactive = 40.0)
+addVarmeter!(system, device; from = "Branch 1", reactive = 10.0)
source

PMU

JuliaGrid.addPmu!Method
addPmu!(system::PowerSystem, device::Measurement; label, bus, from, to, magnitude,
+    varianceMagnitude, statusMagnitude, angle, varianceAngle, statusAngle,
+    noise, correlated, polar)

The function adds a new PMU to the Measurement type within a given PowerSystem type. The PMU can be added to an already defined bus or branch. When defining the PMU, it is essential to provide the bus voltage magnitude and angle if the PMU is located at a bus or the branch current magnitude and angle if the PMU is located at a branch.

Keywords

The PMU is defined with the following keywords:

  • label: Unique label for the PMU.
  • bus: Label of the bus if the PMU is located at the bus.
  • from: Label of the branch if the PMU is located at the from-bus end.
  • to: Label of the branch if the PMU is located at the to-bus end.
  • magnitude (pu or V, A): Bus voltage or branch current magnitude value.
  • varianceMagnitude (pu or V, A): Magnitude measurement variance.
  • statusMagnitude: Operating status of the magnitude measurement:
    • statusMagnitude = 1: in-service,
    • statusMagnitude = 0: out-of-service.
  • angle (rad or deg): Bus voltage or branch current angle value.
  • varianceAngle (rad or deg): Angle measurement variance.
  • statusAngle: Operating status of the angle measurement:
    • statusAngle = 1: in-service,
    • statusAngle = 0: out-of-service.
  • noise: Specifies how to generate the measurement means:
    • noise = true: adds white Gaussian noises with variances to the magnitude and angle,
    • noise = false: uses the magnitude and angle values only.
  • correlated: Specifies error correlation for PMUs for algorithms utilizing rectangular coordinates:
    • correlated = true: considers correlated errors,
    • correlated = false: disregards correlations between errors.
  • polar: Chooses the coordinate system for including phasor measurements in AC state estimation:
    • polar = true: adopts the polar coordinate system,
    • polar = false: adopts the rectangular coordinate system.

Updates

The function updates the pmu field of the Measurement composite type.

Default Settings

Default settings for certain keywords are as follows: varianceMagnitude = 1e-5, statusMagnitude = 1, varianceAngle = 1e-5, statusAngle = 1, noise = false, correlated = false, and polar = false, which apply to PMUs located at the bus, as well as at both the from-bus and to-bus ends. Users can fine-tune these settings by explicitly specifying the variance and status for PMUs positioned at the buses, from-bus ends, or to-bus ends of branches using the @pmu macro.

Units

The default units for the magnitude, varianceMagnitude, and angle, varianceAngle keywords are per-units (pu) and radians (rad). However, users have the option to switch to volts (V) and degrees (deg) when the PMU is located at a bus using the @voltage macro, or amperes (A) and degrees (deg) when the PMU is located at a branch through the use of the @current macro.

Examples

Adding PMUs using the default unit system:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 131.8e3)
+addBus!(system; label = "Bus 2", base = 131.8e3)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.2)
+
+addPmu!(system, device; label = "PMU 1", bus = "Bus 1", magnitude = 1.1, angle = -0.1)
+addPmu!(system, device; label = "PMU 2", from = "Branch 1", magnitude = 1.1, angle = 0.1)

Adding PMUs using a custom unit system:

@voltage(kV, deg, kV)
+@current(A, deg)
+system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 131.8)
+addBus!(system; label = "Bus 2", base = 131.8)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.2)
+
+addPmu!(system, device; label = "PMU 1", bus = "Bus 1", magnitude = 145, angle = -5.7)
+addPmu!(system, device; label = "PMU 2", from = "Branch 1", magnitude = 481, angle = 5.7)
source
JuliaGrid.addPmu!Method
addPmu!(system::PowerSystem, device::Measurement, analysis::AC;
+    varianceMagnitudeBus, statusMagnitudeBus, varianceAngleBus, statusAngleBus,
+    varianceMagnitudeFrom, statusMagnitudeFrom, varianceAngleFrom, statusAngleFrom,
+    varianceMagnitudeTo, statusMagnitudeTo, varianceAngleTo, statusAngleTo,
+    correlated, polar, noise)

The function incorporates PMUs into the Measurement composite type for every bus and branch within the PowerSystem type. These measurements are derived from the exact bus voltage magnitudes and angles, as well as branch current magnitudes and angles defined in the AC type.

Keywords

Users have the option to configure the following keywords:

  • varianceMagnitudeBus (pu or V): Variance of magnitude measurements at buses.
  • statusMagnitudeBus: Operating status of magnitude measurements at buses:
    • statusMagnitudeBus = 1: in-service,
    • statusMagnitudeBus = 0: out-of-service.
  • varianceAngleBus (rad or deg): Variance of angle measurements at buses.
  • statusAngleBus: Operating status of angle measurements at buses:
    • statusAngleBus = 1: in-service,
    • statusAngleBus = 0: out-of-service.
  • varianceMagnitudeFrom (pu or A): Variance of magnitude measurements at the from-bus ends.
  • statusMagnitudeFrom: Operating status of magnitude measurements at the from-bus ends:
    • statusMagnitudeFrom = 1: in-service,
    • statusMagnitudeFrom = 0: out-of-service.
  • varianceAngleFrom (rad or deg): Variance of angle measurements at the from-bus ends.
  • statusAngleFrom: Operating status of angle measurements at the from-bus ends:
    • statusAngleFrom = 1: in-service,
    • statusAngleFrom = 0: out-of-service.
  • varianceMagnitudeTo (pu or A): Variance of magnitude measurements at the to-bus ends.
  • statusMagnitudeTo: Operating status of magnitude measurements at the to-bus ends:
    • statusMagnitudeTo = 1: in-service,
    • statusMagnitudeTo = 0: out-of-service.
  • varianceAngleTo (rad or deg): Variance of angle measurements at the to-bus ends.
  • statusAngleTo: Operating status of angle measurements at the to-bus ends:
    • statusAngleTo = 1: in-service,
    • statusAngleTo = 0: out-of-service.
  • correlated: Specifies error correlation for PMUs for algorithms utilizing rectangular coordinates:
    • correlated = true: considers correlated errors,
    • correlated = false: disregards correlations between errors.
  • polar: Chooses the coordinate system for including phasor measurements in AC state estimation:
    • polar = true: adopts the polar coordinate system,
    • polar = false: adopts the rectangular coordinate system.
  • noise: Specifies how to generate the measurement mean:
    • noise = true: adds white Gaussian noise with the variance to the magnitudes and angles,
    • noise = false: uses the exact magnitude and angles values.

Updates

The function updates the pmu field of the Measurement composite type.

Default Settings

Default settings for variance keywords are established at 1e-5, with all statuses set to 1, polar = false, correlated = false, and noise = false. Users can change these default settings using the @pmu macro.

Units

The default units for the variance keywords are in per-units (pu) and radians (rad). However, users have the option to switch to volts (V) and degrees (deg) when the PMU is located at a bus using the @voltage macro, or amperes (A) and degrees (deg) when the PMU is located at a branch through the use of the @current macro.

Example

system = powerSystem("case14.h5")
+device = measurement()
+
+acModel!(system)
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+current!(system, analysis)
+
+@pmu(label = "PMU ?")
+addPmu!(system, device, analysis; varianceMagnitudeBus = 1e-3)
source
JuliaGrid.updatePmu!Function
updatePmu!(system::PowerSystem, device::Measurement, [analysis::Analysis];
+    kwargs...)

The function allows for the alteration of parameters for a PMU.

Arguments

If the Analysis type is omitted, the function applies changes to the Measurement composite type only. However, when including the Analysis type, it updates both the Measurement and Analysis types. This streamlined process avoids the need to completely rebuild vectors and matrices when adjusting these parameters.

Keywords

To update a specific PMU, provide the necessary kwargs input arguments in accordance with the keywords specified in the addPmu! function, along with their respective values. Ensure that the label keyword matches the label of the existing PMU you want to modify. If any keywords are omitted, their corresponding values will remain unchanged.

Updates

The function updates the pmu field within the Measurement composite type. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.

Units

Units for input parameters can be changed using the same method as described for the addPmu! function.

Example

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 132e3)
+
+addPmu!(system, device; label = "PMU 1", bus = "Bus 1", magnitude = 1.1, angle = -0.1)
+updatePmu!(system, device; label = "PMU 1", magnitude = 1.05)
source
JuliaGrid.statusPmu!Function
statusPmu!(system::PowerSystem, device::Measurement; inservice, inserviceBus,
+    inserviceFrom, inserviceTo, outservice, outserviceBus outserviceFrom, outserviceTo,
+    redundancy, redundancyBus, redundancyFrom, redundancyTo)

The function generates a set of PMUs, assigning PMUs randomly to either in-service or out-of-service states based on specified keywords. It is important to note that when we refer to PMU, we encompass both magnitude and angle measurements.

Keywords

Users may use either one main keyword or three fine-tuning keywords that specify distinct locations per function call:

  • inservice: Sets the number of in-service PMUs or allows fine-tuning:
    • inserviceBus: sets only PMUs loacted at the bus,
    • inserviceFrom: sets only PMUs loacted at the from-bus end,
    • inserviceTo: sets only PMUs loacted at the to-bus end.
  • outservice: Sets the number of out-of-service PMUs or allows fine-tuning:
    • outserviceBus: sets only PMUs loacted at the bus,
    • outserviceFrom: sets only PMUs loacted at the from-bus end,
    • outserviceTo: sets only PMUs loacted at the to-bus end.
  • redundancy: Determines in-service PMUs based on redundancy or allows fine-tuning:
    • redundancyBus: determines only PMUs loacted at the bus,
    • redundancyFrom: determines only PMUs loacted at the from-bus end,
    • redundancyTo: determines only PMUs loacted at the to-bus end.

Updates

The function updates the status fields within the PMU type.

Example

system = powerSystem("case14.h5")
+device = measurement()
+
+acModel!(system)
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+current!(system, analysis)
+
+addPmu!(system, device, analysis)
+statusPmu!(system, device; inserviceBus = 14)
source
JuliaGrid.@pmuMacro
@pmu(label, varianceMagnitudeBus, statusMagnitudeBus, varianceAngleBus, statusAngleBus,
+    varianceMagnitudeFrom, statusMagnitudeFrom, varianceAngleFrom, statusAngleFrom,
+    varianceMagnitudeTo, statusMagnitudeTo, varianceAngleTo, statusAngleTo, noise,
+    correlated, polar)

The macro generates a template for a PMU, which can be utilized to define a PMU using the addPmu! function.

Keywords

To establish the PMU template, users have the option to set default values for magnitude and angle variances, as well as statuses for each component of the phasor. This can be done for PMUs located at the buses using the varianceMagnitudeBus, varianceAngleBus, statusMagnitudeBus, and statusAngleBus keywords.

The same configuration can be applied at both the from-bus ends of the branches using the varianceMagnitudeFrom, varianceAngleFrom, statusMagnitudeFrom, and statusAngleFrom keywords.

For PMUs located at the to-bus ends of the branches, users can use the varianceMagnitudeTo, varianceAngleTo, statusMagnitudeTo, and statusAngleTo keywords.

Additionally, users can configure the pattern for labels using the label keyword, specify the type of noise, and indicate the correlated and polar system utilized for managing phasors during state estimation.

Units

By default, the units for variances are per-units (pu) and radians (rad). However, users have the option to switch to volts (V) and degrees (deg) as the units for PMUs located at the buses by using the @voltage macro, or they can switch to amperes (A) and degrees (deg) as the units for PMUs located at the branches by using the @current macro.

Examples

Adding PMUs using the default unit system:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 132e3)
+addBus!(system; label = "Bus 2", base = 132e3)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.2)
+
+@pmu(label = "PMU ?", varianceAngleBus = 1e-6, varianceMagnitudeFrom = 1e-4)
+addPmu!(system, device; bus = "Bus 1", magnitude = 1.1, angle = -0.1)
+addPmu!(system, device; from = "Branch 1", magnitude = 1.1, angle = -0.2)

Adding PMUs using a custom unit system:

@voltage(kV, deg, kV)
+@current(A, deg)
+system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 132.0)
+addBus!(system; label = "Bus 2", base = 132.0)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.2)
+
+@pmu(label = "PMU ?", varianceAngleBus = 5.73e-5, varianceMagnitudeFrom = 0.0481)
+addPmu!(system, device; bus = "Bus 1", magnitude = 145.2, angle = -5.73)
+addPmu!(system, device; from = "Branch 1", magnitude = 481.125, angle = -11.46)
source
diff --git a/v0.2.0/api/optimalPowerFlow/index.html b/v0.2.0/api/optimalPowerFlow/index.html new file mode 100644 index 000000000..fafd01298 --- /dev/null +++ b/v0.2.0/api/optimalPowerFlow/index.html @@ -0,0 +1,53 @@ + +Optimal Power Flow · JuliaGrid

Optimal Power Flow

For further information on this topic, please see the AC Optimal Power Flow or DC Optimal Power Flow sections of the Manual. Below, we have provided a list of functions that can be utilized for optimal power flow analysis.

To load optimal power flow API functionalities into the current scope, one can employ the following command:

using JuliaGrid, Ipopt, HiGHS

AC Optimal Power Flow
DC Optimal Power Flow

AC Optimal Power Flow

JuliaGrid.acOptimalPowerFlowFunction
acOptimalPowerFlow(system::PowerSystem, optimizer; bridge, name,
+    magnitude, angle, active, reactive)

The function sets up the optimization model for solving the AC optimal power flow problem.

Arguments

The function requires the PowerSystem composite type to establish the framework. Next, the optimizer argument is also required to create and solve the optimization problem. Specifically, JuliaGrid constructs the AC optimal power flow using the JuMP package and provides support for commonly employed solvers. For more detailed information, please consult the JuMP documentation.

Updates

If the AC model has not been created, the function automatically initiates an update within the ac field of the PowerSystem type.

Keywords

JuliaGrid offers the ability to manipulate the jump model based on the guidelines provided in the JuMP documentation. However, certain configurations may require different method calls, such as:

  • bridge: manage the bridging mechanism (default: false),
  • name: manage the creation of string names (default: true).

Additionally, users can modify variable names used for printing and writing through the keywords magnitude, angle, active, and reactive. For instance, users can choose magnitude = "V" and angle = "θ" to display equations in a more readable format.

Returns

The function returns an instance of the ACOptimalPowerFlow type, which includes the following fields:

  • voltage: The bus voltage magnitudes and angles.
  • power: The variable allocated to store the active and reactive powers.
  • current: The variable allocated to store the currents.
  • method: The JuMP model, references to the variables, constraints, and objective.

Example

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
source
JuliaGrid.solve!Method
solve!(system::PowerSystem, analysis::ACOptimalPowerFlow)

The function solves the AC optimal power flow model, computing the active and reactive power outputs of the generators, as well as the bus voltage magnitudes and angles.

Updates

The calculated active and reactive powers, as well as voltage magnitudes and angles, are stored in the power.generator and voltage fields of the ACOptimalPowerFlow type.

Example

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
+solve!(system, analysis)
source
JuliaGrid.startingPrimal!Method
startingPrimal!(system::PowerSystem, analysis::ACOptimalPowerFlow)

The function retrieves the active and reactive power outputs of the generators, as well as the voltage magnitudes and angles from the PowerSystem composite type. It then assigns these values to the ACOptimalPowerFlow type, allowing users to initialize starting primal values as needed.

Updates

This function only updates the voltage and generator fields of the ACOptimalPowerFlow type.

Example

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
+solve!(system, analysis)
+
+updateBus!(system, analysis; label = 14, reactive = 0.13, magnitude = 1.2, angle = -0.17)
+
+startingPrimal!(system, analysis)
+solve!(system, analysis)
source
JuliaGrid.startingDual!Method
startingDual!(system::PowerSystem, analysis::ACOptimalPowerFlow)

The function removes all values of the dual variables.

Updates

This function only updates the dual field of the ACOptimalPowerFlow type.

Example

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
+solve!(system, analysis)
+
+updateBus!(system, analysis; label = 14, reactive = 0.13, magnitude = 1.2, angle = -0.17)
+
+startingDual!(system, analysis)
+solve!(system, analysis)
source

DC Optimal Power Flow

JuliaGrid.dcOptimalPowerFlowFunction
dcOptimalPowerFlow(system::PowerSystem, optimizer; bridge, name, angle, active)

The function sets up the optimization model for solving the DC optimal power flow problem.

Arguments

The function requires the PowerSystem composite type to establish the framework. Next, the optimizer argument is also required to create and solve the optimization problem. Specifically, JuliaGrid constructs the DC optimal power flow using the JuMP package and provides support for commonly employed solvers. For more detailed information, please consult the JuMP documentation.

Updates

If the DC model has not been created, the function automatically initiates an update within the dc field of the PowerSystem type.

Keywords

JuliaGrid offers the ability to manipulate the jump model based on the guidelines provided in the JuMP documentation. However, certain configurations may require different method calls, such as:

  • bridge: manage the bridging mechanism (default: false),
  • name: manage the creation of string names (default: true).

Additionally, users can modify variable names used for printing and writing through the keywords angle and active. For instance, users can choose angle = "θ" to display equations in a more readable format.

Returns

The function returns an instance of the DCOptimalPowerFlow type, which includes the following fields:

  • voltage: The variable allocated to store the bus voltage angle,
  • power: The variable allocated to store the active powers,
  • method: The JuMP model, references to the variables, constraints, and objective.

Example

system = powerSystem("case14.h5")
+dcModel!(system)
+
+analysis = dcOptimalPowerFlow(system, HiGHS.Optimizer)
source
JuliaGrid.solve!Method
solve!(system::PowerSystem, analysis::DCOptimalPowerFlow)

The function solves the DC optimal power flow model, computing the active power outputs of the generators, as well as the bus voltage angles.

Updates

The calculated active powers, as well as voltage angles, are stored in the power.generator and voltage fields of the DCOptimalPowerFlow type.

Example

system = powerSystem("case14.h5")
+dcModel!(system)
+
+analysis = dcOptimalPowerFlow(system, HiGHS.Optimizer)
+solve!(system, analysis)
source
JuliaGrid.startingPrimal!Method
startingPrimal!(system::PowerSystem, analysis::DCOptimalPowerFlow)

The function retrieves the active power outputs of the generators and the bus voltage angles from the PowerSystem composite type. These values are then assigned to the DCOptimalPowerFlow type, enabling users to initialize starting primal values according to their requirements.

Updates

This function only updates the voltage and generator fields of the DCOptimalPowerFlow type.

Example

system = powerSystem("case14.h5")
+dcModel!(system)
+
+analysis = dcOptimalPowerFlow(system, HiGHS.Optimizer)
+solve!(system, analysis)
+
+updateBus!(system, analysis; label = 14, active = 0.1, angle = -0.17)
+
+startingPrimal!(system, analysis)
+solve!(system, analysis)
source
JuliaGrid.startingDual!Method
startingDual!(system::PowerSystem, analysis::DCOptimalPowerFlow)

The function removes all values of the dual variables.

Updates

This function only updates the dual field of the DCOptimalPowerFlow type.

Example

system = powerSystem("case14.h5")
+dcModel!(system)
+
+analysis = dcOptimalPowerFlow(system, HiGHS.Optimizer)
+solve!(system, analysis)
+
+updateBus!(system, analysis; label = 14, active = 0.1, angle = -0.17)
+
+startingDual!(system, analysis)
+solve!(system, analysis)
source
diff --git a/v0.2.0/api/powerFlow/index.html b/v0.2.0/api/powerFlow/index.html new file mode 100644 index 000000000..100fe8b0f --- /dev/null +++ b/v0.2.0/api/powerFlow/index.html @@ -0,0 +1,112 @@ + +Power Flow · JuliaGrid

Power Flow

For further information on this topic, please see the AC Power Flow or DC Power Flow sections of the Manual. Below, we have provided a list of functions that can be utilized for power flow analysis.

To load power flow API functionalities into the current scope, utilize the following command:

using JuliaGrid

AC Power Flow
DC Power Flow

AC Power Flow

JuliaGrid.newtonRaphsonFunction
newtonRaphson(system::PowerSystem, [factorization::Factorization = LU])

The function sets up the Newton-Raphson method to solve the AC power flow.

Arguments

The function requires the PowerSystem composite type to establish the framework. Next, the Factorization argument, while optional, determines the method used to solve the linear system of equations within each iteration. It can take one of the following values:

  • LU: utilizes LU factorization (default),
  • QR: utilizes QR factorization.

Updates

If the AC model has not been created, the function automatically initiates an update within the ac field of the PowerSystem type. It also performs a check on bus types and rectifies any mistakes present.

Returns

The function returns an instance of the ACPowerFlow type, which includes the following fields:

  • voltage: The bus voltage magnitudes and angles.
  • power: The variable allocated to store the active and reactive powers.
  • current: The variable allocated to store the currents.
  • method: The Jacobian matrix, its factorization, mismatches, increments, and indices.

Examples

Set up the Newton-Raphson method utilizing LU factorization:

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = newtonRaphson(system)

Set up the Newton-Raphson method utilizing QR factorization:

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = newtonRaphson(system, QR)
source
JuliaGrid.fastNewtonRaphsonBXFunction
fastNewtonRaphsonBX(system::PowerSystem, [factorization::Factorization = LU])

The function sets up the fast Newton-Raphson method of version BX to solve the AC power flow.

Arguments

The function requires the PowerSystem composite type to establish the framework. Next, the Factorization argument, while optional, determines the method used to solve the linear system of equations within each iteration. It can take one of the following values:

  • LU: utilizes LU factorization (default),
  • QR: utilizes QR factorization.

Updates

If the AC model has not been created, the function automatically initiates an update within the ac field of the PowerSystem type. It also performs a check on bus types and rectifies any mistakes present.

Returns

The function returns an instance of the ACPowerFlow type, which includes the following fields:

  • voltage: The bus voltage magnitudes and angles.
  • power: The variable allocated to store the active and reactive powers.
  • current: The variable allocated to store the currents.
  • method: The Jacobian matrices, their factorizations, mismatches, increments, and indices.

Examples

Set up the fast Newton-Raphson method utilizing LU factorization:

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = fastNewtonRaphsonBX(system)

Set up the fast Newton-Raphson method utilizing QR factorization:

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = fastNewtonRaphsonBX(system, QR)
source
JuliaGrid.fastNewtonRaphsonXBFunction
fastNewtonRaphsonXB(system::PowerSystem, [factorization::Factorization = LU])

The function sets up the fast Newton-Raphson method of version XB to solve the AC power flow.

Arguments

The function requires the PowerSystem composite type to establish the framework. Next, the Factorization argument, while optional, determines the method used to solve the linear system of equations within each iteration. It can take one of the following values:

  • LU: utilizes LU factorization (default),
  • QR: utilizes QR factorization.

Updates

If the AC model has not been created, the function automatically initiates an update within the ac field of the PowerSystem type. It also performs a check on bus types and rectifies any mistakes present.

Returns

The function returns an instance of the ACPowerFlow type, which includes the following fields:

  • voltage: The bus voltage magnitudes and angles.
  • power: The variable allocated to store the active and reactive powers.
  • current: The variable allocated to store the currents.
  • method: The Jacobian matrices, their factorizations, mismatches, increments, and indices.

Examples

Set up the fast Newton-Raphson method utilizing LU factorization:

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = fastNewtonRaphsonXB(system)

Set up the fast Newton-Raphson method utilizing QR factorization:

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = fastNewtonRaphsonXB(system, QR)
source
JuliaGrid.gaussSeidelFunction
gaussSeidel(system::PowerSystem)

The function sets up the Gauss-Seidel method to solve the AC power flow.

Arguments

The function requires the PowerSystem composite type to establish the framework.

Updates

If the AC model has not been created, the function automatically initiates an update within the ac field of the PowerSystem type. It also performs a check on bus types and rectifies any mistakes present.

Returns

The function returns an instance of the ACPowerFlow type, which includes the following fields:

  • voltage: The bus voltage magnitudes and angles.
  • power: The variable allocated to store the active and reactive powers.
  • current: The variable allocated to store the currents.
  • method: The bus complex voltages and indices.

Example

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = gaussSeidel(system)
source
JuliaGrid.mismatch!Method
mismatch!(system::PowerSystem, analysis::ACPowerFlow)

The function calculates both active and reactive power injection mismatches.

Updates

This function updates the mismatch variables in the Newton-Raphson and fast Newton-Raphson methods. It should be employed during the iteration loop before invoking the solve! function.

Returns

The function returns maximum absolute values of the active and reactive power injection mismatches, which can be utilized to terminate the iteration loop of the Newton-Raphson, fast Newton-Raphson, or Gauss-Seidel methods employed to solve the AC power flow problem.

Example

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = newtonRaphson(system)
+mismatch!(system, analysis)
source
JuliaGrid.solve!Method
solve!(system::PowerSystem, analysis::ACPowerFlow)

The function employs the Newton-Raphson, fast Newton-Raphson, or Gauss-Seidel method to solve the AC power flow model and calculate bus voltage magnitudes and angles.

After the mismatch! function is called, this function should be executed to perform a single iteration of the method.

Updates

The calculated voltages are stored in the voltage field of the ACPowerFlow type.

Example

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
source
JuliaGrid.startingVoltage!Function
startingVoltage!(system::PowerSystem, analysis::ACPowerFlow)

The function extracts bus voltage magnitudes and angles from the PowerSystem composite type and assigns them to the ACPowerFlow type, enabling users to initialize voltage values as required.

Updates

This function only updates the voltage field of the ACPowerFlow type.

Example

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+
+updateBus!(system, analysis; label = 14, reactive = 0.13, magnitude = 1.2, angle = -0.17)
+
+startingVoltage!(system, analysis)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
source
JuliaGrid.reactiveLimit!Function
reactiveLimit!(system::PowerSystem, analysis::ACPowerFlow)

The function verifies whether the generators in a power system exceed their reactive power limits. This is done by setting the reactive power of the generators to within the limits if they are violated after determining the bus voltage magnitudes and angles. If the limits are violated, the corresponding generator buses or the slack bus are converted to demand buses.

Updates

The function assigns values to the generator.output.active and bus.supply.active variables of the PowerSystem type.

Additionally, it examines the reactive powers of the generators and adjusts them to their maximum or minimum values if they exceed the specified threshold. This results in the modification of the variable generator.output.reactive of the PowerSystem type accordingly.

As a result of this adjustment, the bus.supply.reactive variable is also updated, and the bus types specified in bus.layout.type are modified. If the slack bus is converted, the bus.layout.slack field is correspondingly adjusted.

Returns

The function returns the variable to indicate which buses violate the limits, with -1 indicating a violation of the minimum limits and 1 indicating a violation of the maximum limits.

Example

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+
+violate = reactiveLimit!(system, analysis)
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
source
JuliaGrid.adjustAngle!Function
adjustAngle!(system::PowerSystem, analysis::ACPowerFlow; slack)

The function modifies the bus voltage angles based on a different slack bus than the one identified by the bus.layout.slack field.

For instance, if the reactive power of the generator exceeds the limit on the slack bus, the reactiveLimit! function will change that bus to the demand bus and designate the first generator bus in the sequence as the new slack bus. After obtaining the updated AC power flow solution based on the new slack bus, it is possible to adjust the voltage angles to align with the angle of the original slack bus.

Keyword

The slack keyword specifies the bus label for which we want to adjust voltage angles.

Updates

This function only updates the voltage.angle variable of the ACPowerFlow type.

Example

system = powerSystem("case14.h5")
+acModel!(system)
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+
+reactiveLimit!(system, analysis)
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+
+adjustAngle!(system, analysis; slack = 1)
source

DC Power Flow

JuliaGrid.dcPowerFlowFunction
dcPowerFlow(system::PowerSystem, [factorization::Factorization = LU])

The function sets up the framework to solve the DC power flow.

Arguments

The function requires the PowerSystem composite type to establish the framework. Next, the Factorization argument, while optional, determines the method used to solve the linear system of equations. It can take one of the following values:

  • LU: utilizes LU factorization (default),
  • LDLt: utilizes LDLt factorization,
  • QR: utilizes QR factorization.

Updates

If the DC model was not created, the function will automatically initiate an update of the dc field within the PowerSystem composite type. Additionally, if the slack bus lacks an in-service generator, JuliaGrid considers it a mistake and defines a new slack bus as the first generator bus with an in-service generator in the bus type list.

Returns

The function returns an instance of the DCPowerFlow type, which includes the following fields:

  • voltage: The variable allocated to store the bus voltage angles.
  • power: The variable allocated to store the active powers.
  • method: The factorized nodal matrix.

Examples

Set up the DC power flow utilizing LU factorization:

system = powerSystem("case14.h5")
+dcModel!(system)
+
+analysis = dcPowerFlow(system)

Set up the DC power flow utilizing QR factorization:

system = powerSystem("case14.h5")
+dcModel!(system)
+
+analysis = dcPowerFlow(system, QR)
source
JuliaGrid.solve!Method
solve!(system::PowerSystem, analysis::DCPowerFlow)

The function solves the DC power flow model and calculates bus voltage angles.

Updates

The calculated voltage angles are stored in the voltage field of the DCPowerFlow type.

Example

system = powerSystem("case14.h5")
+dcModel!(system)
+
+analysis = dcPowerFlow(system)
+solve!(system, analysis)
source
diff --git a/v0.2.0/api/powerSystemModel/index.html b/v0.2.0/api/powerSystemModel/index.html new file mode 100644 index 000000000..3b9ceba3b --- /dev/null +++ b/v0.2.0/api/powerSystemModel/index.html @@ -0,0 +1,97 @@ + +Power System Model · JuliaGrid

Power System Model

For further information on this topic, please see the Power System Model section of the Manual. Below, we have provided a list of functions that can be used to create, save, and manipulate power system structures, as well as to build AC and DC models of power systems.

To load power system model API functionalities into the current scope, utilize the following command:

using JuliaGrid

Power System
Bus
Branch
Generator

Power System

JuliaGrid.powerSystemFunction
powerSystem(file::String)

The function builds the composite type PowerSystem and populates bus, branch, generator and base fields. Once the composite type PowerSystem has been created, it is possible to add new buses, branches, or generators, or modify the parameters of existing ones.

Argument

It requires a string path to:

  • the HDF5 file with the .h5 extension,
  • the Matpower file with the .m extension.

Returns

The PowerSystem composite type with the following fields:

  • bus: Data related to buses.
  • branch: Data related to branches.
  • generator: Data related to generators.
  • base: Base power and base voltages.
  • model: Data associated with AC and DC analyses.

Units

JuliaGrid stores all data in per-units and radians format which are fixed, the exceptions are base values in volt-amperes and volts. The prefixes for these base values can be changed using the @base macro.

Example

system = powerSystem("case14.h5")
source
powerSystem()

Alternatively, the PowerSystem composite type can be initialized by calling the function without any arguments. This allows the model to be built from scratch and modified as needed. This generates an empty PowerSystem type, with only the base power initialized to 1.0e8 volt-amperes (VA).

Example

system = powerSystem()
source
JuliaGrid.savePowerSystemFunction
savePowerSystem(system::PowerSystem; path::String, reference::String, note::String)

The function saves the power system's data in the HDF5 file using the fields bus, branch, generator, and base from the PowerSystem composite type.

Keywords

The location and file name of the HDF5 file is specified by the mandatory keyword path in the format of "path/name.h5". Additional information can be provided by the optional keywords reference and note, which can be saved along with the power system data.

View HDF5 File

To view the saved HDF5 file, you can use the HDFView software.

Example

system = powerSystem("case14.m")
+savePowerSystem(system; path = "D:/case14.h5")
source
JuliaGrid.acModel!Function
acModel!(system::PowerSystem)

The function generates vectors and matrices based on the power system topology and parameters associated with AC analyses.

Updates

The function updates the model.ac field within the PowerSystem composite type, populating the following variables:

  • nodalMatrix: The nodal matrix.
  • nodalMatrixTranspose: The transpose of the nodal matrix.
  • nodalFromFrom: The Y-parameters of the two-port branches.
  • nodalFromTo: The Y-parameters of the two-port branches.
  • nodalToTo: The Y-parameters of the two-port branches.
  • nodalToFrom: The Y-parameters of the two-port branches.
  • admittance: The branch admittances.

Example

system = powerSystem("case14.h5")
+acModel!(system)
source
JuliaGrid.dcModel!Function
dcModel!(system::PowerSystem)

The function generates vectors and matrices based on the power system topology and parameters associated with DC analyses.

Updates

The function updates the model.dc field within the PowerSystem composite type, populating the following variables:

  • nodalMatrix: The nodal matrix.
  • admittance: The branch admittances.
  • shiftPower: The active powers related to phase-shifting transformers.

Example

system = powerSystem("case14.h5")
+dcModel!(system)
source

Bus

JuliaGrid.addBus!Function
addBus!(system::PowerSystem; label, type, active, reactive, conductance, susceptance,
+    magnitude, angle, minMagnitude, maxMagnitude, base, area, lossZone)

The function adds a new bus to the PowerSystem composite type.

Keywords

The bus is defined with the following keywords:

  • label: Unique label for the bus.
  • type: Bus type:
    • type = 1: demand bus (PQ),
    • type = 2: generator bus (PV),
    • type = 3: slack bus (Vθ).
  • active (pu or W): Active power demand at the bus.
  • reactive (pu or VAr): Reactive power demand at the bus.
  • conductance (pu or W): Active power demanded of the shunt element.
  • susceptance (pu or VAr): Reactive power injected/demanded of the shunt element.
  • magnitude (pu or V): Initial value of the bus voltage magnitude.
  • angle (rad or deg): Initial value of the bus voltage angle.
  • minMagnitude (pu or V): Minimum bus voltage magnitude value.
  • maxMagnitude (pu or V): Maximum bus voltage magnitude value.
  • base (V): Voltage base value.
  • area: Area number.
  • lossZone: Loss zone.

Updates

The function updates the bus field of the PowerSystem composite type.

Default Settings

The default settings for certain keywords are as follows: type = 1, magnitude = 1.0, minMagnitude = 0.9, maxMagnitude = 1.1, and base = 138e3. The rest of the keywords are initialized with a value of zero. However, the user can modify these default settings by utilizing the @bus macro.

Units

By default, the keyword parameters use per-units (pu) and radians (rad) as units, with the exception of the base keyword argument, which is in volts (V). However, users have the option to use other units instead of per-units and radians, or to specify prefixes for base voltage by using the @power and @voltage macros.

Examples

Adding a bus using the default unit system:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", active = 0.25, angle = 0.175, base = 132e3)

Adding a bus using a custom unit system:

@power(MW, MVAr, MVA)
+@voltage(pu, deg, kV)
+system = powerSystem()
+
+addBus!(system; label = "Bus 1", active = 25.0, angle = 10.026, base = 132.0)
source
JuliaGrid.updateBus!Function
updateBus!(system::PowerSystem, [analysis::Analysis]; kwargs...)

The function allows for the alteration of parameters for an existing bus.

Arguments

If the Analysis type is omitted, the function applies changes to the PowerSystem composite type only. However, when including the Analysis type, it updates both the PowerSystem and Analysis types. This streamlined process avoids the need to completely rebuild vectors and matrices when adjusting these parameters.

Keywords

To update a specific bus, provide the necessary kwargs input arguments in accordance with the keywords specified in the addBus! function, along with their respective values. Ensure that the label keyword matches the label of the existing bus you want to modify. If any keywords are omitted, their corresponding values will remain unchanged.

Updates

The function updates the bus field within the PowerSystem composite type, and in cases where parameters impact variables in the ac field, it automatically adjusts the field. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.

Units

Units for input parameters can be changed using the same method as described for the addBus! function.

Example

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.25, reactive = -0.04)
+updateBus!(system; label = "Bus 1", active = 0.15, susceptance = 0.15)
source
JuliaGrid.@busMacro
@bus(kwargs...)

The macro generates a template for a bus, which can be utilized to define a bus using the addBus! function.

Keywords

To define the bus template, the kwargs input arguments must be provided in accordance with the keywords specified within the addBus! function, along with their corresponding values.

Units

By default, the keyword parameters use per-units (pu) and radians (rad) as units, with the exception of the base keyword argument, which is in volts (V). However, users have the option to use other units instead of per-units and radians, or to specify prefixes for base voltage by using the @power and @voltage macros.

Examples

Adding a bus template using the default unit system:

system = powerSystem()
+
+@bus(type = 2, active = 0.25, angle = 0.1745)
+addBus!(system; label = "Bus 1", reactive = -0.04, base = 132e3)

Adding a bus template using a custom unit system:

@power(MW, MVAr, MVA)
+@voltage(pu, deg, kV)
+system = powerSystem()
+
+@bus(type = 2, active = 25.0, angle = 10.0, base = 132.0)
+addBus!(system; label = "Bus 1", reactive = -4.0)
source

Branch

JuliaGrid.addBranch!Function
addBranch!(system::PowerSystem, [analysis::Analysis]; label, from, to, status,
+    resistance, reactance, conductance, susceptance, turnsRatio, shiftAngle,
+    minDiffAngle, maxDiffAngle, minFromBus, maxFromBus, minToBus, maxToBus, type)

The function adds a new branch to the PowerSystem composite type. A branch can be added between already defined buses.

Arguments

If the Analysis type is omitted, the function applies changes to the PowerSystem composite type only. However, when including the Analysis type, it updates both the PowerSystem and Analysis types. This streamlined approach circumvents the necessity for completely reconstructing vectors and matrices when adding a new branch.

Keywords

The branch is defined with the following keywords:

  • label: Unique label for the branch.
  • from: From-bus label, corresponds to the bus label.
  • to: To-bus label, corresponds to the bus label.
  • status: Operating status of the branch:
    • status = 1: in-service,
    • status = 0: out-of-service.
  • resistance (pu or Ω): Series resistance.
  • reactance (pu or Ω): Series reactance.
  • conductance (pu or S): Total shunt conductance.
  • susceptance (pu or S): Total shunt susceptance.
  • turnsRatio: Transformer off-nominal turns ratio, equal to one for a line.
  • shiftAngle (rad or deg): Transformer phase shift angle, where positive value defines delay.
  • minDiffAngle (rad or deg): Minimum voltage angle difference value between from-bus and to-bus ends.
  • maxDiffAngle (rad or deg): Maximum voltage angle difference value between from-bus and to-bus ends.
  • minFromBus (pu, VA, W, or A): Minimum branch flow rating at the from-bus end.
  • maxFromBus (pu, VA, W, or A): Maximum branch flow rating at the from-bus end.
  • minToBus (pu, VA, W, or A): Minimum branch flow rating at the to-bus end.
  • maxToBus (pu, VA, W, or A): Maximum branch flow rating at the to-bus end.
  • type: Types of minFromBus, maxFromBus, minToBus, and maxToBus branch flow ratings:
    • type = 1: apparent power flow (pu or VA),
    • type = 2: active power flow (pu or W),
    • type = 3: current magnitude flow (pu or A).

Updates

The function updates the branch field within the PowerSystem composite type, and in cases where parameters impact variables in the ac and dc fields, it automatically adjusts the fields. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.

Default Settings

By default, certain keywords are assigned default values: status = 1, turnsRatio = 1.0, type = 1, minDiffAngle = -2pi, and maxDiffAngle = 2pi. The rest of the keywords are initialized with a value of zero. However, the user can modify these default settings by utilizing the @branch macro.

Units

The default units for the keyword parameters are per-units (pu) and radians (rad). However, the user can choose to use other units besides per-units and radians by utilizing macros such as @power, @voltage, @current, and @parameter.

Examples

Adding a branch using the default unit system:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.25, reactive = -0.04)
+addBus!(system; label = "Bus 2", type = 1, active = 0.15, reactive = 0.08)
+
+addBranch!(system; from = "Bus 1", to = "Bus 2", reactance = 0.12, shiftAngle = 0.1745)

Adding a branch using a custom unit system:

@voltage(pu, deg, kV)
+system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.25, reactive = -0.04)
+addBus!(system; label = "Bus 2", type = 1, active = 0.15, reactive = 0.08)
+
+addBranch!(system; from = "Bus 1", to = "Bus 2", reactance = 0.12, shiftAngle = 10)
source
JuliaGrid.updateBranch!Function
updateBranch!(system::PowerSystem, [analysis::Analysis]; kwargs...)

The function allows for the alteration of parameters for an existing branch.

Arguments

If the Analysis type is omitted, the function applies changes to the PowerSystem composite type only. However, when including the Analysis type, it updates both the PowerSystem and Analysis types. This streamlined process avoids the need to completely rebuild vectors and matrices when adjusting these parameter

Keywords

To update a specific branch, provide the necessary kwargs input arguments in accordance with the keywords specified in the addBranch! function, along with their respective values. Ensure that the label keyword matches the label of the existing branch you want to modify. If any keywords are omitted, their corresponding values will remain unchanged.

Updates

The function updates the branch field within the PowerSystem composite type, and in cases where parameters impact variables in the ac and dc fields, it automatically adjusts the fields. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.

Units

Units for input parameters can be changed using the same method as described for the addBranch! function.

Example

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.25, reactive = -0.04)
+addBus!(system; label = "Bus 2", type = 1, active = 0.15, reactive = 0.08)
+
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.12)
+updateBranch!(system; label = "Branch 1", reactance = 0.02, susceptance = 0.062)
source
JuliaGrid.@branchMacro
@branch(kwargs...)

The macro generates a template for a branch, which can be utilized to define a branch using the addBranch! function.

Keywords

To define the branch template, the kwargs input arguments must be provided in accordance with the keywords specified within the addBranch! function, along with their corresponding values.

Units

The default units for the keyword parameters are per-units and radians. However, the user can choose to use other units besides per-units and radians by utilizing macros such as @power, @voltage, and @parameter.

Examples

Adding a branch template using the default unit system:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.25, reactive = -0.04)
+addBus!(system; label = "Bus 2", type = 1, active = 0.15, reactive = 0.08)
+
+@branch(reactance = 0.12, shiftAngle = 0.1745)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2")

Adding a branch template using a custom unit system:

@voltage(pu, deg, kV)
+system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.25, reactive = -0.04)
+addBus!(system; label = "Bus 2", type = 1,  active = 0.15, reactive = 0.08)
+
+@branch(shiftAngle = 10)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.12)
source

Generator

JuliaGrid.addGenerator!Function
addGenerator!(system::PowerSystem, [analysis::Analysis]; label, bus, status,
+    active, reactive, magnitude, minActive, maxActive, minReactive, maxReactive,
+    lowActive, minLowReactive, maxLowReactive, upActive, minUpReactive, maxUpReactive,
+    loadFollowing, reactiveRamp, reserve10min, reserve30min, area)

The function adds a new generator to the PowerSystem composite type. The generator can be added to an already defined bus.

Arguments

If the Analysis type is omitted, the function applies changes to the PowerSystem composite type only. However, when including the Analysis type, it updates both the PowerSystem and Analysis types. This streamlined approach circumvents the necessity for completely reconstructing vectors and matrices when adding a new generator.

Keywords

The generator is defined with the following keywords:

  • label: Unique label for the generator.
  • bus: Label of the bus to which the generator is connected.
  • status: Operating status of the generator:
    • status = 1: in-service,
    • status = 0: out-of-service.
  • active (pu or W): Output active power.
  • reactive (pu or VAr): Output reactive power.
  • magnitude (pu or V): Voltage magnitude setpoint.
  • minActive (pu or W): Minimum allowed output active power value.
  • maxActive (pu or W): Maximum allowed output active power value.
  • minReactive (pu or VAr): Minimum allowed output reactive power value.
  • maxReactive (pu or VAr): Maximum allowed output reactive power value.
  • lowActive (pu or W): Lower allowed active power output value of PQ capability curve.
  • minLowReactive (pu or VAr): Minimum allowed reactive power output value at lowActive value.
  • maxLowReactive (pu or VAr): Maximum allowed reactive power output value at lowActive value.
  • upActive (pu or W): Upper allowed active power output value of PQ capability curve.
  • minUpReactive (pu or VAr): Minimum allowed reactive power output value at upActive value.
  • maxUpReactive (pu or VAr): Maximum allowed reactive power output value at upActive value.
  • loadFollowing (pu/min or W/min): Ramp rate for load following/AG.
  • reserve10min (pu or W): Ramp rate for 10-minute reserves.
  • reserve30min (pu or W): Ramp rate for 30-minute reserves.
  • reactiveRamp (pu/min or VAr/min): Ramp rate for reactive power, two seconds timescale.
  • area: Area participation factor.

Updates

The function updates the generator field within the PowerSystem composite type, and in cases where parameters impact variables in the bus field, it automatically adjusts the field. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.

Default Settings

By default, certain keywords are assigned default values: status = 1 and magnitude = 1.0 per-unit. The rest of the keywords are initialized with a value of zero. However, the user can modify these default settings by utilizing the @generator macro.

Units

By default, the input units are associated with per-units (pu) as shown. However, users have the option to use other units instead of per-units using the @power and @voltage macros.

Examples

Adding a generator using the default unit system:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 2, active = 0.2, base = 132e3)
+
+addGenerator!(system; bus = "Bus 1", active = 0.5, magnitude = 1.1)

Adding a generator using a custom unit system:

@power(MW, MVAr, MVA)
+@voltage(kV, deg, kV)
+system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 2, active = 20, base = 132)
+
+addGenerator!(system; bus = "Bus 1", active = 50, magnitude = 145.2)
source
JuliaGrid.updateGenerator!Function
updateGenerator!(system::PowerSystem, [analysis::Analysis]; kwargs...)

The function allows for the alteration of parameters for an existing generator.

Arguments

If the Analysis type is omitted, the function applies changes to the PowerSystem composite type only. However, when including the Analysis type, it updates both the PowerSystem and Analysis types. This streamlined process avoids the need to completely rebuild vectors and matrices when adjusting these parameter

Keywords

To update a specific generator, provide the necessary kwargs input arguments in accordance with the keywords specified in the addGenerator! function, along with their respective values. Ensure that the label keyword matches the label of the existing generator you want to modify. If any keywords are omitted, their corresponding values will remain unchanged.

Updates

The function updates the generator field within the PowerSystem composite type, and in cases where parameters impact variables in the bus field, it automatically adjusts the field. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.

Units

Units for input parameters can be changed using the same method as described for the addBranch! function.

Example

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 2, active = 0.2, base = 132e3)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 0.5)
+updateGenerator!(system; label = "Generator 1", active = 0.6, reactive = 0.2)
source
JuliaGrid.cost!Function
cost!(system::PowerSystem, [analysis::Analysis]; label, active, reactive,
+    piecewise, polynomial)

The function either adds a new cost or modifies an existing one for the active or reactive power generated by the corresponding generator within the PowerSystem composite type. It has the capability to append a cost to an already defined generator.

Arguments

If the Analysis type is omitted, the function applies changes to the PowerSystem composite type only. However, when including the Analysis type, it updates both the PowerSystem and Analysis types. This streamlined approach circumvents the necessity for completely reconstructing vectors and matrices when adding a new branch.

Keywords

The function accepts five keywords:

  • label: Corresponds to the already defined generator label.
  • active: Active power cost model:
    • active = 1: adding or updating cost, and piecewise linear is being used,
    • active = 2: adding or updating cost, and polynomial is being used.
  • reactive: Reactive power cost model:
    • reactive = 1: adding or updating cost, and piecewise linear is being used,
    • reactive = 2: adding or updating cost, and polynomial is being used.
  • piecewise: Cost model defined by input-output points given as Vector{Float64}:
    • first column (pu, W or VAr): active or reactive power output of the generator,
    • second column (€/hr): cost for the specified active or reactive power output.
  • polynomial: The n-th degree polynomial coefficients given as Vector{Float64}:
    • first element (€/puⁿ-hr, €/Wⁿhr or €/VArⁿ-hr): coefficient of the n-th degree term, ....,
    • penultimate element (€/pu-hr, €/W-hr or €/VAr-hr): coefficient of the first degree term,
    • last element (€/hr): constant coefficient.

Updates

The function updates the generator.cost field within the PowerSystem composite type. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.

Units

By default, the input units related with active powers are per-units (pu), but they can be modified using the macro @power.

Examples

Adding a cost using the default unit system:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", active = 0.25, reactive = -0.04, base = 132e3)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 0.5)
+cost!(system; label = "Generator 1", active = 2, polynomial = [1100.0; 500.0; 150.0])

Adding a cost using a custom unit system:

@power(MW, MVAr, MVA)
+system = powerSystem()
+
+addBus!(system; label = "Bus 1", active = 25, reactive = -4, base = 132e3)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 50, reactive = 10)
+cost!(system; label = "Generator 1", active = 2, polynomial = [0.11; 5.0; 150.0])
source
JuliaGrid.@generatorMacro
@generator(kwargs...)

The macro generates a template for a generator, which can be utilized to define a generator using the addGenerator! function.

Keywords

To define the generator template, the kwargs input arguments must be provided in accordance with the keywords specified within the addGenerator! function, along with their corresponding values.

Units

By default, the input units are associated with per-units (pu) as shown. However, users have the option to use other units instead of per-units using the @power and @voltage macros.

Examples

Adding a generator using the default unit system:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 2, active = 0.25, reactive = -0.04, base = 132e3)
+
+@generator(magnitude = 1.1)
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 0.5, reactive = 0.1)

Adding a generator using a custom unit system:

@power(MW, MVAr, MVA)
+@voltage(kV, deg, kV)
+system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 2, active = 25, reactive = -4, base = 132)
+
+@generator(magnitude = 145.2)
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 50, reactive = 10)
source
diff --git a/v0.2.0/api/setupPrint/index.html b/v0.2.0/api/setupPrint/index.html new file mode 100644 index 000000000..37f28e317 --- /dev/null +++ b/v0.2.0/api/setupPrint/index.html @@ -0,0 +1,284 @@ + +Setup and Print · JuliaGrid

Setup and Print

For further information on this topic, please see the Power System Model or Measurement Model sections of the Manual. Please note that when using macros, they modify variables within the current scope. Print functions can be used to print results to the REPL, or users can redirect the output to print results to a text file, for example.

To load power system model API functionalities into the current scope, utilize the following command:

using JuliaGrid

Base Units
Input Units
Label Types
Default Settings

Base Units

JuliaGrid.@baseMacro
@base(system::PowerSystem, power, voltage)

By default, the units for base power and base voltages are set to volt-ampere (VA) and volt (V), but you can modify the prefixes using the macro.

Prefixes must be specified according to the SI prefixes and should be included with the unit of power (VA) or unit of voltage (V). Keep in mind that the macro must be used after creating the composite type PowerSystem.

Example

system = powerSystem("case14.h5")
+@base(system, MVA, kV)
source

Input Units

JuliaGrid.@powerMacro
@power(active, reactive, apparent)

JuliaGrid stores all data related with powers in per-units, and these cannot be altered. However, the power units of the built-in functions used to add or modified power system elements can be modified using the macro.

Prefixes must be specified according to the SI prefixes and should be included with the unit of active power (W), reactive power (VAr), or apparent power (VA). Also, it is a possible to combine SI units with/without prefixes with per-units (pu).

Changing the unit of active power is reflected in the following quantities:

Changing the unit of reactive power unit is reflected in the following quantities:

Changing the unit of apparent power unit is reflected in the following quantities:

Example

@power(MW, kVAr, VA)
source
JuliaGrid.@voltageMacro
@voltage(magnitude, angle, base)

JuliaGrid stores all data related with voltages in per-units and radians, and these cannot be altered. However, the voltage magnitude and angle units of the built-in functions used to add or modified power system elements can be modified using the macro.

The prefixes must adhere to the SI prefixes and should be specified along with the unit of voltage, either magnitude (V) or base (V). Alternatively, the unit of voltage magnitude can be expressed in per-unit (pu). The unit of voltage angle should be in radians (rad) or degrees (deg).

Changing the unit of voltage magnitude is reflected in the following quantities:

Changing the unit of voltage angle is reflected in the following quantities:

Changing the unit prefix of voltage base is reflected in the following quantity:

Example

@voltage(pu, deg, kV)
source
JuliaGrid.@currentMacro
@current(magnitude, angle)

JuliaGrid stores all data related with currents in per-units and radians, and these cannot be altered. However, the current magnitude and angle units of the built-in functions used to add or modified measurement devices can be modified using the macro.

The prefixes must adhere to the SI prefixes and should be specified along with the unit of current magnitude (V). Alternatively, the unit of current magnitude can be expressed in per-unit (pu). The unit of current angle should be in radians (rad) or degrees (deg).

Changing the unit of current magnitude is reflected in the following quantities:

Changing the unit of current angle is reflected in the following quantities:

Example

@current(pu, deg)
source
JuliaGrid.@parameterMacro
@parameter(impedance, admittance)

JuliaGrid stores all data related with impedances and admittancies in per-units, and these cannot be altered. However, units of impedance and admittance of the built-in functions used to add or modified power system elements can be modified using the macro.

Prefixes must be specified according to the SI prefixes and should be included with the unit of impedance (Ω) or unit of admittance (S). The second option is to define the units in per-unit (pu).

In the case where impedance and admittance are being used in SI units (Ω and S) and these units are related to the transformer, the assignment must be based on the primary side of the transformer.

Changing the units of impedance is reflected in the following quantities in specific functions:

Changing the units of admittance is reflected in the following quantities:

Example

@parameter(Ω, pu)
source

Label Types

JuliaGrid.@labelsMacro
@labels(type)

JuliaGrid keeps all labels in ordered dictionaries as Strings. Users have the option to use Integers instead, which can be a more efficient way to store labels, particularly for large-scale systems.

Example

@labels(Integer)
source

Default Settings

JuliaGrid.@defaultMacro
@default(mode)

The macro is designed to reset various settings to their default values.

The mode argument can take on the following values:

  • unit: Resets all units to their default settings.
  • power: Sets active, reactive, and apparent power to per-units.
  • voltage: Sets voltage magnitude to per-unit and voltage angle to radian.
  • parameter: Sets impedance and admittance to per-units.
  • template: Resets bus, branch, generator, voltmeter, ammeter, wattmeter, varmeter, and pmu templates to their default settings.
  • bus: Resets the bus template to its default settings.
  • branch: Resets the branch template to its default settings.
  • generator: Resets the generator template to its default settings.
  • voltmeter: Resets the voltmeter template to its default settings.
  • ammeter: Resets the ammeter template to its default settings.
  • wattmeter: Resets the wattmeter template to its default settings.
  • varmeter: Resets the varmeter template to its default settings.
  • pmu: Resets the pmu template to its default settings.

Example

@default(unit)
source

Print Power System Data

JuliaGrid.printBusDataFunction
printBusData(system::PowerSystem, analysis::Analysis, [io::IO];
+    label, fmt, width, show, delimiter, title, header, footer, repeat, style)

The function prints voltages, powers, and currents related to buses. Optionally, an IO may be passed as the last argument to redirect the output.

Keywords

The following keywords control the printed data:

  • label: Prints only the data for the corresponding bus.
  • fmt: Specifies the preferred numeric formats or alignments for the columns.
  • width: Specifies the preferred widths for the columns.
  • show: Toggles the printing of the columns.
  • delimiter: Sets the column delimiter.
  • title: Toggles the printing of the table title.
  • header: Toggles the printing of the header.
  • footer: Toggles the printing of the footer.
  • repeat: Prints the header again after a specified number of lines have been printed.
  • style: Prints either a stylish table or a simple table suitable for easy export.
Julia 1.10

The function printBusData requires Julia 1.10 or later.

Example

system = powerSystem("case14.h5")
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+power!(system, analysis)
+
+# Print data for all buses
+fmt = Dict("Power Demand" => "%.2f", "Voltage Magnitude" => "%.2f", "Label" => "%s")
+show = Dict("Power Injection" => false, "Power Generation Reactive" => false)
+printBusData(system, analysis; fmt, show, repeat = 10)
+
+# Print data for specific buses
+delimiter = " "
+width = Dict("Voltage" => 9, "Power Injection Active" => 9)
+printBusData(system, analysis; label = 2, delimiter, width, title = true, header = true)
+printBusData(system, analysis; label = 10, delimiter, width)
+printBusData(system, analysis; label = 12, delimiter, width)
+printBusData(system, analysis; label = 14, delimiter, width, footer = true)
source
JuliaGrid.printBranchDataFunction
printBranchData(system::PowerSystem, analysis::Analysis, [io::IO];
+    label, fmt, width, show, delimiter, title, header, footer, repeat, style)

The function prints powers and currents related to branches. Optionally, an IO may be passed as the last argument to redirect the output.

Keywords

The following keywords control the printed data:

  • label: Prints only the data for the corresponding branch.
  • fmt: Specifies the preferred numeric formats or alignments for the columns.
  • width: Specifies the preferred widths for the columns.
  • show: Toggles the printing of the columns.
  • delimiter: Sets the column delimiter.
  • title: Toggles the printing of the table title.
  • header: Toggles the printing of the header.
  • footer: Toggles the printing of the footer.
  • repeat: Prints the header again after a specified number of lines have been printed.
  • style: Prints either a stylish table or a simple table suitable for easy export.
Julia 1.10

The function printBranchData requires Julia 1.10 or later.

Example

system = powerSystem("case14.h5")
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+power!(system, analysis)
+
+# Print data for all branches
+fmt = Dict("Shunt Power" => "%.2f", "Series Power Reactive" => "%.2f")
+show = Dict("From-Bus Power" => false, "To-Bus Power Reactive" => false)
+printBranchData(system, analysis; fmt, show, repeat = 11, title = false)
+
+# Print data for specific branches
+delimiter = " "
+width = Dict("From-Bus Power" => 9, "To-Bus Power Active" => 9)
+printBranchData(system, analysis; label = 2, delimiter, width, header = true)
+printBranchData(system, analysis; label = 10, delimiter, width)
+printBranchData(system, analysis; label = 12, delimiter, width)
+printBranchData(system, analysis; label = 14, delimiter, width, footer = true)
source
JuliaGrid.printGeneratorDataFunction
printGeneratorData(system::PowerSystem, analysis::Analysis, [io::IO];
+    label, fmt, width, show, delimiter, title, header, footer, repeat, style)

The function prints powers related to generators. Optionally, an IO may be passed as the last argument to redirect the output.

Keywords

The following keywords control the printed data:

  • label: Prints only the data for the corresponding generator.
  • fmt: Specifies the preferred numeric formats or alignments for the columns.
  • width: Specifies the preferred widths for the columns.
  • show: Toggles the printing of the columns.
  • delimiter: Sets the column delimiter.
  • title: Toggles the printing of the table title.
  • header: Toggles the printing of the header.
  • footer: Toggles the printing of the footer.
  • repeat: Prints the header again after a specified number of lines have been printed.
  • style: Prints either a stylish table or a simple table suitable for easy export.
Julia 1.10

The function printGeneratorData requires Julia 1.10 or later.

Example

system = powerSystem("case14.h5")
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+power!(system, analysis)
+
+# Print data for all generators
+fmt = Dict("Power Output Active" => "%.2f")
+show = Dict("Power Output Reactive" => false)
+printGeneratorData(system, analysis; fmt, show, title = false)
+
+# Print data for specific generators
+delimiter = " "
+width = Dict("Power Output Active" => 7)
+printGeneratorData(system, analysis; label = 1, delimiter, width, header = true)
+printGeneratorData(system, analysis; label = 4, delimiter, width)
+printGeneratorData(system, analysis; label = 5, delimiter, width, footer = true)
source

Print Power System Summary

JuliaGrid.printBusSummaryFunction
printBusSummary(system::PowerSystem, analysis::Analysis, [io::IO];
+    fmt, width, show, delimiter, title, header, footer, style)

The function prints a summary of the electrical quantities related to buses. Optionally, an IO may be passed as the last argument to redirect the output.

Keywords

The following keywords control the printed data:

  • fmt: Specifies the preferred numeric formats or alignments for the columns.
  • width: Specifies the preferred widths for the columns.
  • show: Toggles the printing of the columns.
  • delimiter: Sets the column delimiter.
  • title: Toggles the printing of the table title.
  • header: Toggles the printing of the header.
  • footer: Toggles the printing of the footer.
  • style: Prints either a stylish table or a simple table suitable for easy export.
Julia 1.10

The function printBusSummary requires Julia 1.10 or later.

Example

system = powerSystem("case14.h5")
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+power!(system, analysis)
+
+show = Dict("In-Use" => false)
+printBusSummary(system, analysis; show, delimiter = " ", title = false)
source
JuliaGrid.printBranchSummaryFunction
printBranchSummary(system::PowerSystem, analysis::Analysis, [io::IO];
+    fmt, width, show, delimiter, title, header, footer, style))

The function prints a summary of the electrical quantities related to branches. Optionally, an IO may be passed as the last argument to redirect the output.

Keywords

The following keywords control the printed data:

  • fmt: Specifies the preferred numeric formats or alignments for the columns.
  • width: Specifies the preferred widths for the columns.
  • show: Toggles the printing of the columns.
  • delimiter: Sets the column delimiter.
  • title: Toggles the printing of the table title.
  • header: Toggles the printing of the header.
  • footer: Toggles the printing of the footer.
  • style: Prints either a stylish table or a simple table suitable for easy export.
Julia 1.10

The function printBranchSummary requires Julia 1.10 or later.

Example

system = powerSystem("case14.h5")
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+power!(system, analysis)
+
+show = Dict("Total" => false)
+printBranchSummary(system, analysis; show, delimiter = " ", title = false)
source
JuliaGrid.printGeneratorSummaryFunction
printGeneratorSummary(system::PowerSystem, analysis::Analysis, [io::IO];
+    fmt, width, show, delimiter, title, header, footer, style)

The function prints a summary of the electrical quantities related to generators. Optionally, an IO may be passed as the last argument to redirect the output.

Keywords

The following keywords control the printed data:

  • fmt: Specifies the preferred numeric formats or alignments for the columns.
  • width: Specifies the preferred widths for the columns.
  • show: Toggles the printing of the columns.
  • delimiter: Sets the column delimiter.
  • title: Toggles the printing of the table title.
  • header: Toggles the printing of the header.
  • footer: Toggles the printing of the footer.
  • style: Prints either a stylish table or a simple table suitable for easy export.
Julia 1.10

The function printGeneratorSummary requires Julia 1.10 or later.

Example

system = powerSystem("case14.h5")
+
+analysis = newtonRaphson(system)
+for i = 1:10
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+power!(system, analysis)
+
+show = Dict("Minimum" => false)
+printGeneratorSummary(system, analysis; show, delimiter = " ", title = false)
source

JuliaGrid.printVoltmeterDataFunction
printVoltmeterData(system::PowerSystem, device::Measurement, [analysis::Analysis],
+    [io::IO]; label, fmt, width, show, delimiter, title, header, footer, repeat, style)

The function prints data related to voltmeters. Optionally, an IO may be passed as the last argument to redirect the output. Users can also omit the Analysis type to print only data related to the Measurement type.

Keywords

The following keywords control the printed data:

  • label: Prints only the data for the corresponding voltmeter.
  • fmt: Specifies the preferred numeric formats or alignments for the columns.
  • width: Specifies the preferred widths for the columns.
  • show: Toggles the printing of the columns.
  • delimiter: Sets the column delimiter.
  • title: Toggles the printing of the table title.
  • header: Toggles the printing of the header.
  • footer: Toggles the printing of the footer.
  • repeat: Prints the header again after a specified number of lines have been printed.
  • style: Prints either a stylish table or a simple table suitable for easy export.
Julia 1.10

The function printBusData requires Julia 1.10 or later.

Example

system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = gaussNewton(system, device)
+for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        break
+    end
+end
+power!(system, analysis)
+
+# Print data for all voltmeters
+fmt = Dict("Voltage Magnitude" => "%.2f", "Voltage Magnitude Estimate" => "%.6f")
+show = Dict("Voltage Magnitude Residual" => false)
+printVoltmeterData(system, device, analysis; fmt, show, delimiter = " ", repeat = 10)
+
+# Print data for specific voltmeters
+width = Dict("Voltage Magnitude Estimate" => 11)
+printVoltmeterData(system, device, analysis; label = 1, width, header = true)
+printVoltmeterData(system, device, analysis; label = 6, width)
+printVoltmeterData(system, device, analysis; label = 8, width, footer = true)
source
JuliaGrid.printAmmeterDataFunction
printAmmeterData(system::PowerSystem, device::Measurement, [analysis::Analysis],
+    [io::IO]; label, fmt, width, show, delimiter, title, header, footer, repeat, style)

The function prints data related to ammeters. Optionally, an IO may be passed as the last argument to redirect the output. Users can also omit the Analysis type to print only data related to the Measurement type.

Keywords

The following keywords control the printed data:

  • label: Prints only the data for the corresponding ammeter.
  • fmt: Specifies the preferred numeric formats or alignments for the columns.
  • width: Specifies the preferred widths for the columns.
  • show: Toggles the printing of the columns.
  • delimiter: Sets the column delimiter.
  • title: Toggles the printing of the table title.
  • header: Toggles the printing of the header.
  • footer: Toggles the printing of the footer.
  • repeat: Prints the header again after a specified number of lines have been printed.
  • style: Prints either a stylish table or a simple table suitable for easy export.
Julia 1.10

The function printBusData requires Julia 1.10 or later.

Example

system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = gaussNewton(system, device)
+for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        break
+    end
+end
+current!(system, analysis)
+
+# Print data for all ammeters
+fmt = Dict("Current Magnitude" => "%.2f", "Current Magnitude Estimate" => "%.6f")
+show = Dict("Current Magnitude Residual" => false)
+printAmmeterData(system, device, analysis; fmt, show, delimiter = " ", repeat = 10)
+
+# Print data for specific ammeters
+width = Dict("Current Magnitude" => 10)
+printAmmeterData(system, device, analysis; label = "From 1", width, header = true)
+printAmmeterData(system, device, analysis; label = "From 4", width)
+printAmmeterData(system, device, analysis; label = "From 6", width, footer = true)
source
JuliaGrid.printWattmeterDataFunction
printWattmeterData(system::PowerSystem, device::Measurement, [analysis::Analysis],
+    [io::IO]; label, fmt, width, show, delimiter, title, header, footer, repeat, style)

The function prints data related to wattmeters. Optionally, an IO may be passed as the last argument to redirect the output. Users can also omit the Analysis type to print only data related to the Measurement type.

Keywords

The following keywords control the printed data:

  • label: Prints only the data for the corresponding wattmeter.
  • fmt: Specifies the preferred numeric formats or alignments for the columns.
  • width: Specifies the preferred widths for the columns.
  • show: Toggles the printing of the columns.
  • delimiter: Sets the column delimiter.
  • title: Toggles the printing of the table title.
  • header: Toggles the printing of the header.
  • footer: Toggles the printing of the footer.
  • repeat: Prints the header again after a specified number of lines have been printed.
  • style: Prints either a stylish table or a simple table suitable for easy export.
Julia 1.10

The function printBusData requires Julia 1.10 or later.

Example

system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = gaussNewton(system, device)
+for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        break
+    end
+end
+power!(system, analysis)
+
+# Print data for all wattmeters
+fmt = Dict("Active Power" => "%.2f", "Active Power Estimate" => "%.6f")
+show = Dict("Active Power Status" => false)
+printWattmeterData(system, device, analysis; fmt, show, delimiter = " ", repeat = 14)
+
+# Print data for specific wattmeters
+width = Dict("Active Power Residual" => 11)
+printWattmeterData(system, device, analysis; label = 2, width, header = true)
+printWattmeterData(system, device, analysis; label = 5, width)
+printWattmeterData(system, device, analysis; label = 9, width, footer = true)
source
JuliaGrid.printVarmeterDataFunction
printVarmeterData(system::PowerSystem, device::Measurement, [analysis::Analysis],
+    [io::IO]; label, fmt, width, show, delimiter, title, header, footer, repeat, style)

The function prints data related to varmeters. Optionally, an IO may be passed as the last argument to redirect the output. Users can also omit the Analysis type to print only data related to the Measurement type.

Keywords

The following keywords control the printed data:

  • label: Prints only the data for the corresponding varmeter.
  • fmt: Specifies the preferred numeric formats or alignments for the columns.
  • width: Specifies the preferred widths for the columns.
  • show: Toggles the printing of the columns.
  • delimiter: Sets the column delimiter.
  • title: Toggles the printing of the table title.
  • header: Toggles the printing of the header.
  • footer: Toggles the printing of the footer.
  • repeat: Prints the header again after a specified number of lines have been printed.
  • style: Prints either a stylish table or a simple table suitable for easy export.
Julia 1.10

The function printBusData requires Julia 1.10 or later.

Example

system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = gaussNewton(system, device)
+for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        break
+    end
+end
+power!(system, analysis)
+
+# Print data for all wattmeters
+fmt = Dict("Reactive Power" => "%.2f", "Reactive Power Estimate" => "%.6f")
+show = Dict("Reactive Power Status" => false)
+printVarmeterData(system, device, analysis; fmt, show, delimiter = " ", repeat = 14)
+
+# Print data for specific wattmeters
+width = Dict("Reactive Power Residual" => 11)
+printVarmeterData(system, device, analysis; label = 2, width, header = true)
+printVarmeterData(system, device, analysis; label = 5, width)
+printVarmeterData(system, device, analysis; label = 9, width, footer = true)
source
JuliaGrid.printPmuDataFunction
printPmuData(system::PowerSystem, device::Measurement, [analysis::Analysis],
+    [io::IO]; label, fmt, width, show, delimiter, title, header, footer, repeat, style)

The function prints data related to PMUs. Optionally, an IO may be passed as the last argument to redirect the output. Users can also omit the Analysis type to print only data related to the Measurement type.

Keywords

The following keywords control the printed data:

  • label: Prints only the data for the corresponding PMU.
  • fmt: Specifies the preferred numeric formats or alignments for the columns.
  • width: Specifies the preferred widths for the columns.
  • show: Toggles the printing of the columns.
  • delimiter: Sets the column delimiter.
  • title: Toggles the printing of the table title.
  • header: Toggles the printing of the header.
  • footer: Toggles the printing of the footer.
  • repeat: Prints the header again after a specified number of lines have been printed.
  • style: Prints either a stylish table or a simple table suitable for easy export.
Julia 1.10

The function printPmuData requires Julia 1.10 or later.

Example

system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = gaussNewton(system, device)
+for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        break
+    end
+end
+current!(system, analysis)
+
+# Print data for all PMUs
+fmt = Dict("Current Magnitude" => "%.2f", "Current Magnitude Variance" => "%.5f")
+show = Dict("Current Angle" => false, "Current Magnitude Status" => false)
+printPmuData(system, device, analysis; fmt, show, delimiter = " ", repeat = 10)
+
+# Print data for specific PMUs
+width = Dict("Current Magnitude" => 10, "Current Angle Status" => 8)
+printPmuData(system, device, analysis; label = "From 1", width, header = true)
+printPmuData(system, device, analysis; label = "From 4", width)
+printPmuData(system, device, analysis; label = "From 6", width, footer = true)
source

Print Constraint Data

JuliaGrid.printBusConstraintFunction
printBusConstraint(system::PowerSystem, analysis::OptimalPowerFlow, [io::IO];
+    label, fmt, width, show, delimiter, title, header, footer, repeat, style)

The function prints constraint data related to buses. Optionally, an IO may be passed as the last argument to redirect the output.

Keywords

The following keywords control the printed data:

  • label: Prints only the data for the corresponding bus.
  • fmt: Specifies the preferred numeric formats or alignments for the columns.
  • width: Specifies the preferred widths for the columns.
  • show: Toggles the printing of the columns.
  • delimiter: Sets the column delimiter.
  • title: Toggles the printing of the table title.
  • header: Toggles the printing of the header.
  • footer: Toggles the printing of the footer.
  • repeat: Prints the header again after a specified number of lines have been printed.
  • style: Prints either a stylish table or a simple table suitable for easy export.
Julia 1.10

The function printBusConstraint requires Julia 1.10 or later.

Example

using Ipopt
+
+system = powerSystem("case14.h5")
+
+analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
+solve!(system, analysis)
+
+# Print data for all buses
+fmt = Dict("Active Power Balance" => "%.2e", "Reactive Power Balance Dual" => "%.4e")
+show = Dict("Voltage Magnitude" => false, "Reactive Power Balance Solution" => false)
+printBusConstraint(system, analysis; fmt, show, repeat = 10)
+
+# Print data for specific buses
+delimiter = " "
+width = Dict("Voltage Magnitude" => 8, "Active Power Balance Solution" => 12)
+printBusConstraint(system, analysis; label = 2, delimiter, width, header = true)
+printBusConstraint(system, analysis; label = 10, delimiter, width)
+printBusConstraint(system, analysis; label = 14, delimiter, width, footer = true)
source
JuliaGrid.printBranchConstraintFunction
printBranchConstraint(system::PowerSystem, analysis::OptimalPowerFlow, [io::IO];
+    label, fmt, width, show, delimiter, title, header, footer, repeat, style)

The function prints constraint data related to branches. Optionally, an IO may be passed as the last argument to redirect the output.

Keywords

The following keywords control the printed data:

  • label: Prints only the data for the corresponding branch.
  • fmt: Specifies the preferred numeric formats or alignments for the columns.
  • width: Specifies the preferred widths for the columns.
  • show: Toggles the printing of the columns.
  • delimiter: Sets the column delimiter.
  • title: Toggles the printing of the table title.
  • header: Toggles the printing of the header.
  • footer: Toggles the printing of the footer.
  • repeat: Prints the header again after a specified number of lines have been printed.
  • style: Prints either a stylish table or a simple table suitable for easy export.
Julia 1.10

The function printBranchConstraint requires Julia 1.10 or later.

Example

using Ipopt
+
+system = powerSystem("case14.h5")
+updateBranch!(system; label = 3, minDiffAngle = 0.05, maxDiffAngle = 1.5)
+updateBranch!(system; label = 4, minDiffAngle = 0.05, maxDiffAngle = 1.1)
+updateBranch!(system; label = 4, maxFromBus = 0.4, maxToBus = 0.5)
+updateBranch!(system; label = 9, minFromBus = 0.1, maxFromBus = 0.3)
+
+analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
+solve!(system, analysis)
+
+# Print data for all branches
+fmt = Dict("Voltage Angle Difference" => "%.2f")
+show = Dict("To-Bus Apparent Power Flow Dual" => false)
+printBranchConstraint(system, analysis; fmt, show, repeat = 2)
+
+# Print data for specific branches
+delimiter = " "
+width = Dict("From-Bus Apparent Power Flow" => 13, "Voltage Angle Difference Dual" => 12)
+printBranchConstraint(system, analysis; label = 3, delimiter, width, header = true)
+printBranchConstraint(system, analysis; label = 4, delimiter, width)
+printBranchConstraint(system, analysis; label = 9, delimiter, width, footer = true)
source
JuliaGrid.printGeneratorConstraintFunction
printGeneratorConstraint(system::PowerSystem, analysis::OptimalPowerFlow, [io::IO];
+    label, fmt, width, show, delimiter, title, header, footer, repeat, style)

The function prints constraint data related to generators. Optionally, an IO may be passed as the last argument to redirect the output.

Keywords

The following keywords control the printed data:

  • label: Prints only the data for the corresponding generator.
  • fmt: Specifies the preferred numeric formats or alignments for the columns.
  • width: Specifies the preferred widths for the columns.
  • show: Toggles the printing of the columns.
  • delimiter: Sets the column delimiter.
  • title: Toggles the printing of the table title.
  • header: Toggles the printing of the header.
  • footer: Toggles the printing of the footer.
  • repeat: Prints the header again after a specified number of lines have been printed.
  • style: Prints either a stylish table or a simple table suitable for easy export.
Julia 1.10

The function printGeneratorConstraint requires Julia 1.10 or later.

Example

using Ipopt
+
+system = powerSystem("case14.h5")
+
+analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
+solve!(system, analysis)
+
+# Print data for all generators
+fmt = Dict("Active Power Capability" => "%.2f")
+show = Dict("Reactive Power Capability" => false, "Active Power Capability Dual" => false)
+printGeneratorConstraint(system, analysis; fmt, show, repeat = 3)
+
+# Print data for specific generators
+delimiter = " "
+width = Dict("Active Power Capability" => 11, "Reactive Power Capability Dual" => 10)
+printGeneratorConstraint(system, analysis; label = 2, delimiter, width, header = true)
+printGeneratorConstraint(system, analysis; label = 3, delimiter, width)
+printGeneratorConstraint(system, analysis; label = 5, delimiter, width, footer = true)
source
diff --git a/v0.2.0/api/stateEstimation/index.html b/v0.2.0/api/stateEstimation/index.html new file mode 100644 index 000000000..d6c2bba1f --- /dev/null +++ b/v0.2.0/api/stateEstimation/index.html @@ -0,0 +1,121 @@ + +State Estimation · JuliaGrid

State Estimation

For further information on this topic, please see the AC State Estimation, PMU State Estimation or DC State Estimation sections of the Manual. Below, we have provided a list of functions that can be utilized for state estimation, observability analysis, or bad data processing.

To load state estimation API functionalities into the current scope, utilize the following command:

using JuliaGrid

Observability Analysis
AC State Estimation
PMU State Estimation
DC State Estimation
Bad Data Analysis

Observability Analysis

JuliaGrid.islandTopologicalFlowMethod
islandTopologicalFlow(system::PowerSystem, device::Measurement)

The function utilizes a topological approach to detect flow observable islands, resulting in the formation of disconnected and loop-free subgraphs. It is assumed that active and reactive power measurements are paired, indicating a standard observability analysis. In this analysis, islands formed by active power measurements correspond to those formed by reactive power measurements.

Arguments

To define flow observable islands, this function necessitates the composite types PowerSystem and Measurement.

Returns

The function returns an Island type, containing information about the islands:

  • island: List enumerating observable islands with indices of buses.
  • bus: Positions of buses in relation to each island.
  • tie: Tie data associated with buses and branches.

Example

system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+statusWattmeter!(system, device; inservice = 15)
+device.varmeter.reactive.status = copy(device.wattmeter.active.status)
+
+islands = islandTopologicalFlow(system, device)
source
JuliaGrid.islandTopologicalMethod
islandTopological(system::PowerSystem, meter::Measurement)

The function employs a topological method to identify maximal observable islands. Specifically, it employs active power measurements to pinpoint flow observable islands. Subsequently, these islands are merged based on the available injection measurements.

It is assumed that active and reactive power measurements are paired, indicating a standard observability analysis. In this analysis, islands formed by active power measurements correspond to those formed by reactive power measurements.

Arguments

To define flow observable islands, this function necessitates the composite types PowerSystem and Measurement.

Returns

The function returns an Island type, containing information about the islands:

  • island: List enumerating observable islands with indices of buses.
  • bus: Positions of buses in relation to each island.
  • tie: Tie data associated with buses and branches.

Example

system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+statusWattmeter!(system, device; inservice = 15)
+device.varmeter.reactive.status = copy(device.wattmeter.active.status)
+
+islands = islandTopological(system, device)
source
JuliaGrid.restorationGram!Method
restorationGram!(system::PowerSystem, device::Measurement, pseudo::Measurement,
+    islands::Island; threshold)

Upon identifying the islands, the function incorporates measurements from the available pseudo-measurements in the pseudo variable into the device variable to reinstate observability. This method relies on reduced coefficient matrices and the Gram matrix.

It is important to note that the device labels in the device and pseudo variables must be different to enable the function to successfully incorporate measurements from pseudo into the device set of measurements.

Keyword

The keyword threshold defines the zero pivot threshold value, with a default value of 1e-5. More precisely, all computed pivots less than this value will be treated as zero pivots.

Updates

The function updates the device variable of the Measurement composite type.

Example

system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+pseudo = measurement("pseudomeasurement14.h5")
+
+statusWattmeter!(system, device; inservice = 10)
+islands = islandTopological(system, device)
+
+restorationGram!(system, device, pseudo, islands)
source

AC State Estimation

JuliaGrid.gaussNewtonFunction
gaussNewton(system::PowerSystem, device::Measurement, [method = LU])

The function sets up the Gauss-Newton method to solve the nonlinear or AC state estimation model, where the vector of state variables is given in polar coordinates. The Gauss-Newton method throughout iterations provided WLS estimator.

Arguments

This function requires the PowerSystem and Measurement composite types to establish the nonlinear WLS state estimation framework.

Moreover, the presence of the method parameter is not mandatory. To address the WLS state estimation method, users can opt to utilize factorization techniques to decompose the gain matrix, such as LU, QR, or LDLt especially when the gain matrix is symmetric. Opting for the Orthogonal method is advisable for a more robust solution in scenarios involving ill-conditioned data, particularly when substantial variations in variances are present.

If the user does not provide the method, the default method for solving the estimation model will be LU factorization.

Updates

If the AC model has not been created, the function will automatically trigger an update of the ac field within the PowerSystem composite type.

Returns

The function returns an instance of the ACStateEstimation type, which includes the following fields:

  • voltage: The variable allocated to store the bus voltage magnitudes and angles.
  • power: The variable allocated to store the active and reactive powers.
  • method: The system model vectors and matrices.

Examples

Set up the AC state estimation model to be solved using the default LU factorization:

system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = gaussNewton(system, device)

Set up the AC state estimation model to be solved using the orthogonal method:

system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = gaussNewton(system, device, Orthogonal)
source
JuliaGrid.acLavStateEstimationFunction
acLavStateEstimation(system::PowerSystem, device::Measurement, optimizer)

The function sets up the LAV method to solve the nonlinear or AC state estimation model, where the vector of state variables is given in polar coordinates.

Arguments

This function requires the PowerSystem and Measurement composite types to establish the LAV state estimation model. The LAV method offers increased robustness compared to WLS, ensuring unbiasedness even in the presence of various measurement errors and outliers.

Users can employ the LAV method to find an estimator by choosing one of the available optimization solvers. Typically, Ipopt.Optimizer suffices for most scenarios.

Updates

If the AC model has not been created, the function will automatically trigger an update of the ac field within the PowerSystem composite type.

Returns

The function returns an instance of the ACStateEstimation type, which includes the following fields:

  • voltage: The variable allocated to store the bus voltage magnitudes and angles.
  • power: The variable allocated to store the active and reactive powers.
  • method: The optimization model.

Example

using Ipopt
+
+system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = acLavStateEstimation(system, device, Ipopt.Optimizer)
source
JuliaGrid.solve!Method
solve!(system::PowerSystem, analysis::ACStateEstimation)

By computing the bus voltage magnitudes and angles, the function solves the AC state estimation model.

Updates

The resulting bus voltage magnitudes and angles are stored in the voltage field of the ACStateEstimation type.

Examples

Solving the AC state estimation model and obtaining the WLS estimator:

system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = gaussNewton(system, device)
+for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        break
+    end
+end

Solving the AC state estimation model and obtaining the LAV estimator:

using Ipopt
+
+system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = acLavStateEstimation(system, device, Ipopt.Optimizer)
+solve!(system, analysis)
source

PMU State Estimation

JuliaGrid.pmuPlacementFunction
pmuPlacement(system::PowerSystem, optimizer; bridge)

The function determines the optimal placement of PMUs through integer linear programming. Specifically, it identifies the minimum set of PMU locations required for effective power system state estimation, ensuring observability with the least number of PMUs.

The function accepts a PowerSystem composite type as input to establish the framework for finding the optimal PMU placement. If the ac field within the PowerSystem composite type is not yet created, the function automatically initiates an update process.

Additionally, the optimizer argument is a crucial component for formulating and solving the optimization problem. Typically, using the GLPK or HiGHS solver is sufficient. For more detailed information, please refer to the JuMP documenatation.

Keyword

The bridge keyword enables users to manage the bridging mechanism within the JuMP package.

Returns

The function returns an instance of the PlacementPMU type, containing variables such as:

  • bus: Bus labels with indices marking the positions of PMUs at buses.
  • from: Branch labels with indices marking the positions of PMUs at from-bus ends.
  • to: Branch labels with indices marking the positions of PMUs at to-bus ends.

Note that if the conventional understanding of a PMU involves a device measuring the bus voltage phasor and all branch current phasors incident to the bus, the result is saved only in the bus variable. However, if we consider that a PMU measures individual phasors, each described with magnitude and angle, then measurements are needed at each bus in the bus variable, and each branch with positions given according to from and to variables.

Example

using GLPK, Ipopt
+
+system = powerSystem("case14.h5")
+device = measurement()
+
+analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
+solve!(system, analysis)
+current!(system, analysis)
+
+placement = pmuPlacement(system, GLPK.Optimizer)
+
+@pmu(label = "PMU ?: !")
+for (bus, i) in placement.bus
+    Vi, θi = analysis.voltage.magnitude[i], analysis.voltage.angle[i]
+    addPmu!(system, device; bus = bus, magnitude = Vi, angle = θi)
+end
+for branch in keys(placement.from)
+    Iij, ψij = fromCurrent(system, analysis; label = branch)
+    addPmu!(system, device; from = branch, magnitude = Iij, angle = ψij)
+end
+for branch in keys(placement.to)
+    Iji, ψji = toCurrent(system, analysis; label = branch)
+    addPmu!(system, device; to = branch, magnitude = Iji, angle = ψji)
+end
source
JuliaGrid.pmuStateEstimationFunction
pmuStateEstimation(system::PowerSystem, device::Measurement, [method = LU])

The function establishes the linear WLS model for state estimation with PMUs only. In this model, the vector of state variables contains bus voltages, given in rectangular coordinates.

Arguments

This function requires the PowerSystem and Measurement composite types to establish the WLS state estimation model.

Moreover, the presence of the method parameter is not mandatory. To address the WLS state estimation method, users can opt to utilize factorization techniques to decompose the gain matrix, such as LU, QR, or LDLt especially when the gain matrix is symmetric. Opting for the Orthogonal method is advisable for a more robust solution in scenarios involving ill-conditioned data, particularly when substantial variations in variances are present.

If the user does not provide the method, the default method for solving the estimation model will be LU factorization.

Updates

If the AC model has not been created, the function will automatically trigger an update of the ac field within the PowerSystem composite type.

Returns

The function returns an instance of the PMUStateEstimation abstract type, which includes the following fields:

  • voltage: The variable allocated to store the bus voltage magnitudes and angles.
  • power: The variable allocated to store the active and reactive powers.
  • method: The system model vectors and matrices.

Examples

Set up the PMU state estimation model to be solved using the default LU factorization:

system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = pmuStateEstimation(system, device)

Set up the PMU state estimation model to be solved using the orthogonal method:

system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = pmuStateEstimation(system, device, Orthogonal)
source
JuliaGrid.pmuLavStateEstimationFunction
pmuLavStateEstimation(system::PowerSystem, device::Measurement, optimizer)

The function establishes the LAV model for state estimation with PMUs only. In this model, the vector of state variables contains bus voltages, given in rectangular coordinates.

Arguments

This function requires the PowerSystem and Measurement composite types to establish the LAV state estimation model. The LAV method offers increased robustness compared to WLS, ensuring unbiasedness even in the presence of various measurement errors and outliers.

Users can employ the LAV method to find an estimator by choosing one of the available optimization solvers. Typically, Ipopt.Optimizer suffices for most scenarios.

Updates

If the AC model has not been created, the function will automatically trigger an update of the ac field within the PowerSystem composite type.

Returns

The function returns an instance of the PMUStateEstimation abstract type, which includes the following fields:

  • voltage: The variable allocated to store the bus voltage magnitudes and angles.
  • power: The variable allocated to store the active and reactive powers.
  • method: The optimization model.

Example

using Ipopt
+
+system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = pmuLavStateEstimation(system, device, Ipopt.Optimizer)
source
JuliaGrid.solve!Method
solve!(system::PowerSystem, analysis::PMUStateEstimation)

By computing the bus voltage magnitudes and angles, the function solves the PMU state estimation model.

Updates

The resulting bus voltage magnitudes and angles are stored in the voltage field of the PMUStateEstimation type.

Examples

Solving the PMU state estimation model and obtaining the WLS estimator:

system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = pmuStateEstimation(system, device)
+solve!(system, analysis)

Solving the PMU state estimation model and obtaining the LAV estimator:

using Ipopt
+
+system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = pmuLavStateEstimation(system, device, Ipopt.Optimizer)
+solve!(system, analysis)
source

DC State Estimation

JuliaGrid.dcStateEstimationFunction
dcStateEstimation(system::PowerSystem, device::Measurement, [method = LU])

The function establishes the WLS model for DC state estimation, where the vector of state variables contains only bus voltage angles.

Arguments

This function requires the PowerSystem and Measurement composite types to establish the WLS state estimation model.

Moreover, the presence of the method parameter is not mandatory. To address the WLS state estimation method, users can opt to utilize factorization techniques to decompose the gain matrix, such as LU, QR, or LDLt especially when the gain matrix is symmetric. Opting for the Orthogonal method is advisable for a more robust solution in scenarios involving ill-conditioned data, particularly when substantial variations in variances are present.

If the user does not provide the method, the default method for solving the estimation model will be LU factorization.

Updates

If the DC model was not created, the function will automatically initiate an update of the dc field within the PowerSystem composite type. Additionally, if the slack bus lacks an in-service generator, JuliaGrid considers it a mistake and defines a new slack bus as the first generator bus with an in-service generator in the bus type list.

Returns

The function returns an instance of the DCStateEstimation type, which includes the following fields:

  • voltage: The variable allocated to store the bus voltage angles.
  • power: The variable allocated to store the active powers.
  • method: The system model vectors and matrices.

Examples

Set up the DC state estimation model to be solved using the default LU factorization:

system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = dcStateEstimation(system, device)

Set up the DC state estimation model to be solved using the orthogonal method:

system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = dcStateEstimation(system, device, Orthogonal)
source
JuliaGrid.dcLavStateEstimationFunction
dcLavStateEstimation(system::PowerSystem, device::Measurement, optimizer)

The function establishes the LAV model for DC state estimation, where the vector of state variables contains only bus voltage angles.

Arguments

This function requires the PowerSystem and Measurement composite types to establish the LAV state estimation model. The LAV method offers increased robustness compared to WLS, ensuring unbiasedness even in the presence of various measurement errors and outliers.

Users can employ the LAV method to find an estimator by choosing one of the available optimization solvers. Typically, Ipopt.Optimizer suffices for most scenarios.

Updates

If the DC model was not created, the function will automatically initiate an update of the dc field within the PowerSystem composite type. Additionally, if the slack bus lacks an in-service generator, JuliaGrid considers it a mistake and defines a new slack bus as the first generator bus with an in-service generator in the bus type list.

Returns

The function returns an instance of the DCStateEstimation abstract type, which includes the following fields:

  • voltage: The variable allocated to store the bus voltage angles.
  • power: The variable allocated to store the active powers.
  • method: The optimization model.

Example

using Ipopt
+
+system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = dcLavStateEstimation(system, device, Ipopt.Optimizer)
source
JuliaGrid.solve!Method
solve!(system::PowerSystem, analysis::DCStateEstimation)

By computing the bus voltage angles, the function solves the DC state estimation model.

Updates

The resulting bus voltage angles are stored in the voltage field of the DCStateEstimation type.

Examples

Solving the DC state estimation model and obtaining the WLS estimator:

system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = dcStateEstimation(system, device)
+solve!(system, analysis)

Solving the DC state estimation model and obtaining the LAV estimator:

using Ipopt
+
+system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = dcLavStateEstimation(system, device, Ipopt.Optimizer)
+solve!(system, analysis)
source

Bad Data Analysis

JuliaGrid.residualTest!Function
residualTest!(system::PowerSystem, device::Measurement, analysis::StateEstimation;
+    threshold)

The function conducts bad data detection and identification using the largest normalized residual test, subsequently removing measurement outliers from the measurement set. It can be executed after obtaining WLS estimator.

Arguments

This function requires the types PowerSystem, Measurement, and StateEstimation. The abstract type StateEstimation can have the following subtypes:

  • ACStateEstimation: Conducts bad data analysis within AC state estimation.
  • PMUStateEstimation: Conducts bad data analysis within PMU state estimation.
  • DCStateEstimation: Conducts bad data analysis within DC state estimation.

Keyword

The keyword threshold establishes the identification threshold. If the largest normalized residual surpasses this threshold, the measurement is flagged as bad data. The default threshold value is set to threshold = 3.0.

Updates

If bad data is detected, the function flags the corresponding measurement within the Measurement type as out-of-service.

Moreover, for DCStateEstimation and PMUStateEstimation types, the function removes the corresponding measurement from the coefficient matrix and mean vector. This facilitates direct progress to the function that solves the state estimation problem.

Returns

The function returns an instance of the BadData type, which includes:

  • detect: Returns true after the function's execution if bad data is detected.
  • maxNormalizedResidual: Denotes the value of the largest normalized residual.
  • label: Signifies the label of the bad data.
  • index: Represents the index of the bad data.

Example

system = powerSystem("case14.h5")
+device = measurement("measurement14.h5")
+
+analysis = dcStateEstimation(system, device)
+solve!(system, analysis)
+
+outlier = residualTest!(system, device, analysis; threshold = 4.0)
+solve!(system, analysis)
source
diff --git a/v0.2.0/assets/citations.css b/v0.2.0/assets/citations.css new file mode 100644 index 000000000..687d0a5d2 --- /dev/null +++ b/v0.2.0/assets/citations.css @@ -0,0 +1,17 @@ +.citation dl { + display: grid; + grid-template-columns: max-content auto; } +.citation dt { + grid-column-start: 1; } +.citation dd { + grid-column-start: 2; + margin-bottom: 0.75em; } +.citation ul { + padding: 0 0 2.25em 0; + margin: 0; + list-style: none !important;} +.citation ul li { + text-indent: -2.25em; + margin: 0.33em 0.5em 0.5em 2.25em;} +.citation ol li { + padding-left:0.75em;} \ No newline at end of file diff --git a/v0.2.0/assets/cost_function.svg b/v0.2.0/assets/cost_function.svg new file mode 100644 index 000000000..7a8bdb84f --- /dev/null +++ b/v0.2.0/assets/cost_function.svg @@ -0,0 +1,452 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v0.2.0/assets/cost_function_dc.svg b/v0.2.0/assets/cost_function_dc.svg new file mode 100644 index 000000000..4347ebaef --- /dev/null +++ b/v0.2.0/assets/cost_function_dc.svg @@ -0,0 +1,329 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v0.2.0/assets/cost_function_piecewise.svg b/v0.2.0/assets/cost_function_piecewise.svg new file mode 100644 index 000000000..7743aad21 --- /dev/null +++ b/v0.2.0/assets/cost_function_piecewise.svg @@ -0,0 +1,645 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v0.2.0/assets/cost_function_piecewise_dc.svg b/v0.2.0/assets/cost_function_piecewise_dc.svg new file mode 100644 index 000000000..5d51c6ff6 --- /dev/null +++ b/v0.2.0/assets/cost_function_piecewise_dc.svg @@ -0,0 +1,429 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v0.2.0/assets/dc_model.svg b/v0.2.0/assets/dc_model.svg new file mode 100644 index 000000000..54fc48a60 --- /dev/null +++ b/v0.2.0/assets/dc_model.svg @@ -0,0 +1,201 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v0.2.0/assets/documenter.js b/v0.2.0/assets/documenter.js new file mode 100644 index 000000000..82252a11d --- /dev/null +++ b/v0.2.0/assets/documenter.js @@ -0,0 +1,1064 @@ +// Generated by Documenter.jl +requirejs.config({ + paths: { + 'highlight-julia': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/languages/julia.min', + 'headroom': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.12.0/headroom.min', + 'jqueryui': 'https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min', + 'katex-auto-render': 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.8/contrib/auto-render.min', + 'jquery': 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min', + 'headroom-jquery': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.12.0/jQuery.headroom.min', + 'katex': 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.8/katex.min', + 'highlight': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min', + 'highlight-julia-repl': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/languages/julia-repl.min', + }, + shim: { + "highlight-julia": { + "deps": [ + "highlight" + ] + }, + "katex-auto-render": { + "deps": [ + "katex" + ] + }, + "headroom-jquery": { + "deps": [ + "jquery", + "headroom" + ] + }, + "highlight-julia-repl": { + "deps": [ + "highlight" + ] + } +} +}); +//////////////////////////////////////////////////////////////////////////////// +require(['jquery', 'katex', 'katex-auto-render'], function($, katex, renderMathInElement) { +$(document).ready(function() { + renderMathInElement( + document.body, + { + "delimiters": [ + { + "left": "$", + "right": "$", + "display": false + }, + { + "left": "$$", + "right": "$$", + "display": true + }, + { + "left": "\\[", + "right": "\\]", + "display": true + } + ] +} + + ); +}) + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery', 'highlight', 'highlight-julia', 'highlight-julia-repl'], function($) { +$(document).ready(function() { + hljs.highlightAll(); +}) + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +let timer = 0; +var isExpanded = true; + +$(document).on( + "click", + ".docstring .docstring-article-toggle-button", + function () { + let articleToggleTitle = "Expand docstring"; + const parent = $(this).parent(); + + debounce(() => { + if (parent.siblings("section").is(":visible")) { + parent + .find("a.docstring-article-toggle-button") + .removeClass("fa-chevron-down") + .addClass("fa-chevron-right"); + } else { + parent + .find("a.docstring-article-toggle-button") + .removeClass("fa-chevron-right") + .addClass("fa-chevron-down"); + + articleToggleTitle = "Collapse docstring"; + } + + parent + .children(".docstring-article-toggle-button") + .prop("title", articleToggleTitle); + parent.siblings("section").slideToggle(); + }); + } +); + +$(document).on("click", ".docs-article-toggle-button", function (event) { + let articleToggleTitle = "Expand docstring"; + let navArticleToggleTitle = "Expand all docstrings"; + let animationSpeed = event.noToggleAnimation ? 0 : 400; + + debounce(() => { + if (isExpanded) { + $(this).removeClass("fa-chevron-up").addClass("fa-chevron-down"); + $("a.docstring-article-toggle-button") + .removeClass("fa-chevron-down") + .addClass("fa-chevron-right"); + + isExpanded = false; + + $(".docstring section").slideUp(animationSpeed); + } else { + $(this).removeClass("fa-chevron-down").addClass("fa-chevron-up"); + $("a.docstring-article-toggle-button") + .removeClass("fa-chevron-right") + .addClass("fa-chevron-down"); + + isExpanded = true; + articleToggleTitle = "Collapse docstring"; + navArticleToggleTitle = "Collapse all docstrings"; + + $(".docstring section").slideDown(animationSpeed); + } + + $(this).prop("title", navArticleToggleTitle); + $(".docstring-article-toggle-button").prop("title", articleToggleTitle); + }); +}); + +function debounce(callback, timeout = 300) { + if (Date.now() - timer > timeout) { + callback(); + } + + clearTimeout(timer); + + timer = Date.now(); +} + +}) +//////////////////////////////////////////////////////////////////////////////// +require([], function() { +function addCopyButtonCallbacks() { + for (const el of document.getElementsByTagName("pre")) { + const button = document.createElement("button"); + button.classList.add("copy-button", "fa-solid", "fa-copy"); + button.setAttribute("aria-label", "Copy this code block"); + button.setAttribute("title", "Copy"); + + el.appendChild(button); + + const success = function () { + button.classList.add("success", "fa-check"); + button.classList.remove("fa-copy"); + }; + + const failure = function () { + button.classList.add("error", "fa-xmark"); + button.classList.remove("fa-copy"); + }; + + button.addEventListener("click", function () { + copyToClipboard(el.innerText).then(success, failure); + + setTimeout(function () { + button.classList.add("fa-copy"); + button.classList.remove("success", "fa-check", "fa-xmark"); + }, 5000); + }); + } +} + +function copyToClipboard(text) { + // clipboard API is only available in secure contexts + if (window.navigator && window.navigator.clipboard) { + return window.navigator.clipboard.writeText(text); + } else { + return new Promise(function (resolve, reject) { + try { + const el = document.createElement("textarea"); + el.textContent = text; + el.style.position = "fixed"; + el.style.opacity = 0; + document.body.appendChild(el); + el.select(); + document.execCommand("copy"); + + resolve(); + } catch (err) { + reject(err); + } finally { + document.body.removeChild(el); + } + }); + } +} + +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", addCopyButtonCallbacks); +} else { + addCopyButtonCallbacks(); +} + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery', 'headroom', 'headroom-jquery'], function($, Headroom) { + +// Manages the top navigation bar (hides it when the user starts scrolling down on the +// mobile). +window.Headroom = Headroom; // work around buggy module loading? +$(document).ready(function () { + $("#documenter .docs-navbar").headroom({ + tolerance: { up: 10, down: 10 }, + }); +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +$(document).ready(function () { + let meta = $("div[data-docstringscollapsed]").data(); + + if (meta?.docstringscollapsed) { + $("#documenter-article-toggle-button").trigger({ + type: "click", + noToggleAnimation: true, + }); + } +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +/* +To get an in-depth about the thought process you can refer: https://hetarth02.hashnode.dev/series/gsoc + +PSEUDOCODE: + +Searching happens automatically as the user types or adjusts the selected filters. +To preserve responsiveness, as much as possible of the slow parts of the search are done +in a web worker. Searching and result generation are done in the worker, and filtering and +DOM updates are done in the main thread. The filters are in the main thread as they should +be very quick to apply. This lets filters be changed without re-searching with minisearch +(which is possible even if filtering is on the worker thread) and also lets filters be +changed _while_ the worker is searching and without message passing (neither of which are +possible if filtering is on the worker thread) + +SEARCH WORKER: + +Import minisearch + +Build index + +On message from main thread + run search + find the first 200 unique results from each category, and compute their divs for display + note that this is necessary and sufficient information for the main thread to find the + first 200 unique results from any given filter set + post results to main thread + +MAIN: + +Launch worker + +Declare nonconstant globals (worker_is_running, last_search_text, unfiltered_results) + +On text update + if worker is not running, launch_search() + +launch_search + set worker_is_running to true, set last_search_text to the search text + post the search query to worker + +on message from worker + if last_search_text is not the same as the text in the search field, + the latest search result is not reflective of the latest search query, so update again + launch_search() + otherwise + set worker_is_running to false + + regardless, display the new search results to the user + save the unfiltered_results as a global + update_search() + +on filter click + adjust the filter selection + update_search() + +update_search + apply search filters by looping through the unfiltered_results and finding the first 200 + unique results that match the filters + + Update the DOM +*/ + +/////// SEARCH WORKER /////// + +function worker_function(documenterSearchIndex, documenterBaseURL, filters) { + importScripts( + "https://cdn.jsdelivr.net/npm/minisearch@6.1.0/dist/umd/index.min.js" + ); + + let data = documenterSearchIndex.map((x, key) => { + x["id"] = key; // minisearch requires a unique for each object + return x; + }); + + // list below is the lunr 2.1.3 list minus the intersect with names(Base) + // (all, any, get, in, is, only, which) and (do, else, for, let, where, while, with) + // ideally we'd just filter the original list but it's not available as a variable + const stopWords = new Set([ + "a", + "able", + "about", + "across", + "after", + "almost", + "also", + "am", + "among", + "an", + "and", + "are", + "as", + "at", + "be", + "because", + "been", + "but", + "by", + "can", + "cannot", + "could", + "dear", + "did", + "does", + "either", + "ever", + "every", + "from", + "got", + "had", + "has", + "have", + "he", + "her", + "hers", + "him", + "his", + "how", + "however", + "i", + "if", + "into", + "it", + "its", + "just", + "least", + "like", + "likely", + "may", + "me", + "might", + "most", + "must", + "my", + "neither", + "no", + "nor", + "not", + "of", + "off", + "often", + "on", + "or", + "other", + "our", + "own", + "rather", + "said", + "say", + "says", + "she", + "should", + "since", + "so", + "some", + "than", + "that", + "the", + "their", + "them", + "then", + "there", + "these", + "they", + "this", + "tis", + "to", + "too", + "twas", + "us", + "wants", + "was", + "we", + "were", + "what", + "when", + "who", + "whom", + "why", + "will", + "would", + "yet", + "you", + "your", + ]); + + let index = new MiniSearch({ + fields: ["title", "text"], // fields to index for full-text search + storeFields: ["location", "title", "text", "category", "page"], // fields to return with results + processTerm: (term) => { + let word = stopWords.has(term) ? null : term; + if (word) { + // custom trimmer that doesn't strip @ and !, which are used in julia macro and function names + word = word + .replace(/^[^a-zA-Z0-9@!]+/, "") + .replace(/[^a-zA-Z0-9@!]+$/, ""); + + word = word.toLowerCase(); + } + + return word ?? null; + }, + // add . as a separator, because otherwise "title": "Documenter.Anchors.add!", would not + // find anything if searching for "add!", only for the entire qualification + tokenize: (string) => string.split(/[\s\-\.]+/), + // options which will be applied during the search + searchOptions: { + prefix: true, + boost: { title: 100 }, + fuzzy: 2, + }, + }); + + index.addAll(data); + + /** + * Used to map characters to HTML entities. + * Refer: https://github.com/lodash/lodash/blob/main/src/escape.ts + */ + const htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + }; + + /** + * Used to match HTML entities and HTML characters. + * Refer: https://github.com/lodash/lodash/blob/main/src/escape.ts + */ + const reUnescapedHtml = /[&<>"']/g; + const reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + + /** + * Escape function from lodash + * Refer: https://github.com/lodash/lodash/blob/main/src/escape.ts + */ + function escape(string) { + return string && reHasUnescapedHtml.test(string) + ? string.replace(reUnescapedHtml, (chr) => htmlEscapes[chr]) + : string || ""; + } + + /** + * RegX escape function from MDN + * Refer: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ + function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + } + + /** + * Make the result component given a minisearch result data object and the value + * of the search input as queryString. To view the result object structure, refer: + * https://lucaong.github.io/minisearch/modules/_minisearch_.html#searchresult + * + * @param {object} result + * @param {string} querystring + * @returns string + */ + function make_search_result(result, querystring) { + let search_divider = `
`; + let display_link = + result.location.slice(Math.max(0), Math.min(50, result.location.length)) + + (result.location.length > 30 ? "..." : ""); // To cut-off the link because it messes with the overflow of the whole div + + if (result.page !== "") { + display_link += ` (${result.page})`; + } + searchstring = escapeRegExp(querystring); + let textindex = new RegExp(`${searchstring}`, "i").exec(result.text); + let text = + textindex !== null + ? result.text.slice( + Math.max(textindex.index - 100, 0), + Math.min( + textindex.index + querystring.length + 100, + result.text.length + ) + ) + : ""; // cut-off text before and after from the match + + text = text.length ? escape(text) : ""; + + let display_result = text.length + ? "..." + + text.replace( + new RegExp(`${escape(searchstring)}`, "i"), // For first occurrence + '$&' + ) + + "..." + : ""; // highlights the match + + let in_code = false; + if (!["page", "section"].includes(result.category.toLowerCase())) { + in_code = true; + } + + // We encode the full url to escape some special characters which can lead to broken links + let result_div = ` + +
+
${escape(result.title)}
+
${result.category}
+
+

+ ${display_result} +

+
+ ${display_link} +
+
+ ${search_divider} + `; + + return result_div; + } + + self.onmessage = function (e) { + let query = e.data; + let results = index.search(query, { + filter: (result) => { + // Only return relevant results + return result.score >= 1; + }, + combineWith: "AND", + }); + + // Pre-filter to deduplicate and limit to 200 per category to the extent + // possible without knowing what the filters are. + let filtered_results = []; + let counts = {}; + for (let filter of filters) { + counts[filter] = 0; + } + let present = {}; + + for (let result of results) { + cat = result.category; + cnt = counts[cat]; + if (cnt < 200) { + id = cat + "---" + result.location; + if (present[id]) { + continue; + } + present[id] = true; + filtered_results.push({ + location: result.location, + category: cat, + div: make_search_result(result, query), + }); + } + } + + postMessage(filtered_results); + }; +} + +// `worker = Threads.@spawn worker_function(documenterSearchIndex)`, but in JavaScript! +const filters = [ + ...new Set(documenterSearchIndex["docs"].map((x) => x.category)), +]; +const worker_str = + "(" + + worker_function.toString() + + ")(" + + JSON.stringify(documenterSearchIndex["docs"]) + + "," + + JSON.stringify(documenterBaseURL) + + "," + + JSON.stringify(filters) + + ")"; +const worker_blob = new Blob([worker_str], { type: "text/javascript" }); +const worker = new Worker(URL.createObjectURL(worker_blob)); + +/////// SEARCH MAIN /////// + +// Whether the worker is currently handling a search. This is a boolean +// as the worker only ever handles 1 or 0 searches at a time. +var worker_is_running = false; + +// The last search text that was sent to the worker. This is used to determine +// if the worker should be launched again when it reports back results. +var last_search_text = ""; + +// The results of the last search. This, in combination with the state of the filters +// in the DOM, is used compute the results to display on calls to update_search. +var unfiltered_results = []; + +// Which filter is currently selected +var selected_filter = ""; + +$(document).on("input", ".documenter-search-input", function (event) { + if (!worker_is_running) { + launch_search(); + } +}); + +function launch_search() { + worker_is_running = true; + last_search_text = $(".documenter-search-input").val(); + worker.postMessage(last_search_text); +} + +worker.onmessage = function (e) { + if (last_search_text !== $(".documenter-search-input").val()) { + launch_search(); + } else { + worker_is_running = false; + } + + unfiltered_results = e.data; + update_search(); +}; + +$(document).on("click", ".search-filter", function () { + if ($(this).hasClass("search-filter-selected")) { + selected_filter = ""; + } else { + selected_filter = $(this).text().toLowerCase(); + } + + // This updates search results and toggles classes for UI: + update_search(); +}); + +/** + * Make/Update the search component + */ +function update_search() { + let querystring = $(".documenter-search-input").val(); + + if (querystring.trim()) { + if (selected_filter == "") { + results = unfiltered_results; + } else { + results = unfiltered_results.filter((result) => { + return selected_filter == result.category.toLowerCase(); + }); + } + + let search_result_container = ``; + let modal_filters = make_modal_body_filters(); + let search_divider = `
`; + + if (results.length) { + let links = []; + let count = 0; + let search_results = ""; + + for (var i = 0, n = results.length; i < n && count < 200; ++i) { + let result = results[i]; + if (result.location && !links.includes(result.location)) { + search_results += result.div; + count++; + links.push(result.location); + } + } + + if (count == 1) { + count_str = "1 result"; + } else if (count == 200) { + count_str = "200+ results"; + } else { + count_str = count + " results"; + } + let result_count = `
${count_str}
`; + + search_result_container = ` +
+ ${modal_filters} + ${search_divider} + ${result_count} +
+ ${search_results} +
+
+ `; + } else { + search_result_container = ` +
+ ${modal_filters} + ${search_divider} +
0 result(s)
+
+
No result found!
+ `; + } + + if ($(".search-modal-card-body").hasClass("is-justify-content-center")) { + $(".search-modal-card-body").removeClass("is-justify-content-center"); + } + + $(".search-modal-card-body").html(search_result_container); + } else { + if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) { + $(".search-modal-card-body").addClass("is-justify-content-center"); + } + + $(".search-modal-card-body").html(` +
Type something to get started!
+ `); + } +} + +/** + * Make the modal filter html + * + * @returns string + */ +function make_modal_body_filters() { + let str = filters + .map((val) => { + if (selected_filter == val.toLowerCase()) { + return `${val}`; + } else { + return `${val}`; + } + }) + .join(""); + + return ` +
+ Filters: + ${str} +
`; +} + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +// Modal settings dialog +$(document).ready(function () { + var settings = $("#documenter-settings"); + $("#documenter-settings-button").click(function () { + settings.toggleClass("is-active"); + }); + // Close the dialog if X is clicked + $("#documenter-settings button.delete").click(function () { + settings.removeClass("is-active"); + }); + // Close dialog if ESC is pressed + $(document).keyup(function (e) { + if (e.keyCode == 27) settings.removeClass("is-active"); + }); +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +$(document).ready(function () { + let search_modal_header = ` + + `; + + let initial_search_body = ` +
Type something to get started!
+ `; + + let search_modal_footer = ` + + `; + + $(document.body).append( + ` + + ` + ); + + document.querySelector(".docs-search-query").addEventListener("click", () => { + openModal(); + }); + + document + .querySelector(".close-search-modal") + .addEventListener("click", () => { + closeModal(); + }); + + $(document).on("click", ".search-result-link", function () { + closeModal(); + }); + + document.addEventListener("keydown", (event) => { + if ((event.ctrlKey || event.metaKey) && event.key === "/") { + openModal(); + } else if (event.key === "Escape") { + closeModal(); + } + + return false; + }); + + // Functions to open and close a modal + function openModal() { + let searchModal = document.querySelector("#search-modal"); + + searchModal.classList.add("is-active"); + document.querySelector(".documenter-search-input").focus(); + } + + function closeModal() { + let searchModal = document.querySelector("#search-modal"); + let initial_search_body = ` +
Type something to get started!
+ `; + + searchModal.classList.remove("is-active"); + document.querySelector(".documenter-search-input").blur(); + + if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) { + $(".search-modal-card-body").addClass("is-justify-content-center"); + } + + $(".documenter-search-input").val(""); + $(".search-modal-card-body").html(initial_search_body); + } + + document + .querySelector("#search-modal .modal-background") + .addEventListener("click", () => { + closeModal(); + }); +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +// Manages the showing and hiding of the sidebar. +$(document).ready(function () { + var sidebar = $("#documenter > .docs-sidebar"); + var sidebar_button = $("#documenter-sidebar-button"); + sidebar_button.click(function (ev) { + ev.preventDefault(); + sidebar.toggleClass("visible"); + if (sidebar.hasClass("visible")) { + // Makes sure that the current menu item is visible in the sidebar. + $("#documenter .docs-menu a.is-active").focus(); + } + }); + $("#documenter > .docs-main").bind("click", function (ev) { + if ($(ev.target).is(sidebar_button)) { + return; + } + if (sidebar.hasClass("visible")) { + sidebar.removeClass("visible"); + } + }); +}); + +// Resizes the package name / sitename in the sidebar if it is too wide. +// Inspired by: https://github.com/davatron5000/FitText.js +$(document).ready(function () { + e = $("#documenter .docs-autofit"); + function resize() { + var L = parseInt(e.css("max-width"), 10); + var L0 = e.width(); + if (L0 > L) { + var h0 = parseInt(e.css("font-size"), 10); + e.css("font-size", (L * h0) / L0); + // TODO: make sure it survives resizes? + } + } + // call once and then register events + resize(); + $(window).resize(resize); + $(window).on("orientationchange", resize); +}); + +// Scroll the navigation bar to the currently selected menu item +$(document).ready(function () { + var sidebar = $("#documenter .docs-menu").get(0); + var active = $("#documenter .docs-menu .is-active").get(0); + if (typeof active !== "undefined") { + sidebar.scrollTop = active.offsetTop - sidebar.offsetTop - 15; + } +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +// Theme picker setup +$(document).ready(function () { + // onchange callback + $("#documenter-themepicker").change(function themepick_callback(ev) { + var themename = $("#documenter-themepicker option:selected").attr("value"); + if (themename === "auto") { + // set_theme(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'); + window.localStorage.removeItem("documenter-theme"); + } else { + // set_theme(themename); + window.localStorage.setItem("documenter-theme", themename); + } + // We re-use the global function from themeswap.js to actually do the swapping. + set_theme_from_local_storage(); + }); + + // Make sure that the themepicker displays the correct theme when the theme is retrieved + // from localStorage + if (typeof window.localStorage !== "undefined") { + var theme = window.localStorage.getItem("documenter-theme"); + if (theme !== null) { + $("#documenter-themepicker option").each(function (i, e) { + e.selected = e.value === theme; + }); + } + } +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +// update the version selector with info from the siteinfo.js and ../versions.js files +$(document).ready(function () { + // If the version selector is disabled with DOCUMENTER_VERSION_SELECTOR_DISABLED in the + // siteinfo.js file, we just return immediately and not display the version selector. + if ( + typeof DOCUMENTER_VERSION_SELECTOR_DISABLED === "boolean" && + DOCUMENTER_VERSION_SELECTOR_DISABLED + ) { + return; + } + + var version_selector = $("#documenter .docs-version-selector"); + var version_selector_select = $("#documenter .docs-version-selector select"); + + version_selector_select.change(function (x) { + target_href = version_selector_select + .children("option:selected") + .get(0).value; + window.location.href = target_href; + }); + + // add the current version to the selector based on siteinfo.js, but only if the selector is empty + if ( + typeof DOCUMENTER_CURRENT_VERSION !== "undefined" && + $("#version-selector > option").length == 0 + ) { + var option = $( + "" + ); + version_selector_select.append(option); + } + + if (typeof DOC_VERSIONS !== "undefined") { + var existing_versions = version_selector_select.children("option"); + var existing_versions_texts = existing_versions.map(function (i, x) { + return x.text; + }); + DOC_VERSIONS.forEach(function (each) { + var version_url = documenterBaseURL + "/../" + each + "/"; + var existing_id = $.inArray(each, existing_versions_texts); + // if not already in the version selector, add it as a new option, + // otherwise update the old option with the URL and enable it + if (existing_id == -1) { + var option = $( + "" + ); + version_selector_select.append(option); + } else { + var option = existing_versions[existing_id]; + option.value = version_url; + option.disabled = false; + } + }); + } + + // only show the version selector if the selector has been populated + if (version_selector_select.children("option").length > 0) { + version_selector.toggleClass("visible"); + } +}); + +}) diff --git a/v0.2.0/assets/logo.svg b/v0.2.0/assets/logo.svg new file mode 100644 index 000000000..a9aecc015 --- /dev/null +++ b/v0.2.0/assets/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/v0.2.0/assets/logo2.svg b/v0.2.0/assets/logo2.svg new file mode 100644 index 000000000..5b0431c08 --- /dev/null +++ b/v0.2.0/assets/logo2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/v0.2.0/assets/pi_model.svg b/v0.2.0/assets/pi_model.svg new file mode 100644 index 000000000..5bc4b9d7a --- /dev/null +++ b/v0.2.0/assets/pi_model.svg @@ -0,0 +1,335 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v0.2.0/assets/pi_model_example.svg b/v0.2.0/assets/pi_model_example.svg new file mode 100644 index 000000000..6db4d9ca4 --- /dev/null +++ b/v0.2.0/assets/pi_model_example.svg @@ -0,0 +1,258 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v0.2.0/assets/pq_curve.svg b/v0.2.0/assets/pq_curve.svg new file mode 100644 index 000000000..6d6edb6d4 --- /dev/null +++ b/v0.2.0/assets/pq_curve.svg @@ -0,0 +1,307 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v0.2.0/assets/pq_curve_sloped.svg b/v0.2.0/assets/pq_curve_sloped.svg new file mode 100644 index 000000000..3d7b8ff89 --- /dev/null +++ b/v0.2.0/assets/pq_curve_sloped.svg @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v0.2.0/assets/tablestyle.css b/v0.2.0/assets/tablestyle.css new file mode 100644 index 000000000..2e135bad9 --- /dev/null +++ b/v0.2.0/assets/tablestyle.css @@ -0,0 +1,7 @@ +table { + border-collapse: collapse; + font-family: Tahoma, Geneva, sans-serif; + font-size: 14px; + width: 100%; + overflow: hidden; +} \ No newline at end of file diff --git a/v0.2.0/assets/themes/catppuccin-frappe.css b/v0.2.0/assets/themes/catppuccin-frappe.css new file mode 100644 index 000000000..32e3f0082 --- /dev/null +++ b/v0.2.0/assets/themes/catppuccin-frappe.css @@ -0,0 +1 @@ +html.theme--catppuccin-frappe .pagination-previous,html.theme--catppuccin-frappe .pagination-next,html.theme--catppuccin-frappe .pagination-link,html.theme--catppuccin-frappe .pagination-ellipsis,html.theme--catppuccin-frappe .file-cta,html.theme--catppuccin-frappe .file-name,html.theme--catppuccin-frappe .select select,html.theme--catppuccin-frappe .textarea,html.theme--catppuccin-frappe .input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-frappe .button{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;border-radius:.4em;box-shadow:none;display:inline-flex;font-size:1rem;height:2.5em;justify-content:flex-start;line-height:1.5;padding-bottom:calc(0.5em - 1px);padding-left:calc(0.75em - 1px);padding-right:calc(0.75em - 1px);padding-top:calc(0.5em - 1px);position:relative;vertical-align:top}html.theme--catppuccin-frappe .pagination-previous:focus,html.theme--catppuccin-frappe .pagination-next:focus,html.theme--catppuccin-frappe .pagination-link:focus,html.theme--catppuccin-frappe .pagination-ellipsis:focus,html.theme--catppuccin-frappe .file-cta:focus,html.theme--catppuccin-frappe .file-name:focus,html.theme--catppuccin-frappe .select select:focus,html.theme--catppuccin-frappe .textarea:focus,html.theme--catppuccin-frappe .input:focus,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input:focus,html.theme--catppuccin-frappe .button:focus,html.theme--catppuccin-frappe .is-focused.pagination-previous,html.theme--catppuccin-frappe .is-focused.pagination-next,html.theme--catppuccin-frappe .is-focused.pagination-link,html.theme--catppuccin-frappe .is-focused.pagination-ellipsis,html.theme--catppuccin-frappe .is-focused.file-cta,html.theme--catppuccin-frappe .is-focused.file-name,html.theme--catppuccin-frappe .select select.is-focused,html.theme--catppuccin-frappe .is-focused.textarea,html.theme--catppuccin-frappe .is-focused.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-frappe .is-focused.button,html.theme--catppuccin-frappe .pagination-previous:active,html.theme--catppuccin-frappe .pagination-next:active,html.theme--catppuccin-frappe .pagination-link:active,html.theme--catppuccin-frappe .pagination-ellipsis:active,html.theme--catppuccin-frappe .file-cta:active,html.theme--catppuccin-frappe .file-name:active,html.theme--catppuccin-frappe .select select:active,html.theme--catppuccin-frappe .textarea:active,html.theme--catppuccin-frappe .input:active,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input:active,html.theme--catppuccin-frappe .button:active,html.theme--catppuccin-frappe .is-active.pagination-previous,html.theme--catppuccin-frappe .is-active.pagination-next,html.theme--catppuccin-frappe .is-active.pagination-link,html.theme--catppuccin-frappe .is-active.pagination-ellipsis,html.theme--catppuccin-frappe .is-active.file-cta,html.theme--catppuccin-frappe .is-active.file-name,html.theme--catppuccin-frappe .select select.is-active,html.theme--catppuccin-frappe .is-active.textarea,html.theme--catppuccin-frappe .is-active.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--catppuccin-frappe .is-active.button{outline:none}html.theme--catppuccin-frappe .pagination-previous[disabled],html.theme--catppuccin-frappe .pagination-next[disabled],html.theme--catppuccin-frappe .pagination-link[disabled],html.theme--catppuccin-frappe .pagination-ellipsis[disabled],html.theme--catppuccin-frappe .file-cta[disabled],html.theme--catppuccin-frappe .file-name[disabled],html.theme--catppuccin-frappe .select select[disabled],html.theme--catppuccin-frappe .textarea[disabled],html.theme--catppuccin-frappe .input[disabled],html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input[disabled],html.theme--catppuccin-frappe .button[disabled],fieldset[disabled] html.theme--catppuccin-frappe .pagination-previous,html.theme--catppuccin-frappe fieldset[disabled] .pagination-previous,fieldset[disabled] html.theme--catppuccin-frappe .pagination-next,html.theme--catppuccin-frappe fieldset[disabled] .pagination-next,fieldset[disabled] html.theme--catppuccin-frappe .pagination-link,html.theme--catppuccin-frappe fieldset[disabled] .pagination-link,fieldset[disabled] html.theme--catppuccin-frappe .pagination-ellipsis,html.theme--catppuccin-frappe fieldset[disabled] .pagination-ellipsis,fieldset[disabled] html.theme--catppuccin-frappe .file-cta,html.theme--catppuccin-frappe fieldset[disabled] .file-cta,fieldset[disabled] html.theme--catppuccin-frappe .file-name,html.theme--catppuccin-frappe fieldset[disabled] .file-name,fieldset[disabled] html.theme--catppuccin-frappe .select select,fieldset[disabled] html.theme--catppuccin-frappe .textarea,fieldset[disabled] html.theme--catppuccin-frappe .input,fieldset[disabled] html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-frappe fieldset[disabled] .select select,html.theme--catppuccin-frappe .select fieldset[disabled] select,html.theme--catppuccin-frappe fieldset[disabled] .textarea,html.theme--catppuccin-frappe fieldset[disabled] .input,html.theme--catppuccin-frappe fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-frappe #documenter .docs-sidebar fieldset[disabled] form.docs-search>input,fieldset[disabled] html.theme--catppuccin-frappe .button,html.theme--catppuccin-frappe fieldset[disabled] .button{cursor:not-allowed}html.theme--catppuccin-frappe .tabs,html.theme--catppuccin-frappe .pagination-previous,html.theme--catppuccin-frappe .pagination-next,html.theme--catppuccin-frappe .pagination-link,html.theme--catppuccin-frappe .pagination-ellipsis,html.theme--catppuccin-frappe .breadcrumb,html.theme--catppuccin-frappe .file,html.theme--catppuccin-frappe .button,.is-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}html.theme--catppuccin-frappe .navbar-link:not(.is-arrowless)::after,html.theme--catppuccin-frappe .select:not(.is-multiple):not(.is-loading)::after{border:3px solid rgba(0,0,0,0);border-radius:2px;border-right:0;border-top:0;content:" ";display:block;height:0.625em;margin-top:-0.4375em;pointer-events:none;position:absolute;top:50%;transform:rotate(-45deg);transform-origin:center;width:0.625em}html.theme--catppuccin-frappe .admonition:not(:last-child),html.theme--catppuccin-frappe .tabs:not(:last-child),html.theme--catppuccin-frappe .pagination:not(:last-child),html.theme--catppuccin-frappe .message:not(:last-child),html.theme--catppuccin-frappe .level:not(:last-child),html.theme--catppuccin-frappe .breadcrumb:not(:last-child),html.theme--catppuccin-frappe .block:not(:last-child),html.theme--catppuccin-frappe .title:not(:last-child),html.theme--catppuccin-frappe .subtitle:not(:last-child),html.theme--catppuccin-frappe .table-container:not(:last-child),html.theme--catppuccin-frappe .table:not(:last-child),html.theme--catppuccin-frappe .progress:not(:last-child),html.theme--catppuccin-frappe .notification:not(:last-child),html.theme--catppuccin-frappe .content:not(:last-child),html.theme--catppuccin-frappe .box:not(:last-child){margin-bottom:1.5rem}html.theme--catppuccin-frappe .modal-close,html.theme--catppuccin-frappe .delete{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,0.2);border:none;border-radius:9999px;cursor:pointer;pointer-events:auto;display:inline-block;flex-grow:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:none;position:relative;vertical-align:top;width:20px}html.theme--catppuccin-frappe .modal-close::before,html.theme--catppuccin-frappe .delete::before,html.theme--catppuccin-frappe .modal-close::after,html.theme--catppuccin-frappe .delete::after{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--catppuccin-frappe .modal-close::before,html.theme--catppuccin-frappe .delete::before{height:2px;width:50%}html.theme--catppuccin-frappe .modal-close::after,html.theme--catppuccin-frappe .delete::after{height:50%;width:2px}html.theme--catppuccin-frappe .modal-close:hover,html.theme--catppuccin-frappe .delete:hover,html.theme--catppuccin-frappe .modal-close:focus,html.theme--catppuccin-frappe .delete:focus{background-color:rgba(10,10,10,0.3)}html.theme--catppuccin-frappe .modal-close:active,html.theme--catppuccin-frappe .delete:active{background-color:rgba(10,10,10,0.4)}html.theme--catppuccin-frappe .is-small.modal-close,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.modal-close,html.theme--catppuccin-frappe .is-small.delete,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.delete{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}html.theme--catppuccin-frappe .is-medium.modal-close,html.theme--catppuccin-frappe .is-medium.delete{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}html.theme--catppuccin-frappe .is-large.modal-close,html.theme--catppuccin-frappe .is-large.delete{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}html.theme--catppuccin-frappe .control.is-loading::after,html.theme--catppuccin-frappe .select.is-loading::after,html.theme--catppuccin-frappe .loader,html.theme--catppuccin-frappe .button.is-loading::after{animation:spinAround 500ms infinite linear;border:2px solid #838ba7;border-radius:9999px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em}html.theme--catppuccin-frappe .hero-video,html.theme--catppuccin-frappe .modal-background,html.theme--catppuccin-frappe .modal,html.theme--catppuccin-frappe .image.is-square img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--catppuccin-frappe .image.is-square .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--catppuccin-frappe .image.is-1by1 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--catppuccin-frappe .image.is-1by1 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--catppuccin-frappe .image.is-5by4 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--catppuccin-frappe .image.is-5by4 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--catppuccin-frappe .image.is-4by3 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--catppuccin-frappe .image.is-4by3 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--catppuccin-frappe .image.is-3by2 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--catppuccin-frappe .image.is-3by2 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--catppuccin-frappe .image.is-5by3 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--catppuccin-frappe .image.is-5by3 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--catppuccin-frappe .image.is-16by9 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--catppuccin-frappe .image.is-16by9 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--catppuccin-frappe .image.is-2by1 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--catppuccin-frappe .image.is-2by1 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--catppuccin-frappe .image.is-3by1 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--catppuccin-frappe .image.is-3by1 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--catppuccin-frappe .image.is-4by5 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--catppuccin-frappe .image.is-4by5 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--catppuccin-frappe .image.is-3by4 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--catppuccin-frappe .image.is-3by4 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--catppuccin-frappe .image.is-2by3 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--catppuccin-frappe .image.is-2by3 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--catppuccin-frappe .image.is-3by5 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--catppuccin-frappe .image.is-3by5 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--catppuccin-frappe .image.is-9by16 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--catppuccin-frappe .image.is-9by16 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--catppuccin-frappe .image.is-1by2 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--catppuccin-frappe .image.is-1by2 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--catppuccin-frappe .image.is-1by3 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--catppuccin-frappe .image.is-1by3 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio,.is-overlay{bottom:0;left:0;position:absolute;right:0;top:0}html.theme--catppuccin-frappe .navbar-burger{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0}/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:inherit}.has-text-white{color:#fff !important}a.has-text-white:hover,a.has-text-white:focus{color:#e6e6e6 !important}.has-background-white{background-color:#fff !important}.has-text-black{color:#0a0a0a !important}a.has-text-black:hover,a.has-text-black:focus{color:#000 !important}.has-background-black{background-color:#0a0a0a !important}.has-text-light{color:#f5f5f5 !important}a.has-text-light:hover,a.has-text-light:focus{color:#dbdbdb !important}.has-background-light{background-color:#f5f5f5 !important}.has-text-dark{color:#414559 !important}a.has-text-dark:hover,a.has-text-dark:focus{color:#2b2e3c !important}.has-background-dark{background-color:#414559 !important}.has-text-primary{color:#8caaee !important}a.has-text-primary:hover,a.has-text-primary:focus{color:#6089e7 !important}.has-background-primary{background-color:#8caaee !important}.has-text-primary-light{color:#edf2fc !important}a.has-text-primary-light:hover,a.has-text-primary-light:focus{color:#c1d1f6 !important}.has-background-primary-light{background-color:#edf2fc !important}.has-text-primary-dark{color:#153a8e !important}a.has-text-primary-dark:hover,a.has-text-primary-dark:focus{color:#1c4cbb !important}.has-background-primary-dark{background-color:#153a8e !important}.has-text-link{color:#8caaee !important}a.has-text-link:hover,a.has-text-link:focus{color:#6089e7 !important}.has-background-link{background-color:#8caaee !important}.has-text-link-light{color:#edf2fc !important}a.has-text-link-light:hover,a.has-text-link-light:focus{color:#c1d1f6 !important}.has-background-link-light{background-color:#edf2fc !important}.has-text-link-dark{color:#153a8e !important}a.has-text-link-dark:hover,a.has-text-link-dark:focus{color:#1c4cbb !important}.has-background-link-dark{background-color:#153a8e !important}.has-text-info{color:#81c8be !important}a.has-text-info:hover,a.has-text-info:focus{color:#5db9ac !important}.has-background-info{background-color:#81c8be !important}.has-text-info-light{color:#f1f9f8 !important}a.has-text-info-light:hover,a.has-text-info-light:focus{color:#cde9e5 !important}.has-background-info-light{background-color:#f1f9f8 !important}.has-text-info-dark{color:#2d675f !important}a.has-text-info-dark:hover,a.has-text-info-dark:focus{color:#3c8a7f !important}.has-background-info-dark{background-color:#2d675f !important}.has-text-success{color:#a6d189 !important}a.has-text-success:hover,a.has-text-success:focus{color:#8ac364 !important}.has-background-success{background-color:#a6d189 !important}.has-text-success-light{color:#f4f9f0 !important}a.has-text-success-light:hover,a.has-text-success-light:focus{color:#d8ebcc !important}.has-background-success-light{background-color:#f4f9f0 !important}.has-text-success-dark{color:#446a29 !important}a.has-text-success-dark:hover,a.has-text-success-dark:focus{color:#5b8f38 !important}.has-background-success-dark{background-color:#446a29 !important}.has-text-warning{color:#e5c890 !important}a.has-text-warning:hover,a.has-text-warning:focus{color:#dbb467 !important}.has-background-warning{background-color:#e5c890 !important}.has-text-warning-light{color:#fbf7ee !important}a.has-text-warning-light:hover,a.has-text-warning-light:focus{color:#f1e2c5 !important}.has-background-warning-light{background-color:#fbf7ee !important}.has-text-warning-dark{color:#78591c !important}a.has-text-warning-dark:hover,a.has-text-warning-dark:focus{color:#a17726 !important}.has-background-warning-dark{background-color:#78591c !important}.has-text-danger{color:#e78284 !important}a.has-text-danger:hover,a.has-text-danger:focus{color:#df575a !important}.has-background-danger{background-color:#e78284 !important}.has-text-danger-light{color:#fceeee !important}a.has-text-danger-light:hover,a.has-text-danger-light:focus{color:#f3c3c4 !important}.has-background-danger-light{background-color:#fceeee !important}.has-text-danger-dark{color:#9a1e20 !important}a.has-text-danger-dark:hover,a.has-text-danger-dark:focus{color:#c52629 !important}.has-background-danger-dark{background-color:#9a1e20 !important}.has-text-black-bis{color:#121212 !important}.has-background-black-bis{background-color:#121212 !important}.has-text-black-ter{color:#242424 !important}.has-background-black-ter{background-color:#242424 !important}.has-text-grey-darker{color:#414559 !important}.has-background-grey-darker{background-color:#414559 !important}.has-text-grey-dark{color:#51576d !important}.has-background-grey-dark{background-color:#51576d !important}.has-text-grey{color:#626880 !important}.has-background-grey{background-color:#626880 !important}.has-text-grey-light{color:#737994 !important}.has-background-grey-light{background-color:#737994 !important}.has-text-grey-lighter{color:#838ba7 !important}.has-background-grey-lighter{background-color:#838ba7 !important}.has-text-white-ter{color:#f5f5f5 !important}.has-background-white-ter{background-color:#f5f5f5 !important}.has-text-white-bis{color:#fafafa !important}.has-background-white-bis{background-color:#fafafa !important}.is-flex-direction-row{flex-direction:row !important}.is-flex-direction-row-reverse{flex-direction:row-reverse !important}.is-flex-direction-column{flex-direction:column !important}.is-flex-direction-column-reverse{flex-direction:column-reverse !important}.is-flex-wrap-nowrap{flex-wrap:nowrap !important}.is-flex-wrap-wrap{flex-wrap:wrap !important}.is-flex-wrap-wrap-reverse{flex-wrap:wrap-reverse !important}.is-justify-content-flex-start{justify-content:flex-start !important}.is-justify-content-flex-end{justify-content:flex-end !important}.is-justify-content-center{justify-content:center !important}.is-justify-content-space-between{justify-content:space-between !important}.is-justify-content-space-around{justify-content:space-around !important}.is-justify-content-space-evenly{justify-content:space-evenly !important}.is-justify-content-start{justify-content:start !important}.is-justify-content-end{justify-content:end !important}.is-justify-content-left{justify-content:left !important}.is-justify-content-right{justify-content:right !important}.is-align-content-flex-start{align-content:flex-start !important}.is-align-content-flex-end{align-content:flex-end !important}.is-align-content-center{align-content:center !important}.is-align-content-space-between{align-content:space-between !important}.is-align-content-space-around{align-content:space-around !important}.is-align-content-space-evenly{align-content:space-evenly !important}.is-align-content-stretch{align-content:stretch !important}.is-align-content-start{align-content:start !important}.is-align-content-end{align-content:end !important}.is-align-content-baseline{align-content:baseline !important}.is-align-items-stretch{align-items:stretch !important}.is-align-items-flex-start{align-items:flex-start !important}.is-align-items-flex-end{align-items:flex-end !important}.is-align-items-center{align-items:center !important}.is-align-items-baseline{align-items:baseline !important}.is-align-items-start{align-items:start !important}.is-align-items-end{align-items:end !important}.is-align-items-self-start{align-items:self-start !important}.is-align-items-self-end{align-items:self-end !important}.is-align-self-auto{align-self:auto !important}.is-align-self-flex-start{align-self:flex-start !important}.is-align-self-flex-end{align-self:flex-end !important}.is-align-self-center{align-self:center !important}.is-align-self-baseline{align-self:baseline !important}.is-align-self-stretch{align-self:stretch !important}.is-flex-grow-0{flex-grow:0 !important}.is-flex-grow-1{flex-grow:1 !important}.is-flex-grow-2{flex-grow:2 !important}.is-flex-grow-3{flex-grow:3 !important}.is-flex-grow-4{flex-grow:4 !important}.is-flex-grow-5{flex-grow:5 !important}.is-flex-shrink-0{flex-shrink:0 !important}.is-flex-shrink-1{flex-shrink:1 !important}.is-flex-shrink-2{flex-shrink:2 !important}.is-flex-shrink-3{flex-shrink:3 !important}.is-flex-shrink-4{flex-shrink:4 !important}.is-flex-shrink-5{flex-shrink:5 !important}.is-clearfix::after{clear:both;content:" ";display:table}.is-pulled-left{float:left !important}.is-pulled-right{float:right !important}.is-radiusless{border-radius:0 !important}.is-shadowless{box-shadow:none !important}.is-clickable{cursor:pointer !important;pointer-events:all !important}.is-clipped{overflow:hidden !important}.is-relative{position:relative !important}.is-marginless{margin:0 !important}.is-paddingless{padding:0 !important}.m-0{margin:0 !important}.mt-0{margin-top:0 !important}.mr-0{margin-right:0 !important}.mb-0{margin-bottom:0 !important}.ml-0{margin-left:0 !important}.mx-0{margin-left:0 !important;margin-right:0 !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.m-1{margin:.25rem !important}.mt-1{margin-top:.25rem !important}.mr-1{margin-right:.25rem !important}.mb-1{margin-bottom:.25rem !important}.ml-1{margin-left:.25rem !important}.mx-1{margin-left:.25rem !important;margin-right:.25rem !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.m-2{margin:.5rem !important}.mt-2{margin-top:.5rem !important}.mr-2{margin-right:.5rem !important}.mb-2{margin-bottom:.5rem !important}.ml-2{margin-left:.5rem !important}.mx-2{margin-left:.5rem !important;margin-right:.5rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.m-3{margin:.75rem !important}.mt-3{margin-top:.75rem !important}.mr-3{margin-right:.75rem !important}.mb-3{margin-bottom:.75rem !important}.ml-3{margin-left:.75rem !important}.mx-3{margin-left:.75rem !important;margin-right:.75rem !important}.my-3{margin-top:.75rem !important;margin-bottom:.75rem !important}.m-4{margin:1rem !important}.mt-4{margin-top:1rem !important}.mr-4{margin-right:1rem !important}.mb-4{margin-bottom:1rem !important}.ml-4{margin-left:1rem !important}.mx-4{margin-left:1rem !important;margin-right:1rem !important}.my-4{margin-top:1rem !important;margin-bottom:1rem !important}.m-5{margin:1.5rem !important}.mt-5{margin-top:1.5rem !important}.mr-5{margin-right:1.5rem !important}.mb-5{margin-bottom:1.5rem !important}.ml-5{margin-left:1.5rem !important}.mx-5{margin-left:1.5rem !important;margin-right:1.5rem !important}.my-5{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.m-6{margin:3rem !important}.mt-6{margin-top:3rem !important}.mr-6{margin-right:3rem !important}.mb-6{margin-bottom:3rem !important}.ml-6{margin-left:3rem !important}.mx-6{margin-left:3rem !important;margin-right:3rem !important}.my-6{margin-top:3rem !important;margin-bottom:3rem !important}.m-auto{margin:auto !important}.mt-auto{margin-top:auto !important}.mr-auto{margin-right:auto !important}.mb-auto{margin-bottom:auto !important}.ml-auto{margin-left:auto !important}.mx-auto{margin-left:auto !important;margin-right:auto !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.p-0{padding:0 !important}.pt-0{padding-top:0 !important}.pr-0{padding-right:0 !important}.pb-0{padding-bottom:0 !important}.pl-0{padding-left:0 !important}.px-0{padding-left:0 !important;padding-right:0 !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.p-1{padding:.25rem !important}.pt-1{padding-top:.25rem !important}.pr-1{padding-right:.25rem !important}.pb-1{padding-bottom:.25rem !important}.pl-1{padding-left:.25rem !important}.px-1{padding-left:.25rem !important;padding-right:.25rem !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.p-2{padding:.5rem !important}.pt-2{padding-top:.5rem !important}.pr-2{padding-right:.5rem !important}.pb-2{padding-bottom:.5rem !important}.pl-2{padding-left:.5rem !important}.px-2{padding-left:.5rem !important;padding-right:.5rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.p-3{padding:.75rem !important}.pt-3{padding-top:.75rem !important}.pr-3{padding-right:.75rem !important}.pb-3{padding-bottom:.75rem !important}.pl-3{padding-left:.75rem !important}.px-3{padding-left:.75rem !important;padding-right:.75rem !important}.py-3{padding-top:.75rem !important;padding-bottom:.75rem !important}.p-4{padding:1rem !important}.pt-4{padding-top:1rem !important}.pr-4{padding-right:1rem !important}.pb-4{padding-bottom:1rem !important}.pl-4{padding-left:1rem !important}.px-4{padding-left:1rem !important;padding-right:1rem !important}.py-4{padding-top:1rem !important;padding-bottom:1rem !important}.p-5{padding:1.5rem !important}.pt-5{padding-top:1.5rem !important}.pr-5{padding-right:1.5rem !important}.pb-5{padding-bottom:1.5rem !important}.pl-5{padding-left:1.5rem !important}.px-5{padding-left:1.5rem !important;padding-right:1.5rem !important}.py-5{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.p-6{padding:3rem !important}.pt-6{padding-top:3rem !important}.pr-6{padding-right:3rem !important}.pb-6{padding-bottom:3rem !important}.pl-6{padding-left:3rem !important}.px-6{padding-left:3rem !important;padding-right:3rem !important}.py-6{padding-top:3rem !important;padding-bottom:3rem !important}.p-auto{padding:auto !important}.pt-auto{padding-top:auto !important}.pr-auto{padding-right:auto !important}.pb-auto{padding-bottom:auto !important}.pl-auto{padding-left:auto !important}.px-auto{padding-left:auto !important;padding-right:auto !important}.py-auto{padding-top:auto !important;padding-bottom:auto !important}.is-size-1{font-size:3rem !important}.is-size-2{font-size:2.5rem !important}.is-size-3{font-size:2rem !important}.is-size-4{font-size:1.5rem !important}.is-size-5{font-size:1.25rem !important}.is-size-6{font-size:1rem !important}.is-size-7,html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink{font-size:.75rem !important}@media screen and (max-width: 768px){.is-size-1-mobile{font-size:3rem !important}.is-size-2-mobile{font-size:2.5rem !important}.is-size-3-mobile{font-size:2rem !important}.is-size-4-mobile{font-size:1.5rem !important}.is-size-5-mobile{font-size:1.25rem !important}.is-size-6-mobile{font-size:1rem !important}.is-size-7-mobile{font-size:.75rem !important}}@media screen and (min-width: 769px),print{.is-size-1-tablet{font-size:3rem !important}.is-size-2-tablet{font-size:2.5rem !important}.is-size-3-tablet{font-size:2rem !important}.is-size-4-tablet{font-size:1.5rem !important}.is-size-5-tablet{font-size:1.25rem !important}.is-size-6-tablet{font-size:1rem !important}.is-size-7-tablet{font-size:.75rem !important}}@media screen and (max-width: 1055px){.is-size-1-touch{font-size:3rem !important}.is-size-2-touch{font-size:2.5rem !important}.is-size-3-touch{font-size:2rem !important}.is-size-4-touch{font-size:1.5rem !important}.is-size-5-touch{font-size:1.25rem !important}.is-size-6-touch{font-size:1rem !important}.is-size-7-touch{font-size:.75rem !important}}@media screen and (min-width: 1056px){.is-size-1-desktop{font-size:3rem !important}.is-size-2-desktop{font-size:2.5rem !important}.is-size-3-desktop{font-size:2rem !important}.is-size-4-desktop{font-size:1.5rem !important}.is-size-5-desktop{font-size:1.25rem !important}.is-size-6-desktop{font-size:1rem !important}.is-size-7-desktop{font-size:.75rem !important}}@media screen and (min-width: 1216px){.is-size-1-widescreen{font-size:3rem !important}.is-size-2-widescreen{font-size:2.5rem !important}.is-size-3-widescreen{font-size:2rem !important}.is-size-4-widescreen{font-size:1.5rem !important}.is-size-5-widescreen{font-size:1.25rem !important}.is-size-6-widescreen{font-size:1rem !important}.is-size-7-widescreen{font-size:.75rem !important}}@media screen and (min-width: 1408px){.is-size-1-fullhd{font-size:3rem !important}.is-size-2-fullhd{font-size:2.5rem !important}.is-size-3-fullhd{font-size:2rem !important}.is-size-4-fullhd{font-size:1.5rem !important}.is-size-5-fullhd{font-size:1.25rem !important}.is-size-6-fullhd{font-size:1rem !important}.is-size-7-fullhd{font-size:.75rem !important}}.has-text-centered{text-align:center !important}.has-text-justified{text-align:justify !important}.has-text-left{text-align:left !important}.has-text-right{text-align:right !important}@media screen and (max-width: 768px){.has-text-centered-mobile{text-align:center !important}}@media screen and (min-width: 769px),print{.has-text-centered-tablet{text-align:center !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-centered-tablet-only{text-align:center !important}}@media screen and (max-width: 1055px){.has-text-centered-touch{text-align:center !important}}@media screen and (min-width: 1056px){.has-text-centered-desktop{text-align:center !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-centered-desktop-only{text-align:center !important}}@media screen and (min-width: 1216px){.has-text-centered-widescreen{text-align:center !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-centered-widescreen-only{text-align:center !important}}@media screen and (min-width: 1408px){.has-text-centered-fullhd{text-align:center !important}}@media screen and (max-width: 768px){.has-text-justified-mobile{text-align:justify !important}}@media screen and (min-width: 769px),print{.has-text-justified-tablet{text-align:justify !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-justified-tablet-only{text-align:justify !important}}@media screen and (max-width: 1055px){.has-text-justified-touch{text-align:justify !important}}@media screen and (min-width: 1056px){.has-text-justified-desktop{text-align:justify !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-justified-desktop-only{text-align:justify !important}}@media screen and (min-width: 1216px){.has-text-justified-widescreen{text-align:justify !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-justified-widescreen-only{text-align:justify !important}}@media screen and (min-width: 1408px){.has-text-justified-fullhd{text-align:justify !important}}@media screen and (max-width: 768px){.has-text-left-mobile{text-align:left !important}}@media screen and (min-width: 769px),print{.has-text-left-tablet{text-align:left !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-left-tablet-only{text-align:left !important}}@media screen and (max-width: 1055px){.has-text-left-touch{text-align:left !important}}@media screen and (min-width: 1056px){.has-text-left-desktop{text-align:left !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-left-desktop-only{text-align:left !important}}@media screen and (min-width: 1216px){.has-text-left-widescreen{text-align:left !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-left-widescreen-only{text-align:left !important}}@media screen and (min-width: 1408px){.has-text-left-fullhd{text-align:left !important}}@media screen and (max-width: 768px){.has-text-right-mobile{text-align:right !important}}@media screen and (min-width: 769px),print{.has-text-right-tablet{text-align:right !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-right-tablet-only{text-align:right !important}}@media screen and (max-width: 1055px){.has-text-right-touch{text-align:right !important}}@media screen and (min-width: 1056px){.has-text-right-desktop{text-align:right !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-right-desktop-only{text-align:right !important}}@media screen and (min-width: 1216px){.has-text-right-widescreen{text-align:right !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-right-widescreen-only{text-align:right !important}}@media screen and (min-width: 1408px){.has-text-right-fullhd{text-align:right !important}}.is-capitalized{text-transform:capitalize !important}.is-lowercase{text-transform:lowercase !important}.is-uppercase{text-transform:uppercase !important}.is-italic{font-style:italic !important}.is-underlined{text-decoration:underline !important}.has-text-weight-light{font-weight:300 !important}.has-text-weight-normal{font-weight:400 !important}.has-text-weight-medium{font-weight:500 !important}.has-text-weight-semibold{font-weight:600 !important}.has-text-weight-bold{font-weight:700 !important}.is-family-primary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-secondary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-sans-serif{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-monospace{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-family-code{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-block{display:block !important}@media screen and (max-width: 768px){.is-block-mobile{display:block !important}}@media screen and (min-width: 769px),print{.is-block-tablet{display:block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-block-tablet-only{display:block !important}}@media screen and (max-width: 1055px){.is-block-touch{display:block !important}}@media screen and (min-width: 1056px){.is-block-desktop{display:block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-block-desktop-only{display:block !important}}@media screen and (min-width: 1216px){.is-block-widescreen{display:block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-block-widescreen-only{display:block !important}}@media screen and (min-width: 1408px){.is-block-fullhd{display:block !important}}.is-flex{display:flex !important}@media screen and (max-width: 768px){.is-flex-mobile{display:flex !important}}@media screen and (min-width: 769px),print{.is-flex-tablet{display:flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-flex-tablet-only{display:flex !important}}@media screen and (max-width: 1055px){.is-flex-touch{display:flex !important}}@media screen and (min-width: 1056px){.is-flex-desktop{display:flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-flex-desktop-only{display:flex !important}}@media screen and (min-width: 1216px){.is-flex-widescreen{display:flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-flex-widescreen-only{display:flex !important}}@media screen and (min-width: 1408px){.is-flex-fullhd{display:flex !important}}.is-inline{display:inline !important}@media screen and (max-width: 768px){.is-inline-mobile{display:inline !important}}@media screen and (min-width: 769px),print{.is-inline-tablet{display:inline !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-tablet-only{display:inline !important}}@media screen and (max-width: 1055px){.is-inline-touch{display:inline !important}}@media screen and (min-width: 1056px){.is-inline-desktop{display:inline !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-desktop-only{display:inline !important}}@media screen and (min-width: 1216px){.is-inline-widescreen{display:inline !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-widescreen-only{display:inline !important}}@media screen and (min-width: 1408px){.is-inline-fullhd{display:inline !important}}.is-inline-block{display:inline-block !important}@media screen and (max-width: 768px){.is-inline-block-mobile{display:inline-block !important}}@media screen and (min-width: 769px),print{.is-inline-block-tablet{display:inline-block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-block-tablet-only{display:inline-block !important}}@media screen and (max-width: 1055px){.is-inline-block-touch{display:inline-block !important}}@media screen and (min-width: 1056px){.is-inline-block-desktop{display:inline-block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-block-desktop-only{display:inline-block !important}}@media screen and (min-width: 1216px){.is-inline-block-widescreen{display:inline-block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-block-widescreen-only{display:inline-block !important}}@media screen and (min-width: 1408px){.is-inline-block-fullhd{display:inline-block !important}}.is-inline-flex{display:inline-flex !important}@media screen and (max-width: 768px){.is-inline-flex-mobile{display:inline-flex !important}}@media screen and (min-width: 769px),print{.is-inline-flex-tablet{display:inline-flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-flex-tablet-only{display:inline-flex !important}}@media screen and (max-width: 1055px){.is-inline-flex-touch{display:inline-flex !important}}@media screen and (min-width: 1056px){.is-inline-flex-desktop{display:inline-flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-flex-desktop-only{display:inline-flex !important}}@media screen and (min-width: 1216px){.is-inline-flex-widescreen{display:inline-flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-flex-widescreen-only{display:inline-flex !important}}@media screen and (min-width: 1408px){.is-inline-flex-fullhd{display:inline-flex !important}}.is-hidden{display:none !important}.is-sr-only{border:none !important;clip:rect(0, 0, 0, 0) !important;height:0.01em !important;overflow:hidden !important;padding:0 !important;position:absolute !important;white-space:nowrap !important;width:0.01em !important}@media screen and (max-width: 768px){.is-hidden-mobile{display:none !important}}@media screen and (min-width: 769px),print{.is-hidden-tablet{display:none !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-hidden-tablet-only{display:none !important}}@media screen and (max-width: 1055px){.is-hidden-touch{display:none !important}}@media screen and (min-width: 1056px){.is-hidden-desktop{display:none !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-hidden-desktop-only{display:none !important}}@media screen and (min-width: 1216px){.is-hidden-widescreen{display:none !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-hidden-widescreen-only{display:none !important}}@media screen and (min-width: 1408px){.is-hidden-fullhd{display:none !important}}.is-invisible{visibility:hidden !important}@media screen and (max-width: 768px){.is-invisible-mobile{visibility:hidden !important}}@media screen and (min-width: 769px),print{.is-invisible-tablet{visibility:hidden !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-invisible-tablet-only{visibility:hidden !important}}@media screen and (max-width: 1055px){.is-invisible-touch{visibility:hidden !important}}@media screen and (min-width: 1056px){.is-invisible-desktop{visibility:hidden !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-invisible-desktop-only{visibility:hidden !important}}@media screen and (min-width: 1216px){.is-invisible-widescreen{visibility:hidden !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-invisible-widescreen-only{visibility:hidden !important}}@media screen and (min-width: 1408px){.is-invisible-fullhd{visibility:hidden !important}}html.theme--catppuccin-frappe html{background-color:#303446;font-size:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--catppuccin-frappe article,html.theme--catppuccin-frappe aside,html.theme--catppuccin-frappe figure,html.theme--catppuccin-frappe footer,html.theme--catppuccin-frappe header,html.theme--catppuccin-frappe hgroup,html.theme--catppuccin-frappe section{display:block}html.theme--catppuccin-frappe body,html.theme--catppuccin-frappe button,html.theme--catppuccin-frappe input,html.theme--catppuccin-frappe optgroup,html.theme--catppuccin-frappe select,html.theme--catppuccin-frappe textarea{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif}html.theme--catppuccin-frappe code,html.theme--catppuccin-frappe pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}html.theme--catppuccin-frappe body{color:#c6d0f5;font-size:1em;font-weight:400;line-height:1.5}html.theme--catppuccin-frappe a{color:#8caaee;cursor:pointer;text-decoration:none}html.theme--catppuccin-frappe a strong{color:currentColor}html.theme--catppuccin-frappe a:hover{color:#99d1db}html.theme--catppuccin-frappe code{background-color:#292c3c;color:#c6d0f5;font-size:.875em;font-weight:normal;padding:.1em}html.theme--catppuccin-frappe hr{background-color:#292c3c;border:none;display:block;height:2px;margin:1.5rem 0}html.theme--catppuccin-frappe img{height:auto;max-width:100%}html.theme--catppuccin-frappe input[type="checkbox"],html.theme--catppuccin-frappe input[type="radio"]{vertical-align:baseline}html.theme--catppuccin-frappe small{font-size:.875em}html.theme--catppuccin-frappe span{font-style:inherit;font-weight:inherit}html.theme--catppuccin-frappe strong{color:#b0bef1;font-weight:700}html.theme--catppuccin-frappe fieldset{border:none}html.theme--catppuccin-frappe pre{-webkit-overflow-scrolling:touch;background-color:#292c3c;color:#c6d0f5;font-size:.875em;overflow-x:auto;padding:1.25rem 1.5rem;white-space:pre;word-wrap:normal}html.theme--catppuccin-frappe pre code{background-color:transparent;color:currentColor;font-size:1em;padding:0}html.theme--catppuccin-frappe table td,html.theme--catppuccin-frappe table th{vertical-align:top}html.theme--catppuccin-frappe table td:not([align]),html.theme--catppuccin-frappe table th:not([align]){text-align:inherit}html.theme--catppuccin-frappe table th{color:#b0bef1}html.theme--catppuccin-frappe .box{background-color:#51576d;border-radius:8px;box-shadow:none;color:#c6d0f5;display:block;padding:1.25rem}html.theme--catppuccin-frappe a.box:hover,html.theme--catppuccin-frappe a.box:focus{box-shadow:0 0.5em 1em -0.125em rgba(10,10,10,0.1),0 0 0 1px #8caaee}html.theme--catppuccin-frappe a.box:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2),0 0 0 1px #8caaee}html.theme--catppuccin-frappe .button{background-color:#292c3c;border-color:#484d69;border-width:1px;color:#8caaee;cursor:pointer;justify-content:center;padding-bottom:calc(0.5em - 1px);padding-left:1em;padding-right:1em;padding-top:calc(0.5em - 1px);text-align:center;white-space:nowrap}html.theme--catppuccin-frappe .button strong{color:inherit}html.theme--catppuccin-frappe .button .icon,html.theme--catppuccin-frappe .button .icon.is-small,html.theme--catppuccin-frappe .button #documenter .docs-sidebar form.docs-search>input.icon,html.theme--catppuccin-frappe #documenter .docs-sidebar .button form.docs-search>input.icon,html.theme--catppuccin-frappe .button .icon.is-medium,html.theme--catppuccin-frappe .button .icon.is-large{height:1.5em;width:1.5em}html.theme--catppuccin-frappe .button .icon:first-child:not(:last-child){margin-left:calc(-0.5em - 1px);margin-right:.25em}html.theme--catppuccin-frappe .button .icon:last-child:not(:first-child){margin-left:.25em;margin-right:calc(-0.5em - 1px)}html.theme--catppuccin-frappe .button .icon:first-child:last-child{margin-left:calc(-0.5em - 1px);margin-right:calc(-0.5em - 1px)}html.theme--catppuccin-frappe .button:hover,html.theme--catppuccin-frappe .button.is-hovered{border-color:#737994;color:#b0bef1}html.theme--catppuccin-frappe .button:focus,html.theme--catppuccin-frappe .button.is-focused{border-color:#737994;color:#769aeb}html.theme--catppuccin-frappe .button:focus:not(:active),html.theme--catppuccin-frappe .button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(140,170,238,0.25)}html.theme--catppuccin-frappe .button:active,html.theme--catppuccin-frappe .button.is-active{border-color:#51576d;color:#b0bef1}html.theme--catppuccin-frappe .button.is-text{background-color:transparent;border-color:transparent;color:#c6d0f5;text-decoration:underline}html.theme--catppuccin-frappe .button.is-text:hover,html.theme--catppuccin-frappe .button.is-text.is-hovered,html.theme--catppuccin-frappe .button.is-text:focus,html.theme--catppuccin-frappe .button.is-text.is-focused{background-color:#292c3c;color:#b0bef1}html.theme--catppuccin-frappe .button.is-text:active,html.theme--catppuccin-frappe .button.is-text.is-active{background-color:#1f212d;color:#b0bef1}html.theme--catppuccin-frappe .button.is-text[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-text{background-color:transparent;border-color:transparent;box-shadow:none}html.theme--catppuccin-frappe .button.is-ghost{background:none;border-color:rgba(0,0,0,0);color:#8caaee;text-decoration:none}html.theme--catppuccin-frappe .button.is-ghost:hover,html.theme--catppuccin-frappe .button.is-ghost.is-hovered{color:#8caaee;text-decoration:underline}html.theme--catppuccin-frappe .button.is-white{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-frappe .button.is-white:hover,html.theme--catppuccin-frappe .button.is-white.is-hovered{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-frappe .button.is-white:focus,html.theme--catppuccin-frappe .button.is-white.is-focused{border-color:transparent;color:#0a0a0a}html.theme--catppuccin-frappe .button.is-white:focus:not(:active),html.theme--catppuccin-frappe .button.is-white.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--catppuccin-frappe .button.is-white:active,html.theme--catppuccin-frappe .button.is-white.is-active{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-frappe .button.is-white[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-white{background-color:#fff;border-color:#fff;box-shadow:none}html.theme--catppuccin-frappe .button.is-white.is-inverted{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-frappe .button.is-white.is-inverted:hover,html.theme--catppuccin-frappe .button.is-white.is-inverted.is-hovered{background-color:#000}html.theme--catppuccin-frappe .button.is-white.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-white.is-inverted{background-color:#0a0a0a;border-color:transparent;box-shadow:none;color:#fff}html.theme--catppuccin-frappe .button.is-white.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--catppuccin-frappe .button.is-white.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-frappe .button.is-white.is-outlined:hover,html.theme--catppuccin-frappe .button.is-white.is-outlined.is-hovered,html.theme--catppuccin-frappe .button.is-white.is-outlined:focus,html.theme--catppuccin-frappe .button.is-white.is-outlined.is-focused{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--catppuccin-frappe .button.is-white.is-outlined.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-frappe .button.is-white.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .button.is-white.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .button.is-white.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .button.is-white.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--catppuccin-frappe .button.is-white.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-white.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-frappe .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--catppuccin-frappe .button.is-white.is-inverted.is-outlined:hover,html.theme--catppuccin-frappe .button.is-white.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-frappe .button.is-white.is-inverted.is-outlined:focus,html.theme--catppuccin-frappe .button.is-white.is-inverted.is-outlined.is-focused{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-frappe .button.is-white.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .button.is-white.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .button.is-white.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-frappe .button.is-white.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--catppuccin-frappe .button.is-black{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-black:hover,html.theme--catppuccin-frappe .button.is-black.is-hovered{background-color:#040404;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-black:focus,html.theme--catppuccin-frappe .button.is-black.is-focused{border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-black:focus:not(:active),html.theme--catppuccin-frappe .button.is-black.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--catppuccin-frappe .button.is-black:active,html.theme--catppuccin-frappe .button.is-black.is-active{background-color:#000;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-black[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-black{background-color:#0a0a0a;border-color:#0a0a0a;box-shadow:none}html.theme--catppuccin-frappe .button.is-black.is-inverted{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-frappe .button.is-black.is-inverted:hover,html.theme--catppuccin-frappe .button.is-black.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--catppuccin-frappe .button.is-black.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-black.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#0a0a0a}html.theme--catppuccin-frappe .button.is-black.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-frappe .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--catppuccin-frappe .button.is-black.is-outlined:hover,html.theme--catppuccin-frappe .button.is-black.is-outlined.is-hovered,html.theme--catppuccin-frappe .button.is-black.is-outlined:focus,html.theme--catppuccin-frappe .button.is-black.is-outlined.is-focused{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--catppuccin-frappe .button.is-black.is-outlined.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--catppuccin-frappe .button.is-black.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .button.is-black.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .button.is-black.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .button.is-black.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-frappe .button.is-black.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--catppuccin-frappe .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-frappe .button.is-black.is-inverted.is-outlined:hover,html.theme--catppuccin-frappe .button.is-black.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-frappe .button.is-black.is-inverted.is-outlined:focus,html.theme--catppuccin-frappe .button.is-black.is-inverted.is-outlined.is-focused{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-frappe .button.is-black.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .button.is-black.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .button.is-black.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--catppuccin-frappe .button.is-black.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-frappe .button.is-light{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-light:hover,html.theme--catppuccin-frappe .button.is-light.is-hovered{background-color:#eee;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-light:focus,html.theme--catppuccin-frappe .button.is-light.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-light:focus:not(:active),html.theme--catppuccin-frappe .button.is-light.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}html.theme--catppuccin-frappe .button.is-light:active,html.theme--catppuccin-frappe .button.is-light.is-active{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-light[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-light{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none}html.theme--catppuccin-frappe .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);color:#f5f5f5}html.theme--catppuccin-frappe .button.is-light.is-inverted:hover,html.theme--catppuccin-frappe .button.is-light.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-light.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#f5f5f5}html.theme--catppuccin-frappe .button.is-light.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-frappe .button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;color:#f5f5f5}html.theme--catppuccin-frappe .button.is-light.is-outlined:hover,html.theme--catppuccin-frappe .button.is-light.is-outlined.is-hovered,html.theme--catppuccin-frappe .button.is-light.is-outlined:focus,html.theme--catppuccin-frappe .button.is-light.is-outlined.is-focused{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-light.is-outlined.is-loading::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}html.theme--catppuccin-frappe .button.is-light.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .button.is-light.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .button.is-light.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .button.is-light.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-frappe .button.is-light.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;box-shadow:none;color:#f5f5f5}html.theme--catppuccin-frappe .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-light.is-inverted.is-outlined:hover,html.theme--catppuccin-frappe .button.is-light.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-frappe .button.is-light.is-inverted.is-outlined:focus,html.theme--catppuccin-frappe .button.is-light.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#f5f5f5}html.theme--catppuccin-frappe .button.is-light.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .button.is-light.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .button.is-light.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}html.theme--catppuccin-frappe .button.is-light.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-dark,html.theme--catppuccin-frappe .content kbd.button{background-color:#414559;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-dark:hover,html.theme--catppuccin-frappe .content kbd.button:hover,html.theme--catppuccin-frappe .button.is-dark.is-hovered,html.theme--catppuccin-frappe .content kbd.button.is-hovered{background-color:#3c3f52;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-dark:focus,html.theme--catppuccin-frappe .content kbd.button:focus,html.theme--catppuccin-frappe .button.is-dark.is-focused,html.theme--catppuccin-frappe .content kbd.button.is-focused{border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-dark:focus:not(:active),html.theme--catppuccin-frappe .content kbd.button:focus:not(:active),html.theme--catppuccin-frappe .button.is-dark.is-focused:not(:active),html.theme--catppuccin-frappe .content kbd.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(65,69,89,0.25)}html.theme--catppuccin-frappe .button.is-dark:active,html.theme--catppuccin-frappe .content kbd.button:active,html.theme--catppuccin-frappe .button.is-dark.is-active,html.theme--catppuccin-frappe .content kbd.button.is-active{background-color:#363a4a;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-dark[disabled],html.theme--catppuccin-frappe .content kbd.button[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-dark,fieldset[disabled] html.theme--catppuccin-frappe .content kbd.button{background-color:#414559;border-color:#414559;box-shadow:none}html.theme--catppuccin-frappe .button.is-dark.is-inverted,html.theme--catppuccin-frappe .content kbd.button.is-inverted{background-color:#fff;color:#414559}html.theme--catppuccin-frappe .button.is-dark.is-inverted:hover,html.theme--catppuccin-frappe .content kbd.button.is-inverted:hover,html.theme--catppuccin-frappe .button.is-dark.is-inverted.is-hovered,html.theme--catppuccin-frappe .content kbd.button.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--catppuccin-frappe .button.is-dark.is-inverted[disabled],html.theme--catppuccin-frappe .content kbd.button.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-dark.is-inverted,fieldset[disabled] html.theme--catppuccin-frappe .content kbd.button.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#414559}html.theme--catppuccin-frappe .button.is-dark.is-loading::after,html.theme--catppuccin-frappe .content kbd.button.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-frappe .button.is-dark.is-outlined,html.theme--catppuccin-frappe .content kbd.button.is-outlined{background-color:transparent;border-color:#414559;color:#414559}html.theme--catppuccin-frappe .button.is-dark.is-outlined:hover,html.theme--catppuccin-frappe .content kbd.button.is-outlined:hover,html.theme--catppuccin-frappe .button.is-dark.is-outlined.is-hovered,html.theme--catppuccin-frappe .content kbd.button.is-outlined.is-hovered,html.theme--catppuccin-frappe .button.is-dark.is-outlined:focus,html.theme--catppuccin-frappe .content kbd.button.is-outlined:focus,html.theme--catppuccin-frappe .button.is-dark.is-outlined.is-focused,html.theme--catppuccin-frappe .content kbd.button.is-outlined.is-focused{background-color:#414559;border-color:#414559;color:#fff}html.theme--catppuccin-frappe .button.is-dark.is-outlined.is-loading::after,html.theme--catppuccin-frappe .content kbd.button.is-outlined.is-loading::after{border-color:transparent transparent #414559 #414559 !important}html.theme--catppuccin-frappe .button.is-dark.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .content kbd.button.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .button.is-dark.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .content kbd.button.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .button.is-dark.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .content kbd.button.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .button.is-dark.is-outlined.is-loading.is-focused::after,html.theme--catppuccin-frappe .content kbd.button.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-frappe .button.is-dark.is-outlined[disabled],html.theme--catppuccin-frappe .content kbd.button.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-dark.is-outlined,fieldset[disabled] html.theme--catppuccin-frappe .content kbd.button.is-outlined{background-color:transparent;border-color:#414559;box-shadow:none;color:#414559}html.theme--catppuccin-frappe .button.is-dark.is-inverted.is-outlined,html.theme--catppuccin-frappe .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-frappe .button.is-dark.is-inverted.is-outlined:hover,html.theme--catppuccin-frappe .content kbd.button.is-inverted.is-outlined:hover,html.theme--catppuccin-frappe .button.is-dark.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-frappe .content kbd.button.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-frappe .button.is-dark.is-inverted.is-outlined:focus,html.theme--catppuccin-frappe .content kbd.button.is-inverted.is-outlined:focus,html.theme--catppuccin-frappe .button.is-dark.is-inverted.is-outlined.is-focused,html.theme--catppuccin-frappe .content kbd.button.is-inverted.is-outlined.is-focused{background-color:#fff;color:#414559}html.theme--catppuccin-frappe .button.is-dark.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .content kbd.button.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .content kbd.button.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .button.is-dark.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .content kbd.button.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--catppuccin-frappe .content kbd.button.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #414559 #414559 !important}html.theme--catppuccin-frappe .button.is-dark.is-inverted.is-outlined[disabled],html.theme--catppuccin-frappe .content kbd.button.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-dark.is-inverted.is-outlined,fieldset[disabled] html.theme--catppuccin-frappe .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-frappe .button.is-primary,html.theme--catppuccin-frappe .docstring>section>a.button.docs-sourcelink{background-color:#8caaee;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-primary:hover,html.theme--catppuccin-frappe .docstring>section>a.button.docs-sourcelink:hover,html.theme--catppuccin-frappe .button.is-primary.is-hovered,html.theme--catppuccin-frappe .docstring>section>a.button.is-hovered.docs-sourcelink{background-color:#81a2ec;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-primary:focus,html.theme--catppuccin-frappe .docstring>section>a.button.docs-sourcelink:focus,html.theme--catppuccin-frappe .button.is-primary.is-focused,html.theme--catppuccin-frappe .docstring>section>a.button.is-focused.docs-sourcelink{border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-primary:focus:not(:active),html.theme--catppuccin-frappe .docstring>section>a.button.docs-sourcelink:focus:not(:active),html.theme--catppuccin-frappe .button.is-primary.is-focused:not(:active),html.theme--catppuccin-frappe .docstring>section>a.button.is-focused.docs-sourcelink:not(:active){box-shadow:0 0 0 0.125em rgba(140,170,238,0.25)}html.theme--catppuccin-frappe .button.is-primary:active,html.theme--catppuccin-frappe .docstring>section>a.button.docs-sourcelink:active,html.theme--catppuccin-frappe .button.is-primary.is-active,html.theme--catppuccin-frappe .docstring>section>a.button.is-active.docs-sourcelink{background-color:#769aeb;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-primary[disabled],html.theme--catppuccin-frappe .docstring>section>a.button.docs-sourcelink[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-primary,fieldset[disabled] html.theme--catppuccin-frappe .docstring>section>a.button.docs-sourcelink{background-color:#8caaee;border-color:#8caaee;box-shadow:none}html.theme--catppuccin-frappe .button.is-primary.is-inverted,html.theme--catppuccin-frappe .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;color:#8caaee}html.theme--catppuccin-frappe .button.is-primary.is-inverted:hover,html.theme--catppuccin-frappe .docstring>section>a.button.is-inverted.docs-sourcelink:hover,html.theme--catppuccin-frappe .button.is-primary.is-inverted.is-hovered,html.theme--catppuccin-frappe .docstring>section>a.button.is-inverted.is-hovered.docs-sourcelink{background-color:#f2f2f2}html.theme--catppuccin-frappe .button.is-primary.is-inverted[disabled],html.theme--catppuccin-frappe .docstring>section>a.button.is-inverted.docs-sourcelink[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-primary.is-inverted,fieldset[disabled] html.theme--catppuccin-frappe .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;border-color:transparent;box-shadow:none;color:#8caaee}html.theme--catppuccin-frappe .button.is-primary.is-loading::after,html.theme--catppuccin-frappe .docstring>section>a.button.is-loading.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-frappe .button.is-primary.is-outlined,html.theme--catppuccin-frappe .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#8caaee;color:#8caaee}html.theme--catppuccin-frappe .button.is-primary.is-outlined:hover,html.theme--catppuccin-frappe .docstring>section>a.button.is-outlined.docs-sourcelink:hover,html.theme--catppuccin-frappe .button.is-primary.is-outlined.is-hovered,html.theme--catppuccin-frappe .docstring>section>a.button.is-outlined.is-hovered.docs-sourcelink,html.theme--catppuccin-frappe .button.is-primary.is-outlined:focus,html.theme--catppuccin-frappe .docstring>section>a.button.is-outlined.docs-sourcelink:focus,html.theme--catppuccin-frappe .button.is-primary.is-outlined.is-focused,html.theme--catppuccin-frappe .docstring>section>a.button.is-outlined.is-focused.docs-sourcelink{background-color:#8caaee;border-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .button.is-primary.is-outlined.is-loading::after,html.theme--catppuccin-frappe .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink::after{border-color:transparent transparent #8caaee #8caaee !important}html.theme--catppuccin-frappe .button.is-primary.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--catppuccin-frappe .button.is-primary.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .docstring>section>a.button.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--catppuccin-frappe .button.is-primary.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--catppuccin-frappe .button.is-primary.is-outlined.is-loading.is-focused::after,html.theme--catppuccin-frappe .docstring>section>a.button.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-frappe .button.is-primary.is-outlined[disabled],html.theme--catppuccin-frappe .docstring>section>a.button.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-primary.is-outlined,fieldset[disabled] html.theme--catppuccin-frappe .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#8caaee;box-shadow:none;color:#8caaee}html.theme--catppuccin-frappe .button.is-primary.is-inverted.is-outlined,html.theme--catppuccin-frappe .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-frappe .button.is-primary.is-inverted.is-outlined:hover,html.theme--catppuccin-frappe .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:hover,html.theme--catppuccin-frappe .button.is-primary.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-frappe .docstring>section>a.button.is-inverted.is-outlined.is-hovered.docs-sourcelink,html.theme--catppuccin-frappe .button.is-primary.is-inverted.is-outlined:focus,html.theme--catppuccin-frappe .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:focus,html.theme--catppuccin-frappe .button.is-primary.is-inverted.is-outlined.is-focused,html.theme--catppuccin-frappe .docstring>section>a.button.is-inverted.is-outlined.is-focused.docs-sourcelink{background-color:#fff;color:#8caaee}html.theme--catppuccin-frappe .button.is-primary.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--catppuccin-frappe .button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--catppuccin-frappe .button.is-primary.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--catppuccin-frappe .button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--catppuccin-frappe .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #8caaee #8caaee !important}html.theme--catppuccin-frappe .button.is-primary.is-inverted.is-outlined[disabled],html.theme--catppuccin-frappe .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-primary.is-inverted.is-outlined,fieldset[disabled] html.theme--catppuccin-frappe .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-frappe .button.is-primary.is-light,html.theme--catppuccin-frappe .docstring>section>a.button.is-light.docs-sourcelink{background-color:#edf2fc;color:#153a8e}html.theme--catppuccin-frappe .button.is-primary.is-light:hover,html.theme--catppuccin-frappe .docstring>section>a.button.is-light.docs-sourcelink:hover,html.theme--catppuccin-frappe .button.is-primary.is-light.is-hovered,html.theme--catppuccin-frappe .docstring>section>a.button.is-light.is-hovered.docs-sourcelink{background-color:#e2eafb;border-color:transparent;color:#153a8e}html.theme--catppuccin-frappe .button.is-primary.is-light:active,html.theme--catppuccin-frappe .docstring>section>a.button.is-light.docs-sourcelink:active,html.theme--catppuccin-frappe .button.is-primary.is-light.is-active,html.theme--catppuccin-frappe .docstring>section>a.button.is-light.is-active.docs-sourcelink{background-color:#d7e1f9;border-color:transparent;color:#153a8e}html.theme--catppuccin-frappe .button.is-link{background-color:#8caaee;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-link:hover,html.theme--catppuccin-frappe .button.is-link.is-hovered{background-color:#81a2ec;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-link:focus,html.theme--catppuccin-frappe .button.is-link.is-focused{border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-link:focus:not(:active),html.theme--catppuccin-frappe .button.is-link.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(140,170,238,0.25)}html.theme--catppuccin-frappe .button.is-link:active,html.theme--catppuccin-frappe .button.is-link.is-active{background-color:#769aeb;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-link[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-link{background-color:#8caaee;border-color:#8caaee;box-shadow:none}html.theme--catppuccin-frappe .button.is-link.is-inverted{background-color:#fff;color:#8caaee}html.theme--catppuccin-frappe .button.is-link.is-inverted:hover,html.theme--catppuccin-frappe .button.is-link.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--catppuccin-frappe .button.is-link.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-link.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#8caaee}html.theme--catppuccin-frappe .button.is-link.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-frappe .button.is-link.is-outlined{background-color:transparent;border-color:#8caaee;color:#8caaee}html.theme--catppuccin-frappe .button.is-link.is-outlined:hover,html.theme--catppuccin-frappe .button.is-link.is-outlined.is-hovered,html.theme--catppuccin-frappe .button.is-link.is-outlined:focus,html.theme--catppuccin-frappe .button.is-link.is-outlined.is-focused{background-color:#8caaee;border-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .button.is-link.is-outlined.is-loading::after{border-color:transparent transparent #8caaee #8caaee !important}html.theme--catppuccin-frappe .button.is-link.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .button.is-link.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .button.is-link.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .button.is-link.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-frappe .button.is-link.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-link.is-outlined{background-color:transparent;border-color:#8caaee;box-shadow:none;color:#8caaee}html.theme--catppuccin-frappe .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-frappe .button.is-link.is-inverted.is-outlined:hover,html.theme--catppuccin-frappe .button.is-link.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-frappe .button.is-link.is-inverted.is-outlined:focus,html.theme--catppuccin-frappe .button.is-link.is-inverted.is-outlined.is-focused{background-color:#fff;color:#8caaee}html.theme--catppuccin-frappe .button.is-link.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .button.is-link.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .button.is-link.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #8caaee #8caaee !important}html.theme--catppuccin-frappe .button.is-link.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-frappe .button.is-link.is-light{background-color:#edf2fc;color:#153a8e}html.theme--catppuccin-frappe .button.is-link.is-light:hover,html.theme--catppuccin-frappe .button.is-link.is-light.is-hovered{background-color:#e2eafb;border-color:transparent;color:#153a8e}html.theme--catppuccin-frappe .button.is-link.is-light:active,html.theme--catppuccin-frappe .button.is-link.is-light.is-active{background-color:#d7e1f9;border-color:transparent;color:#153a8e}html.theme--catppuccin-frappe .button.is-info{background-color:#81c8be;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-info:hover,html.theme--catppuccin-frappe .button.is-info.is-hovered{background-color:#78c4b9;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-info:focus,html.theme--catppuccin-frappe .button.is-info.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-info:focus:not(:active),html.theme--catppuccin-frappe .button.is-info.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(129,200,190,0.25)}html.theme--catppuccin-frappe .button.is-info:active,html.theme--catppuccin-frappe .button.is-info.is-active{background-color:#6fc0b5;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-info[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-info{background-color:#81c8be;border-color:#81c8be;box-shadow:none}html.theme--catppuccin-frappe .button.is-info.is-inverted{background-color:rgba(0,0,0,0.7);color:#81c8be}html.theme--catppuccin-frappe .button.is-info.is-inverted:hover,html.theme--catppuccin-frappe .button.is-info.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-info.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-info.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#81c8be}html.theme--catppuccin-frappe .button.is-info.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-frappe .button.is-info.is-outlined{background-color:transparent;border-color:#81c8be;color:#81c8be}html.theme--catppuccin-frappe .button.is-info.is-outlined:hover,html.theme--catppuccin-frappe .button.is-info.is-outlined.is-hovered,html.theme--catppuccin-frappe .button.is-info.is-outlined:focus,html.theme--catppuccin-frappe .button.is-info.is-outlined.is-focused{background-color:#81c8be;border-color:#81c8be;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-info.is-outlined.is-loading::after{border-color:transparent transparent #81c8be #81c8be !important}html.theme--catppuccin-frappe .button.is-info.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .button.is-info.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .button.is-info.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .button.is-info.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-frappe .button.is-info.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-info.is-outlined{background-color:transparent;border-color:#81c8be;box-shadow:none;color:#81c8be}html.theme--catppuccin-frappe .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-info.is-inverted.is-outlined:hover,html.theme--catppuccin-frappe .button.is-info.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-frappe .button.is-info.is-inverted.is-outlined:focus,html.theme--catppuccin-frappe .button.is-info.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#81c8be}html.theme--catppuccin-frappe .button.is-info.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .button.is-info.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .button.is-info.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #81c8be #81c8be !important}html.theme--catppuccin-frappe .button.is-info.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-info.is-light{background-color:#f1f9f8;color:#2d675f}html.theme--catppuccin-frappe .button.is-info.is-light:hover,html.theme--catppuccin-frappe .button.is-info.is-light.is-hovered{background-color:#e8f5f3;border-color:transparent;color:#2d675f}html.theme--catppuccin-frappe .button.is-info.is-light:active,html.theme--catppuccin-frappe .button.is-info.is-light.is-active{background-color:#dff1ef;border-color:transparent;color:#2d675f}html.theme--catppuccin-frappe .button.is-success{background-color:#a6d189;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-success:hover,html.theme--catppuccin-frappe .button.is-success.is-hovered{background-color:#9fcd80;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-success:focus,html.theme--catppuccin-frappe .button.is-success.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-success:focus:not(:active),html.theme--catppuccin-frappe .button.is-success.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(166,209,137,0.25)}html.theme--catppuccin-frappe .button.is-success:active,html.theme--catppuccin-frappe .button.is-success.is-active{background-color:#98ca77;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-success[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-success{background-color:#a6d189;border-color:#a6d189;box-shadow:none}html.theme--catppuccin-frappe .button.is-success.is-inverted{background-color:rgba(0,0,0,0.7);color:#a6d189}html.theme--catppuccin-frappe .button.is-success.is-inverted:hover,html.theme--catppuccin-frappe .button.is-success.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-success.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-success.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#a6d189}html.theme--catppuccin-frappe .button.is-success.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-frappe .button.is-success.is-outlined{background-color:transparent;border-color:#a6d189;color:#a6d189}html.theme--catppuccin-frappe .button.is-success.is-outlined:hover,html.theme--catppuccin-frappe .button.is-success.is-outlined.is-hovered,html.theme--catppuccin-frappe .button.is-success.is-outlined:focus,html.theme--catppuccin-frappe .button.is-success.is-outlined.is-focused{background-color:#a6d189;border-color:#a6d189;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-success.is-outlined.is-loading::after{border-color:transparent transparent #a6d189 #a6d189 !important}html.theme--catppuccin-frappe .button.is-success.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .button.is-success.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .button.is-success.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .button.is-success.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-frappe .button.is-success.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-success.is-outlined{background-color:transparent;border-color:#a6d189;box-shadow:none;color:#a6d189}html.theme--catppuccin-frappe .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-success.is-inverted.is-outlined:hover,html.theme--catppuccin-frappe .button.is-success.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-frappe .button.is-success.is-inverted.is-outlined:focus,html.theme--catppuccin-frappe .button.is-success.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#a6d189}html.theme--catppuccin-frappe .button.is-success.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .button.is-success.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .button.is-success.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #a6d189 #a6d189 !important}html.theme--catppuccin-frappe .button.is-success.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-success.is-light{background-color:#f4f9f0;color:#446a29}html.theme--catppuccin-frappe .button.is-success.is-light:hover,html.theme--catppuccin-frappe .button.is-success.is-light.is-hovered{background-color:#edf6e7;border-color:transparent;color:#446a29}html.theme--catppuccin-frappe .button.is-success.is-light:active,html.theme--catppuccin-frappe .button.is-success.is-light.is-active{background-color:#e6f2de;border-color:transparent;color:#446a29}html.theme--catppuccin-frappe .button.is-warning{background-color:#e5c890;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-warning:hover,html.theme--catppuccin-frappe .button.is-warning.is-hovered{background-color:#e3c386;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-warning:focus,html.theme--catppuccin-frappe .button.is-warning.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-warning:focus:not(:active),html.theme--catppuccin-frappe .button.is-warning.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(229,200,144,0.25)}html.theme--catppuccin-frappe .button.is-warning:active,html.theme--catppuccin-frappe .button.is-warning.is-active{background-color:#e0be7b;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-warning[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-warning{background-color:#e5c890;border-color:#e5c890;box-shadow:none}html.theme--catppuccin-frappe .button.is-warning.is-inverted{background-color:rgba(0,0,0,0.7);color:#e5c890}html.theme--catppuccin-frappe .button.is-warning.is-inverted:hover,html.theme--catppuccin-frappe .button.is-warning.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-warning.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-warning.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#e5c890}html.theme--catppuccin-frappe .button.is-warning.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-frappe .button.is-warning.is-outlined{background-color:transparent;border-color:#e5c890;color:#e5c890}html.theme--catppuccin-frappe .button.is-warning.is-outlined:hover,html.theme--catppuccin-frappe .button.is-warning.is-outlined.is-hovered,html.theme--catppuccin-frappe .button.is-warning.is-outlined:focus,html.theme--catppuccin-frappe .button.is-warning.is-outlined.is-focused{background-color:#e5c890;border-color:#e5c890;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-warning.is-outlined.is-loading::after{border-color:transparent transparent #e5c890 #e5c890 !important}html.theme--catppuccin-frappe .button.is-warning.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .button.is-warning.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .button.is-warning.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .button.is-warning.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-frappe .button.is-warning.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-warning.is-outlined{background-color:transparent;border-color:#e5c890;box-shadow:none;color:#e5c890}html.theme--catppuccin-frappe .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-warning.is-inverted.is-outlined:hover,html.theme--catppuccin-frappe .button.is-warning.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-frappe .button.is-warning.is-inverted.is-outlined:focus,html.theme--catppuccin-frappe .button.is-warning.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#e5c890}html.theme--catppuccin-frappe .button.is-warning.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .button.is-warning.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #e5c890 #e5c890 !important}html.theme--catppuccin-frappe .button.is-warning.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .button.is-warning.is-light{background-color:#fbf7ee;color:#78591c}html.theme--catppuccin-frappe .button.is-warning.is-light:hover,html.theme--catppuccin-frappe .button.is-warning.is-light.is-hovered{background-color:#f9f2e4;border-color:transparent;color:#78591c}html.theme--catppuccin-frappe .button.is-warning.is-light:active,html.theme--catppuccin-frappe .button.is-warning.is-light.is-active{background-color:#f6edda;border-color:transparent;color:#78591c}html.theme--catppuccin-frappe .button.is-danger{background-color:#e78284;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-danger:hover,html.theme--catppuccin-frappe .button.is-danger.is-hovered{background-color:#e57779;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-danger:focus,html.theme--catppuccin-frappe .button.is-danger.is-focused{border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-danger:focus:not(:active),html.theme--catppuccin-frappe .button.is-danger.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(231,130,132,0.25)}html.theme--catppuccin-frappe .button.is-danger:active,html.theme--catppuccin-frappe .button.is-danger.is-active{background-color:#e36d6f;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .button.is-danger[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-danger{background-color:#e78284;border-color:#e78284;box-shadow:none}html.theme--catppuccin-frappe .button.is-danger.is-inverted{background-color:#fff;color:#e78284}html.theme--catppuccin-frappe .button.is-danger.is-inverted:hover,html.theme--catppuccin-frappe .button.is-danger.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--catppuccin-frappe .button.is-danger.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-danger.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#e78284}html.theme--catppuccin-frappe .button.is-danger.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-frappe .button.is-danger.is-outlined{background-color:transparent;border-color:#e78284;color:#e78284}html.theme--catppuccin-frappe .button.is-danger.is-outlined:hover,html.theme--catppuccin-frappe .button.is-danger.is-outlined.is-hovered,html.theme--catppuccin-frappe .button.is-danger.is-outlined:focus,html.theme--catppuccin-frappe .button.is-danger.is-outlined.is-focused{background-color:#e78284;border-color:#e78284;color:#fff}html.theme--catppuccin-frappe .button.is-danger.is-outlined.is-loading::after{border-color:transparent transparent #e78284 #e78284 !important}html.theme--catppuccin-frappe .button.is-danger.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .button.is-danger.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .button.is-danger.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .button.is-danger.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-frappe .button.is-danger.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-danger.is-outlined{background-color:transparent;border-color:#e78284;box-shadow:none;color:#e78284}html.theme--catppuccin-frappe .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-frappe .button.is-danger.is-inverted.is-outlined:hover,html.theme--catppuccin-frappe .button.is-danger.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-frappe .button.is-danger.is-inverted.is-outlined:focus,html.theme--catppuccin-frappe .button.is-danger.is-inverted.is-outlined.is-focused{background-color:#fff;color:#e78284}html.theme--catppuccin-frappe .button.is-danger.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-frappe .button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-frappe .button.is-danger.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-frappe .button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #e78284 #e78284 !important}html.theme--catppuccin-frappe .button.is-danger.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-frappe .button.is-danger.is-light{background-color:#fceeee;color:#9a1e20}html.theme--catppuccin-frappe .button.is-danger.is-light:hover,html.theme--catppuccin-frappe .button.is-danger.is-light.is-hovered{background-color:#fae3e4;border-color:transparent;color:#9a1e20}html.theme--catppuccin-frappe .button.is-danger.is-light:active,html.theme--catppuccin-frappe .button.is-danger.is-light.is-active{background-color:#f8d8d9;border-color:transparent;color:#9a1e20}html.theme--catppuccin-frappe .button.is-small,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.button{font-size:.75rem}html.theme--catppuccin-frappe .button.is-small:not(.is-rounded),html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.button:not(.is-rounded){border-radius:3px}html.theme--catppuccin-frappe .button.is-normal{font-size:1rem}html.theme--catppuccin-frappe .button.is-medium{font-size:1.25rem}html.theme--catppuccin-frappe .button.is-large{font-size:1.5rem}html.theme--catppuccin-frappe .button[disabled],fieldset[disabled] html.theme--catppuccin-frappe .button{background-color:#737994;border-color:#626880;box-shadow:none;opacity:.5}html.theme--catppuccin-frappe .button.is-fullwidth{display:flex;width:100%}html.theme--catppuccin-frappe .button.is-loading{color:transparent !important;pointer-events:none}html.theme--catppuccin-frappe .button.is-loading::after{position:absolute;left:calc(50% - (1em * 0.5));top:calc(50% - (1em * 0.5));position:absolute !important}html.theme--catppuccin-frappe .button.is-static{background-color:#292c3c;border-color:#626880;color:#838ba7;box-shadow:none;pointer-events:none}html.theme--catppuccin-frappe .button.is-rounded,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.button{border-radius:9999px;padding-left:calc(1em + 0.25em);padding-right:calc(1em + 0.25em)}html.theme--catppuccin-frappe .buttons{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--catppuccin-frappe .buttons .button{margin-bottom:0.5rem}html.theme--catppuccin-frappe .buttons .button:not(:last-child):not(.is-fullwidth){margin-right:.5rem}html.theme--catppuccin-frappe .buttons:last-child{margin-bottom:-0.5rem}html.theme--catppuccin-frappe .buttons:not(:last-child){margin-bottom:1rem}html.theme--catppuccin-frappe .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large){font-size:.75rem}html.theme--catppuccin-frappe .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large):not(.is-rounded){border-radius:3px}html.theme--catppuccin-frappe .buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large){font-size:1.25rem}html.theme--catppuccin-frappe .buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium){font-size:1.5rem}html.theme--catppuccin-frappe .buttons.has-addons .button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}html.theme--catppuccin-frappe .buttons.has-addons .button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}html.theme--catppuccin-frappe .buttons.has-addons .button:last-child{margin-right:0}html.theme--catppuccin-frappe .buttons.has-addons .button:hover,html.theme--catppuccin-frappe .buttons.has-addons .button.is-hovered{z-index:2}html.theme--catppuccin-frappe .buttons.has-addons .button:focus,html.theme--catppuccin-frappe .buttons.has-addons .button.is-focused,html.theme--catppuccin-frappe .buttons.has-addons .button:active,html.theme--catppuccin-frappe .buttons.has-addons .button.is-active,html.theme--catppuccin-frappe .buttons.has-addons .button.is-selected{z-index:3}html.theme--catppuccin-frappe .buttons.has-addons .button:focus:hover,html.theme--catppuccin-frappe .buttons.has-addons .button.is-focused:hover,html.theme--catppuccin-frappe .buttons.has-addons .button:active:hover,html.theme--catppuccin-frappe .buttons.has-addons .button.is-active:hover,html.theme--catppuccin-frappe .buttons.has-addons .button.is-selected:hover{z-index:4}html.theme--catppuccin-frappe .buttons.has-addons .button.is-expanded{flex-grow:1;flex-shrink:1}html.theme--catppuccin-frappe .buttons.is-centered{justify-content:center}html.theme--catppuccin-frappe .buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}html.theme--catppuccin-frappe .buttons.is-right{justify-content:flex-end}html.theme--catppuccin-frappe .buttons.is-right:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .button.is-responsive.is-small,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.5625rem}html.theme--catppuccin-frappe .button.is-responsive,html.theme--catppuccin-frappe .button.is-responsive.is-normal{font-size:.65625rem}html.theme--catppuccin-frappe .button.is-responsive.is-medium{font-size:.75rem}html.theme--catppuccin-frappe .button.is-responsive.is-large{font-size:1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-frappe .button.is-responsive.is-small,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.65625rem}html.theme--catppuccin-frappe .button.is-responsive,html.theme--catppuccin-frappe .button.is-responsive.is-normal{font-size:.75rem}html.theme--catppuccin-frappe .button.is-responsive.is-medium{font-size:1rem}html.theme--catppuccin-frappe .button.is-responsive.is-large{font-size:1.25rem}}html.theme--catppuccin-frappe .container{flex-grow:1;margin:0 auto;position:relative;width:auto}html.theme--catppuccin-frappe .container.is-fluid{max-width:none !important;padding-left:32px;padding-right:32px;width:100%}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .container{max-width:992px}}@media screen and (max-width: 1215px){html.theme--catppuccin-frappe .container.is-widescreen:not(.is-max-desktop){max-width:1152px}}@media screen and (max-width: 1407px){html.theme--catppuccin-frappe .container.is-fullhd:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}@media screen and (min-width: 1216px){html.theme--catppuccin-frappe .container:not(.is-max-desktop){max-width:1152px}}@media screen and (min-width: 1408px){html.theme--catppuccin-frappe .container:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}html.theme--catppuccin-frappe .content li+li{margin-top:0.25em}html.theme--catppuccin-frappe .content p:not(:last-child),html.theme--catppuccin-frappe .content dl:not(:last-child),html.theme--catppuccin-frappe .content ol:not(:last-child),html.theme--catppuccin-frappe .content ul:not(:last-child),html.theme--catppuccin-frappe .content blockquote:not(:last-child),html.theme--catppuccin-frappe .content pre:not(:last-child),html.theme--catppuccin-frappe .content table:not(:last-child){margin-bottom:1em}html.theme--catppuccin-frappe .content h1,html.theme--catppuccin-frappe .content h2,html.theme--catppuccin-frappe .content h3,html.theme--catppuccin-frappe .content h4,html.theme--catppuccin-frappe .content h5,html.theme--catppuccin-frappe .content h6{color:#c6d0f5;font-weight:600;line-height:1.125}html.theme--catppuccin-frappe .content h1{font-size:2em;margin-bottom:0.5em}html.theme--catppuccin-frappe .content h1:not(:first-child){margin-top:1em}html.theme--catppuccin-frappe .content h2{font-size:1.75em;margin-bottom:0.5714em}html.theme--catppuccin-frappe .content h2:not(:first-child){margin-top:1.1428em}html.theme--catppuccin-frappe .content h3{font-size:1.5em;margin-bottom:0.6666em}html.theme--catppuccin-frappe .content h3:not(:first-child){margin-top:1.3333em}html.theme--catppuccin-frappe .content h4{font-size:1.25em;margin-bottom:0.8em}html.theme--catppuccin-frappe .content h5{font-size:1.125em;margin-bottom:0.8888em}html.theme--catppuccin-frappe .content h6{font-size:1em;margin-bottom:1em}html.theme--catppuccin-frappe .content blockquote{background-color:#292c3c;border-left:5px solid #626880;padding:1.25em 1.5em}html.theme--catppuccin-frappe .content ol{list-style-position:outside;margin-left:2em;margin-top:1em}html.theme--catppuccin-frappe .content ol:not([type]){list-style-type:decimal}html.theme--catppuccin-frappe .content ol.is-lower-alpha:not([type]){list-style-type:lower-alpha}html.theme--catppuccin-frappe .content ol.is-lower-roman:not([type]){list-style-type:lower-roman}html.theme--catppuccin-frappe .content ol.is-upper-alpha:not([type]){list-style-type:upper-alpha}html.theme--catppuccin-frappe .content ol.is-upper-roman:not([type]){list-style-type:upper-roman}html.theme--catppuccin-frappe .content ul{list-style:disc outside;margin-left:2em;margin-top:1em}html.theme--catppuccin-frappe .content ul ul{list-style-type:circle;margin-top:0.5em}html.theme--catppuccin-frappe .content ul ul ul{list-style-type:square}html.theme--catppuccin-frappe .content dd{margin-left:2em}html.theme--catppuccin-frappe .content figure{margin-left:2em;margin-right:2em;text-align:center}html.theme--catppuccin-frappe .content figure:not(:first-child){margin-top:2em}html.theme--catppuccin-frappe .content figure:not(:last-child){margin-bottom:2em}html.theme--catppuccin-frappe .content figure img{display:inline-block}html.theme--catppuccin-frappe .content figure figcaption{font-style:italic}html.theme--catppuccin-frappe .content pre{-webkit-overflow-scrolling:touch;overflow-x:auto;padding:0;white-space:pre;word-wrap:normal}html.theme--catppuccin-frappe .content sup,html.theme--catppuccin-frappe .content sub{font-size:75%}html.theme--catppuccin-frappe .content table{width:100%}html.theme--catppuccin-frappe .content table td,html.theme--catppuccin-frappe .content table th{border:1px solid #626880;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--catppuccin-frappe .content table th{color:#b0bef1}html.theme--catppuccin-frappe .content table th:not([align]){text-align:inherit}html.theme--catppuccin-frappe .content table thead td,html.theme--catppuccin-frappe .content table thead th{border-width:0 0 2px;color:#b0bef1}html.theme--catppuccin-frappe .content table tfoot td,html.theme--catppuccin-frappe .content table tfoot th{border-width:2px 0 0;color:#b0bef1}html.theme--catppuccin-frappe .content table tbody tr:last-child td,html.theme--catppuccin-frappe .content table tbody tr:last-child th{border-bottom-width:0}html.theme--catppuccin-frappe .content .tabs li+li{margin-top:0}html.theme--catppuccin-frappe .content.is-small,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.content{font-size:.75rem}html.theme--catppuccin-frappe .content.is-normal{font-size:1rem}html.theme--catppuccin-frappe .content.is-medium{font-size:1.25rem}html.theme--catppuccin-frappe .content.is-large{font-size:1.5rem}html.theme--catppuccin-frappe .icon{align-items:center;display:inline-flex;justify-content:center;height:1.5rem;width:1.5rem}html.theme--catppuccin-frappe .icon.is-small,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.icon{height:1rem;width:1rem}html.theme--catppuccin-frappe .icon.is-medium{height:2rem;width:2rem}html.theme--catppuccin-frappe .icon.is-large{height:3rem;width:3rem}html.theme--catppuccin-frappe .icon-text{align-items:flex-start;color:inherit;display:inline-flex;flex-wrap:wrap;line-height:1.5rem;vertical-align:top}html.theme--catppuccin-frappe .icon-text .icon{flex-grow:0;flex-shrink:0}html.theme--catppuccin-frappe .icon-text .icon:not(:last-child){margin-right:.25em}html.theme--catppuccin-frappe .icon-text .icon:not(:first-child){margin-left:.25em}html.theme--catppuccin-frappe div.icon-text{display:flex}html.theme--catppuccin-frappe .image,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img{display:block;position:relative}html.theme--catppuccin-frappe .image img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img img{display:block;height:auto;width:100%}html.theme--catppuccin-frappe .image img.is-rounded,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img img.is-rounded{border-radius:9999px}html.theme--catppuccin-frappe .image.is-fullwidth,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-fullwidth{width:100%}html.theme--catppuccin-frappe .image.is-square img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--catppuccin-frappe .image.is-square .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--catppuccin-frappe .image.is-1by1 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--catppuccin-frappe .image.is-1by1 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--catppuccin-frappe .image.is-5by4 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--catppuccin-frappe .image.is-5by4 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--catppuccin-frappe .image.is-4by3 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--catppuccin-frappe .image.is-4by3 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--catppuccin-frappe .image.is-3by2 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--catppuccin-frappe .image.is-3by2 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--catppuccin-frappe .image.is-5by3 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--catppuccin-frappe .image.is-5by3 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--catppuccin-frappe .image.is-16by9 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--catppuccin-frappe .image.is-16by9 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--catppuccin-frappe .image.is-2by1 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--catppuccin-frappe .image.is-2by1 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--catppuccin-frappe .image.is-3by1 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--catppuccin-frappe .image.is-3by1 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--catppuccin-frappe .image.is-4by5 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--catppuccin-frappe .image.is-4by5 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--catppuccin-frappe .image.is-3by4 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--catppuccin-frappe .image.is-3by4 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--catppuccin-frappe .image.is-2by3 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--catppuccin-frappe .image.is-2by3 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--catppuccin-frappe .image.is-3by5 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--catppuccin-frappe .image.is-3by5 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--catppuccin-frappe .image.is-9by16 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--catppuccin-frappe .image.is-9by16 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--catppuccin-frappe .image.is-1by2 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--catppuccin-frappe .image.is-1by2 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--catppuccin-frappe .image.is-1by3 img,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--catppuccin-frappe .image.is-1by3 .has-ratio,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio{height:100%;width:100%}html.theme--catppuccin-frappe .image.is-square,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-square,html.theme--catppuccin-frappe .image.is-1by1,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-1by1{padding-top:100%}html.theme--catppuccin-frappe .image.is-5by4,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-5by4{padding-top:80%}html.theme--catppuccin-frappe .image.is-4by3,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-4by3{padding-top:75%}html.theme--catppuccin-frappe .image.is-3by2,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by2{padding-top:66.6666%}html.theme--catppuccin-frappe .image.is-5by3,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-5by3{padding-top:60%}html.theme--catppuccin-frappe .image.is-16by9,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-16by9{padding-top:56.25%}html.theme--catppuccin-frappe .image.is-2by1,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-2by1{padding-top:50%}html.theme--catppuccin-frappe .image.is-3by1,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by1{padding-top:33.3333%}html.theme--catppuccin-frappe .image.is-4by5,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-4by5{padding-top:125%}html.theme--catppuccin-frappe .image.is-3by4,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by4{padding-top:133.3333%}html.theme--catppuccin-frappe .image.is-2by3,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-2by3{padding-top:150%}html.theme--catppuccin-frappe .image.is-3by5,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-3by5{padding-top:166.6666%}html.theme--catppuccin-frappe .image.is-9by16,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-9by16{padding-top:177.7777%}html.theme--catppuccin-frappe .image.is-1by2,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-1by2{padding-top:200%}html.theme--catppuccin-frappe .image.is-1by3,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-1by3{padding-top:300%}html.theme--catppuccin-frappe .image.is-16x16,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-16x16{height:16px;width:16px}html.theme--catppuccin-frappe .image.is-24x24,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-24x24{height:24px;width:24px}html.theme--catppuccin-frappe .image.is-32x32,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-32x32{height:32px;width:32px}html.theme--catppuccin-frappe .image.is-48x48,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-48x48{height:48px;width:48px}html.theme--catppuccin-frappe .image.is-64x64,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-64x64{height:64px;width:64px}html.theme--catppuccin-frappe .image.is-96x96,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-96x96{height:96px;width:96px}html.theme--catppuccin-frappe .image.is-128x128,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img.is-128x128{height:128px;width:128px}html.theme--catppuccin-frappe .notification{background-color:#292c3c;border-radius:.4em;position:relative;padding:1.25rem 2.5rem 1.25rem 1.5rem}html.theme--catppuccin-frappe .notification a:not(.button):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--catppuccin-frappe .notification strong{color:currentColor}html.theme--catppuccin-frappe .notification code,html.theme--catppuccin-frappe .notification pre{background:#fff}html.theme--catppuccin-frappe .notification pre code{background:transparent}html.theme--catppuccin-frappe .notification>.delete{right:.5rem;position:absolute;top:0.5rem}html.theme--catppuccin-frappe .notification .title,html.theme--catppuccin-frappe .notification .subtitle,html.theme--catppuccin-frappe .notification .content{color:currentColor}html.theme--catppuccin-frappe .notification.is-white{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-frappe .notification.is-black{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-frappe .notification.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .notification.is-dark,html.theme--catppuccin-frappe .content kbd.notification{background-color:#414559;color:#fff}html.theme--catppuccin-frappe .notification.is-primary,html.theme--catppuccin-frappe .docstring>section>a.notification.docs-sourcelink{background-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .notification.is-primary.is-light,html.theme--catppuccin-frappe .docstring>section>a.notification.is-light.docs-sourcelink{background-color:#edf2fc;color:#153a8e}html.theme--catppuccin-frappe .notification.is-link{background-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .notification.is-link.is-light{background-color:#edf2fc;color:#153a8e}html.theme--catppuccin-frappe .notification.is-info{background-color:#81c8be;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .notification.is-info.is-light{background-color:#f1f9f8;color:#2d675f}html.theme--catppuccin-frappe .notification.is-success{background-color:#a6d189;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .notification.is-success.is-light{background-color:#f4f9f0;color:#446a29}html.theme--catppuccin-frappe .notification.is-warning{background-color:#e5c890;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .notification.is-warning.is-light{background-color:#fbf7ee;color:#78591c}html.theme--catppuccin-frappe .notification.is-danger{background-color:#e78284;color:#fff}html.theme--catppuccin-frappe .notification.is-danger.is-light{background-color:#fceeee;color:#9a1e20}html.theme--catppuccin-frappe .progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:9999px;display:block;height:1rem;overflow:hidden;padding:0;width:100%}html.theme--catppuccin-frappe .progress::-webkit-progress-bar{background-color:#51576d}html.theme--catppuccin-frappe .progress::-webkit-progress-value{background-color:#838ba7}html.theme--catppuccin-frappe .progress::-moz-progress-bar{background-color:#838ba7}html.theme--catppuccin-frappe .progress::-ms-fill{background-color:#838ba7;border:none}html.theme--catppuccin-frappe .progress.is-white::-webkit-progress-value{background-color:#fff}html.theme--catppuccin-frappe .progress.is-white::-moz-progress-bar{background-color:#fff}html.theme--catppuccin-frappe .progress.is-white::-ms-fill{background-color:#fff}html.theme--catppuccin-frappe .progress.is-white:indeterminate{background-image:linear-gradient(to right, #fff 30%, #51576d 30%)}html.theme--catppuccin-frappe .progress.is-black::-webkit-progress-value{background-color:#0a0a0a}html.theme--catppuccin-frappe .progress.is-black::-moz-progress-bar{background-color:#0a0a0a}html.theme--catppuccin-frappe .progress.is-black::-ms-fill{background-color:#0a0a0a}html.theme--catppuccin-frappe .progress.is-black:indeterminate{background-image:linear-gradient(to right, #0a0a0a 30%, #51576d 30%)}html.theme--catppuccin-frappe .progress.is-light::-webkit-progress-value{background-color:#f5f5f5}html.theme--catppuccin-frappe .progress.is-light::-moz-progress-bar{background-color:#f5f5f5}html.theme--catppuccin-frappe .progress.is-light::-ms-fill{background-color:#f5f5f5}html.theme--catppuccin-frappe .progress.is-light:indeterminate{background-image:linear-gradient(to right, #f5f5f5 30%, #51576d 30%)}html.theme--catppuccin-frappe .progress.is-dark::-webkit-progress-value,html.theme--catppuccin-frappe .content kbd.progress::-webkit-progress-value{background-color:#414559}html.theme--catppuccin-frappe .progress.is-dark::-moz-progress-bar,html.theme--catppuccin-frappe .content kbd.progress::-moz-progress-bar{background-color:#414559}html.theme--catppuccin-frappe .progress.is-dark::-ms-fill,html.theme--catppuccin-frappe .content kbd.progress::-ms-fill{background-color:#414559}html.theme--catppuccin-frappe .progress.is-dark:indeterminate,html.theme--catppuccin-frappe .content kbd.progress:indeterminate{background-image:linear-gradient(to right, #414559 30%, #51576d 30%)}html.theme--catppuccin-frappe .progress.is-primary::-webkit-progress-value,html.theme--catppuccin-frappe .docstring>section>a.progress.docs-sourcelink::-webkit-progress-value{background-color:#8caaee}html.theme--catppuccin-frappe .progress.is-primary::-moz-progress-bar,html.theme--catppuccin-frappe .docstring>section>a.progress.docs-sourcelink::-moz-progress-bar{background-color:#8caaee}html.theme--catppuccin-frappe .progress.is-primary::-ms-fill,html.theme--catppuccin-frappe .docstring>section>a.progress.docs-sourcelink::-ms-fill{background-color:#8caaee}html.theme--catppuccin-frappe .progress.is-primary:indeterminate,html.theme--catppuccin-frappe .docstring>section>a.progress.docs-sourcelink:indeterminate{background-image:linear-gradient(to right, #8caaee 30%, #51576d 30%)}html.theme--catppuccin-frappe .progress.is-link::-webkit-progress-value{background-color:#8caaee}html.theme--catppuccin-frappe .progress.is-link::-moz-progress-bar{background-color:#8caaee}html.theme--catppuccin-frappe .progress.is-link::-ms-fill{background-color:#8caaee}html.theme--catppuccin-frappe .progress.is-link:indeterminate{background-image:linear-gradient(to right, #8caaee 30%, #51576d 30%)}html.theme--catppuccin-frappe .progress.is-info::-webkit-progress-value{background-color:#81c8be}html.theme--catppuccin-frappe .progress.is-info::-moz-progress-bar{background-color:#81c8be}html.theme--catppuccin-frappe .progress.is-info::-ms-fill{background-color:#81c8be}html.theme--catppuccin-frappe .progress.is-info:indeterminate{background-image:linear-gradient(to right, #81c8be 30%, #51576d 30%)}html.theme--catppuccin-frappe .progress.is-success::-webkit-progress-value{background-color:#a6d189}html.theme--catppuccin-frappe .progress.is-success::-moz-progress-bar{background-color:#a6d189}html.theme--catppuccin-frappe .progress.is-success::-ms-fill{background-color:#a6d189}html.theme--catppuccin-frappe .progress.is-success:indeterminate{background-image:linear-gradient(to right, #a6d189 30%, #51576d 30%)}html.theme--catppuccin-frappe .progress.is-warning::-webkit-progress-value{background-color:#e5c890}html.theme--catppuccin-frappe .progress.is-warning::-moz-progress-bar{background-color:#e5c890}html.theme--catppuccin-frappe .progress.is-warning::-ms-fill{background-color:#e5c890}html.theme--catppuccin-frappe .progress.is-warning:indeterminate{background-image:linear-gradient(to right, #e5c890 30%, #51576d 30%)}html.theme--catppuccin-frappe .progress.is-danger::-webkit-progress-value{background-color:#e78284}html.theme--catppuccin-frappe .progress.is-danger::-moz-progress-bar{background-color:#e78284}html.theme--catppuccin-frappe .progress.is-danger::-ms-fill{background-color:#e78284}html.theme--catppuccin-frappe .progress.is-danger:indeterminate{background-image:linear-gradient(to right, #e78284 30%, #51576d 30%)}html.theme--catppuccin-frappe .progress:indeterminate{animation-duration:1.5s;animation-iteration-count:infinite;animation-name:moveIndeterminate;animation-timing-function:linear;background-color:#51576d;background-image:linear-gradient(to right, #c6d0f5 30%, #51576d 30%);background-position:top left;background-repeat:no-repeat;background-size:150% 150%}html.theme--catppuccin-frappe .progress:indeterminate::-webkit-progress-bar{background-color:transparent}html.theme--catppuccin-frappe .progress:indeterminate::-moz-progress-bar{background-color:transparent}html.theme--catppuccin-frappe .progress:indeterminate::-ms-fill{animation-name:none}html.theme--catppuccin-frappe .progress.is-small,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.progress{height:.75rem}html.theme--catppuccin-frappe .progress.is-medium{height:1.25rem}html.theme--catppuccin-frappe .progress.is-large{height:1.5rem}@keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}html.theme--catppuccin-frappe .table{background-color:#51576d;color:#c6d0f5}html.theme--catppuccin-frappe .table td,html.theme--catppuccin-frappe .table th{border:1px solid #626880;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--catppuccin-frappe .table td.is-white,html.theme--catppuccin-frappe .table th.is-white{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--catppuccin-frappe .table td.is-black,html.theme--catppuccin-frappe .table th.is-black{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--catppuccin-frappe .table td.is-light,html.theme--catppuccin-frappe .table th.is-light{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .table td.is-dark,html.theme--catppuccin-frappe .table th.is-dark{background-color:#414559;border-color:#414559;color:#fff}html.theme--catppuccin-frappe .table td.is-primary,html.theme--catppuccin-frappe .table th.is-primary{background-color:#8caaee;border-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .table td.is-link,html.theme--catppuccin-frappe .table th.is-link{background-color:#8caaee;border-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .table td.is-info,html.theme--catppuccin-frappe .table th.is-info{background-color:#81c8be;border-color:#81c8be;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .table td.is-success,html.theme--catppuccin-frappe .table th.is-success{background-color:#a6d189;border-color:#a6d189;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .table td.is-warning,html.theme--catppuccin-frappe .table th.is-warning{background-color:#e5c890;border-color:#e5c890;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .table td.is-danger,html.theme--catppuccin-frappe .table th.is-danger{background-color:#e78284;border-color:#e78284;color:#fff}html.theme--catppuccin-frappe .table td.is-narrow,html.theme--catppuccin-frappe .table th.is-narrow{white-space:nowrap;width:1%}html.theme--catppuccin-frappe .table td.is-selected,html.theme--catppuccin-frappe .table th.is-selected{background-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .table td.is-selected a,html.theme--catppuccin-frappe .table td.is-selected strong,html.theme--catppuccin-frappe .table th.is-selected a,html.theme--catppuccin-frappe .table th.is-selected strong{color:currentColor}html.theme--catppuccin-frappe .table td.is-vcentered,html.theme--catppuccin-frappe .table th.is-vcentered{vertical-align:middle}html.theme--catppuccin-frappe .table th{color:#b0bef1}html.theme--catppuccin-frappe .table th:not([align]){text-align:left}html.theme--catppuccin-frappe .table tr.is-selected{background-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .table tr.is-selected a,html.theme--catppuccin-frappe .table tr.is-selected strong{color:currentColor}html.theme--catppuccin-frappe .table tr.is-selected td,html.theme--catppuccin-frappe .table tr.is-selected th{border-color:#fff;color:currentColor}html.theme--catppuccin-frappe .table thead{background-color:rgba(0,0,0,0)}html.theme--catppuccin-frappe .table thead td,html.theme--catppuccin-frappe .table thead th{border-width:0 0 2px;color:#b0bef1}html.theme--catppuccin-frappe .table tfoot{background-color:rgba(0,0,0,0)}html.theme--catppuccin-frappe .table tfoot td,html.theme--catppuccin-frappe .table tfoot th{border-width:2px 0 0;color:#b0bef1}html.theme--catppuccin-frappe .table tbody{background-color:rgba(0,0,0,0)}html.theme--catppuccin-frappe .table tbody tr:last-child td,html.theme--catppuccin-frappe .table tbody tr:last-child th{border-bottom-width:0}html.theme--catppuccin-frappe .table.is-bordered td,html.theme--catppuccin-frappe .table.is-bordered th{border-width:1px}html.theme--catppuccin-frappe .table.is-bordered tr:last-child td,html.theme--catppuccin-frappe .table.is-bordered tr:last-child th{border-bottom-width:1px}html.theme--catppuccin-frappe .table.is-fullwidth{width:100%}html.theme--catppuccin-frappe .table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#414559}html.theme--catppuccin-frappe .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover{background-color:#414559}html.theme--catppuccin-frappe .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even){background-color:#454a5f}html.theme--catppuccin-frappe .table.is-narrow td,html.theme--catppuccin-frappe .table.is-narrow th{padding:0.25em 0.5em}html.theme--catppuccin-frappe .table.is-striped tbody tr:not(.is-selected):nth-child(even){background-color:#414559}html.theme--catppuccin-frappe .table-container{-webkit-overflow-scrolling:touch;overflow:auto;overflow-y:hidden;max-width:100%}html.theme--catppuccin-frappe .tags{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--catppuccin-frappe .tags .tag,html.theme--catppuccin-frappe .tags .content kbd,html.theme--catppuccin-frappe .content .tags kbd,html.theme--catppuccin-frappe .tags .docstring>section>a.docs-sourcelink{margin-bottom:0.5rem}html.theme--catppuccin-frappe .tags .tag:not(:last-child),html.theme--catppuccin-frappe .tags .content kbd:not(:last-child),html.theme--catppuccin-frappe .content .tags kbd:not(:last-child),html.theme--catppuccin-frappe .tags .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:.5rem}html.theme--catppuccin-frappe .tags:last-child{margin-bottom:-0.5rem}html.theme--catppuccin-frappe .tags:not(:last-child){margin-bottom:1rem}html.theme--catppuccin-frappe .tags.are-medium .tag:not(.is-normal):not(.is-large),html.theme--catppuccin-frappe .tags.are-medium .content kbd:not(.is-normal):not(.is-large),html.theme--catppuccin-frappe .content .tags.are-medium kbd:not(.is-normal):not(.is-large),html.theme--catppuccin-frappe .tags.are-medium .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-large){font-size:1rem}html.theme--catppuccin-frappe .tags.are-large .tag:not(.is-normal):not(.is-medium),html.theme--catppuccin-frappe .tags.are-large .content kbd:not(.is-normal):not(.is-medium),html.theme--catppuccin-frappe .content .tags.are-large kbd:not(.is-normal):not(.is-medium),html.theme--catppuccin-frappe .tags.are-large .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-medium){font-size:1.25rem}html.theme--catppuccin-frappe .tags.is-centered{justify-content:center}html.theme--catppuccin-frappe .tags.is-centered .tag,html.theme--catppuccin-frappe .tags.is-centered .content kbd,html.theme--catppuccin-frappe .content .tags.is-centered kbd,html.theme--catppuccin-frappe .tags.is-centered .docstring>section>a.docs-sourcelink{margin-right:0.25rem;margin-left:0.25rem}html.theme--catppuccin-frappe .tags.is-right{justify-content:flex-end}html.theme--catppuccin-frappe .tags.is-right .tag:not(:first-child),html.theme--catppuccin-frappe .tags.is-right .content kbd:not(:first-child),html.theme--catppuccin-frappe .content .tags.is-right kbd:not(:first-child),html.theme--catppuccin-frappe .tags.is-right .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0.5rem}html.theme--catppuccin-frappe .tags.is-right .tag:not(:last-child),html.theme--catppuccin-frappe .tags.is-right .content kbd:not(:last-child),html.theme--catppuccin-frappe .content .tags.is-right kbd:not(:last-child),html.theme--catppuccin-frappe .tags.is-right .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:0}html.theme--catppuccin-frappe .tags.has-addons .tag,html.theme--catppuccin-frappe .tags.has-addons .content kbd,html.theme--catppuccin-frappe .content .tags.has-addons kbd,html.theme--catppuccin-frappe .tags.has-addons .docstring>section>a.docs-sourcelink{margin-right:0}html.theme--catppuccin-frappe .tags.has-addons .tag:not(:first-child),html.theme--catppuccin-frappe .tags.has-addons .content kbd:not(:first-child),html.theme--catppuccin-frappe .content .tags.has-addons kbd:not(:first-child),html.theme--catppuccin-frappe .tags.has-addons .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0;border-top-left-radius:0;border-bottom-left-radius:0}html.theme--catppuccin-frappe .tags.has-addons .tag:not(:last-child),html.theme--catppuccin-frappe .tags.has-addons .content kbd:not(:last-child),html.theme--catppuccin-frappe .content .tags.has-addons kbd:not(:last-child),html.theme--catppuccin-frappe .tags.has-addons .docstring>section>a.docs-sourcelink:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}html.theme--catppuccin-frappe .tag:not(body),html.theme--catppuccin-frappe .content kbd:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink:not(body){align-items:center;background-color:#292c3c;border-radius:.4em;color:#c6d0f5;display:inline-flex;font-size:.75rem;height:2em;justify-content:center;line-height:1.5;padding-left:0.75em;padding-right:0.75em;white-space:nowrap}html.theme--catppuccin-frappe .tag:not(body) .delete,html.theme--catppuccin-frappe .content kbd:not(body) .delete,html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink:not(body) .delete{margin-left:.25rem;margin-right:-.375rem}html.theme--catppuccin-frappe .tag.is-white:not(body),html.theme--catppuccin-frappe .content kbd.is-white:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-white:not(body){background-color:#fff;color:#0a0a0a}html.theme--catppuccin-frappe .tag.is-black:not(body),html.theme--catppuccin-frappe .content kbd.is-black:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-black:not(body){background-color:#0a0a0a;color:#fff}html.theme--catppuccin-frappe .tag.is-light:not(body),html.theme--catppuccin-frappe .content kbd.is-light:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .tag.is-dark:not(body),html.theme--catppuccin-frappe .content kbd:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-dark:not(body),html.theme--catppuccin-frappe .content .docstring>section>kbd:not(body){background-color:#414559;color:#fff}html.theme--catppuccin-frappe .tag.is-primary:not(body),html.theme--catppuccin-frappe .content kbd.is-primary:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink:not(body){background-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .tag.is-primary.is-light:not(body),html.theme--catppuccin-frappe .content kbd.is-primary.is-light:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#edf2fc;color:#153a8e}html.theme--catppuccin-frappe .tag.is-link:not(body),html.theme--catppuccin-frappe .content kbd.is-link:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-link:not(body){background-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .tag.is-link.is-light:not(body),html.theme--catppuccin-frappe .content kbd.is-link.is-light:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-link.is-light:not(body){background-color:#edf2fc;color:#153a8e}html.theme--catppuccin-frappe .tag.is-info:not(body),html.theme--catppuccin-frappe .content kbd.is-info:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-info:not(body){background-color:#81c8be;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .tag.is-info.is-light:not(body),html.theme--catppuccin-frappe .content kbd.is-info.is-light:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-info.is-light:not(body){background-color:#f1f9f8;color:#2d675f}html.theme--catppuccin-frappe .tag.is-success:not(body),html.theme--catppuccin-frappe .content kbd.is-success:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-success:not(body){background-color:#a6d189;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .tag.is-success.is-light:not(body),html.theme--catppuccin-frappe .content kbd.is-success.is-light:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-success.is-light:not(body){background-color:#f4f9f0;color:#446a29}html.theme--catppuccin-frappe .tag.is-warning:not(body),html.theme--catppuccin-frappe .content kbd.is-warning:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-warning:not(body){background-color:#e5c890;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .tag.is-warning.is-light:not(body),html.theme--catppuccin-frappe .content kbd.is-warning.is-light:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-warning.is-light:not(body){background-color:#fbf7ee;color:#78591c}html.theme--catppuccin-frappe .tag.is-danger:not(body),html.theme--catppuccin-frappe .content kbd.is-danger:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-danger:not(body){background-color:#e78284;color:#fff}html.theme--catppuccin-frappe .tag.is-danger.is-light:not(body),html.theme--catppuccin-frappe .content kbd.is-danger.is-light:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-danger.is-light:not(body){background-color:#fceeee;color:#9a1e20}html.theme--catppuccin-frappe .tag.is-normal:not(body),html.theme--catppuccin-frappe .content kbd.is-normal:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-normal:not(body){font-size:.75rem}html.theme--catppuccin-frappe .tag.is-medium:not(body),html.theme--catppuccin-frappe .content kbd.is-medium:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-medium:not(body){font-size:1rem}html.theme--catppuccin-frappe .tag.is-large:not(body),html.theme--catppuccin-frappe .content kbd.is-large:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-large:not(body){font-size:1.25rem}html.theme--catppuccin-frappe .tag:not(body) .icon:first-child:not(:last-child),html.theme--catppuccin-frappe .content kbd:not(body) .icon:first-child:not(:last-child),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:not(:last-child){margin-left:-.375em;margin-right:.1875em}html.theme--catppuccin-frappe .tag:not(body) .icon:last-child:not(:first-child),html.theme--catppuccin-frappe .content kbd:not(body) .icon:last-child:not(:first-child),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink:not(body) .icon:last-child:not(:first-child){margin-left:.1875em;margin-right:-.375em}html.theme--catppuccin-frappe .tag:not(body) .icon:first-child:last-child,html.theme--catppuccin-frappe .content kbd:not(body) .icon:first-child:last-child,html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:last-child{margin-left:-.375em;margin-right:-.375em}html.theme--catppuccin-frappe .tag.is-delete:not(body),html.theme--catppuccin-frappe .content kbd.is-delete:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-delete:not(body){margin-left:1px;padding:0;position:relative;width:2em}html.theme--catppuccin-frappe .tag.is-delete:not(body)::before,html.theme--catppuccin-frappe .content kbd.is-delete:not(body)::before,html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-delete:not(body)::before,html.theme--catppuccin-frappe .tag.is-delete:not(body)::after,html.theme--catppuccin-frappe .content kbd.is-delete:not(body)::after,html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{background-color:currentColor;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--catppuccin-frappe .tag.is-delete:not(body)::before,html.theme--catppuccin-frappe .content kbd.is-delete:not(body)::before,html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-delete:not(body)::before{height:1px;width:50%}html.theme--catppuccin-frappe .tag.is-delete:not(body)::after,html.theme--catppuccin-frappe .content kbd.is-delete:not(body)::after,html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{height:50%;width:1px}html.theme--catppuccin-frappe .tag.is-delete:not(body):hover,html.theme--catppuccin-frappe .content kbd.is-delete:not(body):hover,html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-delete:not(body):hover,html.theme--catppuccin-frappe .tag.is-delete:not(body):focus,html.theme--catppuccin-frappe .content kbd.is-delete:not(body):focus,html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-delete:not(body):focus{background-color:#1f212d}html.theme--catppuccin-frappe .tag.is-delete:not(body):active,html.theme--catppuccin-frappe .content kbd.is-delete:not(body):active,html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-delete:not(body):active{background-color:#14161e}html.theme--catppuccin-frappe .tag.is-rounded:not(body),html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input:not(body),html.theme--catppuccin-frappe .content kbd.is-rounded:not(body),html.theme--catppuccin-frappe #documenter .docs-sidebar .content form.docs-search>input:not(body),html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink.is-rounded:not(body){border-radius:9999px}html.theme--catppuccin-frappe a.tag:hover,html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink:hover{text-decoration:underline}html.theme--catppuccin-frappe .title,html.theme--catppuccin-frappe .subtitle{word-break:break-word}html.theme--catppuccin-frappe .title em,html.theme--catppuccin-frappe .title span,html.theme--catppuccin-frappe .subtitle em,html.theme--catppuccin-frappe .subtitle span{font-weight:inherit}html.theme--catppuccin-frappe .title sub,html.theme--catppuccin-frappe .subtitle sub{font-size:.75em}html.theme--catppuccin-frappe .title sup,html.theme--catppuccin-frappe .subtitle sup{font-size:.75em}html.theme--catppuccin-frappe .title .tag,html.theme--catppuccin-frappe .title .content kbd,html.theme--catppuccin-frappe .content .title kbd,html.theme--catppuccin-frappe .title .docstring>section>a.docs-sourcelink,html.theme--catppuccin-frappe .subtitle .tag,html.theme--catppuccin-frappe .subtitle .content kbd,html.theme--catppuccin-frappe .content .subtitle kbd,html.theme--catppuccin-frappe .subtitle .docstring>section>a.docs-sourcelink{vertical-align:middle}html.theme--catppuccin-frappe .title{color:#fff;font-size:2rem;font-weight:500;line-height:1.125}html.theme--catppuccin-frappe .title strong{color:inherit;font-weight:inherit}html.theme--catppuccin-frappe .title:not(.is-spaced)+.subtitle{margin-top:-1.25rem}html.theme--catppuccin-frappe .title.is-1{font-size:3rem}html.theme--catppuccin-frappe .title.is-2{font-size:2.5rem}html.theme--catppuccin-frappe .title.is-3{font-size:2rem}html.theme--catppuccin-frappe .title.is-4{font-size:1.5rem}html.theme--catppuccin-frappe .title.is-5{font-size:1.25rem}html.theme--catppuccin-frappe .title.is-6{font-size:1rem}html.theme--catppuccin-frappe .title.is-7{font-size:.75rem}html.theme--catppuccin-frappe .subtitle{color:#737994;font-size:1.25rem;font-weight:400;line-height:1.25}html.theme--catppuccin-frappe .subtitle strong{color:#737994;font-weight:600}html.theme--catppuccin-frappe .subtitle:not(.is-spaced)+.title{margin-top:-1.25rem}html.theme--catppuccin-frappe .subtitle.is-1{font-size:3rem}html.theme--catppuccin-frappe .subtitle.is-2{font-size:2.5rem}html.theme--catppuccin-frappe .subtitle.is-3{font-size:2rem}html.theme--catppuccin-frappe .subtitle.is-4{font-size:1.5rem}html.theme--catppuccin-frappe .subtitle.is-5{font-size:1.25rem}html.theme--catppuccin-frappe .subtitle.is-6{font-size:1rem}html.theme--catppuccin-frappe .subtitle.is-7{font-size:.75rem}html.theme--catppuccin-frappe .heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}html.theme--catppuccin-frappe .number{align-items:center;background-color:#292c3c;border-radius:9999px;display:inline-flex;font-size:1.25rem;height:2em;justify-content:center;margin-right:1.5rem;min-width:2.5em;padding:0.25rem 0.5rem;text-align:center;vertical-align:top}html.theme--catppuccin-frappe .select select,html.theme--catppuccin-frappe .textarea,html.theme--catppuccin-frappe .input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input{background-color:#303446;border-color:#626880;border-radius:.4em;color:#838ba7}html.theme--catppuccin-frappe .select select::-moz-placeholder,html.theme--catppuccin-frappe .textarea::-moz-placeholder,html.theme--catppuccin-frappe .input::-moz-placeholder,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:#868c98}html.theme--catppuccin-frappe .select select::-webkit-input-placeholder,html.theme--catppuccin-frappe .textarea::-webkit-input-placeholder,html.theme--catppuccin-frappe .input::-webkit-input-placeholder,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:#868c98}html.theme--catppuccin-frappe .select select:-moz-placeholder,html.theme--catppuccin-frappe .textarea:-moz-placeholder,html.theme--catppuccin-frappe .input:-moz-placeholder,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:#868c98}html.theme--catppuccin-frappe .select select:-ms-input-placeholder,html.theme--catppuccin-frappe .textarea:-ms-input-placeholder,html.theme--catppuccin-frappe .input:-ms-input-placeholder,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:#868c98}html.theme--catppuccin-frappe .select select:hover,html.theme--catppuccin-frappe .textarea:hover,html.theme--catppuccin-frappe .input:hover,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input:hover,html.theme--catppuccin-frappe .select select.is-hovered,html.theme--catppuccin-frappe .is-hovered.textarea,html.theme--catppuccin-frappe .is-hovered.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-hovered{border-color:#737994}html.theme--catppuccin-frappe .select select:focus,html.theme--catppuccin-frappe .textarea:focus,html.theme--catppuccin-frappe .input:focus,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input:focus,html.theme--catppuccin-frappe .select select.is-focused,html.theme--catppuccin-frappe .is-focused.textarea,html.theme--catppuccin-frappe .is-focused.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-frappe .select select:active,html.theme--catppuccin-frappe .textarea:active,html.theme--catppuccin-frappe .input:active,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input:active,html.theme--catppuccin-frappe .select select.is-active,html.theme--catppuccin-frappe .is-active.textarea,html.theme--catppuccin-frappe .is-active.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-active{border-color:#8caaee;box-shadow:0 0 0 0.125em rgba(140,170,238,0.25)}html.theme--catppuccin-frappe .select select[disabled],html.theme--catppuccin-frappe .textarea[disabled],html.theme--catppuccin-frappe .input[disabled],html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input[disabled],fieldset[disabled] html.theme--catppuccin-frappe .select select,fieldset[disabled] html.theme--catppuccin-frappe .textarea,fieldset[disabled] html.theme--catppuccin-frappe .input,fieldset[disabled] html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input{background-color:#737994;border-color:#292c3c;box-shadow:none;color:#f1f4fd}html.theme--catppuccin-frappe .select select[disabled]::-moz-placeholder,html.theme--catppuccin-frappe .textarea[disabled]::-moz-placeholder,html.theme--catppuccin-frappe .input[disabled]::-moz-placeholder,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input[disabled]::-moz-placeholder,fieldset[disabled] html.theme--catppuccin-frappe .select select::-moz-placeholder,fieldset[disabled] html.theme--catppuccin-frappe .textarea::-moz-placeholder,fieldset[disabled] html.theme--catppuccin-frappe .input::-moz-placeholder,fieldset[disabled] html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:rgba(241,244,253,0.3)}html.theme--catppuccin-frappe .select select[disabled]::-webkit-input-placeholder,html.theme--catppuccin-frappe .textarea[disabled]::-webkit-input-placeholder,html.theme--catppuccin-frappe .input[disabled]::-webkit-input-placeholder,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input[disabled]::-webkit-input-placeholder,fieldset[disabled] html.theme--catppuccin-frappe .select select::-webkit-input-placeholder,fieldset[disabled] html.theme--catppuccin-frappe .textarea::-webkit-input-placeholder,fieldset[disabled] html.theme--catppuccin-frappe .input::-webkit-input-placeholder,fieldset[disabled] html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:rgba(241,244,253,0.3)}html.theme--catppuccin-frappe .select select[disabled]:-moz-placeholder,html.theme--catppuccin-frappe .textarea[disabled]:-moz-placeholder,html.theme--catppuccin-frappe .input[disabled]:-moz-placeholder,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input[disabled]:-moz-placeholder,fieldset[disabled] html.theme--catppuccin-frappe .select select:-moz-placeholder,fieldset[disabled] html.theme--catppuccin-frappe .textarea:-moz-placeholder,fieldset[disabled] html.theme--catppuccin-frappe .input:-moz-placeholder,fieldset[disabled] html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:rgba(241,244,253,0.3)}html.theme--catppuccin-frappe .select select[disabled]:-ms-input-placeholder,html.theme--catppuccin-frappe .textarea[disabled]:-ms-input-placeholder,html.theme--catppuccin-frappe .input[disabled]:-ms-input-placeholder,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input[disabled]:-ms-input-placeholder,fieldset[disabled] html.theme--catppuccin-frappe .select select:-ms-input-placeholder,fieldset[disabled] html.theme--catppuccin-frappe .textarea:-ms-input-placeholder,fieldset[disabled] html.theme--catppuccin-frappe .input:-ms-input-placeholder,fieldset[disabled] html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:rgba(241,244,253,0.3)}html.theme--catppuccin-frappe .textarea,html.theme--catppuccin-frappe .input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input{box-shadow:inset 0 0.0625em 0.125em rgba(10,10,10,0.05);max-width:100%;width:100%}html.theme--catppuccin-frappe .textarea[readonly],html.theme--catppuccin-frappe .input[readonly],html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input[readonly]{box-shadow:none}html.theme--catppuccin-frappe .is-white.textarea,html.theme--catppuccin-frappe .is-white.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-white{border-color:#fff}html.theme--catppuccin-frappe .is-white.textarea:focus,html.theme--catppuccin-frappe .is-white.input:focus,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-white:focus,html.theme--catppuccin-frappe .is-white.is-focused.textarea,html.theme--catppuccin-frappe .is-white.is-focused.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-frappe .is-white.textarea:active,html.theme--catppuccin-frappe .is-white.input:active,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-white:active,html.theme--catppuccin-frappe .is-white.is-active.textarea,html.theme--catppuccin-frappe .is-white.is-active.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--catppuccin-frappe .is-black.textarea,html.theme--catppuccin-frappe .is-black.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-black{border-color:#0a0a0a}html.theme--catppuccin-frappe .is-black.textarea:focus,html.theme--catppuccin-frappe .is-black.input:focus,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-black:focus,html.theme--catppuccin-frappe .is-black.is-focused.textarea,html.theme--catppuccin-frappe .is-black.is-focused.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-frappe .is-black.textarea:active,html.theme--catppuccin-frappe .is-black.input:active,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-black:active,html.theme--catppuccin-frappe .is-black.is-active.textarea,html.theme--catppuccin-frappe .is-black.is-active.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--catppuccin-frappe .is-light.textarea,html.theme--catppuccin-frappe .is-light.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-light{border-color:#f5f5f5}html.theme--catppuccin-frappe .is-light.textarea:focus,html.theme--catppuccin-frappe .is-light.input:focus,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-light:focus,html.theme--catppuccin-frappe .is-light.is-focused.textarea,html.theme--catppuccin-frappe .is-light.is-focused.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-frappe .is-light.textarea:active,html.theme--catppuccin-frappe .is-light.input:active,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-light:active,html.theme--catppuccin-frappe .is-light.is-active.textarea,html.theme--catppuccin-frappe .is-light.is-active.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}html.theme--catppuccin-frappe .is-dark.textarea,html.theme--catppuccin-frappe .content kbd.textarea,html.theme--catppuccin-frappe .is-dark.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-dark,html.theme--catppuccin-frappe .content kbd.input{border-color:#414559}html.theme--catppuccin-frappe .is-dark.textarea:focus,html.theme--catppuccin-frappe .content kbd.textarea:focus,html.theme--catppuccin-frappe .is-dark.input:focus,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-dark:focus,html.theme--catppuccin-frappe .content kbd.input:focus,html.theme--catppuccin-frappe .is-dark.is-focused.textarea,html.theme--catppuccin-frappe .content kbd.is-focused.textarea,html.theme--catppuccin-frappe .is-dark.is-focused.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-frappe .content kbd.is-focused.input,html.theme--catppuccin-frappe #documenter .docs-sidebar .content form.docs-search>input.is-focused,html.theme--catppuccin-frappe .is-dark.textarea:active,html.theme--catppuccin-frappe .content kbd.textarea:active,html.theme--catppuccin-frappe .is-dark.input:active,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-dark:active,html.theme--catppuccin-frappe .content kbd.input:active,html.theme--catppuccin-frappe .is-dark.is-active.textarea,html.theme--catppuccin-frappe .content kbd.is-active.textarea,html.theme--catppuccin-frappe .is-dark.is-active.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--catppuccin-frappe .content kbd.is-active.input,html.theme--catppuccin-frappe #documenter .docs-sidebar .content form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(65,69,89,0.25)}html.theme--catppuccin-frappe .is-primary.textarea,html.theme--catppuccin-frappe .docstring>section>a.textarea.docs-sourcelink,html.theme--catppuccin-frappe .is-primary.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-primary,html.theme--catppuccin-frappe .docstring>section>a.input.docs-sourcelink{border-color:#8caaee}html.theme--catppuccin-frappe .is-primary.textarea:focus,html.theme--catppuccin-frappe .docstring>section>a.textarea.docs-sourcelink:focus,html.theme--catppuccin-frappe .is-primary.input:focus,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-primary:focus,html.theme--catppuccin-frappe .docstring>section>a.input.docs-sourcelink:focus,html.theme--catppuccin-frappe .is-primary.is-focused.textarea,html.theme--catppuccin-frappe .docstring>section>a.is-focused.textarea.docs-sourcelink,html.theme--catppuccin-frappe .is-primary.is-focused.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-frappe .docstring>section>a.is-focused.input.docs-sourcelink,html.theme--catppuccin-frappe .is-primary.textarea:active,html.theme--catppuccin-frappe .docstring>section>a.textarea.docs-sourcelink:active,html.theme--catppuccin-frappe .is-primary.input:active,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-primary:active,html.theme--catppuccin-frappe .docstring>section>a.input.docs-sourcelink:active,html.theme--catppuccin-frappe .is-primary.is-active.textarea,html.theme--catppuccin-frappe .docstring>section>a.is-active.textarea.docs-sourcelink,html.theme--catppuccin-frappe .is-primary.is-active.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--catppuccin-frappe .docstring>section>a.is-active.input.docs-sourcelink{box-shadow:0 0 0 0.125em rgba(140,170,238,0.25)}html.theme--catppuccin-frappe .is-link.textarea,html.theme--catppuccin-frappe .is-link.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-link{border-color:#8caaee}html.theme--catppuccin-frappe .is-link.textarea:focus,html.theme--catppuccin-frappe .is-link.input:focus,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-link:focus,html.theme--catppuccin-frappe .is-link.is-focused.textarea,html.theme--catppuccin-frappe .is-link.is-focused.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-frappe .is-link.textarea:active,html.theme--catppuccin-frappe .is-link.input:active,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-link:active,html.theme--catppuccin-frappe .is-link.is-active.textarea,html.theme--catppuccin-frappe .is-link.is-active.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(140,170,238,0.25)}html.theme--catppuccin-frappe .is-info.textarea,html.theme--catppuccin-frappe .is-info.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-info{border-color:#81c8be}html.theme--catppuccin-frappe .is-info.textarea:focus,html.theme--catppuccin-frappe .is-info.input:focus,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-info:focus,html.theme--catppuccin-frappe .is-info.is-focused.textarea,html.theme--catppuccin-frappe .is-info.is-focused.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-frappe .is-info.textarea:active,html.theme--catppuccin-frappe .is-info.input:active,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-info:active,html.theme--catppuccin-frappe .is-info.is-active.textarea,html.theme--catppuccin-frappe .is-info.is-active.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(129,200,190,0.25)}html.theme--catppuccin-frappe .is-success.textarea,html.theme--catppuccin-frappe .is-success.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-success{border-color:#a6d189}html.theme--catppuccin-frappe .is-success.textarea:focus,html.theme--catppuccin-frappe .is-success.input:focus,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-success:focus,html.theme--catppuccin-frappe .is-success.is-focused.textarea,html.theme--catppuccin-frappe .is-success.is-focused.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-frappe .is-success.textarea:active,html.theme--catppuccin-frappe .is-success.input:active,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-success:active,html.theme--catppuccin-frappe .is-success.is-active.textarea,html.theme--catppuccin-frappe .is-success.is-active.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(166,209,137,0.25)}html.theme--catppuccin-frappe .is-warning.textarea,html.theme--catppuccin-frappe .is-warning.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-warning{border-color:#e5c890}html.theme--catppuccin-frappe .is-warning.textarea:focus,html.theme--catppuccin-frappe .is-warning.input:focus,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-warning:focus,html.theme--catppuccin-frappe .is-warning.is-focused.textarea,html.theme--catppuccin-frappe .is-warning.is-focused.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-frappe .is-warning.textarea:active,html.theme--catppuccin-frappe .is-warning.input:active,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-warning:active,html.theme--catppuccin-frappe .is-warning.is-active.textarea,html.theme--catppuccin-frappe .is-warning.is-active.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(229,200,144,0.25)}html.theme--catppuccin-frappe .is-danger.textarea,html.theme--catppuccin-frappe .is-danger.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-danger{border-color:#e78284}html.theme--catppuccin-frappe .is-danger.textarea:focus,html.theme--catppuccin-frappe .is-danger.input:focus,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-danger:focus,html.theme--catppuccin-frappe .is-danger.is-focused.textarea,html.theme--catppuccin-frappe .is-danger.is-focused.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-frappe .is-danger.textarea:active,html.theme--catppuccin-frappe .is-danger.input:active,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-danger:active,html.theme--catppuccin-frappe .is-danger.is-active.textarea,html.theme--catppuccin-frappe .is-danger.is-active.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(231,130,132,0.25)}html.theme--catppuccin-frappe .is-small.textarea,html.theme--catppuccin-frappe .is-small.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input{border-radius:3px;font-size:.75rem}html.theme--catppuccin-frappe .is-medium.textarea,html.theme--catppuccin-frappe .is-medium.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-medium{font-size:1.25rem}html.theme--catppuccin-frappe .is-large.textarea,html.theme--catppuccin-frappe .is-large.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-large{font-size:1.5rem}html.theme--catppuccin-frappe .is-fullwidth.textarea,html.theme--catppuccin-frappe .is-fullwidth.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-fullwidth{display:block;width:100%}html.theme--catppuccin-frappe .is-inline.textarea,html.theme--catppuccin-frappe .is-inline.input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-inline{display:inline;width:auto}html.theme--catppuccin-frappe .input.is-rounded,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input{border-radius:9999px;padding-left:calc(calc(0.75em - 1px) + 0.375em);padding-right:calc(calc(0.75em - 1px) + 0.375em)}html.theme--catppuccin-frappe .input.is-static,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-static{background-color:transparent;border-color:transparent;box-shadow:none;padding-left:0;padding-right:0}html.theme--catppuccin-frappe .textarea{display:block;max-width:100%;min-width:100%;padding:calc(0.75em - 1px);resize:vertical}html.theme--catppuccin-frappe .textarea:not([rows]){max-height:40em;min-height:8em}html.theme--catppuccin-frappe .textarea[rows]{height:initial}html.theme--catppuccin-frappe .textarea.has-fixed-size{resize:none}html.theme--catppuccin-frappe .radio,html.theme--catppuccin-frappe .checkbox{cursor:pointer;display:inline-block;line-height:1.25;position:relative}html.theme--catppuccin-frappe .radio input,html.theme--catppuccin-frappe .checkbox input{cursor:pointer}html.theme--catppuccin-frappe .radio:hover,html.theme--catppuccin-frappe .checkbox:hover{color:#99d1db}html.theme--catppuccin-frappe .radio[disabled],html.theme--catppuccin-frappe .checkbox[disabled],fieldset[disabled] html.theme--catppuccin-frappe .radio,fieldset[disabled] html.theme--catppuccin-frappe .checkbox,html.theme--catppuccin-frappe .radio input[disabled],html.theme--catppuccin-frappe .checkbox input[disabled]{color:#f1f4fd;cursor:not-allowed}html.theme--catppuccin-frappe .radio+.radio{margin-left:.5em}html.theme--catppuccin-frappe .select{display:inline-block;max-width:100%;position:relative;vertical-align:top}html.theme--catppuccin-frappe .select:not(.is-multiple){height:2.5em}html.theme--catppuccin-frappe .select:not(.is-multiple):not(.is-loading)::after{border-color:#8caaee;right:1.125em;z-index:4}html.theme--catppuccin-frappe .select.is-rounded select,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.select select{border-radius:9999px;padding-left:1em}html.theme--catppuccin-frappe .select select{cursor:pointer;display:block;font-size:1em;max-width:100%;outline:none}html.theme--catppuccin-frappe .select select::-ms-expand{display:none}html.theme--catppuccin-frappe .select select[disabled]:hover,fieldset[disabled] html.theme--catppuccin-frappe .select select:hover{border-color:#292c3c}html.theme--catppuccin-frappe .select select:not([multiple]){padding-right:2.5em}html.theme--catppuccin-frappe .select select[multiple]{height:auto;padding:0}html.theme--catppuccin-frappe .select select[multiple] option{padding:0.5em 1em}html.theme--catppuccin-frappe .select:not(.is-multiple):not(.is-loading):hover::after{border-color:#99d1db}html.theme--catppuccin-frappe .select.is-white:not(:hover)::after{border-color:#fff}html.theme--catppuccin-frappe .select.is-white select{border-color:#fff}html.theme--catppuccin-frappe .select.is-white select:hover,html.theme--catppuccin-frappe .select.is-white select.is-hovered{border-color:#f2f2f2}html.theme--catppuccin-frappe .select.is-white select:focus,html.theme--catppuccin-frappe .select.is-white select.is-focused,html.theme--catppuccin-frappe .select.is-white select:active,html.theme--catppuccin-frappe .select.is-white select.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--catppuccin-frappe .select.is-black:not(:hover)::after{border-color:#0a0a0a}html.theme--catppuccin-frappe .select.is-black select{border-color:#0a0a0a}html.theme--catppuccin-frappe .select.is-black select:hover,html.theme--catppuccin-frappe .select.is-black select.is-hovered{border-color:#000}html.theme--catppuccin-frappe .select.is-black select:focus,html.theme--catppuccin-frappe .select.is-black select.is-focused,html.theme--catppuccin-frappe .select.is-black select:active,html.theme--catppuccin-frappe .select.is-black select.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--catppuccin-frappe .select.is-light:not(:hover)::after{border-color:#f5f5f5}html.theme--catppuccin-frappe .select.is-light select{border-color:#f5f5f5}html.theme--catppuccin-frappe .select.is-light select:hover,html.theme--catppuccin-frappe .select.is-light select.is-hovered{border-color:#e8e8e8}html.theme--catppuccin-frappe .select.is-light select:focus,html.theme--catppuccin-frappe .select.is-light select.is-focused,html.theme--catppuccin-frappe .select.is-light select:active,html.theme--catppuccin-frappe .select.is-light select.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}html.theme--catppuccin-frappe .select.is-dark:not(:hover)::after,html.theme--catppuccin-frappe .content kbd.select:not(:hover)::after{border-color:#414559}html.theme--catppuccin-frappe .select.is-dark select,html.theme--catppuccin-frappe .content kbd.select select{border-color:#414559}html.theme--catppuccin-frappe .select.is-dark select:hover,html.theme--catppuccin-frappe .content kbd.select select:hover,html.theme--catppuccin-frappe .select.is-dark select.is-hovered,html.theme--catppuccin-frappe .content kbd.select select.is-hovered{border-color:#363a4a}html.theme--catppuccin-frappe .select.is-dark select:focus,html.theme--catppuccin-frappe .content kbd.select select:focus,html.theme--catppuccin-frappe .select.is-dark select.is-focused,html.theme--catppuccin-frappe .content kbd.select select.is-focused,html.theme--catppuccin-frappe .select.is-dark select:active,html.theme--catppuccin-frappe .content kbd.select select:active,html.theme--catppuccin-frappe .select.is-dark select.is-active,html.theme--catppuccin-frappe .content kbd.select select.is-active{box-shadow:0 0 0 0.125em rgba(65,69,89,0.25)}html.theme--catppuccin-frappe .select.is-primary:not(:hover)::after,html.theme--catppuccin-frappe .docstring>section>a.select.docs-sourcelink:not(:hover)::after{border-color:#8caaee}html.theme--catppuccin-frappe .select.is-primary select,html.theme--catppuccin-frappe .docstring>section>a.select.docs-sourcelink select{border-color:#8caaee}html.theme--catppuccin-frappe .select.is-primary select:hover,html.theme--catppuccin-frappe .docstring>section>a.select.docs-sourcelink select:hover,html.theme--catppuccin-frappe .select.is-primary select.is-hovered,html.theme--catppuccin-frappe .docstring>section>a.select.docs-sourcelink select.is-hovered{border-color:#769aeb}html.theme--catppuccin-frappe .select.is-primary select:focus,html.theme--catppuccin-frappe .docstring>section>a.select.docs-sourcelink select:focus,html.theme--catppuccin-frappe .select.is-primary select.is-focused,html.theme--catppuccin-frappe .docstring>section>a.select.docs-sourcelink select.is-focused,html.theme--catppuccin-frappe .select.is-primary select:active,html.theme--catppuccin-frappe .docstring>section>a.select.docs-sourcelink select:active,html.theme--catppuccin-frappe .select.is-primary select.is-active,html.theme--catppuccin-frappe .docstring>section>a.select.docs-sourcelink select.is-active{box-shadow:0 0 0 0.125em rgba(140,170,238,0.25)}html.theme--catppuccin-frappe .select.is-link:not(:hover)::after{border-color:#8caaee}html.theme--catppuccin-frappe .select.is-link select{border-color:#8caaee}html.theme--catppuccin-frappe .select.is-link select:hover,html.theme--catppuccin-frappe .select.is-link select.is-hovered{border-color:#769aeb}html.theme--catppuccin-frappe .select.is-link select:focus,html.theme--catppuccin-frappe .select.is-link select.is-focused,html.theme--catppuccin-frappe .select.is-link select:active,html.theme--catppuccin-frappe .select.is-link select.is-active{box-shadow:0 0 0 0.125em rgba(140,170,238,0.25)}html.theme--catppuccin-frappe .select.is-info:not(:hover)::after{border-color:#81c8be}html.theme--catppuccin-frappe .select.is-info select{border-color:#81c8be}html.theme--catppuccin-frappe .select.is-info select:hover,html.theme--catppuccin-frappe .select.is-info select.is-hovered{border-color:#6fc0b5}html.theme--catppuccin-frappe .select.is-info select:focus,html.theme--catppuccin-frappe .select.is-info select.is-focused,html.theme--catppuccin-frappe .select.is-info select:active,html.theme--catppuccin-frappe .select.is-info select.is-active{box-shadow:0 0 0 0.125em rgba(129,200,190,0.25)}html.theme--catppuccin-frappe .select.is-success:not(:hover)::after{border-color:#a6d189}html.theme--catppuccin-frappe .select.is-success select{border-color:#a6d189}html.theme--catppuccin-frappe .select.is-success select:hover,html.theme--catppuccin-frappe .select.is-success select.is-hovered{border-color:#98ca77}html.theme--catppuccin-frappe .select.is-success select:focus,html.theme--catppuccin-frappe .select.is-success select.is-focused,html.theme--catppuccin-frappe .select.is-success select:active,html.theme--catppuccin-frappe .select.is-success select.is-active{box-shadow:0 0 0 0.125em rgba(166,209,137,0.25)}html.theme--catppuccin-frappe .select.is-warning:not(:hover)::after{border-color:#e5c890}html.theme--catppuccin-frappe .select.is-warning select{border-color:#e5c890}html.theme--catppuccin-frappe .select.is-warning select:hover,html.theme--catppuccin-frappe .select.is-warning select.is-hovered{border-color:#e0be7b}html.theme--catppuccin-frappe .select.is-warning select:focus,html.theme--catppuccin-frappe .select.is-warning select.is-focused,html.theme--catppuccin-frappe .select.is-warning select:active,html.theme--catppuccin-frappe .select.is-warning select.is-active{box-shadow:0 0 0 0.125em rgba(229,200,144,0.25)}html.theme--catppuccin-frappe .select.is-danger:not(:hover)::after{border-color:#e78284}html.theme--catppuccin-frappe .select.is-danger select{border-color:#e78284}html.theme--catppuccin-frappe .select.is-danger select:hover,html.theme--catppuccin-frappe .select.is-danger select.is-hovered{border-color:#e36d6f}html.theme--catppuccin-frappe .select.is-danger select:focus,html.theme--catppuccin-frappe .select.is-danger select.is-focused,html.theme--catppuccin-frappe .select.is-danger select:active,html.theme--catppuccin-frappe .select.is-danger select.is-active{box-shadow:0 0 0 0.125em rgba(231,130,132,0.25)}html.theme--catppuccin-frappe .select.is-small,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.select{border-radius:3px;font-size:.75rem}html.theme--catppuccin-frappe .select.is-medium{font-size:1.25rem}html.theme--catppuccin-frappe .select.is-large{font-size:1.5rem}html.theme--catppuccin-frappe .select.is-disabled::after{border-color:#f1f4fd !important;opacity:0.5}html.theme--catppuccin-frappe .select.is-fullwidth{width:100%}html.theme--catppuccin-frappe .select.is-fullwidth select{width:100%}html.theme--catppuccin-frappe .select.is-loading::after{margin-top:0;position:absolute;right:.625em;top:0.625em;transform:none}html.theme--catppuccin-frappe .select.is-loading.is-small:after,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}html.theme--catppuccin-frappe .select.is-loading.is-medium:after{font-size:1.25rem}html.theme--catppuccin-frappe .select.is-loading.is-large:after{font-size:1.5rem}html.theme--catppuccin-frappe .file{align-items:stretch;display:flex;justify-content:flex-start;position:relative}html.theme--catppuccin-frappe .file.is-white .file-cta{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-frappe .file.is-white:hover .file-cta,html.theme--catppuccin-frappe .file.is-white.is-hovered .file-cta{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-frappe .file.is-white:focus .file-cta,html.theme--catppuccin-frappe .file.is-white.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,255,255,0.25);color:#0a0a0a}html.theme--catppuccin-frappe .file.is-white:active .file-cta,html.theme--catppuccin-frappe .file.is-white.is-active .file-cta{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-frappe .file.is-black .file-cta{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .file.is-black:hover .file-cta,html.theme--catppuccin-frappe .file.is-black.is-hovered .file-cta{background-color:#040404;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .file.is-black:focus .file-cta,html.theme--catppuccin-frappe .file.is-black.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(10,10,10,0.25);color:#fff}html.theme--catppuccin-frappe .file.is-black:active .file-cta,html.theme--catppuccin-frappe .file.is-black.is-active .file-cta{background-color:#000;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .file.is-light .file-cta{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .file.is-light:hover .file-cta,html.theme--catppuccin-frappe .file.is-light.is-hovered .file-cta{background-color:#eee;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .file.is-light:focus .file-cta,html.theme--catppuccin-frappe .file.is-light.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(245,245,245,0.25);color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .file.is-light:active .file-cta,html.theme--catppuccin-frappe .file.is-light.is-active .file-cta{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .file.is-dark .file-cta,html.theme--catppuccin-frappe .content kbd.file .file-cta{background-color:#414559;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .file.is-dark:hover .file-cta,html.theme--catppuccin-frappe .content kbd.file:hover .file-cta,html.theme--catppuccin-frappe .file.is-dark.is-hovered .file-cta,html.theme--catppuccin-frappe .content kbd.file.is-hovered .file-cta{background-color:#3c3f52;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .file.is-dark:focus .file-cta,html.theme--catppuccin-frappe .content kbd.file:focus .file-cta,html.theme--catppuccin-frappe .file.is-dark.is-focused .file-cta,html.theme--catppuccin-frappe .content kbd.file.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(65,69,89,0.25);color:#fff}html.theme--catppuccin-frappe .file.is-dark:active .file-cta,html.theme--catppuccin-frappe .content kbd.file:active .file-cta,html.theme--catppuccin-frappe .file.is-dark.is-active .file-cta,html.theme--catppuccin-frappe .content kbd.file.is-active .file-cta{background-color:#363a4a;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .file.is-primary .file-cta,html.theme--catppuccin-frappe .docstring>section>a.file.docs-sourcelink .file-cta{background-color:#8caaee;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .file.is-primary:hover .file-cta,html.theme--catppuccin-frappe .docstring>section>a.file.docs-sourcelink:hover .file-cta,html.theme--catppuccin-frappe .file.is-primary.is-hovered .file-cta,html.theme--catppuccin-frappe .docstring>section>a.file.is-hovered.docs-sourcelink .file-cta{background-color:#81a2ec;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .file.is-primary:focus .file-cta,html.theme--catppuccin-frappe .docstring>section>a.file.docs-sourcelink:focus .file-cta,html.theme--catppuccin-frappe .file.is-primary.is-focused .file-cta,html.theme--catppuccin-frappe .docstring>section>a.file.is-focused.docs-sourcelink .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(140,170,238,0.25);color:#fff}html.theme--catppuccin-frappe .file.is-primary:active .file-cta,html.theme--catppuccin-frappe .docstring>section>a.file.docs-sourcelink:active .file-cta,html.theme--catppuccin-frappe .file.is-primary.is-active .file-cta,html.theme--catppuccin-frappe .docstring>section>a.file.is-active.docs-sourcelink .file-cta{background-color:#769aeb;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .file.is-link .file-cta{background-color:#8caaee;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .file.is-link:hover .file-cta,html.theme--catppuccin-frappe .file.is-link.is-hovered .file-cta{background-color:#81a2ec;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .file.is-link:focus .file-cta,html.theme--catppuccin-frappe .file.is-link.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(140,170,238,0.25);color:#fff}html.theme--catppuccin-frappe .file.is-link:active .file-cta,html.theme--catppuccin-frappe .file.is-link.is-active .file-cta{background-color:#769aeb;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .file.is-info .file-cta{background-color:#81c8be;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .file.is-info:hover .file-cta,html.theme--catppuccin-frappe .file.is-info.is-hovered .file-cta{background-color:#78c4b9;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .file.is-info:focus .file-cta,html.theme--catppuccin-frappe .file.is-info.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(129,200,190,0.25);color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .file.is-info:active .file-cta,html.theme--catppuccin-frappe .file.is-info.is-active .file-cta{background-color:#6fc0b5;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .file.is-success .file-cta{background-color:#a6d189;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .file.is-success:hover .file-cta,html.theme--catppuccin-frappe .file.is-success.is-hovered .file-cta{background-color:#9fcd80;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .file.is-success:focus .file-cta,html.theme--catppuccin-frappe .file.is-success.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(166,209,137,0.25);color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .file.is-success:active .file-cta,html.theme--catppuccin-frappe .file.is-success.is-active .file-cta{background-color:#98ca77;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .file.is-warning .file-cta{background-color:#e5c890;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .file.is-warning:hover .file-cta,html.theme--catppuccin-frappe .file.is-warning.is-hovered .file-cta{background-color:#e3c386;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .file.is-warning:focus .file-cta,html.theme--catppuccin-frappe .file.is-warning.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(229,200,144,0.25);color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .file.is-warning:active .file-cta,html.theme--catppuccin-frappe .file.is-warning.is-active .file-cta{background-color:#e0be7b;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .file.is-danger .file-cta{background-color:#e78284;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .file.is-danger:hover .file-cta,html.theme--catppuccin-frappe .file.is-danger.is-hovered .file-cta{background-color:#e57779;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .file.is-danger:focus .file-cta,html.theme--catppuccin-frappe .file.is-danger.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(231,130,132,0.25);color:#fff}html.theme--catppuccin-frappe .file.is-danger:active .file-cta,html.theme--catppuccin-frappe .file.is-danger.is-active .file-cta{background-color:#e36d6f;border-color:transparent;color:#fff}html.theme--catppuccin-frappe .file.is-small,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.file{font-size:.75rem}html.theme--catppuccin-frappe .file.is-normal{font-size:1rem}html.theme--catppuccin-frappe .file.is-medium{font-size:1.25rem}html.theme--catppuccin-frappe .file.is-medium .file-icon .fa{font-size:21px}html.theme--catppuccin-frappe .file.is-large{font-size:1.5rem}html.theme--catppuccin-frappe .file.is-large .file-icon .fa{font-size:28px}html.theme--catppuccin-frappe .file.has-name .file-cta{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--catppuccin-frappe .file.has-name .file-name{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--catppuccin-frappe .file.has-name.is-empty .file-cta{border-radius:.4em}html.theme--catppuccin-frappe .file.has-name.is-empty .file-name{display:none}html.theme--catppuccin-frappe .file.is-boxed .file-label{flex-direction:column}html.theme--catppuccin-frappe .file.is-boxed .file-cta{flex-direction:column;height:auto;padding:1em 3em}html.theme--catppuccin-frappe .file.is-boxed .file-name{border-width:0 1px 1px}html.theme--catppuccin-frappe .file.is-boxed .file-icon{height:1.5em;width:1.5em}html.theme--catppuccin-frappe .file.is-boxed .file-icon .fa{font-size:21px}html.theme--catppuccin-frappe .file.is-boxed.is-small .file-icon .fa,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-boxed .file-icon .fa{font-size:14px}html.theme--catppuccin-frappe .file.is-boxed.is-medium .file-icon .fa{font-size:28px}html.theme--catppuccin-frappe .file.is-boxed.is-large .file-icon .fa{font-size:35px}html.theme--catppuccin-frappe .file.is-boxed.has-name .file-cta{border-radius:.4em .4em 0 0}html.theme--catppuccin-frappe .file.is-boxed.has-name .file-name{border-radius:0 0 .4em .4em;border-width:0 1px 1px}html.theme--catppuccin-frappe .file.is-centered{justify-content:center}html.theme--catppuccin-frappe .file.is-fullwidth .file-label{width:100%}html.theme--catppuccin-frappe .file.is-fullwidth .file-name{flex-grow:1;max-width:none}html.theme--catppuccin-frappe .file.is-right{justify-content:flex-end}html.theme--catppuccin-frappe .file.is-right .file-cta{border-radius:0 .4em .4em 0}html.theme--catppuccin-frappe .file.is-right .file-name{border-radius:.4em 0 0 .4em;border-width:1px 0 1px 1px;order:-1}html.theme--catppuccin-frappe .file-label{align-items:stretch;display:flex;cursor:pointer;justify-content:flex-start;overflow:hidden;position:relative}html.theme--catppuccin-frappe .file-label:hover .file-cta{background-color:#3c3f52;color:#b0bef1}html.theme--catppuccin-frappe .file-label:hover .file-name{border-color:#5c6279}html.theme--catppuccin-frappe .file-label:active .file-cta{background-color:#363a4a;color:#b0bef1}html.theme--catppuccin-frappe .file-label:active .file-name{border-color:#575c72}html.theme--catppuccin-frappe .file-input{height:100%;left:0;opacity:0;outline:none;position:absolute;top:0;width:100%}html.theme--catppuccin-frappe .file-cta,html.theme--catppuccin-frappe .file-name{border-color:#626880;border-radius:.4em;font-size:1em;padding-left:1em;padding-right:1em;white-space:nowrap}html.theme--catppuccin-frappe .file-cta{background-color:#414559;color:#c6d0f5}html.theme--catppuccin-frappe .file-name{border-color:#626880;border-style:solid;border-width:1px 1px 1px 0;display:block;max-width:16em;overflow:hidden;text-align:inherit;text-overflow:ellipsis}html.theme--catppuccin-frappe .file-icon{align-items:center;display:flex;height:1em;justify-content:center;margin-right:.5em;width:1em}html.theme--catppuccin-frappe .file-icon .fa{font-size:14px}html.theme--catppuccin-frappe .label{color:#b0bef1;display:block;font-size:1rem;font-weight:700}html.theme--catppuccin-frappe .label:not(:last-child){margin-bottom:0.5em}html.theme--catppuccin-frappe .label.is-small,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.label{font-size:.75rem}html.theme--catppuccin-frappe .label.is-medium{font-size:1.25rem}html.theme--catppuccin-frappe .label.is-large{font-size:1.5rem}html.theme--catppuccin-frappe .help{display:block;font-size:.75rem;margin-top:0.25rem}html.theme--catppuccin-frappe .help.is-white{color:#fff}html.theme--catppuccin-frappe .help.is-black{color:#0a0a0a}html.theme--catppuccin-frappe .help.is-light{color:#f5f5f5}html.theme--catppuccin-frappe .help.is-dark,html.theme--catppuccin-frappe .content kbd.help{color:#414559}html.theme--catppuccin-frappe .help.is-primary,html.theme--catppuccin-frappe .docstring>section>a.help.docs-sourcelink{color:#8caaee}html.theme--catppuccin-frappe .help.is-link{color:#8caaee}html.theme--catppuccin-frappe .help.is-info{color:#81c8be}html.theme--catppuccin-frappe .help.is-success{color:#a6d189}html.theme--catppuccin-frappe .help.is-warning{color:#e5c890}html.theme--catppuccin-frappe .help.is-danger{color:#e78284}html.theme--catppuccin-frappe .field:not(:last-child){margin-bottom:0.75rem}html.theme--catppuccin-frappe .field.has-addons{display:flex;justify-content:flex-start}html.theme--catppuccin-frappe .field.has-addons .control:not(:last-child){margin-right:-1px}html.theme--catppuccin-frappe .field.has-addons .control:not(:first-child):not(:last-child) .button,html.theme--catppuccin-frappe .field.has-addons .control:not(:first-child):not(:last-child) .input,html.theme--catppuccin-frappe .field.has-addons .control:not(:first-child):not(:last-child) #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-frappe #documenter .docs-sidebar .field.has-addons .control:not(:first-child):not(:last-child) form.docs-search>input,html.theme--catppuccin-frappe .field.has-addons .control:not(:first-child):not(:last-child) .select select{border-radius:0}html.theme--catppuccin-frappe .field.has-addons .control:first-child:not(:only-child) .button,html.theme--catppuccin-frappe .field.has-addons .control:first-child:not(:only-child) .input,html.theme--catppuccin-frappe .field.has-addons .control:first-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-frappe #documenter .docs-sidebar .field.has-addons .control:first-child:not(:only-child) form.docs-search>input,html.theme--catppuccin-frappe .field.has-addons .control:first-child:not(:only-child) .select select{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--catppuccin-frappe .field.has-addons .control:last-child:not(:only-child) .button,html.theme--catppuccin-frappe .field.has-addons .control:last-child:not(:only-child) .input,html.theme--catppuccin-frappe .field.has-addons .control:last-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-frappe #documenter .docs-sidebar .field.has-addons .control:last-child:not(:only-child) form.docs-search>input,html.theme--catppuccin-frappe .field.has-addons .control:last-child:not(:only-child) .select select{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--catppuccin-frappe .field.has-addons .control .button:not([disabled]):hover,html.theme--catppuccin-frappe .field.has-addons .control .button.is-hovered:not([disabled]),html.theme--catppuccin-frappe .field.has-addons .control .input:not([disabled]):hover,html.theme--catppuccin-frappe .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):hover,html.theme--catppuccin-frappe #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):hover,html.theme--catppuccin-frappe .field.has-addons .control .input.is-hovered:not([disabled]),html.theme--catppuccin-frappe .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-hovered:not([disabled]),html.theme--catppuccin-frappe #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-hovered:not([disabled]),html.theme--catppuccin-frappe .field.has-addons .control .select select:not([disabled]):hover,html.theme--catppuccin-frappe .field.has-addons .control .select select.is-hovered:not([disabled]){z-index:2}html.theme--catppuccin-frappe .field.has-addons .control .button:not([disabled]):focus,html.theme--catppuccin-frappe .field.has-addons .control .button.is-focused:not([disabled]),html.theme--catppuccin-frappe .field.has-addons .control .button:not([disabled]):active,html.theme--catppuccin-frappe .field.has-addons .control .button.is-active:not([disabled]),html.theme--catppuccin-frappe .field.has-addons .control .input:not([disabled]):focus,html.theme--catppuccin-frappe .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus,html.theme--catppuccin-frappe #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus,html.theme--catppuccin-frappe .field.has-addons .control .input.is-focused:not([disabled]),html.theme--catppuccin-frappe .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]),html.theme--catppuccin-frappe #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]),html.theme--catppuccin-frappe .field.has-addons .control .input:not([disabled]):active,html.theme--catppuccin-frappe .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active,html.theme--catppuccin-frappe #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active,html.theme--catppuccin-frappe .field.has-addons .control .input.is-active:not([disabled]),html.theme--catppuccin-frappe .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]),html.theme--catppuccin-frappe #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]),html.theme--catppuccin-frappe .field.has-addons .control .select select:not([disabled]):focus,html.theme--catppuccin-frappe .field.has-addons .control .select select.is-focused:not([disabled]),html.theme--catppuccin-frappe .field.has-addons .control .select select:not([disabled]):active,html.theme--catppuccin-frappe .field.has-addons .control .select select.is-active:not([disabled]){z-index:3}html.theme--catppuccin-frappe .field.has-addons .control .button:not([disabled]):focus:hover,html.theme--catppuccin-frappe .field.has-addons .control .button.is-focused:not([disabled]):hover,html.theme--catppuccin-frappe .field.has-addons .control .button:not([disabled]):active:hover,html.theme--catppuccin-frappe .field.has-addons .control .button.is-active:not([disabled]):hover,html.theme--catppuccin-frappe .field.has-addons .control .input:not([disabled]):focus:hover,html.theme--catppuccin-frappe .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus:hover,html.theme--catppuccin-frappe #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus:hover,html.theme--catppuccin-frappe .field.has-addons .control .input.is-focused:not([disabled]):hover,html.theme--catppuccin-frappe .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]):hover,html.theme--catppuccin-frappe #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]):hover,html.theme--catppuccin-frappe .field.has-addons .control .input:not([disabled]):active:hover,html.theme--catppuccin-frappe .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active:hover,html.theme--catppuccin-frappe #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active:hover,html.theme--catppuccin-frappe .field.has-addons .control .input.is-active:not([disabled]):hover,html.theme--catppuccin-frappe .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]):hover,html.theme--catppuccin-frappe #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]):hover,html.theme--catppuccin-frappe .field.has-addons .control .select select:not([disabled]):focus:hover,html.theme--catppuccin-frappe .field.has-addons .control .select select.is-focused:not([disabled]):hover,html.theme--catppuccin-frappe .field.has-addons .control .select select:not([disabled]):active:hover,html.theme--catppuccin-frappe .field.has-addons .control .select select.is-active:not([disabled]):hover{z-index:4}html.theme--catppuccin-frappe .field.has-addons .control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--catppuccin-frappe .field.has-addons.has-addons-centered{justify-content:center}html.theme--catppuccin-frappe .field.has-addons.has-addons-right{justify-content:flex-end}html.theme--catppuccin-frappe .field.has-addons.has-addons-fullwidth .control{flex-grow:1;flex-shrink:0}html.theme--catppuccin-frappe .field.is-grouped{display:flex;justify-content:flex-start}html.theme--catppuccin-frappe .field.is-grouped>.control{flex-shrink:0}html.theme--catppuccin-frappe .field.is-grouped>.control:not(:last-child){margin-bottom:0;margin-right:.75rem}html.theme--catppuccin-frappe .field.is-grouped>.control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--catppuccin-frappe .field.is-grouped.is-grouped-centered{justify-content:center}html.theme--catppuccin-frappe .field.is-grouped.is-grouped-right{justify-content:flex-end}html.theme--catppuccin-frappe .field.is-grouped.is-grouped-multiline{flex-wrap:wrap}html.theme--catppuccin-frappe .field.is-grouped.is-grouped-multiline>.control:last-child,html.theme--catppuccin-frappe .field.is-grouped.is-grouped-multiline>.control:not(:last-child){margin-bottom:0.75rem}html.theme--catppuccin-frappe .field.is-grouped.is-grouped-multiline:last-child{margin-bottom:-0.75rem}html.theme--catppuccin-frappe .field.is-grouped.is-grouped-multiline:not(:last-child){margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .field.is-horizontal{display:flex}}html.theme--catppuccin-frappe .field-label .label{font-size:inherit}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .field-label{margin-bottom:0.5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .field-label{flex-basis:0;flex-grow:1;flex-shrink:0;margin-right:1.5rem;text-align:right}html.theme--catppuccin-frappe .field-label.is-small,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.field-label{font-size:.75rem;padding-top:0.375em}html.theme--catppuccin-frappe .field-label.is-normal{padding-top:0.375em}html.theme--catppuccin-frappe .field-label.is-medium{font-size:1.25rem;padding-top:0.375em}html.theme--catppuccin-frappe .field-label.is-large{font-size:1.5rem;padding-top:0.375em}}html.theme--catppuccin-frappe .field-body .field .field{margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .field-body{display:flex;flex-basis:0;flex-grow:5;flex-shrink:1}html.theme--catppuccin-frappe .field-body .field{margin-bottom:0}html.theme--catppuccin-frappe .field-body>.field{flex-shrink:1}html.theme--catppuccin-frappe .field-body>.field:not(.is-narrow){flex-grow:1}html.theme--catppuccin-frappe .field-body>.field:not(:last-child){margin-right:.75rem}}html.theme--catppuccin-frappe .control{box-sizing:border-box;clear:both;font-size:1rem;position:relative;text-align:inherit}html.theme--catppuccin-frappe .control.has-icons-left .input:focus~.icon,html.theme--catppuccin-frappe .control.has-icons-left #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--catppuccin-frappe #documenter .docs-sidebar .control.has-icons-left form.docs-search>input:focus~.icon,html.theme--catppuccin-frappe .control.has-icons-left .select:focus~.icon,html.theme--catppuccin-frappe .control.has-icons-right .input:focus~.icon,html.theme--catppuccin-frappe .control.has-icons-right #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--catppuccin-frappe #documenter .docs-sidebar .control.has-icons-right form.docs-search>input:focus~.icon,html.theme--catppuccin-frappe .control.has-icons-right .select:focus~.icon{color:#414559}html.theme--catppuccin-frappe .control.has-icons-left .input.is-small~.icon,html.theme--catppuccin-frappe .control.has-icons-left #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--catppuccin-frappe #documenter .docs-sidebar .control.has-icons-left form.docs-search>input~.icon,html.theme--catppuccin-frappe .control.has-icons-left .select.is-small~.icon,html.theme--catppuccin-frappe .control.has-icons-right .input.is-small~.icon,html.theme--catppuccin-frappe .control.has-icons-right #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--catppuccin-frappe #documenter .docs-sidebar .control.has-icons-right form.docs-search>input~.icon,html.theme--catppuccin-frappe .control.has-icons-right .select.is-small~.icon{font-size:.75rem}html.theme--catppuccin-frappe .control.has-icons-left .input.is-medium~.icon,html.theme--catppuccin-frappe .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--catppuccin-frappe #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-medium~.icon,html.theme--catppuccin-frappe .control.has-icons-left .select.is-medium~.icon,html.theme--catppuccin-frappe .control.has-icons-right .input.is-medium~.icon,html.theme--catppuccin-frappe .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--catppuccin-frappe #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-medium~.icon,html.theme--catppuccin-frappe .control.has-icons-right .select.is-medium~.icon{font-size:1.25rem}html.theme--catppuccin-frappe .control.has-icons-left .input.is-large~.icon,html.theme--catppuccin-frappe .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--catppuccin-frappe #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-large~.icon,html.theme--catppuccin-frappe .control.has-icons-left .select.is-large~.icon,html.theme--catppuccin-frappe .control.has-icons-right .input.is-large~.icon,html.theme--catppuccin-frappe .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--catppuccin-frappe #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-large~.icon,html.theme--catppuccin-frappe .control.has-icons-right .select.is-large~.icon{font-size:1.5rem}html.theme--catppuccin-frappe .control.has-icons-left .icon,html.theme--catppuccin-frappe .control.has-icons-right .icon{color:#626880;height:2.5em;pointer-events:none;position:absolute;top:0;width:2.5em;z-index:4}html.theme--catppuccin-frappe .control.has-icons-left .input,html.theme--catppuccin-frappe .control.has-icons-left #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-frappe #documenter .docs-sidebar .control.has-icons-left form.docs-search>input,html.theme--catppuccin-frappe .control.has-icons-left .select select{padding-left:2.5em}html.theme--catppuccin-frappe .control.has-icons-left .icon.is-left{left:0}html.theme--catppuccin-frappe .control.has-icons-right .input,html.theme--catppuccin-frappe .control.has-icons-right #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-frappe #documenter .docs-sidebar .control.has-icons-right form.docs-search>input,html.theme--catppuccin-frappe .control.has-icons-right .select select{padding-right:2.5em}html.theme--catppuccin-frappe .control.has-icons-right .icon.is-right{right:0}html.theme--catppuccin-frappe .control.is-loading::after{position:absolute !important;right:.625em;top:0.625em;z-index:4}html.theme--catppuccin-frappe .control.is-loading.is-small:after,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}html.theme--catppuccin-frappe .control.is-loading.is-medium:after{font-size:1.25rem}html.theme--catppuccin-frappe .control.is-loading.is-large:after{font-size:1.5rem}html.theme--catppuccin-frappe .breadcrumb{font-size:1rem;white-space:nowrap}html.theme--catppuccin-frappe .breadcrumb a{align-items:center;color:#8caaee;display:flex;justify-content:center;padding:0 .75em}html.theme--catppuccin-frappe .breadcrumb a:hover{color:#99d1db}html.theme--catppuccin-frappe .breadcrumb li{align-items:center;display:flex}html.theme--catppuccin-frappe .breadcrumb li:first-child a{padding-left:0}html.theme--catppuccin-frappe .breadcrumb li.is-active a{color:#b0bef1;cursor:default;pointer-events:none}html.theme--catppuccin-frappe .breadcrumb li+li::before{color:#737994;content:"\0002f"}html.theme--catppuccin-frappe .breadcrumb ul,html.theme--catppuccin-frappe .breadcrumb ol{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--catppuccin-frappe .breadcrumb .icon:first-child{margin-right:.5em}html.theme--catppuccin-frappe .breadcrumb .icon:last-child{margin-left:.5em}html.theme--catppuccin-frappe .breadcrumb.is-centered ol,html.theme--catppuccin-frappe .breadcrumb.is-centered ul{justify-content:center}html.theme--catppuccin-frappe .breadcrumb.is-right ol,html.theme--catppuccin-frappe .breadcrumb.is-right ul{justify-content:flex-end}html.theme--catppuccin-frappe .breadcrumb.is-small,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.breadcrumb{font-size:.75rem}html.theme--catppuccin-frappe .breadcrumb.is-medium{font-size:1.25rem}html.theme--catppuccin-frappe .breadcrumb.is-large{font-size:1.5rem}html.theme--catppuccin-frappe .breadcrumb.has-arrow-separator li+li::before{content:"\02192"}html.theme--catppuccin-frappe .breadcrumb.has-bullet-separator li+li::before{content:"\02022"}html.theme--catppuccin-frappe .breadcrumb.has-dot-separator li+li::before{content:"\000b7"}html.theme--catppuccin-frappe .breadcrumb.has-succeeds-separator li+li::before{content:"\0227B"}html.theme--catppuccin-frappe .card{background-color:#fff;border-radius:.25rem;box-shadow:#171717;color:#c6d0f5;max-width:100%;position:relative}html.theme--catppuccin-frappe .card-footer:first-child,html.theme--catppuccin-frappe .card-content:first-child,html.theme--catppuccin-frappe .card-header:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}html.theme--catppuccin-frappe .card-footer:last-child,html.theme--catppuccin-frappe .card-content:last-child,html.theme--catppuccin-frappe .card-header:last-child{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}html.theme--catppuccin-frappe .card-header{background-color:rgba(0,0,0,0);align-items:stretch;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);display:flex}html.theme--catppuccin-frappe .card-header-title{align-items:center;color:#b0bef1;display:flex;flex-grow:1;font-weight:700;padding:0.75rem 1rem}html.theme--catppuccin-frappe .card-header-title.is-centered{justify-content:center}html.theme--catppuccin-frappe .card-header-icon{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0;align-items:center;cursor:pointer;display:flex;justify-content:center;padding:0.75rem 1rem}html.theme--catppuccin-frappe .card-image{display:block;position:relative}html.theme--catppuccin-frappe .card-image:first-child img{border-top-left-radius:.25rem;border-top-right-radius:.25rem}html.theme--catppuccin-frappe .card-image:last-child img{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}html.theme--catppuccin-frappe .card-content{background-color:rgba(0,0,0,0);padding:1.5rem}html.theme--catppuccin-frappe .card-footer{background-color:rgba(0,0,0,0);border-top:1px solid #ededed;align-items:stretch;display:flex}html.theme--catppuccin-frappe .card-footer-item{align-items:center;display:flex;flex-basis:0;flex-grow:1;flex-shrink:0;justify-content:center;padding:.75rem}html.theme--catppuccin-frappe .card-footer-item:not(:last-child){border-right:1px solid #ededed}html.theme--catppuccin-frappe .card .media:not(:last-child){margin-bottom:1.5rem}html.theme--catppuccin-frappe .dropdown{display:inline-flex;position:relative;vertical-align:top}html.theme--catppuccin-frappe .dropdown.is-active .dropdown-menu,html.theme--catppuccin-frappe .dropdown.is-hoverable:hover .dropdown-menu{display:block}html.theme--catppuccin-frappe .dropdown.is-right .dropdown-menu{left:auto;right:0}html.theme--catppuccin-frappe .dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:initial;top:auto}html.theme--catppuccin-frappe .dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:20}html.theme--catppuccin-frappe .dropdown-content{background-color:#292c3c;border-radius:.4em;box-shadow:#171717;padding-bottom:.5rem;padding-top:.5rem}html.theme--catppuccin-frappe .dropdown-item{color:#c6d0f5;display:block;font-size:0.875rem;line-height:1.5;padding:0.375rem 1rem;position:relative}html.theme--catppuccin-frappe a.dropdown-item,html.theme--catppuccin-frappe button.dropdown-item{padding-right:3rem;text-align:inherit;white-space:nowrap;width:100%}html.theme--catppuccin-frappe a.dropdown-item:hover,html.theme--catppuccin-frappe button.dropdown-item:hover{background-color:#292c3c;color:#0a0a0a}html.theme--catppuccin-frappe a.dropdown-item.is-active,html.theme--catppuccin-frappe button.dropdown-item.is-active{background-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .dropdown-divider{background-color:#ededed;border:none;display:block;height:1px;margin:0.5rem 0}html.theme--catppuccin-frappe .level{align-items:center;justify-content:space-between}html.theme--catppuccin-frappe .level code{border-radius:.4em}html.theme--catppuccin-frappe .level img{display:inline-block;vertical-align:top}html.theme--catppuccin-frappe .level.is-mobile{display:flex}html.theme--catppuccin-frappe .level.is-mobile .level-left,html.theme--catppuccin-frappe .level.is-mobile .level-right{display:flex}html.theme--catppuccin-frappe .level.is-mobile .level-left+.level-right{margin-top:0}html.theme--catppuccin-frappe .level.is-mobile .level-item:not(:last-child){margin-bottom:0;margin-right:.75rem}html.theme--catppuccin-frappe .level.is-mobile .level-item:not(.is-narrow){flex-grow:1}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .level{display:flex}html.theme--catppuccin-frappe .level>.level-item:not(.is-narrow){flex-grow:1}}html.theme--catppuccin-frappe .level-item{align-items:center;display:flex;flex-basis:auto;flex-grow:0;flex-shrink:0;justify-content:center}html.theme--catppuccin-frappe .level-item .title,html.theme--catppuccin-frappe .level-item .subtitle{margin-bottom:0}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .level-item:not(:last-child){margin-bottom:.75rem}}html.theme--catppuccin-frappe .level-left,html.theme--catppuccin-frappe .level-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--catppuccin-frappe .level-left .level-item.is-flexible,html.theme--catppuccin-frappe .level-right .level-item.is-flexible{flex-grow:1}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .level-left .level-item:not(:last-child),html.theme--catppuccin-frappe .level-right .level-item:not(:last-child){margin-right:.75rem}}html.theme--catppuccin-frappe .level-left{align-items:center;justify-content:flex-start}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .level-left+.level-right{margin-top:1.5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .level-left{display:flex}}html.theme--catppuccin-frappe .level-right{align-items:center;justify-content:flex-end}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .level-right{display:flex}}html.theme--catppuccin-frappe .media{align-items:flex-start;display:flex;text-align:inherit}html.theme--catppuccin-frappe .media .content:not(:last-child){margin-bottom:.75rem}html.theme--catppuccin-frappe .media .media{border-top:1px solid rgba(98,104,128,0.5);display:flex;padding-top:.75rem}html.theme--catppuccin-frappe .media .media .content:not(:last-child),html.theme--catppuccin-frappe .media .media .control:not(:last-child){margin-bottom:.5rem}html.theme--catppuccin-frappe .media .media .media{padding-top:.5rem}html.theme--catppuccin-frappe .media .media .media+.media{margin-top:.5rem}html.theme--catppuccin-frappe .media+.media{border-top:1px solid rgba(98,104,128,0.5);margin-top:1rem;padding-top:1rem}html.theme--catppuccin-frappe .media.is-large+.media{margin-top:1.5rem;padding-top:1.5rem}html.theme--catppuccin-frappe .media-left,html.theme--catppuccin-frappe .media-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--catppuccin-frappe .media-left{margin-right:1rem}html.theme--catppuccin-frappe .media-right{margin-left:1rem}html.theme--catppuccin-frappe .media-content{flex-basis:auto;flex-grow:1;flex-shrink:1;text-align:inherit}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .media-content{overflow-x:auto}}html.theme--catppuccin-frappe .menu{font-size:1rem}html.theme--catppuccin-frappe .menu.is-small,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.menu{font-size:.75rem}html.theme--catppuccin-frappe .menu.is-medium{font-size:1.25rem}html.theme--catppuccin-frappe .menu.is-large{font-size:1.5rem}html.theme--catppuccin-frappe .menu-list{line-height:1.25}html.theme--catppuccin-frappe .menu-list a{border-radius:3px;color:#c6d0f5;display:block;padding:0.5em 0.75em}html.theme--catppuccin-frappe .menu-list a:hover{background-color:#292c3c;color:#b0bef1}html.theme--catppuccin-frappe .menu-list a.is-active{background-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .menu-list li ul{border-left:1px solid #626880;margin:.75em;padding-left:.75em}html.theme--catppuccin-frappe .menu-label{color:#f1f4fd;font-size:.75em;letter-spacing:.1em;text-transform:uppercase}html.theme--catppuccin-frappe .menu-label:not(:first-child){margin-top:1em}html.theme--catppuccin-frappe .menu-label:not(:last-child){margin-bottom:1em}html.theme--catppuccin-frappe .message{background-color:#292c3c;border-radius:.4em;font-size:1rem}html.theme--catppuccin-frappe .message strong{color:currentColor}html.theme--catppuccin-frappe .message a:not(.button):not(.tag):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--catppuccin-frappe .message.is-small,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.message{font-size:.75rem}html.theme--catppuccin-frappe .message.is-medium{font-size:1.25rem}html.theme--catppuccin-frappe .message.is-large{font-size:1.5rem}html.theme--catppuccin-frappe .message.is-white{background-color:#fff}html.theme--catppuccin-frappe .message.is-white .message-header{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-frappe .message.is-white .message-body{border-color:#fff}html.theme--catppuccin-frappe .message.is-black{background-color:#fafafa}html.theme--catppuccin-frappe .message.is-black .message-header{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-frappe .message.is-black .message-body{border-color:#0a0a0a}html.theme--catppuccin-frappe .message.is-light{background-color:#fafafa}html.theme--catppuccin-frappe .message.is-light .message-header{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .message.is-light .message-body{border-color:#f5f5f5}html.theme--catppuccin-frappe .message.is-dark,html.theme--catppuccin-frappe .content kbd.message{background-color:#f9f9fb}html.theme--catppuccin-frappe .message.is-dark .message-header,html.theme--catppuccin-frappe .content kbd.message .message-header{background-color:#414559;color:#fff}html.theme--catppuccin-frappe .message.is-dark .message-body,html.theme--catppuccin-frappe .content kbd.message .message-body{border-color:#414559}html.theme--catppuccin-frappe .message.is-primary,html.theme--catppuccin-frappe .docstring>section>a.message.docs-sourcelink{background-color:#edf2fc}html.theme--catppuccin-frappe .message.is-primary .message-header,html.theme--catppuccin-frappe .docstring>section>a.message.docs-sourcelink .message-header{background-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .message.is-primary .message-body,html.theme--catppuccin-frappe .docstring>section>a.message.docs-sourcelink .message-body{border-color:#8caaee;color:#153a8e}html.theme--catppuccin-frappe .message.is-link{background-color:#edf2fc}html.theme--catppuccin-frappe .message.is-link .message-header{background-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .message.is-link .message-body{border-color:#8caaee;color:#153a8e}html.theme--catppuccin-frappe .message.is-info{background-color:#f1f9f8}html.theme--catppuccin-frappe .message.is-info .message-header{background-color:#81c8be;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .message.is-info .message-body{border-color:#81c8be;color:#2d675f}html.theme--catppuccin-frappe .message.is-success{background-color:#f4f9f0}html.theme--catppuccin-frappe .message.is-success .message-header{background-color:#a6d189;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .message.is-success .message-body{border-color:#a6d189;color:#446a29}html.theme--catppuccin-frappe .message.is-warning{background-color:#fbf7ee}html.theme--catppuccin-frappe .message.is-warning .message-header{background-color:#e5c890;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .message.is-warning .message-body{border-color:#e5c890;color:#78591c}html.theme--catppuccin-frappe .message.is-danger{background-color:#fceeee}html.theme--catppuccin-frappe .message.is-danger .message-header{background-color:#e78284;color:#fff}html.theme--catppuccin-frappe .message.is-danger .message-body{border-color:#e78284;color:#9a1e20}html.theme--catppuccin-frappe .message-header{align-items:center;background-color:#c6d0f5;border-radius:.4em .4em 0 0;color:rgba(0,0,0,0.7);display:flex;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.75em 1em;position:relative}html.theme--catppuccin-frappe .message-header .delete{flex-grow:0;flex-shrink:0;margin-left:.75em}html.theme--catppuccin-frappe .message-header+.message-body{border-width:0;border-top-left-radius:0;border-top-right-radius:0}html.theme--catppuccin-frappe .message-body{border-color:#626880;border-radius:.4em;border-style:solid;border-width:0 0 0 4px;color:#c6d0f5;padding:1.25em 1.5em}html.theme--catppuccin-frappe .message-body code,html.theme--catppuccin-frappe .message-body pre{background-color:#fff}html.theme--catppuccin-frappe .message-body pre code{background-color:rgba(0,0,0,0)}html.theme--catppuccin-frappe .modal{align-items:center;display:none;flex-direction:column;justify-content:center;overflow:hidden;position:fixed;z-index:40}html.theme--catppuccin-frappe .modal.is-active{display:flex}html.theme--catppuccin-frappe .modal-background{background-color:rgba(10,10,10,0.86)}html.theme--catppuccin-frappe .modal-content,html.theme--catppuccin-frappe .modal-card{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width: 769px){html.theme--catppuccin-frappe .modal-content,html.theme--catppuccin-frappe .modal-card{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}html.theme--catppuccin-frappe .modal-close{background:none;height:40px;position:fixed;right:20px;top:20px;width:40px}html.theme--catppuccin-frappe .modal-card{display:flex;flex-direction:column;max-height:calc(100vh - 40px);overflow:hidden;-ms-overflow-y:visible}html.theme--catppuccin-frappe .modal-card-head,html.theme--catppuccin-frappe .modal-card-foot{align-items:center;background-color:#292c3c;display:flex;flex-shrink:0;justify-content:flex-start;padding:20px;position:relative}html.theme--catppuccin-frappe .modal-card-head{border-bottom:1px solid #626880;border-top-left-radius:8px;border-top-right-radius:8px}html.theme--catppuccin-frappe .modal-card-title{color:#c6d0f5;flex-grow:1;flex-shrink:0;font-size:1.5rem;line-height:1}html.theme--catppuccin-frappe .modal-card-foot{border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid #626880}html.theme--catppuccin-frappe .modal-card-foot .button:not(:last-child){margin-right:.5em}html.theme--catppuccin-frappe .modal-card-body{-webkit-overflow-scrolling:touch;background-color:#303446;flex-grow:1;flex-shrink:1;overflow:auto;padding:20px}html.theme--catppuccin-frappe .navbar{background-color:#8caaee;min-height:4rem;position:relative;z-index:30}html.theme--catppuccin-frappe .navbar.is-white{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-frappe .navbar.is-white .navbar-brand>.navbar-item,html.theme--catppuccin-frappe .navbar.is-white .navbar-brand .navbar-link{color:#0a0a0a}html.theme--catppuccin-frappe .navbar.is-white .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-white .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-white .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-white .navbar-brand .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-white .navbar-brand .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-white .navbar-brand .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--catppuccin-frappe .navbar.is-white .navbar-brand .navbar-link::after{border-color:#0a0a0a}html.theme--catppuccin-frappe .navbar.is-white .navbar-burger{color:#0a0a0a}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .navbar.is-white .navbar-start>.navbar-item,html.theme--catppuccin-frappe .navbar.is-white .navbar-start .navbar-link,html.theme--catppuccin-frappe .navbar.is-white .navbar-end>.navbar-item,html.theme--catppuccin-frappe .navbar.is-white .navbar-end .navbar-link{color:#0a0a0a}html.theme--catppuccin-frappe .navbar.is-white .navbar-start>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-white .navbar-start>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-white .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-white .navbar-start .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-white .navbar-start .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-white .navbar-start .navbar-link.is-active,html.theme--catppuccin-frappe .navbar.is-white .navbar-end>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-white .navbar-end>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-white .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-white .navbar-end .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-white .navbar-end .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-white .navbar-end .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--catppuccin-frappe .navbar.is-white .navbar-start .navbar-link::after,html.theme--catppuccin-frappe .navbar.is-white .navbar-end .navbar-link::after{border-color:#0a0a0a}html.theme--catppuccin-frappe .navbar.is-white .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-frappe .navbar.is-white .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-frappe .navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link{background-color:#f2f2f2;color:#0a0a0a}html.theme--catppuccin-frappe .navbar.is-white .navbar-dropdown a.navbar-item.is-active{background-color:#fff;color:#0a0a0a}}html.theme--catppuccin-frappe .navbar.is-black{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-frappe .navbar.is-black .navbar-brand>.navbar-item,html.theme--catppuccin-frappe .navbar.is-black .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-frappe .navbar.is-black .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-black .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-black .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-black .navbar-brand .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-black .navbar-brand .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-black .navbar-brand .navbar-link.is-active{background-color:#000;color:#fff}html.theme--catppuccin-frappe .navbar.is-black .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-frappe .navbar.is-black .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .navbar.is-black .navbar-start>.navbar-item,html.theme--catppuccin-frappe .navbar.is-black .navbar-start .navbar-link,html.theme--catppuccin-frappe .navbar.is-black .navbar-end>.navbar-item,html.theme--catppuccin-frappe .navbar.is-black .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-frappe .navbar.is-black .navbar-start>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-black .navbar-start>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-black .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-black .navbar-start .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-black .navbar-start .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-black .navbar-start .navbar-link.is-active,html.theme--catppuccin-frappe .navbar.is-black .navbar-end>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-black .navbar-end>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-black .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-black .navbar-end .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-black .navbar-end .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-black .navbar-end .navbar-link.is-active{background-color:#000;color:#fff}html.theme--catppuccin-frappe .navbar.is-black .navbar-start .navbar-link::after,html.theme--catppuccin-frappe .navbar.is-black .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-frappe .navbar.is-black .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-frappe .navbar.is-black .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-frappe .navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link{background-color:#000;color:#fff}html.theme--catppuccin-frappe .navbar.is-black .navbar-dropdown a.navbar-item.is-active{background-color:#0a0a0a;color:#fff}}html.theme--catppuccin-frappe .navbar.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-light .navbar-brand>.navbar-item,html.theme--catppuccin-frappe .navbar.is-light .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-light .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-light .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-light .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-light .navbar-brand .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-light .navbar-brand .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-light .navbar-brand .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-light .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-light .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .navbar.is-light .navbar-start>.navbar-item,html.theme--catppuccin-frappe .navbar.is-light .navbar-start .navbar-link,html.theme--catppuccin-frappe .navbar.is-light .navbar-end>.navbar-item,html.theme--catppuccin-frappe .navbar.is-light .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-light .navbar-start>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-light .navbar-start>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-light .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-light .navbar-start .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-light .navbar-start .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-light .navbar-start .navbar-link.is-active,html.theme--catppuccin-frappe .navbar.is-light .navbar-end>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-light .navbar-end>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-light .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-light .navbar-end .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-light .navbar-end .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-light .navbar-end .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-light .navbar-start .navbar-link::after,html.theme--catppuccin-frappe .navbar.is-light .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-light .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-frappe .navbar.is-light .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-frappe .navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-light .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}}html.theme--catppuccin-frappe .navbar.is-dark,html.theme--catppuccin-frappe .content kbd.navbar{background-color:#414559;color:#fff}html.theme--catppuccin-frappe .navbar.is-dark .navbar-brand>.navbar-item,html.theme--catppuccin-frappe .content kbd.navbar .navbar-brand>.navbar-item,html.theme--catppuccin-frappe .navbar.is-dark .navbar-brand .navbar-link,html.theme--catppuccin-frappe .content kbd.navbar .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-frappe .navbar.is-dark .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-frappe .content kbd.navbar .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-dark .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-frappe .content kbd.navbar .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-dark .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-frappe .content kbd.navbar .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-dark .navbar-brand .navbar-link:focus,html.theme--catppuccin-frappe .content kbd.navbar .navbar-brand .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-dark .navbar-brand .navbar-link:hover,html.theme--catppuccin-frappe .content kbd.navbar .navbar-brand .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-dark .navbar-brand .navbar-link.is-active,html.theme--catppuccin-frappe .content kbd.navbar .navbar-brand .navbar-link.is-active{background-color:#363a4a;color:#fff}html.theme--catppuccin-frappe .navbar.is-dark .navbar-brand .navbar-link::after,html.theme--catppuccin-frappe .content kbd.navbar .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-frappe .navbar.is-dark .navbar-burger,html.theme--catppuccin-frappe .content kbd.navbar .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .navbar.is-dark .navbar-start>.navbar-item,html.theme--catppuccin-frappe .content kbd.navbar .navbar-start>.navbar-item,html.theme--catppuccin-frappe .navbar.is-dark .navbar-start .navbar-link,html.theme--catppuccin-frappe .content kbd.navbar .navbar-start .navbar-link,html.theme--catppuccin-frappe .navbar.is-dark .navbar-end>.navbar-item,html.theme--catppuccin-frappe .content kbd.navbar .navbar-end>.navbar-item,html.theme--catppuccin-frappe .navbar.is-dark .navbar-end .navbar-link,html.theme--catppuccin-frappe .content kbd.navbar .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-frappe .navbar.is-dark .navbar-start>a.navbar-item:focus,html.theme--catppuccin-frappe .content kbd.navbar .navbar-start>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-dark .navbar-start>a.navbar-item:hover,html.theme--catppuccin-frappe .content kbd.navbar .navbar-start>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-dark .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-frappe .content kbd.navbar .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-dark .navbar-start .navbar-link:focus,html.theme--catppuccin-frappe .content kbd.navbar .navbar-start .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-dark .navbar-start .navbar-link:hover,html.theme--catppuccin-frappe .content kbd.navbar .navbar-start .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-dark .navbar-start .navbar-link.is-active,html.theme--catppuccin-frappe .content kbd.navbar .navbar-start .navbar-link.is-active,html.theme--catppuccin-frappe .navbar.is-dark .navbar-end>a.navbar-item:focus,html.theme--catppuccin-frappe .content kbd.navbar .navbar-end>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-dark .navbar-end>a.navbar-item:hover,html.theme--catppuccin-frappe .content kbd.navbar .navbar-end>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-dark .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-frappe .content kbd.navbar .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-dark .navbar-end .navbar-link:focus,html.theme--catppuccin-frappe .content kbd.navbar .navbar-end .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-dark .navbar-end .navbar-link:hover,html.theme--catppuccin-frappe .content kbd.navbar .navbar-end .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-dark .navbar-end .navbar-link.is-active,html.theme--catppuccin-frappe .content kbd.navbar .navbar-end .navbar-link.is-active{background-color:#363a4a;color:#fff}html.theme--catppuccin-frappe .navbar.is-dark .navbar-start .navbar-link::after,html.theme--catppuccin-frappe .content kbd.navbar .navbar-start .navbar-link::after,html.theme--catppuccin-frappe .navbar.is-dark .navbar-end .navbar-link::after,html.theme--catppuccin-frappe .content kbd.navbar .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-frappe .navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-frappe .content kbd.navbar .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-frappe .navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-frappe .content kbd.navbar .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-frappe .navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link,html.theme--catppuccin-frappe .content kbd.navbar .navbar-item.has-dropdown.is-active .navbar-link{background-color:#363a4a;color:#fff}html.theme--catppuccin-frappe .navbar.is-dark .navbar-dropdown a.navbar-item.is-active,html.theme--catppuccin-frappe .content kbd.navbar .navbar-dropdown a.navbar-item.is-active{background-color:#414559;color:#fff}}html.theme--catppuccin-frappe .navbar.is-primary,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink{background-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .navbar.is-primary .navbar-brand>.navbar-item,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-brand>.navbar-item,html.theme--catppuccin-frappe .navbar.is-primary .navbar-brand .navbar-link,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-frappe .navbar.is-primary .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-primary .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-primary .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-primary .navbar-brand .navbar-link:focus,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-primary .navbar-brand .navbar-link:hover,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-primary .navbar-brand .navbar-link.is-active,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link.is-active{background-color:#769aeb;color:#fff}html.theme--catppuccin-frappe .navbar.is-primary .navbar-brand .navbar-link::after,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-frappe .navbar.is-primary .navbar-burger,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .navbar.is-primary .navbar-start>.navbar-item,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-start>.navbar-item,html.theme--catppuccin-frappe .navbar.is-primary .navbar-start .navbar-link,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link,html.theme--catppuccin-frappe .navbar.is-primary .navbar-end>.navbar-item,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-end>.navbar-item,html.theme--catppuccin-frappe .navbar.is-primary .navbar-end .navbar-link,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-frappe .navbar.is-primary .navbar-start>a.navbar-item:focus,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-primary .navbar-start>a.navbar-item:hover,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-primary .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-primary .navbar-start .navbar-link:focus,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-primary .navbar-start .navbar-link:hover,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-primary .navbar-start .navbar-link.is-active,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link.is-active,html.theme--catppuccin-frappe .navbar.is-primary .navbar-end>a.navbar-item:focus,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-primary .navbar-end>a.navbar-item:hover,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-primary .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-primary .navbar-end .navbar-link:focus,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-primary .navbar-end .navbar-link:hover,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-primary .navbar-end .navbar-link.is-active,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link.is-active{background-color:#769aeb;color:#fff}html.theme--catppuccin-frappe .navbar.is-primary .navbar-start .navbar-link::after,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link::after,html.theme--catppuccin-frappe .navbar.is-primary .navbar-end .navbar-link::after,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-frappe .navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-frappe .navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-frappe .navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown.is-active .navbar-link{background-color:#769aeb;color:#fff}html.theme--catppuccin-frappe .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#8caaee;color:#fff}}html.theme--catppuccin-frappe .navbar.is-link{background-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .navbar.is-link .navbar-brand>.navbar-item,html.theme--catppuccin-frappe .navbar.is-link .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-frappe .navbar.is-link .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-link .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-link .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-link .navbar-brand .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-link .navbar-brand .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-link .navbar-brand .navbar-link.is-active{background-color:#769aeb;color:#fff}html.theme--catppuccin-frappe .navbar.is-link .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-frappe .navbar.is-link .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .navbar.is-link .navbar-start>.navbar-item,html.theme--catppuccin-frappe .navbar.is-link .navbar-start .navbar-link,html.theme--catppuccin-frappe .navbar.is-link .navbar-end>.navbar-item,html.theme--catppuccin-frappe .navbar.is-link .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-frappe .navbar.is-link .navbar-start>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-link .navbar-start>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-link .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-link .navbar-start .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-link .navbar-start .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-link .navbar-start .navbar-link.is-active,html.theme--catppuccin-frappe .navbar.is-link .navbar-end>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-link .navbar-end>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-link .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-link .navbar-end .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-link .navbar-end .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-link .navbar-end .navbar-link.is-active{background-color:#769aeb;color:#fff}html.theme--catppuccin-frappe .navbar.is-link .navbar-start .navbar-link::after,html.theme--catppuccin-frappe .navbar.is-link .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-frappe .navbar.is-link .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-frappe .navbar.is-link .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-frappe .navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link{background-color:#769aeb;color:#fff}html.theme--catppuccin-frappe .navbar.is-link .navbar-dropdown a.navbar-item.is-active{background-color:#8caaee;color:#fff}}html.theme--catppuccin-frappe .navbar.is-info{background-color:#81c8be;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-info .navbar-brand>.navbar-item,html.theme--catppuccin-frappe .navbar.is-info .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-info .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-info .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-info .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-info .navbar-brand .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-info .navbar-brand .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-info .navbar-brand .navbar-link.is-active{background-color:#6fc0b5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-info .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-info .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .navbar.is-info .navbar-start>.navbar-item,html.theme--catppuccin-frappe .navbar.is-info .navbar-start .navbar-link,html.theme--catppuccin-frappe .navbar.is-info .navbar-end>.navbar-item,html.theme--catppuccin-frappe .navbar.is-info .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-info .navbar-start>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-info .navbar-start>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-info .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-info .navbar-start .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-info .navbar-start .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-info .navbar-start .navbar-link.is-active,html.theme--catppuccin-frappe .navbar.is-info .navbar-end>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-info .navbar-end>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-info .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-info .navbar-end .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-info .navbar-end .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-info .navbar-end .navbar-link.is-active{background-color:#6fc0b5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-info .navbar-start .navbar-link::after,html.theme--catppuccin-frappe .navbar.is-info .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-info .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-frappe .navbar.is-info .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-frappe .navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link{background-color:#6fc0b5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-info .navbar-dropdown a.navbar-item.is-active{background-color:#81c8be;color:rgba(0,0,0,0.7)}}html.theme--catppuccin-frappe .navbar.is-success{background-color:#a6d189;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-success .navbar-brand>.navbar-item,html.theme--catppuccin-frappe .navbar.is-success .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-success .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-success .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-success .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-success .navbar-brand .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-success .navbar-brand .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-success .navbar-brand .navbar-link.is-active{background-color:#98ca77;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-success .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-success .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .navbar.is-success .navbar-start>.navbar-item,html.theme--catppuccin-frappe .navbar.is-success .navbar-start .navbar-link,html.theme--catppuccin-frappe .navbar.is-success .navbar-end>.navbar-item,html.theme--catppuccin-frappe .navbar.is-success .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-success .navbar-start>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-success .navbar-start>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-success .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-success .navbar-start .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-success .navbar-start .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-success .navbar-start .navbar-link.is-active,html.theme--catppuccin-frappe .navbar.is-success .navbar-end>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-success .navbar-end>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-success .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-success .navbar-end .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-success .navbar-end .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-success .navbar-end .navbar-link.is-active{background-color:#98ca77;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-success .navbar-start .navbar-link::after,html.theme--catppuccin-frappe .navbar.is-success .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-success .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-frappe .navbar.is-success .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-frappe .navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link{background-color:#98ca77;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-success .navbar-dropdown a.navbar-item.is-active{background-color:#a6d189;color:rgba(0,0,0,0.7)}}html.theme--catppuccin-frappe .navbar.is-warning{background-color:#e5c890;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-warning .navbar-brand>.navbar-item,html.theme--catppuccin-frappe .navbar.is-warning .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-warning .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-warning .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-warning .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-warning .navbar-brand .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-warning .navbar-brand .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-warning .navbar-brand .navbar-link.is-active{background-color:#e0be7b;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-warning .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-warning .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .navbar.is-warning .navbar-start>.navbar-item,html.theme--catppuccin-frappe .navbar.is-warning .navbar-start .navbar-link,html.theme--catppuccin-frappe .navbar.is-warning .navbar-end>.navbar-item,html.theme--catppuccin-frappe .navbar.is-warning .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-warning .navbar-start>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-warning .navbar-start>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-warning .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-warning .navbar-start .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-warning .navbar-start .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-warning .navbar-start .navbar-link.is-active,html.theme--catppuccin-frappe .navbar.is-warning .navbar-end>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-warning .navbar-end>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-warning .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-warning .navbar-end .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-warning .navbar-end .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-warning .navbar-end .navbar-link.is-active{background-color:#e0be7b;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-warning .navbar-start .navbar-link::after,html.theme--catppuccin-frappe .navbar.is-warning .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-frappe .navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-frappe .navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link{background-color:#e0be7b;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .navbar.is-warning .navbar-dropdown a.navbar-item.is-active{background-color:#e5c890;color:rgba(0,0,0,0.7)}}html.theme--catppuccin-frappe .navbar.is-danger{background-color:#e78284;color:#fff}html.theme--catppuccin-frappe .navbar.is-danger .navbar-brand>.navbar-item,html.theme--catppuccin-frappe .navbar.is-danger .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-frappe .navbar.is-danger .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-danger .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-danger .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-danger .navbar-brand .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-danger .navbar-brand .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-danger .navbar-brand .navbar-link.is-active{background-color:#e36d6f;color:#fff}html.theme--catppuccin-frappe .navbar.is-danger .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-frappe .navbar.is-danger .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .navbar.is-danger .navbar-start>.navbar-item,html.theme--catppuccin-frappe .navbar.is-danger .navbar-start .navbar-link,html.theme--catppuccin-frappe .navbar.is-danger .navbar-end>.navbar-item,html.theme--catppuccin-frappe .navbar.is-danger .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-frappe .navbar.is-danger .navbar-start>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-danger .navbar-start>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-danger .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-danger .navbar-start .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-danger .navbar-start .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-danger .navbar-start .navbar-link.is-active,html.theme--catppuccin-frappe .navbar.is-danger .navbar-end>a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-danger .navbar-end>a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-danger .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-danger .navbar-end .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-danger .navbar-end .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-danger .navbar-end .navbar-link.is-active{background-color:#e36d6f;color:#fff}html.theme--catppuccin-frappe .navbar.is-danger .navbar-start .navbar-link::after,html.theme--catppuccin-frappe .navbar.is-danger .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-frappe .navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-frappe .navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-frappe .navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link{background-color:#e36d6f;color:#fff}html.theme--catppuccin-frappe .navbar.is-danger .navbar-dropdown a.navbar-item.is-active{background-color:#e78284;color:#fff}}html.theme--catppuccin-frappe .navbar>.container{align-items:stretch;display:flex;min-height:4rem;width:100%}html.theme--catppuccin-frappe .navbar.has-shadow{box-shadow:0 2px 0 0 #292c3c}html.theme--catppuccin-frappe .navbar.is-fixed-bottom,html.theme--catppuccin-frappe .navbar.is-fixed-top{left:0;position:fixed;right:0;z-index:30}html.theme--catppuccin-frappe .navbar.is-fixed-bottom{bottom:0}html.theme--catppuccin-frappe .navbar.is-fixed-bottom.has-shadow{box-shadow:0 -2px 0 0 #292c3c}html.theme--catppuccin-frappe .navbar.is-fixed-top{top:0}html.theme--catppuccin-frappe html.has-navbar-fixed-top,html.theme--catppuccin-frappe body.has-navbar-fixed-top{padding-top:4rem}html.theme--catppuccin-frappe html.has-navbar-fixed-bottom,html.theme--catppuccin-frappe body.has-navbar-fixed-bottom{padding-bottom:4rem}html.theme--catppuccin-frappe .navbar-brand,html.theme--catppuccin-frappe .navbar-tabs{align-items:stretch;display:flex;flex-shrink:0;min-height:4rem}html.theme--catppuccin-frappe .navbar-brand a.navbar-item:focus,html.theme--catppuccin-frappe .navbar-brand a.navbar-item:hover{background-color:transparent}html.theme--catppuccin-frappe .navbar-tabs{-webkit-overflow-scrolling:touch;max-width:100vw;overflow-x:auto;overflow-y:hidden}html.theme--catppuccin-frappe .navbar-burger{color:#c6d0f5;-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;cursor:pointer;display:block;height:4rem;position:relative;width:4rem;margin-left:auto}html.theme--catppuccin-frappe .navbar-burger span{background-color:currentColor;display:block;height:1px;left:calc(50% - 8px);position:absolute;transform-origin:center;transition-duration:86ms;transition-property:background-color, opacity, transform;transition-timing-function:ease-out;width:16px}html.theme--catppuccin-frappe .navbar-burger span:nth-child(1){top:calc(50% - 6px)}html.theme--catppuccin-frappe .navbar-burger span:nth-child(2){top:calc(50% - 1px)}html.theme--catppuccin-frappe .navbar-burger span:nth-child(3){top:calc(50% + 4px)}html.theme--catppuccin-frappe .navbar-burger:hover{background-color:rgba(0,0,0,0.05)}html.theme--catppuccin-frappe .navbar-burger.is-active span:nth-child(1){transform:translateY(5px) rotate(45deg)}html.theme--catppuccin-frappe .navbar-burger.is-active span:nth-child(2){opacity:0}html.theme--catppuccin-frappe .navbar-burger.is-active span:nth-child(3){transform:translateY(-5px) rotate(-45deg)}html.theme--catppuccin-frappe .navbar-menu{display:none}html.theme--catppuccin-frappe .navbar-item,html.theme--catppuccin-frappe .navbar-link{color:#c6d0f5;display:block;line-height:1.5;padding:0.5rem 0.75rem;position:relative}html.theme--catppuccin-frappe .navbar-item .icon:only-child,html.theme--catppuccin-frappe .navbar-link .icon:only-child{margin-left:-0.25rem;margin-right:-0.25rem}html.theme--catppuccin-frappe a.navbar-item,html.theme--catppuccin-frappe .navbar-link{cursor:pointer}html.theme--catppuccin-frappe a.navbar-item:focus,html.theme--catppuccin-frappe a.navbar-item:focus-within,html.theme--catppuccin-frappe a.navbar-item:hover,html.theme--catppuccin-frappe a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar-link:focus,html.theme--catppuccin-frappe .navbar-link:focus-within,html.theme--catppuccin-frappe .navbar-link:hover,html.theme--catppuccin-frappe .navbar-link.is-active{background-color:rgba(0,0,0,0);color:#8caaee}html.theme--catppuccin-frappe .navbar-item{flex-grow:0;flex-shrink:0}html.theme--catppuccin-frappe .navbar-item img{max-height:1.75rem}html.theme--catppuccin-frappe .navbar-item.has-dropdown{padding:0}html.theme--catppuccin-frappe .navbar-item.is-expanded{flex-grow:1;flex-shrink:1}html.theme--catppuccin-frappe .navbar-item.is-tab{border-bottom:1px solid transparent;min-height:4rem;padding-bottom:calc(0.5rem - 1px)}html.theme--catppuccin-frappe .navbar-item.is-tab:focus,html.theme--catppuccin-frappe .navbar-item.is-tab:hover{background-color:rgba(0,0,0,0);border-bottom-color:#8caaee}html.theme--catppuccin-frappe .navbar-item.is-tab.is-active{background-color:rgba(0,0,0,0);border-bottom-color:#8caaee;border-bottom-style:solid;border-bottom-width:3px;color:#8caaee;padding-bottom:calc(0.5rem - 3px)}html.theme--catppuccin-frappe .navbar-content{flex-grow:1;flex-shrink:1}html.theme--catppuccin-frappe .navbar-link:not(.is-arrowless){padding-right:2.5em}html.theme--catppuccin-frappe .navbar-link:not(.is-arrowless)::after{border-color:#fff;margin-top:-0.375em;right:1.125em}html.theme--catppuccin-frappe .navbar-dropdown{font-size:0.875rem;padding-bottom:0.5rem;padding-top:0.5rem}html.theme--catppuccin-frappe .navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}html.theme--catppuccin-frappe .navbar-divider{background-color:rgba(0,0,0,0.2);border:none;display:none;height:2px;margin:0.5rem 0}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .navbar>.container{display:block}html.theme--catppuccin-frappe .navbar-brand .navbar-item,html.theme--catppuccin-frappe .navbar-tabs .navbar-item{align-items:center;display:flex}html.theme--catppuccin-frappe .navbar-link::after{display:none}html.theme--catppuccin-frappe .navbar-menu{background-color:#8caaee;box-shadow:0 8px 16px rgba(10,10,10,0.1);padding:0.5rem 0}html.theme--catppuccin-frappe .navbar-menu.is-active{display:block}html.theme--catppuccin-frappe .navbar.is-fixed-bottom-touch,html.theme--catppuccin-frappe .navbar.is-fixed-top-touch{left:0;position:fixed;right:0;z-index:30}html.theme--catppuccin-frappe .navbar.is-fixed-bottom-touch{bottom:0}html.theme--catppuccin-frappe .navbar.is-fixed-bottom-touch.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--catppuccin-frappe .navbar.is-fixed-top-touch{top:0}html.theme--catppuccin-frappe .navbar.is-fixed-top .navbar-menu,html.theme--catppuccin-frappe .navbar.is-fixed-top-touch .navbar-menu{-webkit-overflow-scrolling:touch;max-height:calc(100vh - 4rem);overflow:auto}html.theme--catppuccin-frappe html.has-navbar-fixed-top-touch,html.theme--catppuccin-frappe body.has-navbar-fixed-top-touch{padding-top:4rem}html.theme--catppuccin-frappe html.has-navbar-fixed-bottom-touch,html.theme--catppuccin-frappe body.has-navbar-fixed-bottom-touch{padding-bottom:4rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .navbar,html.theme--catppuccin-frappe .navbar-menu,html.theme--catppuccin-frappe .navbar-start,html.theme--catppuccin-frappe .navbar-end{align-items:stretch;display:flex}html.theme--catppuccin-frappe .navbar{min-height:4rem}html.theme--catppuccin-frappe .navbar.is-spaced{padding:1rem 2rem}html.theme--catppuccin-frappe .navbar.is-spaced .navbar-start,html.theme--catppuccin-frappe .navbar.is-spaced .navbar-end{align-items:center}html.theme--catppuccin-frappe .navbar.is-spaced a.navbar-item,html.theme--catppuccin-frappe .navbar.is-spaced .navbar-link{border-radius:.4em}html.theme--catppuccin-frappe .navbar.is-transparent a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-transparent a.navbar-item:hover,html.theme--catppuccin-frappe .navbar.is-transparent a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar.is-transparent .navbar-link:focus,html.theme--catppuccin-frappe .navbar.is-transparent .navbar-link:hover,html.theme--catppuccin-frappe .navbar.is-transparent .navbar-link.is-active{background-color:transparent !important}html.theme--catppuccin-frappe .navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link,html.theme--catppuccin-frappe .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link,html.theme--catppuccin-frappe .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link,html.theme--catppuccin-frappe .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link{background-color:transparent !important}html.theme--catppuccin-frappe .navbar.is-transparent .navbar-dropdown a.navbar-item:focus,html.theme--catppuccin-frappe .navbar.is-transparent .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#838ba7}html.theme--catppuccin-frappe .navbar.is-transparent .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#8caaee}html.theme--catppuccin-frappe .navbar-burger{display:none}html.theme--catppuccin-frappe .navbar-item,html.theme--catppuccin-frappe .navbar-link{align-items:center;display:flex}html.theme--catppuccin-frappe .navbar-item.has-dropdown{align-items:stretch}html.theme--catppuccin-frappe .navbar-item.has-dropdown-up .navbar-link::after{transform:rotate(135deg) translate(0.25em, -0.25em)}html.theme--catppuccin-frappe .navbar-item.has-dropdown-up .navbar-dropdown{border-bottom:1px solid rgba(0,0,0,0.2);border-radius:8px 8px 0 0;border-top:none;bottom:100%;box-shadow:0 -8px 8px rgba(10,10,10,0.1);top:auto}html.theme--catppuccin-frappe .navbar-item.is-active .navbar-dropdown,html.theme--catppuccin-frappe .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--catppuccin-frappe .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--catppuccin-frappe .navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar.is-spaced html.theme--catppuccin-frappe .navbar-item.is-active .navbar-dropdown,html.theme--catppuccin-frappe .navbar-item.is-active .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--catppuccin-frappe .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--catppuccin-frappe .navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--catppuccin-frappe .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--catppuccin-frappe .navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--catppuccin-frappe .navbar-item.is-hoverable:hover .navbar-dropdown,html.theme--catppuccin-frappe .navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed{opacity:1;pointer-events:auto;transform:translateY(0)}html.theme--catppuccin-frappe .navbar-menu{flex-grow:1;flex-shrink:0}html.theme--catppuccin-frappe .navbar-start{justify-content:flex-start;margin-right:auto}html.theme--catppuccin-frappe .navbar-end{justify-content:flex-end;margin-left:auto}html.theme--catppuccin-frappe .navbar-dropdown{background-color:#8caaee;border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid rgba(0,0,0,0.2);box-shadow:0 8px 8px rgba(10,10,10,0.1);display:none;font-size:0.875rem;left:0;min-width:100%;position:absolute;top:100%;z-index:20}html.theme--catppuccin-frappe .navbar-dropdown .navbar-item{padding:0.375rem 1rem;white-space:nowrap}html.theme--catppuccin-frappe .navbar-dropdown a.navbar-item{padding-right:3rem}html.theme--catppuccin-frappe .navbar-dropdown a.navbar-item:focus,html.theme--catppuccin-frappe .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#838ba7}html.theme--catppuccin-frappe .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#8caaee}.navbar.is-spaced html.theme--catppuccin-frappe .navbar-dropdown,html.theme--catppuccin-frappe .navbar-dropdown.is-boxed{border-radius:8px;border-top:none;box-shadow:0 8px 8px rgba(10,10,10,0.1), 0 0 0 1px rgba(10,10,10,0.1);display:block;opacity:0;pointer-events:none;top:calc(100% + (-4px));transform:translateY(-5px);transition-duration:86ms;transition-property:opacity, transform}html.theme--catppuccin-frappe .navbar-dropdown.is-right{left:auto;right:0}html.theme--catppuccin-frappe .navbar-divider{display:block}html.theme--catppuccin-frappe .navbar>.container .navbar-brand,html.theme--catppuccin-frappe .container>.navbar .navbar-brand{margin-left:-.75rem}html.theme--catppuccin-frappe .navbar>.container .navbar-menu,html.theme--catppuccin-frappe .container>.navbar .navbar-menu{margin-right:-.75rem}html.theme--catppuccin-frappe .navbar.is-fixed-bottom-desktop,html.theme--catppuccin-frappe .navbar.is-fixed-top-desktop{left:0;position:fixed;right:0;z-index:30}html.theme--catppuccin-frappe .navbar.is-fixed-bottom-desktop{bottom:0}html.theme--catppuccin-frappe .navbar.is-fixed-bottom-desktop.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--catppuccin-frappe .navbar.is-fixed-top-desktop{top:0}html.theme--catppuccin-frappe html.has-navbar-fixed-top-desktop,html.theme--catppuccin-frappe body.has-navbar-fixed-top-desktop{padding-top:4rem}html.theme--catppuccin-frappe html.has-navbar-fixed-bottom-desktop,html.theme--catppuccin-frappe body.has-navbar-fixed-bottom-desktop{padding-bottom:4rem}html.theme--catppuccin-frappe html.has-spaced-navbar-fixed-top,html.theme--catppuccin-frappe body.has-spaced-navbar-fixed-top{padding-top:6rem}html.theme--catppuccin-frappe html.has-spaced-navbar-fixed-bottom,html.theme--catppuccin-frappe body.has-spaced-navbar-fixed-bottom{padding-bottom:6rem}html.theme--catppuccin-frappe a.navbar-item.is-active,html.theme--catppuccin-frappe .navbar-link.is-active{color:#8caaee}html.theme--catppuccin-frappe a.navbar-item.is-active:not(:focus):not(:hover),html.theme--catppuccin-frappe .navbar-link.is-active:not(:focus):not(:hover){background-color:rgba(0,0,0,0)}html.theme--catppuccin-frappe .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-frappe .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-frappe .navbar-item.has-dropdown.is-active .navbar-link{background-color:rgba(0,0,0,0)}}html.theme--catppuccin-frappe .hero.is-fullheight-with-navbar{min-height:calc(100vh - 4rem)}html.theme--catppuccin-frappe .pagination{font-size:1rem;margin:-.25rem}html.theme--catppuccin-frappe .pagination.is-small,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.pagination{font-size:.75rem}html.theme--catppuccin-frappe .pagination.is-medium{font-size:1.25rem}html.theme--catppuccin-frappe .pagination.is-large{font-size:1.5rem}html.theme--catppuccin-frappe .pagination.is-rounded .pagination-previous,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.pagination .pagination-previous,html.theme--catppuccin-frappe .pagination.is-rounded .pagination-next,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.pagination .pagination-next{padding-left:1em;padding-right:1em;border-radius:9999px}html.theme--catppuccin-frappe .pagination.is-rounded .pagination-link,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.pagination .pagination-link{border-radius:9999px}html.theme--catppuccin-frappe .pagination,html.theme--catppuccin-frappe .pagination-list{align-items:center;display:flex;justify-content:center;text-align:center}html.theme--catppuccin-frappe .pagination-previous,html.theme--catppuccin-frappe .pagination-next,html.theme--catppuccin-frappe .pagination-link,html.theme--catppuccin-frappe .pagination-ellipsis{font-size:1em;justify-content:center;margin:.25rem;padding-left:.5em;padding-right:.5em;text-align:center}html.theme--catppuccin-frappe .pagination-previous,html.theme--catppuccin-frappe .pagination-next,html.theme--catppuccin-frappe .pagination-link{border-color:#626880;color:#8caaee;min-width:2.5em}html.theme--catppuccin-frappe .pagination-previous:hover,html.theme--catppuccin-frappe .pagination-next:hover,html.theme--catppuccin-frappe .pagination-link:hover{border-color:#737994;color:#99d1db}html.theme--catppuccin-frappe .pagination-previous:focus,html.theme--catppuccin-frappe .pagination-next:focus,html.theme--catppuccin-frappe .pagination-link:focus{border-color:#737994}html.theme--catppuccin-frappe .pagination-previous:active,html.theme--catppuccin-frappe .pagination-next:active,html.theme--catppuccin-frappe .pagination-link:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2)}html.theme--catppuccin-frappe .pagination-previous[disabled],html.theme--catppuccin-frappe .pagination-previous.is-disabled,html.theme--catppuccin-frappe .pagination-next[disabled],html.theme--catppuccin-frappe .pagination-next.is-disabled,html.theme--catppuccin-frappe .pagination-link[disabled],html.theme--catppuccin-frappe .pagination-link.is-disabled{background-color:#626880;border-color:#626880;box-shadow:none;color:#f1f4fd;opacity:0.5}html.theme--catppuccin-frappe .pagination-previous,html.theme--catppuccin-frappe .pagination-next{padding-left:.75em;padding-right:.75em;white-space:nowrap}html.theme--catppuccin-frappe .pagination-link.is-current{background-color:#8caaee;border-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .pagination-ellipsis{color:#737994;pointer-events:none}html.theme--catppuccin-frappe .pagination-list{flex-wrap:wrap}html.theme--catppuccin-frappe .pagination-list li{list-style:none}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .pagination{flex-wrap:wrap}html.theme--catppuccin-frappe .pagination-previous,html.theme--catppuccin-frappe .pagination-next{flex-grow:1;flex-shrink:1}html.theme--catppuccin-frappe .pagination-list li{flex-grow:1;flex-shrink:1}}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .pagination-list{flex-grow:1;flex-shrink:1;justify-content:flex-start;order:1}html.theme--catppuccin-frappe .pagination-previous,html.theme--catppuccin-frappe .pagination-next,html.theme--catppuccin-frappe .pagination-link,html.theme--catppuccin-frappe .pagination-ellipsis{margin-bottom:0;margin-top:0}html.theme--catppuccin-frappe .pagination-previous{order:2}html.theme--catppuccin-frappe .pagination-next{order:3}html.theme--catppuccin-frappe .pagination{justify-content:space-between;margin-bottom:0;margin-top:0}html.theme--catppuccin-frappe .pagination.is-centered .pagination-previous{order:1}html.theme--catppuccin-frappe .pagination.is-centered .pagination-list{justify-content:center;order:2}html.theme--catppuccin-frappe .pagination.is-centered .pagination-next{order:3}html.theme--catppuccin-frappe .pagination.is-right .pagination-previous{order:1}html.theme--catppuccin-frappe .pagination.is-right .pagination-next{order:2}html.theme--catppuccin-frappe .pagination.is-right .pagination-list{justify-content:flex-end;order:3}}html.theme--catppuccin-frappe .panel{border-radius:8px;box-shadow:#171717;font-size:1rem}html.theme--catppuccin-frappe .panel:not(:last-child){margin-bottom:1.5rem}html.theme--catppuccin-frappe .panel.is-white .panel-heading{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-frappe .panel.is-white .panel-tabs a.is-active{border-bottom-color:#fff}html.theme--catppuccin-frappe .panel.is-white .panel-block.is-active .panel-icon{color:#fff}html.theme--catppuccin-frappe .panel.is-black .panel-heading{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-frappe .panel.is-black .panel-tabs a.is-active{border-bottom-color:#0a0a0a}html.theme--catppuccin-frappe .panel.is-black .panel-block.is-active .panel-icon{color:#0a0a0a}html.theme--catppuccin-frappe .panel.is-light .panel-heading{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .panel.is-light .panel-tabs a.is-active{border-bottom-color:#f5f5f5}html.theme--catppuccin-frappe .panel.is-light .panel-block.is-active .panel-icon{color:#f5f5f5}html.theme--catppuccin-frappe .panel.is-dark .panel-heading,html.theme--catppuccin-frappe .content kbd.panel .panel-heading{background-color:#414559;color:#fff}html.theme--catppuccin-frappe .panel.is-dark .panel-tabs a.is-active,html.theme--catppuccin-frappe .content kbd.panel .panel-tabs a.is-active{border-bottom-color:#414559}html.theme--catppuccin-frappe .panel.is-dark .panel-block.is-active .panel-icon,html.theme--catppuccin-frappe .content kbd.panel .panel-block.is-active .panel-icon{color:#414559}html.theme--catppuccin-frappe .panel.is-primary .panel-heading,html.theme--catppuccin-frappe .docstring>section>a.panel.docs-sourcelink .panel-heading{background-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .panel.is-primary .panel-tabs a.is-active,html.theme--catppuccin-frappe .docstring>section>a.panel.docs-sourcelink .panel-tabs a.is-active{border-bottom-color:#8caaee}html.theme--catppuccin-frappe .panel.is-primary .panel-block.is-active .panel-icon,html.theme--catppuccin-frappe .docstring>section>a.panel.docs-sourcelink .panel-block.is-active .panel-icon{color:#8caaee}html.theme--catppuccin-frappe .panel.is-link .panel-heading{background-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .panel.is-link .panel-tabs a.is-active{border-bottom-color:#8caaee}html.theme--catppuccin-frappe .panel.is-link .panel-block.is-active .panel-icon{color:#8caaee}html.theme--catppuccin-frappe .panel.is-info .panel-heading{background-color:#81c8be;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .panel.is-info .panel-tabs a.is-active{border-bottom-color:#81c8be}html.theme--catppuccin-frappe .panel.is-info .panel-block.is-active .panel-icon{color:#81c8be}html.theme--catppuccin-frappe .panel.is-success .panel-heading{background-color:#a6d189;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .panel.is-success .panel-tabs a.is-active{border-bottom-color:#a6d189}html.theme--catppuccin-frappe .panel.is-success .panel-block.is-active .panel-icon{color:#a6d189}html.theme--catppuccin-frappe .panel.is-warning .panel-heading{background-color:#e5c890;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .panel.is-warning .panel-tabs a.is-active{border-bottom-color:#e5c890}html.theme--catppuccin-frappe .panel.is-warning .panel-block.is-active .panel-icon{color:#e5c890}html.theme--catppuccin-frappe .panel.is-danger .panel-heading{background-color:#e78284;color:#fff}html.theme--catppuccin-frappe .panel.is-danger .panel-tabs a.is-active{border-bottom-color:#e78284}html.theme--catppuccin-frappe .panel.is-danger .panel-block.is-active .panel-icon{color:#e78284}html.theme--catppuccin-frappe .panel-tabs:not(:last-child),html.theme--catppuccin-frappe .panel-block:not(:last-child){border-bottom:1px solid #ededed}html.theme--catppuccin-frappe .panel-heading{background-color:#51576d;border-radius:8px 8px 0 0;color:#b0bef1;font-size:1.25em;font-weight:700;line-height:1.25;padding:0.75em 1em}html.theme--catppuccin-frappe .panel-tabs{align-items:flex-end;display:flex;font-size:.875em;justify-content:center}html.theme--catppuccin-frappe .panel-tabs a{border-bottom:1px solid #626880;margin-bottom:-1px;padding:0.5em}html.theme--catppuccin-frappe .panel-tabs a.is-active{border-bottom-color:#51576d;color:#769aeb}html.theme--catppuccin-frappe .panel-list a{color:#c6d0f5}html.theme--catppuccin-frappe .panel-list a:hover{color:#8caaee}html.theme--catppuccin-frappe .panel-block{align-items:center;color:#b0bef1;display:flex;justify-content:flex-start;padding:0.5em 0.75em}html.theme--catppuccin-frappe .panel-block input[type="checkbox"]{margin-right:.75em}html.theme--catppuccin-frappe .panel-block>.control{flex-grow:1;flex-shrink:1;width:100%}html.theme--catppuccin-frappe .panel-block.is-wrapped{flex-wrap:wrap}html.theme--catppuccin-frappe .panel-block.is-active{border-left-color:#8caaee;color:#769aeb}html.theme--catppuccin-frappe .panel-block.is-active .panel-icon{color:#8caaee}html.theme--catppuccin-frappe .panel-block:last-child{border-bottom-left-radius:8px;border-bottom-right-radius:8px}html.theme--catppuccin-frappe a.panel-block,html.theme--catppuccin-frappe label.panel-block{cursor:pointer}html.theme--catppuccin-frappe a.panel-block:hover,html.theme--catppuccin-frappe label.panel-block:hover{background-color:#292c3c}html.theme--catppuccin-frappe .panel-icon{display:inline-block;font-size:14px;height:1em;line-height:1em;text-align:center;vertical-align:top;width:1em;color:#f1f4fd;margin-right:.75em}html.theme--catppuccin-frappe .panel-icon .fa{font-size:inherit;line-height:inherit}html.theme--catppuccin-frappe .tabs{-webkit-overflow-scrolling:touch;align-items:stretch;display:flex;font-size:1rem;justify-content:space-between;overflow:hidden;overflow-x:auto;white-space:nowrap}html.theme--catppuccin-frappe .tabs a{align-items:center;border-bottom-color:#626880;border-bottom-style:solid;border-bottom-width:1px;color:#c6d0f5;display:flex;justify-content:center;margin-bottom:-1px;padding:0.5em 1em;vertical-align:top}html.theme--catppuccin-frappe .tabs a:hover{border-bottom-color:#b0bef1;color:#b0bef1}html.theme--catppuccin-frappe .tabs li{display:block}html.theme--catppuccin-frappe .tabs li.is-active a{border-bottom-color:#8caaee;color:#8caaee}html.theme--catppuccin-frappe .tabs ul{align-items:center;border-bottom-color:#626880;border-bottom-style:solid;border-bottom-width:1px;display:flex;flex-grow:1;flex-shrink:0;justify-content:flex-start}html.theme--catppuccin-frappe .tabs ul.is-left{padding-right:0.75em}html.theme--catppuccin-frappe .tabs ul.is-center{flex:none;justify-content:center;padding-left:0.75em;padding-right:0.75em}html.theme--catppuccin-frappe .tabs ul.is-right{justify-content:flex-end;padding-left:0.75em}html.theme--catppuccin-frappe .tabs .icon:first-child{margin-right:.5em}html.theme--catppuccin-frappe .tabs .icon:last-child{margin-left:.5em}html.theme--catppuccin-frappe .tabs.is-centered ul{justify-content:center}html.theme--catppuccin-frappe .tabs.is-right ul{justify-content:flex-end}html.theme--catppuccin-frappe .tabs.is-boxed a{border:1px solid transparent;border-radius:.4em .4em 0 0}html.theme--catppuccin-frappe .tabs.is-boxed a:hover{background-color:#292c3c;border-bottom-color:#626880}html.theme--catppuccin-frappe .tabs.is-boxed li.is-active a{background-color:#fff;border-color:#626880;border-bottom-color:rgba(0,0,0,0) !important}html.theme--catppuccin-frappe .tabs.is-fullwidth li{flex-grow:1;flex-shrink:0}html.theme--catppuccin-frappe .tabs.is-toggle a{border-color:#626880;border-style:solid;border-width:1px;margin-bottom:0;position:relative}html.theme--catppuccin-frappe .tabs.is-toggle a:hover{background-color:#292c3c;border-color:#737994;z-index:2}html.theme--catppuccin-frappe .tabs.is-toggle li+li{margin-left:-1px}html.theme--catppuccin-frappe .tabs.is-toggle li:first-child a{border-top-left-radius:.4em;border-bottom-left-radius:.4em}html.theme--catppuccin-frappe .tabs.is-toggle li:last-child a{border-top-right-radius:.4em;border-bottom-right-radius:.4em}html.theme--catppuccin-frappe .tabs.is-toggle li.is-active a{background-color:#8caaee;border-color:#8caaee;color:#fff;z-index:1}html.theme--catppuccin-frappe .tabs.is-toggle ul{border-bottom:none}html.theme--catppuccin-frappe .tabs.is-toggle.is-toggle-rounded li:first-child a{border-bottom-left-radius:9999px;border-top-left-radius:9999px;padding-left:1.25em}html.theme--catppuccin-frappe .tabs.is-toggle.is-toggle-rounded li:last-child a{border-bottom-right-radius:9999px;border-top-right-radius:9999px;padding-right:1.25em}html.theme--catppuccin-frappe .tabs.is-small,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.tabs{font-size:.75rem}html.theme--catppuccin-frappe .tabs.is-medium{font-size:1.25rem}html.theme--catppuccin-frappe .tabs.is-large{font-size:1.5rem}html.theme--catppuccin-frappe .column{display:block;flex-basis:0;flex-grow:1;flex-shrink:1;padding:.75rem}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-narrow{flex:none;width:unset}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-full{flex:none;width:100%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-three-quarters{flex:none;width:75%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-two-thirds{flex:none;width:66.6666%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-half{flex:none;width:50%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-one-third{flex:none;width:33.3333%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-one-quarter{flex:none;width:25%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-one-fifth{flex:none;width:20%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-two-fifths{flex:none;width:40%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-three-fifths{flex:none;width:60%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-four-fifths{flex:none;width:80%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-three-quarters{margin-left:75%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-two-thirds{margin-left:66.6666%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-half{margin-left:50%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-one-third{margin-left:33.3333%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-one-quarter{margin-left:25%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-one-fifth{margin-left:20%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-two-fifths{margin-left:40%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-three-fifths{margin-left:60%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-four-fifths{margin-left:80%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-0{flex:none;width:0%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-0{margin-left:0%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-1{flex:none;width:8.33333337%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-1{margin-left:8.33333337%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-2{flex:none;width:16.66666674%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-2{margin-left:16.66666674%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-3{flex:none;width:25%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-3{margin-left:25%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-4{flex:none;width:33.33333337%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-4{margin-left:33.33333337%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-5{flex:none;width:41.66666674%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-5{margin-left:41.66666674%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-6{flex:none;width:50%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-6{margin-left:50%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-7{flex:none;width:58.33333337%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-7{margin-left:58.33333337%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-8{flex:none;width:66.66666674%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-8{margin-left:66.66666674%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-9{flex:none;width:75%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-9{margin-left:75%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-10{flex:none;width:83.33333337%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-10{margin-left:83.33333337%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-11{flex:none;width:91.66666674%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-11{margin-left:91.66666674%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-12{flex:none;width:100%}.columns.is-mobile>html.theme--catppuccin-frappe .column.is-offset-12{margin-left:100%}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .column.is-narrow-mobile{flex:none;width:unset}html.theme--catppuccin-frappe .column.is-full-mobile{flex:none;width:100%}html.theme--catppuccin-frappe .column.is-three-quarters-mobile{flex:none;width:75%}html.theme--catppuccin-frappe .column.is-two-thirds-mobile{flex:none;width:66.6666%}html.theme--catppuccin-frappe .column.is-half-mobile{flex:none;width:50%}html.theme--catppuccin-frappe .column.is-one-third-mobile{flex:none;width:33.3333%}html.theme--catppuccin-frappe .column.is-one-quarter-mobile{flex:none;width:25%}html.theme--catppuccin-frappe .column.is-one-fifth-mobile{flex:none;width:20%}html.theme--catppuccin-frappe .column.is-two-fifths-mobile{flex:none;width:40%}html.theme--catppuccin-frappe .column.is-three-fifths-mobile{flex:none;width:60%}html.theme--catppuccin-frappe .column.is-four-fifths-mobile{flex:none;width:80%}html.theme--catppuccin-frappe .column.is-offset-three-quarters-mobile{margin-left:75%}html.theme--catppuccin-frappe .column.is-offset-two-thirds-mobile{margin-left:66.6666%}html.theme--catppuccin-frappe .column.is-offset-half-mobile{margin-left:50%}html.theme--catppuccin-frappe .column.is-offset-one-third-mobile{margin-left:33.3333%}html.theme--catppuccin-frappe .column.is-offset-one-quarter-mobile{margin-left:25%}html.theme--catppuccin-frappe .column.is-offset-one-fifth-mobile{margin-left:20%}html.theme--catppuccin-frappe .column.is-offset-two-fifths-mobile{margin-left:40%}html.theme--catppuccin-frappe .column.is-offset-three-fifths-mobile{margin-left:60%}html.theme--catppuccin-frappe .column.is-offset-four-fifths-mobile{margin-left:80%}html.theme--catppuccin-frappe .column.is-0-mobile{flex:none;width:0%}html.theme--catppuccin-frappe .column.is-offset-0-mobile{margin-left:0%}html.theme--catppuccin-frappe .column.is-1-mobile{flex:none;width:8.33333337%}html.theme--catppuccin-frappe .column.is-offset-1-mobile{margin-left:8.33333337%}html.theme--catppuccin-frappe .column.is-2-mobile{flex:none;width:16.66666674%}html.theme--catppuccin-frappe .column.is-offset-2-mobile{margin-left:16.66666674%}html.theme--catppuccin-frappe .column.is-3-mobile{flex:none;width:25%}html.theme--catppuccin-frappe .column.is-offset-3-mobile{margin-left:25%}html.theme--catppuccin-frappe .column.is-4-mobile{flex:none;width:33.33333337%}html.theme--catppuccin-frappe .column.is-offset-4-mobile{margin-left:33.33333337%}html.theme--catppuccin-frappe .column.is-5-mobile{flex:none;width:41.66666674%}html.theme--catppuccin-frappe .column.is-offset-5-mobile{margin-left:41.66666674%}html.theme--catppuccin-frappe .column.is-6-mobile{flex:none;width:50%}html.theme--catppuccin-frappe .column.is-offset-6-mobile{margin-left:50%}html.theme--catppuccin-frappe .column.is-7-mobile{flex:none;width:58.33333337%}html.theme--catppuccin-frappe .column.is-offset-7-mobile{margin-left:58.33333337%}html.theme--catppuccin-frappe .column.is-8-mobile{flex:none;width:66.66666674%}html.theme--catppuccin-frappe .column.is-offset-8-mobile{margin-left:66.66666674%}html.theme--catppuccin-frappe .column.is-9-mobile{flex:none;width:75%}html.theme--catppuccin-frappe .column.is-offset-9-mobile{margin-left:75%}html.theme--catppuccin-frappe .column.is-10-mobile{flex:none;width:83.33333337%}html.theme--catppuccin-frappe .column.is-offset-10-mobile{margin-left:83.33333337%}html.theme--catppuccin-frappe .column.is-11-mobile{flex:none;width:91.66666674%}html.theme--catppuccin-frappe .column.is-offset-11-mobile{margin-left:91.66666674%}html.theme--catppuccin-frappe .column.is-12-mobile{flex:none;width:100%}html.theme--catppuccin-frappe .column.is-offset-12-mobile{margin-left:100%}}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .column.is-narrow,html.theme--catppuccin-frappe .column.is-narrow-tablet{flex:none;width:unset}html.theme--catppuccin-frappe .column.is-full,html.theme--catppuccin-frappe .column.is-full-tablet{flex:none;width:100%}html.theme--catppuccin-frappe .column.is-three-quarters,html.theme--catppuccin-frappe .column.is-three-quarters-tablet{flex:none;width:75%}html.theme--catppuccin-frappe .column.is-two-thirds,html.theme--catppuccin-frappe .column.is-two-thirds-tablet{flex:none;width:66.6666%}html.theme--catppuccin-frappe .column.is-half,html.theme--catppuccin-frappe .column.is-half-tablet{flex:none;width:50%}html.theme--catppuccin-frappe .column.is-one-third,html.theme--catppuccin-frappe .column.is-one-third-tablet{flex:none;width:33.3333%}html.theme--catppuccin-frappe .column.is-one-quarter,html.theme--catppuccin-frappe .column.is-one-quarter-tablet{flex:none;width:25%}html.theme--catppuccin-frappe .column.is-one-fifth,html.theme--catppuccin-frappe .column.is-one-fifth-tablet{flex:none;width:20%}html.theme--catppuccin-frappe .column.is-two-fifths,html.theme--catppuccin-frappe .column.is-two-fifths-tablet{flex:none;width:40%}html.theme--catppuccin-frappe .column.is-three-fifths,html.theme--catppuccin-frappe .column.is-three-fifths-tablet{flex:none;width:60%}html.theme--catppuccin-frappe .column.is-four-fifths,html.theme--catppuccin-frappe .column.is-four-fifths-tablet{flex:none;width:80%}html.theme--catppuccin-frappe .column.is-offset-three-quarters,html.theme--catppuccin-frappe .column.is-offset-three-quarters-tablet{margin-left:75%}html.theme--catppuccin-frappe .column.is-offset-two-thirds,html.theme--catppuccin-frappe .column.is-offset-two-thirds-tablet{margin-left:66.6666%}html.theme--catppuccin-frappe .column.is-offset-half,html.theme--catppuccin-frappe .column.is-offset-half-tablet{margin-left:50%}html.theme--catppuccin-frappe .column.is-offset-one-third,html.theme--catppuccin-frappe .column.is-offset-one-third-tablet{margin-left:33.3333%}html.theme--catppuccin-frappe .column.is-offset-one-quarter,html.theme--catppuccin-frappe .column.is-offset-one-quarter-tablet{margin-left:25%}html.theme--catppuccin-frappe .column.is-offset-one-fifth,html.theme--catppuccin-frappe .column.is-offset-one-fifth-tablet{margin-left:20%}html.theme--catppuccin-frappe .column.is-offset-two-fifths,html.theme--catppuccin-frappe .column.is-offset-two-fifths-tablet{margin-left:40%}html.theme--catppuccin-frappe .column.is-offset-three-fifths,html.theme--catppuccin-frappe .column.is-offset-three-fifths-tablet{margin-left:60%}html.theme--catppuccin-frappe .column.is-offset-four-fifths,html.theme--catppuccin-frappe .column.is-offset-four-fifths-tablet{margin-left:80%}html.theme--catppuccin-frappe .column.is-0,html.theme--catppuccin-frappe .column.is-0-tablet{flex:none;width:0%}html.theme--catppuccin-frappe .column.is-offset-0,html.theme--catppuccin-frappe .column.is-offset-0-tablet{margin-left:0%}html.theme--catppuccin-frappe .column.is-1,html.theme--catppuccin-frappe .column.is-1-tablet{flex:none;width:8.33333337%}html.theme--catppuccin-frappe .column.is-offset-1,html.theme--catppuccin-frappe .column.is-offset-1-tablet{margin-left:8.33333337%}html.theme--catppuccin-frappe .column.is-2,html.theme--catppuccin-frappe .column.is-2-tablet{flex:none;width:16.66666674%}html.theme--catppuccin-frappe .column.is-offset-2,html.theme--catppuccin-frappe .column.is-offset-2-tablet{margin-left:16.66666674%}html.theme--catppuccin-frappe .column.is-3,html.theme--catppuccin-frappe .column.is-3-tablet{flex:none;width:25%}html.theme--catppuccin-frappe .column.is-offset-3,html.theme--catppuccin-frappe .column.is-offset-3-tablet{margin-left:25%}html.theme--catppuccin-frappe .column.is-4,html.theme--catppuccin-frappe .column.is-4-tablet{flex:none;width:33.33333337%}html.theme--catppuccin-frappe .column.is-offset-4,html.theme--catppuccin-frappe .column.is-offset-4-tablet{margin-left:33.33333337%}html.theme--catppuccin-frappe .column.is-5,html.theme--catppuccin-frappe .column.is-5-tablet{flex:none;width:41.66666674%}html.theme--catppuccin-frappe .column.is-offset-5,html.theme--catppuccin-frappe .column.is-offset-5-tablet{margin-left:41.66666674%}html.theme--catppuccin-frappe .column.is-6,html.theme--catppuccin-frappe .column.is-6-tablet{flex:none;width:50%}html.theme--catppuccin-frappe .column.is-offset-6,html.theme--catppuccin-frappe .column.is-offset-6-tablet{margin-left:50%}html.theme--catppuccin-frappe .column.is-7,html.theme--catppuccin-frappe .column.is-7-tablet{flex:none;width:58.33333337%}html.theme--catppuccin-frappe .column.is-offset-7,html.theme--catppuccin-frappe .column.is-offset-7-tablet{margin-left:58.33333337%}html.theme--catppuccin-frappe .column.is-8,html.theme--catppuccin-frappe .column.is-8-tablet{flex:none;width:66.66666674%}html.theme--catppuccin-frappe .column.is-offset-8,html.theme--catppuccin-frappe .column.is-offset-8-tablet{margin-left:66.66666674%}html.theme--catppuccin-frappe .column.is-9,html.theme--catppuccin-frappe .column.is-9-tablet{flex:none;width:75%}html.theme--catppuccin-frappe .column.is-offset-9,html.theme--catppuccin-frappe .column.is-offset-9-tablet{margin-left:75%}html.theme--catppuccin-frappe .column.is-10,html.theme--catppuccin-frappe .column.is-10-tablet{flex:none;width:83.33333337%}html.theme--catppuccin-frappe .column.is-offset-10,html.theme--catppuccin-frappe .column.is-offset-10-tablet{margin-left:83.33333337%}html.theme--catppuccin-frappe .column.is-11,html.theme--catppuccin-frappe .column.is-11-tablet{flex:none;width:91.66666674%}html.theme--catppuccin-frappe .column.is-offset-11,html.theme--catppuccin-frappe .column.is-offset-11-tablet{margin-left:91.66666674%}html.theme--catppuccin-frappe .column.is-12,html.theme--catppuccin-frappe .column.is-12-tablet{flex:none;width:100%}html.theme--catppuccin-frappe .column.is-offset-12,html.theme--catppuccin-frappe .column.is-offset-12-tablet{margin-left:100%}}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .column.is-narrow-touch{flex:none;width:unset}html.theme--catppuccin-frappe .column.is-full-touch{flex:none;width:100%}html.theme--catppuccin-frappe .column.is-three-quarters-touch{flex:none;width:75%}html.theme--catppuccin-frappe .column.is-two-thirds-touch{flex:none;width:66.6666%}html.theme--catppuccin-frappe .column.is-half-touch{flex:none;width:50%}html.theme--catppuccin-frappe .column.is-one-third-touch{flex:none;width:33.3333%}html.theme--catppuccin-frappe .column.is-one-quarter-touch{flex:none;width:25%}html.theme--catppuccin-frappe .column.is-one-fifth-touch{flex:none;width:20%}html.theme--catppuccin-frappe .column.is-two-fifths-touch{flex:none;width:40%}html.theme--catppuccin-frappe .column.is-three-fifths-touch{flex:none;width:60%}html.theme--catppuccin-frappe .column.is-four-fifths-touch{flex:none;width:80%}html.theme--catppuccin-frappe .column.is-offset-three-quarters-touch{margin-left:75%}html.theme--catppuccin-frappe .column.is-offset-two-thirds-touch{margin-left:66.6666%}html.theme--catppuccin-frappe .column.is-offset-half-touch{margin-left:50%}html.theme--catppuccin-frappe .column.is-offset-one-third-touch{margin-left:33.3333%}html.theme--catppuccin-frappe .column.is-offset-one-quarter-touch{margin-left:25%}html.theme--catppuccin-frappe .column.is-offset-one-fifth-touch{margin-left:20%}html.theme--catppuccin-frappe .column.is-offset-two-fifths-touch{margin-left:40%}html.theme--catppuccin-frappe .column.is-offset-three-fifths-touch{margin-left:60%}html.theme--catppuccin-frappe .column.is-offset-four-fifths-touch{margin-left:80%}html.theme--catppuccin-frappe .column.is-0-touch{flex:none;width:0%}html.theme--catppuccin-frappe .column.is-offset-0-touch{margin-left:0%}html.theme--catppuccin-frappe .column.is-1-touch{flex:none;width:8.33333337%}html.theme--catppuccin-frappe .column.is-offset-1-touch{margin-left:8.33333337%}html.theme--catppuccin-frappe .column.is-2-touch{flex:none;width:16.66666674%}html.theme--catppuccin-frappe .column.is-offset-2-touch{margin-left:16.66666674%}html.theme--catppuccin-frappe .column.is-3-touch{flex:none;width:25%}html.theme--catppuccin-frappe .column.is-offset-3-touch{margin-left:25%}html.theme--catppuccin-frappe .column.is-4-touch{flex:none;width:33.33333337%}html.theme--catppuccin-frappe .column.is-offset-4-touch{margin-left:33.33333337%}html.theme--catppuccin-frappe .column.is-5-touch{flex:none;width:41.66666674%}html.theme--catppuccin-frappe .column.is-offset-5-touch{margin-left:41.66666674%}html.theme--catppuccin-frappe .column.is-6-touch{flex:none;width:50%}html.theme--catppuccin-frappe .column.is-offset-6-touch{margin-left:50%}html.theme--catppuccin-frappe .column.is-7-touch{flex:none;width:58.33333337%}html.theme--catppuccin-frappe .column.is-offset-7-touch{margin-left:58.33333337%}html.theme--catppuccin-frappe .column.is-8-touch{flex:none;width:66.66666674%}html.theme--catppuccin-frappe .column.is-offset-8-touch{margin-left:66.66666674%}html.theme--catppuccin-frappe .column.is-9-touch{flex:none;width:75%}html.theme--catppuccin-frappe .column.is-offset-9-touch{margin-left:75%}html.theme--catppuccin-frappe .column.is-10-touch{flex:none;width:83.33333337%}html.theme--catppuccin-frappe .column.is-offset-10-touch{margin-left:83.33333337%}html.theme--catppuccin-frappe .column.is-11-touch{flex:none;width:91.66666674%}html.theme--catppuccin-frappe .column.is-offset-11-touch{margin-left:91.66666674%}html.theme--catppuccin-frappe .column.is-12-touch{flex:none;width:100%}html.theme--catppuccin-frappe .column.is-offset-12-touch{margin-left:100%}}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .column.is-narrow-desktop{flex:none;width:unset}html.theme--catppuccin-frappe .column.is-full-desktop{flex:none;width:100%}html.theme--catppuccin-frappe .column.is-three-quarters-desktop{flex:none;width:75%}html.theme--catppuccin-frappe .column.is-two-thirds-desktop{flex:none;width:66.6666%}html.theme--catppuccin-frappe .column.is-half-desktop{flex:none;width:50%}html.theme--catppuccin-frappe .column.is-one-third-desktop{flex:none;width:33.3333%}html.theme--catppuccin-frappe .column.is-one-quarter-desktop{flex:none;width:25%}html.theme--catppuccin-frappe .column.is-one-fifth-desktop{flex:none;width:20%}html.theme--catppuccin-frappe .column.is-two-fifths-desktop{flex:none;width:40%}html.theme--catppuccin-frappe .column.is-three-fifths-desktop{flex:none;width:60%}html.theme--catppuccin-frappe .column.is-four-fifths-desktop{flex:none;width:80%}html.theme--catppuccin-frappe .column.is-offset-three-quarters-desktop{margin-left:75%}html.theme--catppuccin-frappe .column.is-offset-two-thirds-desktop{margin-left:66.6666%}html.theme--catppuccin-frappe .column.is-offset-half-desktop{margin-left:50%}html.theme--catppuccin-frappe .column.is-offset-one-third-desktop{margin-left:33.3333%}html.theme--catppuccin-frappe .column.is-offset-one-quarter-desktop{margin-left:25%}html.theme--catppuccin-frappe .column.is-offset-one-fifth-desktop{margin-left:20%}html.theme--catppuccin-frappe .column.is-offset-two-fifths-desktop{margin-left:40%}html.theme--catppuccin-frappe .column.is-offset-three-fifths-desktop{margin-left:60%}html.theme--catppuccin-frappe .column.is-offset-four-fifths-desktop{margin-left:80%}html.theme--catppuccin-frappe .column.is-0-desktop{flex:none;width:0%}html.theme--catppuccin-frappe .column.is-offset-0-desktop{margin-left:0%}html.theme--catppuccin-frappe .column.is-1-desktop{flex:none;width:8.33333337%}html.theme--catppuccin-frappe .column.is-offset-1-desktop{margin-left:8.33333337%}html.theme--catppuccin-frappe .column.is-2-desktop{flex:none;width:16.66666674%}html.theme--catppuccin-frappe .column.is-offset-2-desktop{margin-left:16.66666674%}html.theme--catppuccin-frappe .column.is-3-desktop{flex:none;width:25%}html.theme--catppuccin-frappe .column.is-offset-3-desktop{margin-left:25%}html.theme--catppuccin-frappe .column.is-4-desktop{flex:none;width:33.33333337%}html.theme--catppuccin-frappe .column.is-offset-4-desktop{margin-left:33.33333337%}html.theme--catppuccin-frappe .column.is-5-desktop{flex:none;width:41.66666674%}html.theme--catppuccin-frappe .column.is-offset-5-desktop{margin-left:41.66666674%}html.theme--catppuccin-frappe .column.is-6-desktop{flex:none;width:50%}html.theme--catppuccin-frappe .column.is-offset-6-desktop{margin-left:50%}html.theme--catppuccin-frappe .column.is-7-desktop{flex:none;width:58.33333337%}html.theme--catppuccin-frappe .column.is-offset-7-desktop{margin-left:58.33333337%}html.theme--catppuccin-frappe .column.is-8-desktop{flex:none;width:66.66666674%}html.theme--catppuccin-frappe .column.is-offset-8-desktop{margin-left:66.66666674%}html.theme--catppuccin-frappe .column.is-9-desktop{flex:none;width:75%}html.theme--catppuccin-frappe .column.is-offset-9-desktop{margin-left:75%}html.theme--catppuccin-frappe .column.is-10-desktop{flex:none;width:83.33333337%}html.theme--catppuccin-frappe .column.is-offset-10-desktop{margin-left:83.33333337%}html.theme--catppuccin-frappe .column.is-11-desktop{flex:none;width:91.66666674%}html.theme--catppuccin-frappe .column.is-offset-11-desktop{margin-left:91.66666674%}html.theme--catppuccin-frappe .column.is-12-desktop{flex:none;width:100%}html.theme--catppuccin-frappe .column.is-offset-12-desktop{margin-left:100%}}@media screen and (min-width: 1216px){html.theme--catppuccin-frappe .column.is-narrow-widescreen{flex:none;width:unset}html.theme--catppuccin-frappe .column.is-full-widescreen{flex:none;width:100%}html.theme--catppuccin-frappe .column.is-three-quarters-widescreen{flex:none;width:75%}html.theme--catppuccin-frappe .column.is-two-thirds-widescreen{flex:none;width:66.6666%}html.theme--catppuccin-frappe .column.is-half-widescreen{flex:none;width:50%}html.theme--catppuccin-frappe .column.is-one-third-widescreen{flex:none;width:33.3333%}html.theme--catppuccin-frappe .column.is-one-quarter-widescreen{flex:none;width:25%}html.theme--catppuccin-frappe .column.is-one-fifth-widescreen{flex:none;width:20%}html.theme--catppuccin-frappe .column.is-two-fifths-widescreen{flex:none;width:40%}html.theme--catppuccin-frappe .column.is-three-fifths-widescreen{flex:none;width:60%}html.theme--catppuccin-frappe .column.is-four-fifths-widescreen{flex:none;width:80%}html.theme--catppuccin-frappe .column.is-offset-three-quarters-widescreen{margin-left:75%}html.theme--catppuccin-frappe .column.is-offset-two-thirds-widescreen{margin-left:66.6666%}html.theme--catppuccin-frappe .column.is-offset-half-widescreen{margin-left:50%}html.theme--catppuccin-frappe .column.is-offset-one-third-widescreen{margin-left:33.3333%}html.theme--catppuccin-frappe .column.is-offset-one-quarter-widescreen{margin-left:25%}html.theme--catppuccin-frappe .column.is-offset-one-fifth-widescreen{margin-left:20%}html.theme--catppuccin-frappe .column.is-offset-two-fifths-widescreen{margin-left:40%}html.theme--catppuccin-frappe .column.is-offset-three-fifths-widescreen{margin-left:60%}html.theme--catppuccin-frappe .column.is-offset-four-fifths-widescreen{margin-left:80%}html.theme--catppuccin-frappe .column.is-0-widescreen{flex:none;width:0%}html.theme--catppuccin-frappe .column.is-offset-0-widescreen{margin-left:0%}html.theme--catppuccin-frappe .column.is-1-widescreen{flex:none;width:8.33333337%}html.theme--catppuccin-frappe .column.is-offset-1-widescreen{margin-left:8.33333337%}html.theme--catppuccin-frappe .column.is-2-widescreen{flex:none;width:16.66666674%}html.theme--catppuccin-frappe .column.is-offset-2-widescreen{margin-left:16.66666674%}html.theme--catppuccin-frappe .column.is-3-widescreen{flex:none;width:25%}html.theme--catppuccin-frappe .column.is-offset-3-widescreen{margin-left:25%}html.theme--catppuccin-frappe .column.is-4-widescreen{flex:none;width:33.33333337%}html.theme--catppuccin-frappe .column.is-offset-4-widescreen{margin-left:33.33333337%}html.theme--catppuccin-frappe .column.is-5-widescreen{flex:none;width:41.66666674%}html.theme--catppuccin-frappe .column.is-offset-5-widescreen{margin-left:41.66666674%}html.theme--catppuccin-frappe .column.is-6-widescreen{flex:none;width:50%}html.theme--catppuccin-frappe .column.is-offset-6-widescreen{margin-left:50%}html.theme--catppuccin-frappe .column.is-7-widescreen{flex:none;width:58.33333337%}html.theme--catppuccin-frappe .column.is-offset-7-widescreen{margin-left:58.33333337%}html.theme--catppuccin-frappe .column.is-8-widescreen{flex:none;width:66.66666674%}html.theme--catppuccin-frappe .column.is-offset-8-widescreen{margin-left:66.66666674%}html.theme--catppuccin-frappe .column.is-9-widescreen{flex:none;width:75%}html.theme--catppuccin-frappe .column.is-offset-9-widescreen{margin-left:75%}html.theme--catppuccin-frappe .column.is-10-widescreen{flex:none;width:83.33333337%}html.theme--catppuccin-frappe .column.is-offset-10-widescreen{margin-left:83.33333337%}html.theme--catppuccin-frappe .column.is-11-widescreen{flex:none;width:91.66666674%}html.theme--catppuccin-frappe .column.is-offset-11-widescreen{margin-left:91.66666674%}html.theme--catppuccin-frappe .column.is-12-widescreen{flex:none;width:100%}html.theme--catppuccin-frappe .column.is-offset-12-widescreen{margin-left:100%}}@media screen and (min-width: 1408px){html.theme--catppuccin-frappe .column.is-narrow-fullhd{flex:none;width:unset}html.theme--catppuccin-frappe .column.is-full-fullhd{flex:none;width:100%}html.theme--catppuccin-frappe .column.is-three-quarters-fullhd{flex:none;width:75%}html.theme--catppuccin-frappe .column.is-two-thirds-fullhd{flex:none;width:66.6666%}html.theme--catppuccin-frappe .column.is-half-fullhd{flex:none;width:50%}html.theme--catppuccin-frappe .column.is-one-third-fullhd{flex:none;width:33.3333%}html.theme--catppuccin-frappe .column.is-one-quarter-fullhd{flex:none;width:25%}html.theme--catppuccin-frappe .column.is-one-fifth-fullhd{flex:none;width:20%}html.theme--catppuccin-frappe .column.is-two-fifths-fullhd{flex:none;width:40%}html.theme--catppuccin-frappe .column.is-three-fifths-fullhd{flex:none;width:60%}html.theme--catppuccin-frappe .column.is-four-fifths-fullhd{flex:none;width:80%}html.theme--catppuccin-frappe .column.is-offset-three-quarters-fullhd{margin-left:75%}html.theme--catppuccin-frappe .column.is-offset-two-thirds-fullhd{margin-left:66.6666%}html.theme--catppuccin-frappe .column.is-offset-half-fullhd{margin-left:50%}html.theme--catppuccin-frappe .column.is-offset-one-third-fullhd{margin-left:33.3333%}html.theme--catppuccin-frappe .column.is-offset-one-quarter-fullhd{margin-left:25%}html.theme--catppuccin-frappe .column.is-offset-one-fifth-fullhd{margin-left:20%}html.theme--catppuccin-frappe .column.is-offset-two-fifths-fullhd{margin-left:40%}html.theme--catppuccin-frappe .column.is-offset-three-fifths-fullhd{margin-left:60%}html.theme--catppuccin-frappe .column.is-offset-four-fifths-fullhd{margin-left:80%}html.theme--catppuccin-frappe .column.is-0-fullhd{flex:none;width:0%}html.theme--catppuccin-frappe .column.is-offset-0-fullhd{margin-left:0%}html.theme--catppuccin-frappe .column.is-1-fullhd{flex:none;width:8.33333337%}html.theme--catppuccin-frappe .column.is-offset-1-fullhd{margin-left:8.33333337%}html.theme--catppuccin-frappe .column.is-2-fullhd{flex:none;width:16.66666674%}html.theme--catppuccin-frappe .column.is-offset-2-fullhd{margin-left:16.66666674%}html.theme--catppuccin-frappe .column.is-3-fullhd{flex:none;width:25%}html.theme--catppuccin-frappe .column.is-offset-3-fullhd{margin-left:25%}html.theme--catppuccin-frappe .column.is-4-fullhd{flex:none;width:33.33333337%}html.theme--catppuccin-frappe .column.is-offset-4-fullhd{margin-left:33.33333337%}html.theme--catppuccin-frappe .column.is-5-fullhd{flex:none;width:41.66666674%}html.theme--catppuccin-frappe .column.is-offset-5-fullhd{margin-left:41.66666674%}html.theme--catppuccin-frappe .column.is-6-fullhd{flex:none;width:50%}html.theme--catppuccin-frappe .column.is-offset-6-fullhd{margin-left:50%}html.theme--catppuccin-frappe .column.is-7-fullhd{flex:none;width:58.33333337%}html.theme--catppuccin-frappe .column.is-offset-7-fullhd{margin-left:58.33333337%}html.theme--catppuccin-frappe .column.is-8-fullhd{flex:none;width:66.66666674%}html.theme--catppuccin-frappe .column.is-offset-8-fullhd{margin-left:66.66666674%}html.theme--catppuccin-frappe .column.is-9-fullhd{flex:none;width:75%}html.theme--catppuccin-frappe .column.is-offset-9-fullhd{margin-left:75%}html.theme--catppuccin-frappe .column.is-10-fullhd{flex:none;width:83.33333337%}html.theme--catppuccin-frappe .column.is-offset-10-fullhd{margin-left:83.33333337%}html.theme--catppuccin-frappe .column.is-11-fullhd{flex:none;width:91.66666674%}html.theme--catppuccin-frappe .column.is-offset-11-fullhd{margin-left:91.66666674%}html.theme--catppuccin-frappe .column.is-12-fullhd{flex:none;width:100%}html.theme--catppuccin-frappe .column.is-offset-12-fullhd{margin-left:100%}}html.theme--catppuccin-frappe .columns{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--catppuccin-frappe .columns:last-child{margin-bottom:-.75rem}html.theme--catppuccin-frappe .columns:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}html.theme--catppuccin-frappe .columns.is-centered{justify-content:center}html.theme--catppuccin-frappe .columns.is-gapless{margin-left:0;margin-right:0;margin-top:0}html.theme--catppuccin-frappe .columns.is-gapless>.column{margin:0;padding:0 !important}html.theme--catppuccin-frappe .columns.is-gapless:not(:last-child){margin-bottom:1.5rem}html.theme--catppuccin-frappe .columns.is-gapless:last-child{margin-bottom:0}html.theme--catppuccin-frappe .columns.is-mobile{display:flex}html.theme--catppuccin-frappe .columns.is-multiline{flex-wrap:wrap}html.theme--catppuccin-frappe .columns.is-vcentered{align-items:center}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .columns:not(.is-desktop){display:flex}}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .columns.is-desktop{display:flex}}html.theme--catppuccin-frappe .columns.is-variable{--columnGap: 0.75rem;margin-left:calc(-1 * var(--columnGap));margin-right:calc(-1 * var(--columnGap))}html.theme--catppuccin-frappe .columns.is-variable>.column{padding-left:var(--columnGap);padding-right:var(--columnGap)}html.theme--catppuccin-frappe .columns.is-variable.is-0{--columnGap: 0rem}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .columns.is-variable.is-0-mobile{--columnGap: 0rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .columns.is-variable.is-0-tablet{--columnGap: 0rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-frappe .columns.is-variable.is-0-tablet-only{--columnGap: 0rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .columns.is-variable.is-0-touch{--columnGap: 0rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .columns.is-variable.is-0-desktop{--columnGap: 0rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-frappe .columns.is-variable.is-0-desktop-only{--columnGap: 0rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-frappe .columns.is-variable.is-0-widescreen{--columnGap: 0rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-frappe .columns.is-variable.is-0-widescreen-only{--columnGap: 0rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-frappe .columns.is-variable.is-0-fullhd{--columnGap: 0rem}}html.theme--catppuccin-frappe .columns.is-variable.is-1{--columnGap: .25rem}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .columns.is-variable.is-1-mobile{--columnGap: .25rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .columns.is-variable.is-1-tablet{--columnGap: .25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-frappe .columns.is-variable.is-1-tablet-only{--columnGap: .25rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .columns.is-variable.is-1-touch{--columnGap: .25rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .columns.is-variable.is-1-desktop{--columnGap: .25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-frappe .columns.is-variable.is-1-desktop-only{--columnGap: .25rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-frappe .columns.is-variable.is-1-widescreen{--columnGap: .25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-frappe .columns.is-variable.is-1-widescreen-only{--columnGap: .25rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-frappe .columns.is-variable.is-1-fullhd{--columnGap: .25rem}}html.theme--catppuccin-frappe .columns.is-variable.is-2{--columnGap: .5rem}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .columns.is-variable.is-2-mobile{--columnGap: .5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .columns.is-variable.is-2-tablet{--columnGap: .5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-frappe .columns.is-variable.is-2-tablet-only{--columnGap: .5rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .columns.is-variable.is-2-touch{--columnGap: .5rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .columns.is-variable.is-2-desktop{--columnGap: .5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-frappe .columns.is-variable.is-2-desktop-only{--columnGap: .5rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-frappe .columns.is-variable.is-2-widescreen{--columnGap: .5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-frappe .columns.is-variable.is-2-widescreen-only{--columnGap: .5rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-frappe .columns.is-variable.is-2-fullhd{--columnGap: .5rem}}html.theme--catppuccin-frappe .columns.is-variable.is-3{--columnGap: .75rem}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .columns.is-variable.is-3-mobile{--columnGap: .75rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .columns.is-variable.is-3-tablet{--columnGap: .75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-frappe .columns.is-variable.is-3-tablet-only{--columnGap: .75rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .columns.is-variable.is-3-touch{--columnGap: .75rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .columns.is-variable.is-3-desktop{--columnGap: .75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-frappe .columns.is-variable.is-3-desktop-only{--columnGap: .75rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-frappe .columns.is-variable.is-3-widescreen{--columnGap: .75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-frappe .columns.is-variable.is-3-widescreen-only{--columnGap: .75rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-frappe .columns.is-variable.is-3-fullhd{--columnGap: .75rem}}html.theme--catppuccin-frappe .columns.is-variable.is-4{--columnGap: 1rem}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .columns.is-variable.is-4-mobile{--columnGap: 1rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .columns.is-variable.is-4-tablet{--columnGap: 1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-frappe .columns.is-variable.is-4-tablet-only{--columnGap: 1rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .columns.is-variable.is-4-touch{--columnGap: 1rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .columns.is-variable.is-4-desktop{--columnGap: 1rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-frappe .columns.is-variable.is-4-desktop-only{--columnGap: 1rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-frappe .columns.is-variable.is-4-widescreen{--columnGap: 1rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-frappe .columns.is-variable.is-4-widescreen-only{--columnGap: 1rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-frappe .columns.is-variable.is-4-fullhd{--columnGap: 1rem}}html.theme--catppuccin-frappe .columns.is-variable.is-5{--columnGap: 1.25rem}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .columns.is-variable.is-5-mobile{--columnGap: 1.25rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .columns.is-variable.is-5-tablet{--columnGap: 1.25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-frappe .columns.is-variable.is-5-tablet-only{--columnGap: 1.25rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .columns.is-variable.is-5-touch{--columnGap: 1.25rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .columns.is-variable.is-5-desktop{--columnGap: 1.25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-frappe .columns.is-variable.is-5-desktop-only{--columnGap: 1.25rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-frappe .columns.is-variable.is-5-widescreen{--columnGap: 1.25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-frappe .columns.is-variable.is-5-widescreen-only{--columnGap: 1.25rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-frappe .columns.is-variable.is-5-fullhd{--columnGap: 1.25rem}}html.theme--catppuccin-frappe .columns.is-variable.is-6{--columnGap: 1.5rem}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .columns.is-variable.is-6-mobile{--columnGap: 1.5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .columns.is-variable.is-6-tablet{--columnGap: 1.5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-frappe .columns.is-variable.is-6-tablet-only{--columnGap: 1.5rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .columns.is-variable.is-6-touch{--columnGap: 1.5rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .columns.is-variable.is-6-desktop{--columnGap: 1.5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-frappe .columns.is-variable.is-6-desktop-only{--columnGap: 1.5rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-frappe .columns.is-variable.is-6-widescreen{--columnGap: 1.5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-frappe .columns.is-variable.is-6-widescreen-only{--columnGap: 1.5rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-frappe .columns.is-variable.is-6-fullhd{--columnGap: 1.5rem}}html.theme--catppuccin-frappe .columns.is-variable.is-7{--columnGap: 1.75rem}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .columns.is-variable.is-7-mobile{--columnGap: 1.75rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .columns.is-variable.is-7-tablet{--columnGap: 1.75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-frappe .columns.is-variable.is-7-tablet-only{--columnGap: 1.75rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .columns.is-variable.is-7-touch{--columnGap: 1.75rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .columns.is-variable.is-7-desktop{--columnGap: 1.75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-frappe .columns.is-variable.is-7-desktop-only{--columnGap: 1.75rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-frappe .columns.is-variable.is-7-widescreen{--columnGap: 1.75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-frappe .columns.is-variable.is-7-widescreen-only{--columnGap: 1.75rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-frappe .columns.is-variable.is-7-fullhd{--columnGap: 1.75rem}}html.theme--catppuccin-frappe .columns.is-variable.is-8{--columnGap: 2rem}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .columns.is-variable.is-8-mobile{--columnGap: 2rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .columns.is-variable.is-8-tablet{--columnGap: 2rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-frappe .columns.is-variable.is-8-tablet-only{--columnGap: 2rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .columns.is-variable.is-8-touch{--columnGap: 2rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .columns.is-variable.is-8-desktop{--columnGap: 2rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-frappe .columns.is-variable.is-8-desktop-only{--columnGap: 2rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-frappe .columns.is-variable.is-8-widescreen{--columnGap: 2rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-frappe .columns.is-variable.is-8-widescreen-only{--columnGap: 2rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-frappe .columns.is-variable.is-8-fullhd{--columnGap: 2rem}}html.theme--catppuccin-frappe .tile{align-items:stretch;display:block;flex-basis:0;flex-grow:1;flex-shrink:1;min-height:min-content}html.theme--catppuccin-frappe .tile.is-ancestor{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--catppuccin-frappe .tile.is-ancestor:last-child{margin-bottom:-.75rem}html.theme--catppuccin-frappe .tile.is-ancestor:not(:last-child){margin-bottom:.75rem}html.theme--catppuccin-frappe .tile.is-child{margin:0 !important}html.theme--catppuccin-frappe .tile.is-parent{padding:.75rem}html.theme--catppuccin-frappe .tile.is-vertical{flex-direction:column}html.theme--catppuccin-frappe .tile.is-vertical>.tile.is-child:not(:last-child){margin-bottom:1.5rem !important}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .tile:not(.is-child){display:flex}html.theme--catppuccin-frappe .tile.is-1{flex:none;width:8.33333337%}html.theme--catppuccin-frappe .tile.is-2{flex:none;width:16.66666674%}html.theme--catppuccin-frappe .tile.is-3{flex:none;width:25%}html.theme--catppuccin-frappe .tile.is-4{flex:none;width:33.33333337%}html.theme--catppuccin-frappe .tile.is-5{flex:none;width:41.66666674%}html.theme--catppuccin-frappe .tile.is-6{flex:none;width:50%}html.theme--catppuccin-frappe .tile.is-7{flex:none;width:58.33333337%}html.theme--catppuccin-frappe .tile.is-8{flex:none;width:66.66666674%}html.theme--catppuccin-frappe .tile.is-9{flex:none;width:75%}html.theme--catppuccin-frappe .tile.is-10{flex:none;width:83.33333337%}html.theme--catppuccin-frappe .tile.is-11{flex:none;width:91.66666674%}html.theme--catppuccin-frappe .tile.is-12{flex:none;width:100%}}html.theme--catppuccin-frappe .hero{align-items:stretch;display:flex;flex-direction:column;justify-content:space-between}html.theme--catppuccin-frappe .hero .navbar{background:none}html.theme--catppuccin-frappe .hero .tabs ul{border-bottom:none}html.theme--catppuccin-frappe .hero.is-white{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-frappe .hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-frappe .hero.is-white strong{color:inherit}html.theme--catppuccin-frappe .hero.is-white .title{color:#0a0a0a}html.theme--catppuccin-frappe .hero.is-white .subtitle{color:rgba(10,10,10,0.9)}html.theme--catppuccin-frappe .hero.is-white .subtitle a:not(.button),html.theme--catppuccin-frappe .hero.is-white .subtitle strong{color:#0a0a0a}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .hero.is-white .navbar-menu{background-color:#fff}}html.theme--catppuccin-frappe .hero.is-white .navbar-item,html.theme--catppuccin-frappe .hero.is-white .navbar-link{color:rgba(10,10,10,0.7)}html.theme--catppuccin-frappe .hero.is-white a.navbar-item:hover,html.theme--catppuccin-frappe .hero.is-white a.navbar-item.is-active,html.theme--catppuccin-frappe .hero.is-white .navbar-link:hover,html.theme--catppuccin-frappe .hero.is-white .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--catppuccin-frappe .hero.is-white .tabs a{color:#0a0a0a;opacity:0.9}html.theme--catppuccin-frappe .hero.is-white .tabs a:hover{opacity:1}html.theme--catppuccin-frappe .hero.is-white .tabs li.is-active a{color:#fff !important;opacity:1}html.theme--catppuccin-frappe .hero.is-white .tabs.is-boxed a,html.theme--catppuccin-frappe .hero.is-white .tabs.is-toggle a{color:#0a0a0a}html.theme--catppuccin-frappe .hero.is-white .tabs.is-boxed a:hover,html.theme--catppuccin-frappe .hero.is-white .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-frappe .hero.is-white .tabs.is-boxed li.is-active a,html.theme--catppuccin-frappe .hero.is-white .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-frappe .hero.is-white .tabs.is-toggle li.is-active a,html.theme--catppuccin-frappe .hero.is-white .tabs.is-toggle li.is-active a:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--catppuccin-frappe .hero.is-white.is-bold{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .hero.is-white.is-bold .navbar-menu{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}}html.theme--catppuccin-frappe .hero.is-black{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-frappe .hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-frappe .hero.is-black strong{color:inherit}html.theme--catppuccin-frappe .hero.is-black .title{color:#fff}html.theme--catppuccin-frappe .hero.is-black .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-frappe .hero.is-black .subtitle a:not(.button),html.theme--catppuccin-frappe .hero.is-black .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .hero.is-black .navbar-menu{background-color:#0a0a0a}}html.theme--catppuccin-frappe .hero.is-black .navbar-item,html.theme--catppuccin-frappe .hero.is-black .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-frappe .hero.is-black a.navbar-item:hover,html.theme--catppuccin-frappe .hero.is-black a.navbar-item.is-active,html.theme--catppuccin-frappe .hero.is-black .navbar-link:hover,html.theme--catppuccin-frappe .hero.is-black .navbar-link.is-active{background-color:#000;color:#fff}html.theme--catppuccin-frappe .hero.is-black .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-frappe .hero.is-black .tabs a:hover{opacity:1}html.theme--catppuccin-frappe .hero.is-black .tabs li.is-active a{color:#0a0a0a !important;opacity:1}html.theme--catppuccin-frappe .hero.is-black .tabs.is-boxed a,html.theme--catppuccin-frappe .hero.is-black .tabs.is-toggle a{color:#fff}html.theme--catppuccin-frappe .hero.is-black .tabs.is-boxed a:hover,html.theme--catppuccin-frappe .hero.is-black .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-frappe .hero.is-black .tabs.is-boxed li.is-active a,html.theme--catppuccin-frappe .hero.is-black .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-frappe .hero.is-black .tabs.is-toggle li.is-active a,html.theme--catppuccin-frappe .hero.is-black .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--catppuccin-frappe .hero.is-black.is-bold{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .hero.is-black.is-bold .navbar-menu{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}}html.theme--catppuccin-frappe .hero.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-frappe .hero.is-light strong{color:inherit}html.theme--catppuccin-frappe .hero.is-light .title{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-light .subtitle{color:rgba(0,0,0,0.9)}html.theme--catppuccin-frappe .hero.is-light .subtitle a:not(.button),html.theme--catppuccin-frappe .hero.is-light .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .hero.is-light .navbar-menu{background-color:#f5f5f5}}html.theme--catppuccin-frappe .hero.is-light .navbar-item,html.theme--catppuccin-frappe .hero.is-light .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-light a.navbar-item:hover,html.theme--catppuccin-frappe .hero.is-light a.navbar-item.is-active,html.theme--catppuccin-frappe .hero.is-light .navbar-link:hover,html.theme--catppuccin-frappe .hero.is-light .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-light .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--catppuccin-frappe .hero.is-light .tabs a:hover{opacity:1}html.theme--catppuccin-frappe .hero.is-light .tabs li.is-active a{color:#f5f5f5 !important;opacity:1}html.theme--catppuccin-frappe .hero.is-light .tabs.is-boxed a,html.theme--catppuccin-frappe .hero.is-light .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-light .tabs.is-boxed a:hover,html.theme--catppuccin-frappe .hero.is-light .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-frappe .hero.is-light .tabs.is-boxed li.is-active a,html.theme--catppuccin-frappe .hero.is-light .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-frappe .hero.is-light .tabs.is-toggle li.is-active a,html.theme--catppuccin-frappe .hero.is-light .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#f5f5f5}html.theme--catppuccin-frappe .hero.is-light.is-bold{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .hero.is-light.is-bold .navbar-menu{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}}html.theme--catppuccin-frappe .hero.is-dark,html.theme--catppuccin-frappe .content kbd.hero{background-color:#414559;color:#fff}html.theme--catppuccin-frappe .hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-frappe .content kbd.hero a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-frappe .hero.is-dark strong,html.theme--catppuccin-frappe .content kbd.hero strong{color:inherit}html.theme--catppuccin-frappe .hero.is-dark .title,html.theme--catppuccin-frappe .content kbd.hero .title{color:#fff}html.theme--catppuccin-frappe .hero.is-dark .subtitle,html.theme--catppuccin-frappe .content kbd.hero .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-frappe .hero.is-dark .subtitle a:not(.button),html.theme--catppuccin-frappe .content kbd.hero .subtitle a:not(.button),html.theme--catppuccin-frappe .hero.is-dark .subtitle strong,html.theme--catppuccin-frappe .content kbd.hero .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .hero.is-dark .navbar-menu,html.theme--catppuccin-frappe .content kbd.hero .navbar-menu{background-color:#414559}}html.theme--catppuccin-frappe .hero.is-dark .navbar-item,html.theme--catppuccin-frappe .content kbd.hero .navbar-item,html.theme--catppuccin-frappe .hero.is-dark .navbar-link,html.theme--catppuccin-frappe .content kbd.hero .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-frappe .hero.is-dark a.navbar-item:hover,html.theme--catppuccin-frappe .content kbd.hero a.navbar-item:hover,html.theme--catppuccin-frappe .hero.is-dark a.navbar-item.is-active,html.theme--catppuccin-frappe .content kbd.hero a.navbar-item.is-active,html.theme--catppuccin-frappe .hero.is-dark .navbar-link:hover,html.theme--catppuccin-frappe .content kbd.hero .navbar-link:hover,html.theme--catppuccin-frappe .hero.is-dark .navbar-link.is-active,html.theme--catppuccin-frappe .content kbd.hero .navbar-link.is-active{background-color:#363a4a;color:#fff}html.theme--catppuccin-frappe .hero.is-dark .tabs a,html.theme--catppuccin-frappe .content kbd.hero .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-frappe .hero.is-dark .tabs a:hover,html.theme--catppuccin-frappe .content kbd.hero .tabs a:hover{opacity:1}html.theme--catppuccin-frappe .hero.is-dark .tabs li.is-active a,html.theme--catppuccin-frappe .content kbd.hero .tabs li.is-active a{color:#414559 !important;opacity:1}html.theme--catppuccin-frappe .hero.is-dark .tabs.is-boxed a,html.theme--catppuccin-frappe .content kbd.hero .tabs.is-boxed a,html.theme--catppuccin-frappe .hero.is-dark .tabs.is-toggle a,html.theme--catppuccin-frappe .content kbd.hero .tabs.is-toggle a{color:#fff}html.theme--catppuccin-frappe .hero.is-dark .tabs.is-boxed a:hover,html.theme--catppuccin-frappe .content kbd.hero .tabs.is-boxed a:hover,html.theme--catppuccin-frappe .hero.is-dark .tabs.is-toggle a:hover,html.theme--catppuccin-frappe .content kbd.hero .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-frappe .hero.is-dark .tabs.is-boxed li.is-active a,html.theme--catppuccin-frappe .content kbd.hero .tabs.is-boxed li.is-active a,html.theme--catppuccin-frappe .hero.is-dark .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-frappe .hero.is-dark .tabs.is-toggle li.is-active a,html.theme--catppuccin-frappe .content kbd.hero .tabs.is-toggle li.is-active a,html.theme--catppuccin-frappe .hero.is-dark .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#414559}html.theme--catppuccin-frappe .hero.is-dark.is-bold,html.theme--catppuccin-frappe .content kbd.hero.is-bold{background-image:linear-gradient(141deg, #262f41 0%, #414559 71%, #47476c 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .hero.is-dark.is-bold .navbar-menu,html.theme--catppuccin-frappe .content kbd.hero.is-bold .navbar-menu{background-image:linear-gradient(141deg, #262f41 0%, #414559 71%, #47476c 100%)}}html.theme--catppuccin-frappe .hero.is-primary,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink{background-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-frappe .hero.is-primary strong,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink strong{color:inherit}html.theme--catppuccin-frappe .hero.is-primary .title,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink .title{color:#fff}html.theme--catppuccin-frappe .hero.is-primary .subtitle,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-frappe .hero.is-primary .subtitle a:not(.button),html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink .subtitle a:not(.button),html.theme--catppuccin-frappe .hero.is-primary .subtitle strong,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .hero.is-primary .navbar-menu,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink .navbar-menu{background-color:#8caaee}}html.theme--catppuccin-frappe .hero.is-primary .navbar-item,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink .navbar-item,html.theme--catppuccin-frappe .hero.is-primary .navbar-link,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-frappe .hero.is-primary a.navbar-item:hover,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink a.navbar-item:hover,html.theme--catppuccin-frappe .hero.is-primary a.navbar-item.is-active,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink a.navbar-item.is-active,html.theme--catppuccin-frappe .hero.is-primary .navbar-link:hover,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink .navbar-link:hover,html.theme--catppuccin-frappe .hero.is-primary .navbar-link.is-active,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink .navbar-link.is-active{background-color:#769aeb;color:#fff}html.theme--catppuccin-frappe .hero.is-primary .tabs a,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-frappe .hero.is-primary .tabs a:hover,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink .tabs a:hover{opacity:1}html.theme--catppuccin-frappe .hero.is-primary .tabs li.is-active a,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink .tabs li.is-active a{color:#8caaee !important;opacity:1}html.theme--catppuccin-frappe .hero.is-primary .tabs.is-boxed a,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a,html.theme--catppuccin-frappe .hero.is-primary .tabs.is-toggle a,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a{color:#fff}html.theme--catppuccin-frappe .hero.is-primary .tabs.is-boxed a:hover,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a:hover,html.theme--catppuccin-frappe .hero.is-primary .tabs.is-toggle a:hover,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-frappe .hero.is-primary .tabs.is-boxed li.is-active a,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed li.is-active a,html.theme--catppuccin-frappe .hero.is-primary .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-frappe .hero.is-primary .tabs.is-toggle li.is-active a,html.theme--catppuccin-frappe .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle li.is-active a,html.theme--catppuccin-frappe .hero.is-primary .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#8caaee}html.theme--catppuccin-frappe .hero.is-primary.is-bold,html.theme--catppuccin-frappe .docstring>section>a.hero.is-bold.docs-sourcelink{background-image:linear-gradient(141deg, #569ff1 0%, #8caaee 71%, #a0abf4 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .hero.is-primary.is-bold .navbar-menu,html.theme--catppuccin-frappe .docstring>section>a.hero.is-bold.docs-sourcelink .navbar-menu{background-image:linear-gradient(141deg, #569ff1 0%, #8caaee 71%, #a0abf4 100%)}}html.theme--catppuccin-frappe .hero.is-link{background-color:#8caaee;color:#fff}html.theme--catppuccin-frappe .hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-frappe .hero.is-link strong{color:inherit}html.theme--catppuccin-frappe .hero.is-link .title{color:#fff}html.theme--catppuccin-frappe .hero.is-link .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-frappe .hero.is-link .subtitle a:not(.button),html.theme--catppuccin-frappe .hero.is-link .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .hero.is-link .navbar-menu{background-color:#8caaee}}html.theme--catppuccin-frappe .hero.is-link .navbar-item,html.theme--catppuccin-frappe .hero.is-link .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-frappe .hero.is-link a.navbar-item:hover,html.theme--catppuccin-frappe .hero.is-link a.navbar-item.is-active,html.theme--catppuccin-frappe .hero.is-link .navbar-link:hover,html.theme--catppuccin-frappe .hero.is-link .navbar-link.is-active{background-color:#769aeb;color:#fff}html.theme--catppuccin-frappe .hero.is-link .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-frappe .hero.is-link .tabs a:hover{opacity:1}html.theme--catppuccin-frappe .hero.is-link .tabs li.is-active a{color:#8caaee !important;opacity:1}html.theme--catppuccin-frappe .hero.is-link .tabs.is-boxed a,html.theme--catppuccin-frappe .hero.is-link .tabs.is-toggle a{color:#fff}html.theme--catppuccin-frappe .hero.is-link .tabs.is-boxed a:hover,html.theme--catppuccin-frappe .hero.is-link .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-frappe .hero.is-link .tabs.is-boxed li.is-active a,html.theme--catppuccin-frappe .hero.is-link .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-frappe .hero.is-link .tabs.is-toggle li.is-active a,html.theme--catppuccin-frappe .hero.is-link .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#8caaee}html.theme--catppuccin-frappe .hero.is-link.is-bold{background-image:linear-gradient(141deg, #569ff1 0%, #8caaee 71%, #a0abf4 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .hero.is-link.is-bold .navbar-menu{background-image:linear-gradient(141deg, #569ff1 0%, #8caaee 71%, #a0abf4 100%)}}html.theme--catppuccin-frappe .hero.is-info{background-color:#81c8be;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-frappe .hero.is-info strong{color:inherit}html.theme--catppuccin-frappe .hero.is-info .title{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-info .subtitle{color:rgba(0,0,0,0.9)}html.theme--catppuccin-frappe .hero.is-info .subtitle a:not(.button),html.theme--catppuccin-frappe .hero.is-info .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .hero.is-info .navbar-menu{background-color:#81c8be}}html.theme--catppuccin-frappe .hero.is-info .navbar-item,html.theme--catppuccin-frappe .hero.is-info .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-info a.navbar-item:hover,html.theme--catppuccin-frappe .hero.is-info a.navbar-item.is-active,html.theme--catppuccin-frappe .hero.is-info .navbar-link:hover,html.theme--catppuccin-frappe .hero.is-info .navbar-link.is-active{background-color:#6fc0b5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-info .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--catppuccin-frappe .hero.is-info .tabs a:hover{opacity:1}html.theme--catppuccin-frappe .hero.is-info .tabs li.is-active a{color:#81c8be !important;opacity:1}html.theme--catppuccin-frappe .hero.is-info .tabs.is-boxed a,html.theme--catppuccin-frappe .hero.is-info .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-info .tabs.is-boxed a:hover,html.theme--catppuccin-frappe .hero.is-info .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-frappe .hero.is-info .tabs.is-boxed li.is-active a,html.theme--catppuccin-frappe .hero.is-info .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-frappe .hero.is-info .tabs.is-toggle li.is-active a,html.theme--catppuccin-frappe .hero.is-info .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#81c8be}html.theme--catppuccin-frappe .hero.is-info.is-bold{background-image:linear-gradient(141deg, #52c4a1 0%, #81c8be 71%, #8fd2d4 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .hero.is-info.is-bold .navbar-menu{background-image:linear-gradient(141deg, #52c4a1 0%, #81c8be 71%, #8fd2d4 100%)}}html.theme--catppuccin-frappe .hero.is-success{background-color:#a6d189;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-frappe .hero.is-success strong{color:inherit}html.theme--catppuccin-frappe .hero.is-success .title{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-success .subtitle{color:rgba(0,0,0,0.9)}html.theme--catppuccin-frappe .hero.is-success .subtitle a:not(.button),html.theme--catppuccin-frappe .hero.is-success .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .hero.is-success .navbar-menu{background-color:#a6d189}}html.theme--catppuccin-frappe .hero.is-success .navbar-item,html.theme--catppuccin-frappe .hero.is-success .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-success a.navbar-item:hover,html.theme--catppuccin-frappe .hero.is-success a.navbar-item.is-active,html.theme--catppuccin-frappe .hero.is-success .navbar-link:hover,html.theme--catppuccin-frappe .hero.is-success .navbar-link.is-active{background-color:#98ca77;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-success .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--catppuccin-frappe .hero.is-success .tabs a:hover{opacity:1}html.theme--catppuccin-frappe .hero.is-success .tabs li.is-active a{color:#a6d189 !important;opacity:1}html.theme--catppuccin-frappe .hero.is-success .tabs.is-boxed a,html.theme--catppuccin-frappe .hero.is-success .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-success .tabs.is-boxed a:hover,html.theme--catppuccin-frappe .hero.is-success .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-frappe .hero.is-success .tabs.is-boxed li.is-active a,html.theme--catppuccin-frappe .hero.is-success .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-frappe .hero.is-success .tabs.is-toggle li.is-active a,html.theme--catppuccin-frappe .hero.is-success .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#a6d189}html.theme--catppuccin-frappe .hero.is-success.is-bold{background-image:linear-gradient(141deg, #9ccd5a 0%, #a6d189 71%, #a8dc98 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .hero.is-success.is-bold .navbar-menu{background-image:linear-gradient(141deg, #9ccd5a 0%, #a6d189 71%, #a8dc98 100%)}}html.theme--catppuccin-frappe .hero.is-warning{background-color:#e5c890;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-frappe .hero.is-warning strong{color:inherit}html.theme--catppuccin-frappe .hero.is-warning .title{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-warning .subtitle{color:rgba(0,0,0,0.9)}html.theme--catppuccin-frappe .hero.is-warning .subtitle a:not(.button),html.theme--catppuccin-frappe .hero.is-warning .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .hero.is-warning .navbar-menu{background-color:#e5c890}}html.theme--catppuccin-frappe .hero.is-warning .navbar-item,html.theme--catppuccin-frappe .hero.is-warning .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-warning a.navbar-item:hover,html.theme--catppuccin-frappe .hero.is-warning a.navbar-item.is-active,html.theme--catppuccin-frappe .hero.is-warning .navbar-link:hover,html.theme--catppuccin-frappe .hero.is-warning .navbar-link.is-active{background-color:#e0be7b;color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-warning .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--catppuccin-frappe .hero.is-warning .tabs a:hover{opacity:1}html.theme--catppuccin-frappe .hero.is-warning .tabs li.is-active a{color:#e5c890 !important;opacity:1}html.theme--catppuccin-frappe .hero.is-warning .tabs.is-boxed a,html.theme--catppuccin-frappe .hero.is-warning .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--catppuccin-frappe .hero.is-warning .tabs.is-boxed a:hover,html.theme--catppuccin-frappe .hero.is-warning .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-frappe .hero.is-warning .tabs.is-boxed li.is-active a,html.theme--catppuccin-frappe .hero.is-warning .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-frappe .hero.is-warning .tabs.is-toggle li.is-active a,html.theme--catppuccin-frappe .hero.is-warning .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#e5c890}html.theme--catppuccin-frappe .hero.is-warning.is-bold{background-image:linear-gradient(141deg, #e5a05d 0%, #e5c890 71%, #ede0a2 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .hero.is-warning.is-bold .navbar-menu{background-image:linear-gradient(141deg, #e5a05d 0%, #e5c890 71%, #ede0a2 100%)}}html.theme--catppuccin-frappe .hero.is-danger{background-color:#e78284;color:#fff}html.theme--catppuccin-frappe .hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-frappe .hero.is-danger strong{color:inherit}html.theme--catppuccin-frappe .hero.is-danger .title{color:#fff}html.theme--catppuccin-frappe .hero.is-danger .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-frappe .hero.is-danger .subtitle a:not(.button),html.theme--catppuccin-frappe .hero.is-danger .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .hero.is-danger .navbar-menu{background-color:#e78284}}html.theme--catppuccin-frappe .hero.is-danger .navbar-item,html.theme--catppuccin-frappe .hero.is-danger .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-frappe .hero.is-danger a.navbar-item:hover,html.theme--catppuccin-frappe .hero.is-danger a.navbar-item.is-active,html.theme--catppuccin-frappe .hero.is-danger .navbar-link:hover,html.theme--catppuccin-frappe .hero.is-danger .navbar-link.is-active{background-color:#e36d6f;color:#fff}html.theme--catppuccin-frappe .hero.is-danger .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-frappe .hero.is-danger .tabs a:hover{opacity:1}html.theme--catppuccin-frappe .hero.is-danger .tabs li.is-active a{color:#e78284 !important;opacity:1}html.theme--catppuccin-frappe .hero.is-danger .tabs.is-boxed a,html.theme--catppuccin-frappe .hero.is-danger .tabs.is-toggle a{color:#fff}html.theme--catppuccin-frappe .hero.is-danger .tabs.is-boxed a:hover,html.theme--catppuccin-frappe .hero.is-danger .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-frappe .hero.is-danger .tabs.is-boxed li.is-active a,html.theme--catppuccin-frappe .hero.is-danger .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-frappe .hero.is-danger .tabs.is-toggle li.is-active a,html.theme--catppuccin-frappe .hero.is-danger .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#e78284}html.theme--catppuccin-frappe .hero.is-danger.is-bold{background-image:linear-gradient(141deg, #e94d6a 0%, #e78284 71%, #eea294 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .hero.is-danger.is-bold .navbar-menu{background-image:linear-gradient(141deg, #e94d6a 0%, #e78284 71%, #eea294 100%)}}html.theme--catppuccin-frappe .hero.is-small .hero-body,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.hero .hero-body{padding:1.5rem}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .hero.is-medium .hero-body{padding:9rem 4.5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .hero.is-large .hero-body{padding:18rem 6rem}}html.theme--catppuccin-frappe .hero.is-halfheight .hero-body,html.theme--catppuccin-frappe .hero.is-fullheight .hero-body,html.theme--catppuccin-frappe .hero.is-fullheight-with-navbar .hero-body{align-items:center;display:flex}html.theme--catppuccin-frappe .hero.is-halfheight .hero-body>.container,html.theme--catppuccin-frappe .hero.is-fullheight .hero-body>.container,html.theme--catppuccin-frappe .hero.is-fullheight-with-navbar .hero-body>.container{flex-grow:1;flex-shrink:1}html.theme--catppuccin-frappe .hero.is-halfheight{min-height:50vh}html.theme--catppuccin-frappe .hero.is-fullheight{min-height:100vh}html.theme--catppuccin-frappe .hero-video{overflow:hidden}html.theme--catppuccin-frappe .hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;transform:translate3d(-50%, -50%, 0)}html.theme--catppuccin-frappe .hero-video.is-transparent{opacity:0.3}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .hero-video{display:none}}html.theme--catppuccin-frappe .hero-buttons{margin-top:1.5rem}@media screen and (max-width: 768px){html.theme--catppuccin-frappe .hero-buttons .button{display:flex}html.theme--catppuccin-frappe .hero-buttons .button:not(:last-child){margin-bottom:0.75rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .hero-buttons{display:flex;justify-content:center}html.theme--catppuccin-frappe .hero-buttons .button:not(:last-child){margin-right:1.5rem}}html.theme--catppuccin-frappe .hero-head,html.theme--catppuccin-frappe .hero-foot{flex-grow:0;flex-shrink:0}html.theme--catppuccin-frappe .hero-body{flex-grow:1;flex-shrink:0;padding:3rem 1.5rem}@media screen and (min-width: 769px),print{html.theme--catppuccin-frappe .hero-body{padding:3rem 3rem}}html.theme--catppuccin-frappe .section{padding:3rem 1.5rem}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe .section{padding:3rem 3rem}html.theme--catppuccin-frappe .section.is-medium{padding:9rem 4.5rem}html.theme--catppuccin-frappe .section.is-large{padding:18rem 6rem}}html.theme--catppuccin-frappe .footer{background-color:#292c3c;padding:3rem 1.5rem 6rem}html.theme--catppuccin-frappe h1 .docs-heading-anchor,html.theme--catppuccin-frappe h1 .docs-heading-anchor:hover,html.theme--catppuccin-frappe h1 .docs-heading-anchor:visited,html.theme--catppuccin-frappe h2 .docs-heading-anchor,html.theme--catppuccin-frappe h2 .docs-heading-anchor:hover,html.theme--catppuccin-frappe h2 .docs-heading-anchor:visited,html.theme--catppuccin-frappe h3 .docs-heading-anchor,html.theme--catppuccin-frappe h3 .docs-heading-anchor:hover,html.theme--catppuccin-frappe h3 .docs-heading-anchor:visited,html.theme--catppuccin-frappe h4 .docs-heading-anchor,html.theme--catppuccin-frappe h4 .docs-heading-anchor:hover,html.theme--catppuccin-frappe h4 .docs-heading-anchor:visited,html.theme--catppuccin-frappe h5 .docs-heading-anchor,html.theme--catppuccin-frappe h5 .docs-heading-anchor:hover,html.theme--catppuccin-frappe h5 .docs-heading-anchor:visited,html.theme--catppuccin-frappe h6 .docs-heading-anchor,html.theme--catppuccin-frappe h6 .docs-heading-anchor:hover,html.theme--catppuccin-frappe h6 .docs-heading-anchor:visited{color:#c6d0f5}html.theme--catppuccin-frappe h1 .docs-heading-anchor-permalink,html.theme--catppuccin-frappe h2 .docs-heading-anchor-permalink,html.theme--catppuccin-frappe h3 .docs-heading-anchor-permalink,html.theme--catppuccin-frappe h4 .docs-heading-anchor-permalink,html.theme--catppuccin-frappe h5 .docs-heading-anchor-permalink,html.theme--catppuccin-frappe h6 .docs-heading-anchor-permalink{visibility:hidden;vertical-align:middle;margin-left:0.5em;font-size:0.7rem}html.theme--catppuccin-frappe h1 .docs-heading-anchor-permalink::before,html.theme--catppuccin-frappe h2 .docs-heading-anchor-permalink::before,html.theme--catppuccin-frappe h3 .docs-heading-anchor-permalink::before,html.theme--catppuccin-frappe h4 .docs-heading-anchor-permalink::before,html.theme--catppuccin-frappe h5 .docs-heading-anchor-permalink::before,html.theme--catppuccin-frappe h6 .docs-heading-anchor-permalink::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f0c1"}html.theme--catppuccin-frappe h1:hover .docs-heading-anchor-permalink,html.theme--catppuccin-frappe h2:hover .docs-heading-anchor-permalink,html.theme--catppuccin-frappe h3:hover .docs-heading-anchor-permalink,html.theme--catppuccin-frappe h4:hover .docs-heading-anchor-permalink,html.theme--catppuccin-frappe h5:hover .docs-heading-anchor-permalink,html.theme--catppuccin-frappe h6:hover .docs-heading-anchor-permalink{visibility:visible}html.theme--catppuccin-frappe .docs-light-only{display:none !important}html.theme--catppuccin-frappe pre{position:relative;overflow:hidden}html.theme--catppuccin-frappe pre code,html.theme--catppuccin-frappe pre code.hljs{padding:0 .75rem !important;overflow:auto;display:block}html.theme--catppuccin-frappe pre code:first-of-type,html.theme--catppuccin-frappe pre code.hljs:first-of-type{padding-top:0.5rem !important}html.theme--catppuccin-frappe pre code:last-of-type,html.theme--catppuccin-frappe pre code.hljs:last-of-type{padding-bottom:0.5rem !important}html.theme--catppuccin-frappe pre .copy-button{opacity:0.2;transition:opacity 0.2s;position:absolute;right:0em;top:0em;padding:0.5em;width:2.5em;height:2.5em;background:transparent;border:none;font-family:"Font Awesome 6 Free";color:#c6d0f5;cursor:pointer;text-align:center}html.theme--catppuccin-frappe pre .copy-button:focus,html.theme--catppuccin-frappe pre .copy-button:hover{opacity:1;background:rgba(198,208,245,0.1);color:#8caaee}html.theme--catppuccin-frappe pre .copy-button.success{color:#a6d189;opacity:1}html.theme--catppuccin-frappe pre .copy-button.error{color:#e78284;opacity:1}html.theme--catppuccin-frappe pre:hover .copy-button{opacity:1}html.theme--catppuccin-frappe .admonition{background-color:#292c3c;border-style:solid;border-width:2px;border-color:#b5bfe2;border-radius:4px;font-size:1rem}html.theme--catppuccin-frappe .admonition strong{color:currentColor}html.theme--catppuccin-frappe .admonition.is-small,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input.admonition{font-size:.75rem}html.theme--catppuccin-frappe .admonition.is-medium{font-size:1.25rem}html.theme--catppuccin-frappe .admonition.is-large{font-size:1.5rem}html.theme--catppuccin-frappe .admonition.is-default{background-color:#292c3c;border-color:#b5bfe2}html.theme--catppuccin-frappe .admonition.is-default>.admonition-header{background-color:rgba(0,0,0,0);color:#b5bfe2}html.theme--catppuccin-frappe .admonition.is-default>.admonition-body{color:#c6d0f5}html.theme--catppuccin-frappe .admonition.is-info{background-color:#292c3c;border-color:#81c8be}html.theme--catppuccin-frappe .admonition.is-info>.admonition-header{background-color:rgba(0,0,0,0);color:#81c8be}html.theme--catppuccin-frappe .admonition.is-info>.admonition-body{color:#c6d0f5}html.theme--catppuccin-frappe .admonition.is-success{background-color:#292c3c;border-color:#a6d189}html.theme--catppuccin-frappe .admonition.is-success>.admonition-header{background-color:rgba(0,0,0,0);color:#a6d189}html.theme--catppuccin-frappe .admonition.is-success>.admonition-body{color:#c6d0f5}html.theme--catppuccin-frappe .admonition.is-warning{background-color:#292c3c;border-color:#e5c890}html.theme--catppuccin-frappe .admonition.is-warning>.admonition-header{background-color:rgba(0,0,0,0);color:#e5c890}html.theme--catppuccin-frappe .admonition.is-warning>.admonition-body{color:#c6d0f5}html.theme--catppuccin-frappe .admonition.is-danger{background-color:#292c3c;border-color:#e78284}html.theme--catppuccin-frappe .admonition.is-danger>.admonition-header{background-color:rgba(0,0,0,0);color:#e78284}html.theme--catppuccin-frappe .admonition.is-danger>.admonition-body{color:#c6d0f5}html.theme--catppuccin-frappe .admonition.is-compat{background-color:#292c3c;border-color:#99d1db}html.theme--catppuccin-frappe .admonition.is-compat>.admonition-header{background-color:rgba(0,0,0,0);color:#99d1db}html.theme--catppuccin-frappe .admonition.is-compat>.admonition-body{color:#c6d0f5}html.theme--catppuccin-frappe .admonition.is-todo{background-color:#292c3c;border-color:#ca9ee6}html.theme--catppuccin-frappe .admonition.is-todo>.admonition-header{background-color:rgba(0,0,0,0);color:#ca9ee6}html.theme--catppuccin-frappe .admonition.is-todo>.admonition-body{color:#c6d0f5}html.theme--catppuccin-frappe .admonition-header{color:#b5bfe2;background-color:rgba(0,0,0,0);align-items:center;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.5rem .75rem;position:relative}html.theme--catppuccin-frappe .admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;margin-right:.75rem;content:"\f06a"}html.theme--catppuccin-frappe details.admonition.is-details>.admonition-header{list-style:none}html.theme--catppuccin-frappe details.admonition.is-details>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f055"}html.theme--catppuccin-frappe details.admonition.is-details[open]>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f056"}html.theme--catppuccin-frappe .admonition-body{color:#c6d0f5;padding:0.5rem .75rem}html.theme--catppuccin-frappe .admonition-body pre{background-color:#292c3c}html.theme--catppuccin-frappe .admonition-body code{background-color:#292c3c}html.theme--catppuccin-frappe .docstring{margin-bottom:1em;background-color:rgba(0,0,0,0);border:2px solid #626880;border-radius:4px;box-shadow:none;max-width:100%}html.theme--catppuccin-frappe .docstring>header{cursor:pointer;display:flex;flex-grow:1;align-items:stretch;padding:0.5rem .75rem;background-color:#292c3c;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);box-shadow:none;border-bottom:1px solid #626880;overflow:auto}html.theme--catppuccin-frappe .docstring>header code{background-color:transparent}html.theme--catppuccin-frappe .docstring>header .docstring-article-toggle-button{min-width:1.1rem;padding:0.2rem 0.2rem 0.2rem 0}html.theme--catppuccin-frappe .docstring>header .docstring-binding{margin-right:0.3em}html.theme--catppuccin-frappe .docstring>header .docstring-category{margin-left:0.3em}html.theme--catppuccin-frappe .docstring>section{position:relative;padding:.75rem .75rem;border-bottom:1px solid #626880}html.theme--catppuccin-frappe .docstring>section:last-child{border-bottom:none}html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink{transition:opacity 0.3s;opacity:0;position:absolute;right:.375rem;bottom:.375rem}html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink:focus{opacity:1 !important}html.theme--catppuccin-frappe .docstring:hover>section>a.docs-sourcelink{opacity:0.2}html.theme--catppuccin-frappe .docstring:focus-within>section>a.docs-sourcelink{opacity:0.2}html.theme--catppuccin-frappe .docstring>section:hover a.docs-sourcelink{opacity:1}html.theme--catppuccin-frappe .documenter-example-output{background-color:#303446}html.theme--catppuccin-frappe .outdated-warning-overlay{position:fixed;top:0;left:0;right:0;box-shadow:0 0 10px rgba(0,0,0,0.3);z-index:999;background-color:#292c3c;color:#c6d0f5;border-bottom:3px solid rgba(0,0,0,0);padding:10px 35px;text-align:center;font-size:15px}html.theme--catppuccin-frappe .outdated-warning-overlay .outdated-warning-closer{position:absolute;top:calc(50% - 10px);right:18px;cursor:pointer;width:12px}html.theme--catppuccin-frappe .outdated-warning-overlay a{color:#8caaee}html.theme--catppuccin-frappe .outdated-warning-overlay a:hover{color:#99d1db}html.theme--catppuccin-frappe .content pre{border:2px solid #626880;border-radius:4px}html.theme--catppuccin-frappe .content code{font-weight:inherit}html.theme--catppuccin-frappe .content a code{color:#8caaee}html.theme--catppuccin-frappe .content a:hover code{color:#99d1db}html.theme--catppuccin-frappe .content h1 code,html.theme--catppuccin-frappe .content h2 code,html.theme--catppuccin-frappe .content h3 code,html.theme--catppuccin-frappe .content h4 code,html.theme--catppuccin-frappe .content h5 code,html.theme--catppuccin-frappe .content h6 code{color:#c6d0f5}html.theme--catppuccin-frappe .content table{display:block;width:initial;max-width:100%;overflow-x:auto}html.theme--catppuccin-frappe .content blockquote>ul:first-child,html.theme--catppuccin-frappe .content blockquote>ol:first-child,html.theme--catppuccin-frappe .content .admonition-body>ul:first-child,html.theme--catppuccin-frappe .content .admonition-body>ol:first-child{margin-top:0}html.theme--catppuccin-frappe pre,html.theme--catppuccin-frappe code{font-variant-ligatures:no-contextual}html.theme--catppuccin-frappe .breadcrumb a.is-disabled{cursor:default;pointer-events:none}html.theme--catppuccin-frappe .breadcrumb a.is-disabled,html.theme--catppuccin-frappe .breadcrumb a.is-disabled:hover{color:#b0bef1}html.theme--catppuccin-frappe .hljs{background:initial !important}html.theme--catppuccin-frappe .katex .katex-mathml{top:0;right:0}html.theme--catppuccin-frappe .katex-display,html.theme--catppuccin-frappe mjx-container,html.theme--catppuccin-frappe .MathJax_Display{margin:0.5em 0 !important}html.theme--catppuccin-frappe html{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto}html.theme--catppuccin-frappe li.no-marker{list-style:none}html.theme--catppuccin-frappe #documenter .docs-main>article{overflow-wrap:break-word}html.theme--catppuccin-frappe #documenter .docs-main>article .math-container{overflow-x:auto;overflow-y:hidden}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe #documenter .docs-main{max-width:52rem;margin-left:20rem;padding-right:1rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe #documenter .docs-main{width:100%}html.theme--catppuccin-frappe #documenter .docs-main>article{max-width:52rem;margin-left:auto;margin-right:auto;margin-bottom:1rem;padding:0 1rem}html.theme--catppuccin-frappe #documenter .docs-main>header,html.theme--catppuccin-frappe #documenter .docs-main>nav{max-width:100%;width:100%;margin:0}}html.theme--catppuccin-frappe #documenter .docs-main header.docs-navbar{background-color:#303446;border-bottom:1px solid #626880;z-index:2;min-height:4rem;margin-bottom:1rem;display:flex}html.theme--catppuccin-frappe #documenter .docs-main header.docs-navbar .breadcrumb{flex-grow:1;overflow-x:hidden}html.theme--catppuccin-frappe #documenter .docs-main header.docs-navbar .docs-sidebar-button{display:block;font-size:1.5rem;padding-bottom:0.1rem;margin-right:1rem}html.theme--catppuccin-frappe #documenter .docs-main header.docs-navbar .docs-right{display:flex;white-space:nowrap;gap:1rem;align-items:center}html.theme--catppuccin-frappe #documenter .docs-main header.docs-navbar .docs-right .docs-icon,html.theme--catppuccin-frappe #documenter .docs-main header.docs-navbar .docs-right .docs-label{display:inline-block}html.theme--catppuccin-frappe #documenter .docs-main header.docs-navbar .docs-right .docs-label{padding:0;margin-left:0.3em}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe #documenter .docs-main header.docs-navbar .docs-right .docs-navbar-link{margin-left:0.4rem;margin-right:0.4rem}}html.theme--catppuccin-frappe #documenter .docs-main header.docs-navbar>*{margin:auto 0}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe #documenter .docs-main header.docs-navbar{position:sticky;top:0;padding:0 1rem;transition-property:top, box-shadow;-webkit-transition-property:top, box-shadow;transition-duration:0.3s;-webkit-transition-duration:0.3s}html.theme--catppuccin-frappe #documenter .docs-main header.docs-navbar.headroom--not-top{box-shadow:.2rem 0rem .4rem #171717;transition-duration:0.7s;-webkit-transition-duration:0.7s}html.theme--catppuccin-frappe #documenter .docs-main header.docs-navbar.headroom--unpinned.headroom--not-top.headroom--not-bottom{top:-4.5rem;transition-duration:0.7s;-webkit-transition-duration:0.7s}}html.theme--catppuccin-frappe #documenter .docs-main section.footnotes{border-top:1px solid #626880}html.theme--catppuccin-frappe #documenter .docs-main section.footnotes li .tag:first-child,html.theme--catppuccin-frappe #documenter .docs-main section.footnotes li .docstring>section>a.docs-sourcelink:first-child,html.theme--catppuccin-frappe #documenter .docs-main section.footnotes li .content kbd:first-child,html.theme--catppuccin-frappe .content #documenter .docs-main section.footnotes li kbd:first-child{margin-right:1em;margin-bottom:0.4em}html.theme--catppuccin-frappe #documenter .docs-main .docs-footer{display:flex;flex-wrap:wrap;margin-left:0;margin-right:0;border-top:1px solid #626880;padding-top:1rem;padding-bottom:1rem}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe #documenter .docs-main .docs-footer{padding-left:1rem;padding-right:1rem}}html.theme--catppuccin-frappe #documenter .docs-main .docs-footer .docs-footer-nextpage,html.theme--catppuccin-frappe #documenter .docs-main .docs-footer .docs-footer-prevpage{flex-grow:1}html.theme--catppuccin-frappe #documenter .docs-main .docs-footer .docs-footer-nextpage{text-align:right}html.theme--catppuccin-frappe #documenter .docs-main .docs-footer .flexbox-break{flex-basis:100%;height:0}html.theme--catppuccin-frappe #documenter .docs-main .docs-footer .footer-message{font-size:0.8em;margin:0.5em auto 0 auto;text-align:center}html.theme--catppuccin-frappe #documenter .docs-sidebar{display:flex;flex-direction:column;color:#c6d0f5;background-color:#292c3c;border-right:1px solid #626880;padding:0;flex:0 0 18rem;z-index:5;font-size:1rem;position:fixed;left:-18rem;width:18rem;height:100%;transition:left 0.3s}html.theme--catppuccin-frappe #documenter .docs-sidebar.visible{left:0;box-shadow:.4rem 0rem .8rem #171717}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe #documenter .docs-sidebar.visible{box-shadow:none}}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe #documenter .docs-sidebar{left:0;top:0}}html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo{margin-top:1rem;padding:0 1rem}html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-logo>img{max-height:6rem;margin:auto}html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-package-name{flex-shrink:0;font-size:1.5rem;font-weight:700;text-align:center;white-space:nowrap;overflow:hidden;padding:0.5rem 0}html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-package-name .docs-autofit{max-width:16.2rem}html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-package-name a,html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-package-name a:hover{color:#c6d0f5}html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-version-selector{border-top:1px solid #626880;display:none;padding:0.5rem}html.theme--catppuccin-frappe #documenter .docs-sidebar .docs-version-selector.visible{display:flex}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu{flex-grow:1;user-select:none;border-top:1px solid #626880;padding-bottom:1.5rem}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu>li>.tocitem{font-weight:bold}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu>li li{font-size:.95rem;margin-left:1em;border-left:1px solid #626880}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu input.collapse-toggle{display:none}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu ul.collapsed{display:none}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu input:checked~ul.collapsed{display:block}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu label.tocitem{display:flex}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-label{flex-grow:2}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-size:.75rem;margin-left:1rem;margin-top:auto;margin-bottom:auto}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f054"}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu input:checked~label.tocitem .docs-chevron::before{content:"\f078"}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu .tocitem{display:block;padding:0.5rem 0.5rem}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu .tocitem,html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu .tocitem:hover{color:#c6d0f5;background:#292c3c}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu a.tocitem:hover,html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu label.tocitem:hover{color:#c6d0f5;background-color:#313548}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu li.is-active{border-top:1px solid #626880;border-bottom:1px solid #626880;background-color:#232634}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem,html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem:hover{background-color:#232634;color:#c6d0f5}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu li.is-active ul.internal .tocitem:hover{background-color:#313548;color:#c6d0f5}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu>li.is-active:first-child{border-top:none}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu ul.internal{margin:0 0.5rem 0.5rem;border-top:1px solid #626880}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu ul.internal li{font-size:.85rem;border-left:none;margin-left:0;margin-top:0.5rem}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem{width:100%;padding:0}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem::before{content:"⚬";margin-right:0.4em}html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search{margin:auto;margin-top:0.5rem;margin-bottom:0.5rem}html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input{width:14.4rem}html.theme--catppuccin-frappe #documenter .docs-sidebar #documenter-search-query{color:#868c98;width:14.4rem;box-shadow:inset 0 1px 2px rgba(10,10,10,0.1)}@media screen and (min-width: 1056px){html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar{width:.3rem;background:none}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#3a3e54}html.theme--catppuccin-frappe #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb:hover{background:#4a506c}}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe #documenter .docs-sidebar{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--catppuccin-frappe #documenter .docs-sidebar::-webkit-scrollbar{width:.3rem;background:none}html.theme--catppuccin-frappe #documenter .docs-sidebar::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#3a3e54}html.theme--catppuccin-frappe #documenter .docs-sidebar::-webkit-scrollbar-thumb:hover{background:#4a506c}}html.theme--catppuccin-frappe kbd.search-modal-key-hints{border-radius:0.25rem;border:1px solid rgba(245,245,245,0.6);box-shadow:0 2px 0 1px rgba(245,245,245,0.6);cursor:default;font-size:0.9rem;line-height:1.5;min-width:0.75rem;text-align:center;padding:0.1rem 0.3rem;position:relative;top:-1px}html.theme--catppuccin-frappe .search-min-width-50{min-width:50%}html.theme--catppuccin-frappe .search-min-height-100{min-height:100%}html.theme--catppuccin-frappe .search-modal-card-body{max-height:calc(100vh - 15rem)}html.theme--catppuccin-frappe .search-result-link{border-radius:0.7em;transition:all 300ms}html.theme--catppuccin-frappe .search-result-link:hover,html.theme--catppuccin-frappe .search-result-link:focus{background-color:rgba(0,128,128,0.1)}html.theme--catppuccin-frappe .search-result-link .property-search-result-badge,html.theme--catppuccin-frappe .search-result-link .search-filter{transition:all 300ms}html.theme--catppuccin-frappe .property-search-result-badge,html.theme--catppuccin-frappe .search-filter{padding:0.15em 0.5em;font-size:0.8em;font-style:italic;text-transform:none !important;line-height:1.5;color:#f5f5f5;background-color:rgba(51,65,85,0.501961);border-radius:0.6rem}html.theme--catppuccin-frappe .search-result-link:hover .property-search-result-badge,html.theme--catppuccin-frappe .search-result-link:hover .search-filter,html.theme--catppuccin-frappe .search-result-link:focus .property-search-result-badge,html.theme--catppuccin-frappe .search-result-link:focus .search-filter{color:#333;background-color:#f1f5f9}html.theme--catppuccin-frappe .search-filter{color:#333;background-color:#f5f5f5;transition:all 300ms}html.theme--catppuccin-frappe .search-filter:hover,html.theme--catppuccin-frappe .search-filter:focus{color:#333}html.theme--catppuccin-frappe .search-filter-selected{color:#414559;background-color:#babbf1}html.theme--catppuccin-frappe .search-filter-selected:hover,html.theme--catppuccin-frappe .search-filter-selected:focus{color:#414559}html.theme--catppuccin-frappe .search-result-highlight{background-color:#ffdd57;color:black}html.theme--catppuccin-frappe .search-divider{border-bottom:1px solid #626880}html.theme--catppuccin-frappe .search-result-title{width:85%;color:#f5f5f5}html.theme--catppuccin-frappe .search-result-code-title{font-size:0.875rem;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}html.theme--catppuccin-frappe #search-modal .modal-card-body::-webkit-scrollbar,html.theme--catppuccin-frappe #search-modal .filter-tabs::-webkit-scrollbar{height:10px;width:10px;background-color:transparent}html.theme--catppuccin-frappe #search-modal .modal-card-body::-webkit-scrollbar-thumb,html.theme--catppuccin-frappe #search-modal .filter-tabs::-webkit-scrollbar-thumb{background-color:gray;border-radius:1rem}html.theme--catppuccin-frappe #search-modal .modal-card-body::-webkit-scrollbar-track,html.theme--catppuccin-frappe #search-modal .filter-tabs::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,0.6);background-color:transparent}html.theme--catppuccin-frappe .w-100{width:100%}html.theme--catppuccin-frappe .gap-2{gap:0.5rem}html.theme--catppuccin-frappe .gap-4{gap:1rem}html.theme--catppuccin-frappe .gap-8{gap:2rem}html.theme--catppuccin-frappe{background-color:#303446;font-size:16px;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--catppuccin-frappe a{transition:all 200ms ease}html.theme--catppuccin-frappe .label{color:#c6d0f5}html.theme--catppuccin-frappe .button,html.theme--catppuccin-frappe .control.has-icons-left .icon,html.theme--catppuccin-frappe .control.has-icons-right .icon,html.theme--catppuccin-frappe .input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-frappe .pagination-ellipsis,html.theme--catppuccin-frappe .pagination-link,html.theme--catppuccin-frappe .pagination-next,html.theme--catppuccin-frappe .pagination-previous,html.theme--catppuccin-frappe .select,html.theme--catppuccin-frappe .select select,html.theme--catppuccin-frappe .textarea{height:2.5em;color:#c6d0f5}html.theme--catppuccin-frappe .input,html.theme--catppuccin-frappe #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-frappe .textarea{transition:all 200ms ease;box-shadow:none;border-width:1px;padding-left:1em;padding-right:1em;color:#c6d0f5}html.theme--catppuccin-frappe .select:after,html.theme--catppuccin-frappe .select select{border-width:1px}html.theme--catppuccin-frappe .menu-list a{transition:all 300ms ease}html.theme--catppuccin-frappe .modal-card-foot,html.theme--catppuccin-frappe .modal-card-head{border-color:#626880}html.theme--catppuccin-frappe .navbar{border-radius:.4em}html.theme--catppuccin-frappe .navbar.is-transparent{background:none}html.theme--catppuccin-frappe .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--catppuccin-frappe .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#8caaee}@media screen and (max-width: 1055px){html.theme--catppuccin-frappe .navbar .navbar-menu{background-color:#8caaee;border-radius:0 0 .4em .4em}}html.theme--catppuccin-frappe .docstring>section>a.docs-sourcelink:not(body){color:#414559}html.theme--catppuccin-frappe .tag.is-link:not(body),html.theme--catppuccin-frappe .docstring>section>a.is-link.docs-sourcelink:not(body),html.theme--catppuccin-frappe .content kbd.is-link:not(body){color:#414559}html.theme--catppuccin-frappe .ansi span.sgr1{font-weight:bolder}html.theme--catppuccin-frappe .ansi span.sgr2{font-weight:lighter}html.theme--catppuccin-frappe .ansi span.sgr3{font-style:italic}html.theme--catppuccin-frappe .ansi span.sgr4{text-decoration:underline}html.theme--catppuccin-frappe .ansi span.sgr7{color:#303446;background-color:#c6d0f5}html.theme--catppuccin-frappe .ansi span.sgr8{color:transparent}html.theme--catppuccin-frappe .ansi span.sgr8 span{color:transparent}html.theme--catppuccin-frappe .ansi span.sgr9{text-decoration:line-through}html.theme--catppuccin-frappe .ansi span.sgr30{color:#51576d}html.theme--catppuccin-frappe .ansi span.sgr31{color:#e78284}html.theme--catppuccin-frappe .ansi span.sgr32{color:#a6d189}html.theme--catppuccin-frappe .ansi span.sgr33{color:#e5c890}html.theme--catppuccin-frappe .ansi span.sgr34{color:#8caaee}html.theme--catppuccin-frappe .ansi span.sgr35{color:#f4b8e4}html.theme--catppuccin-frappe .ansi span.sgr36{color:#81c8be}html.theme--catppuccin-frappe .ansi span.sgr37{color:#b5bfe2}html.theme--catppuccin-frappe .ansi span.sgr40{background-color:#51576d}html.theme--catppuccin-frappe .ansi span.sgr41{background-color:#e78284}html.theme--catppuccin-frappe .ansi span.sgr42{background-color:#a6d189}html.theme--catppuccin-frappe .ansi span.sgr43{background-color:#e5c890}html.theme--catppuccin-frappe .ansi span.sgr44{background-color:#8caaee}html.theme--catppuccin-frappe .ansi span.sgr45{background-color:#f4b8e4}html.theme--catppuccin-frappe .ansi span.sgr46{background-color:#81c8be}html.theme--catppuccin-frappe .ansi span.sgr47{background-color:#b5bfe2}html.theme--catppuccin-frappe .ansi span.sgr90{color:#626880}html.theme--catppuccin-frappe .ansi span.sgr91{color:#e78284}html.theme--catppuccin-frappe .ansi span.sgr92{color:#a6d189}html.theme--catppuccin-frappe .ansi span.sgr93{color:#e5c890}html.theme--catppuccin-frappe .ansi span.sgr94{color:#8caaee}html.theme--catppuccin-frappe .ansi span.sgr95{color:#f4b8e4}html.theme--catppuccin-frappe .ansi span.sgr96{color:#81c8be}html.theme--catppuccin-frappe .ansi span.sgr97{color:#a5adce}html.theme--catppuccin-frappe .ansi span.sgr100{background-color:#626880}html.theme--catppuccin-frappe .ansi span.sgr101{background-color:#e78284}html.theme--catppuccin-frappe .ansi span.sgr102{background-color:#a6d189}html.theme--catppuccin-frappe .ansi span.sgr103{background-color:#e5c890}html.theme--catppuccin-frappe .ansi span.sgr104{background-color:#8caaee}html.theme--catppuccin-frappe .ansi span.sgr105{background-color:#f4b8e4}html.theme--catppuccin-frappe .ansi span.sgr106{background-color:#81c8be}html.theme--catppuccin-frappe .ansi span.sgr107{background-color:#a5adce}html.theme--catppuccin-frappe code.language-julia-repl>span.hljs-meta{color:#a6d189;font-weight:bolder}html.theme--catppuccin-frappe code .hljs{color:#c6d0f5;background:#303446}html.theme--catppuccin-frappe code .hljs-keyword{color:#ca9ee6}html.theme--catppuccin-frappe code .hljs-built_in{color:#e78284}html.theme--catppuccin-frappe code .hljs-type{color:#e5c890}html.theme--catppuccin-frappe code .hljs-literal{color:#ef9f76}html.theme--catppuccin-frappe code .hljs-number{color:#ef9f76}html.theme--catppuccin-frappe code .hljs-operator{color:#81c8be}html.theme--catppuccin-frappe code .hljs-punctuation{color:#b5bfe2}html.theme--catppuccin-frappe code .hljs-property{color:#81c8be}html.theme--catppuccin-frappe code .hljs-regexp{color:#f4b8e4}html.theme--catppuccin-frappe code .hljs-string{color:#a6d189}html.theme--catppuccin-frappe code .hljs-char.escape_{color:#a6d189}html.theme--catppuccin-frappe code .hljs-subst{color:#a5adce}html.theme--catppuccin-frappe code .hljs-symbol{color:#eebebe}html.theme--catppuccin-frappe code .hljs-variable{color:#ca9ee6}html.theme--catppuccin-frappe code .hljs-variable.language_{color:#ca9ee6}html.theme--catppuccin-frappe code .hljs-variable.constant_{color:#ef9f76}html.theme--catppuccin-frappe code .hljs-title{color:#8caaee}html.theme--catppuccin-frappe code .hljs-title.class_{color:#e5c890}html.theme--catppuccin-frappe code .hljs-title.function_{color:#8caaee}html.theme--catppuccin-frappe code .hljs-params{color:#c6d0f5}html.theme--catppuccin-frappe code .hljs-comment{color:#626880}html.theme--catppuccin-frappe code .hljs-doctag{color:#e78284}html.theme--catppuccin-frappe code .hljs-meta{color:#ef9f76}html.theme--catppuccin-frappe code .hljs-section{color:#8caaee}html.theme--catppuccin-frappe code .hljs-tag{color:#a5adce}html.theme--catppuccin-frappe code .hljs-name{color:#ca9ee6}html.theme--catppuccin-frappe code .hljs-attr{color:#8caaee}html.theme--catppuccin-frappe code .hljs-attribute{color:#a6d189}html.theme--catppuccin-frappe code .hljs-bullet{color:#81c8be}html.theme--catppuccin-frappe code .hljs-code{color:#a6d189}html.theme--catppuccin-frappe code .hljs-emphasis{color:#e78284;font-style:italic}html.theme--catppuccin-frappe code .hljs-strong{color:#e78284;font-weight:bold}html.theme--catppuccin-frappe code .hljs-formula{color:#81c8be}html.theme--catppuccin-frappe code .hljs-link{color:#85c1dc;font-style:italic}html.theme--catppuccin-frappe code .hljs-quote{color:#a6d189;font-style:italic}html.theme--catppuccin-frappe code .hljs-selector-tag{color:#e5c890}html.theme--catppuccin-frappe code .hljs-selector-id{color:#8caaee}html.theme--catppuccin-frappe code .hljs-selector-class{color:#81c8be}html.theme--catppuccin-frappe code .hljs-selector-attr{color:#ca9ee6}html.theme--catppuccin-frappe code .hljs-selector-pseudo{color:#81c8be}html.theme--catppuccin-frappe code .hljs-template-tag{color:#eebebe}html.theme--catppuccin-frappe code .hljs-template-variable{color:#eebebe}html.theme--catppuccin-frappe code .hljs-addition{color:#a6d189;background:rgba(166,227,161,0.15)}html.theme--catppuccin-frappe code .hljs-deletion{color:#e78284;background:rgba(243,139,168,0.15)}html.theme--catppuccin-frappe .search-result-link{border-radius:0.7em;transition:all 300ms}html.theme--catppuccin-frappe .search-result-link:hover,html.theme--catppuccin-frappe .search-result-link:focus{background-color:#414559}html.theme--catppuccin-frappe .search-result-link .property-search-result-badge,html.theme--catppuccin-frappe .search-result-link .search-filter{transition:all 300ms}html.theme--catppuccin-frappe .search-result-link:hover .property-search-result-badge,html.theme--catppuccin-frappe .search-result-link:hover .search-filter,html.theme--catppuccin-frappe .search-result-link:focus .property-search-result-badge,html.theme--catppuccin-frappe .search-result-link:focus .search-filter{color:#414559 !important;background-color:#babbf1 !important}html.theme--catppuccin-frappe .search-result-title{color:#c6d0f5}html.theme--catppuccin-frappe .search-result-highlight{background-color:#e78284;color:#292c3c}html.theme--catppuccin-frappe .search-divider{border-bottom:1px solid #5e6d6f50}html.theme--catppuccin-frappe .w-100{width:100%}html.theme--catppuccin-frappe .gap-2{gap:0.5rem}html.theme--catppuccin-frappe .gap-4{gap:1rem} diff --git a/v0.2.0/assets/themes/catppuccin-latte.css b/v0.2.0/assets/themes/catppuccin-latte.css new file mode 100644 index 000000000..63160d344 --- /dev/null +++ b/v0.2.0/assets/themes/catppuccin-latte.css @@ -0,0 +1 @@ +html.theme--catppuccin-latte .pagination-previous,html.theme--catppuccin-latte .pagination-next,html.theme--catppuccin-latte .pagination-link,html.theme--catppuccin-latte .pagination-ellipsis,html.theme--catppuccin-latte .file-cta,html.theme--catppuccin-latte .file-name,html.theme--catppuccin-latte .select select,html.theme--catppuccin-latte .textarea,html.theme--catppuccin-latte .input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-latte .button{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;border-radius:.4em;box-shadow:none;display:inline-flex;font-size:1rem;height:2.5em;justify-content:flex-start;line-height:1.5;padding-bottom:calc(0.5em - 1px);padding-left:calc(0.75em - 1px);padding-right:calc(0.75em - 1px);padding-top:calc(0.5em - 1px);position:relative;vertical-align:top}html.theme--catppuccin-latte .pagination-previous:focus,html.theme--catppuccin-latte .pagination-next:focus,html.theme--catppuccin-latte .pagination-link:focus,html.theme--catppuccin-latte .pagination-ellipsis:focus,html.theme--catppuccin-latte .file-cta:focus,html.theme--catppuccin-latte .file-name:focus,html.theme--catppuccin-latte .select select:focus,html.theme--catppuccin-latte .textarea:focus,html.theme--catppuccin-latte .input:focus,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input:focus,html.theme--catppuccin-latte .button:focus,html.theme--catppuccin-latte .is-focused.pagination-previous,html.theme--catppuccin-latte .is-focused.pagination-next,html.theme--catppuccin-latte .is-focused.pagination-link,html.theme--catppuccin-latte .is-focused.pagination-ellipsis,html.theme--catppuccin-latte .is-focused.file-cta,html.theme--catppuccin-latte .is-focused.file-name,html.theme--catppuccin-latte .select select.is-focused,html.theme--catppuccin-latte .is-focused.textarea,html.theme--catppuccin-latte .is-focused.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-latte .is-focused.button,html.theme--catppuccin-latte .pagination-previous:active,html.theme--catppuccin-latte .pagination-next:active,html.theme--catppuccin-latte .pagination-link:active,html.theme--catppuccin-latte .pagination-ellipsis:active,html.theme--catppuccin-latte .file-cta:active,html.theme--catppuccin-latte .file-name:active,html.theme--catppuccin-latte .select select:active,html.theme--catppuccin-latte .textarea:active,html.theme--catppuccin-latte .input:active,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input:active,html.theme--catppuccin-latte .button:active,html.theme--catppuccin-latte .is-active.pagination-previous,html.theme--catppuccin-latte .is-active.pagination-next,html.theme--catppuccin-latte .is-active.pagination-link,html.theme--catppuccin-latte .is-active.pagination-ellipsis,html.theme--catppuccin-latte .is-active.file-cta,html.theme--catppuccin-latte .is-active.file-name,html.theme--catppuccin-latte .select select.is-active,html.theme--catppuccin-latte .is-active.textarea,html.theme--catppuccin-latte .is-active.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--catppuccin-latte .is-active.button{outline:none}html.theme--catppuccin-latte .pagination-previous[disabled],html.theme--catppuccin-latte .pagination-next[disabled],html.theme--catppuccin-latte .pagination-link[disabled],html.theme--catppuccin-latte .pagination-ellipsis[disabled],html.theme--catppuccin-latte .file-cta[disabled],html.theme--catppuccin-latte .file-name[disabled],html.theme--catppuccin-latte .select select[disabled],html.theme--catppuccin-latte .textarea[disabled],html.theme--catppuccin-latte .input[disabled],html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input[disabled],html.theme--catppuccin-latte .button[disabled],fieldset[disabled] html.theme--catppuccin-latte .pagination-previous,html.theme--catppuccin-latte fieldset[disabled] .pagination-previous,fieldset[disabled] html.theme--catppuccin-latte .pagination-next,html.theme--catppuccin-latte fieldset[disabled] .pagination-next,fieldset[disabled] html.theme--catppuccin-latte .pagination-link,html.theme--catppuccin-latte fieldset[disabled] .pagination-link,fieldset[disabled] html.theme--catppuccin-latte .pagination-ellipsis,html.theme--catppuccin-latte fieldset[disabled] .pagination-ellipsis,fieldset[disabled] html.theme--catppuccin-latte .file-cta,html.theme--catppuccin-latte fieldset[disabled] .file-cta,fieldset[disabled] html.theme--catppuccin-latte .file-name,html.theme--catppuccin-latte fieldset[disabled] .file-name,fieldset[disabled] html.theme--catppuccin-latte .select select,fieldset[disabled] html.theme--catppuccin-latte .textarea,fieldset[disabled] html.theme--catppuccin-latte .input,fieldset[disabled] html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-latte fieldset[disabled] .select select,html.theme--catppuccin-latte .select fieldset[disabled] select,html.theme--catppuccin-latte fieldset[disabled] .textarea,html.theme--catppuccin-latte fieldset[disabled] .input,html.theme--catppuccin-latte fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-latte #documenter .docs-sidebar fieldset[disabled] form.docs-search>input,fieldset[disabled] html.theme--catppuccin-latte .button,html.theme--catppuccin-latte fieldset[disabled] .button{cursor:not-allowed}html.theme--catppuccin-latte .tabs,html.theme--catppuccin-latte .pagination-previous,html.theme--catppuccin-latte .pagination-next,html.theme--catppuccin-latte .pagination-link,html.theme--catppuccin-latte .pagination-ellipsis,html.theme--catppuccin-latte .breadcrumb,html.theme--catppuccin-latte .file,html.theme--catppuccin-latte .button,.is-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}html.theme--catppuccin-latte .navbar-link:not(.is-arrowless)::after,html.theme--catppuccin-latte .select:not(.is-multiple):not(.is-loading)::after{border:3px solid rgba(0,0,0,0);border-radius:2px;border-right:0;border-top:0;content:" ";display:block;height:0.625em;margin-top:-0.4375em;pointer-events:none;position:absolute;top:50%;transform:rotate(-45deg);transform-origin:center;width:0.625em}html.theme--catppuccin-latte .admonition:not(:last-child),html.theme--catppuccin-latte .tabs:not(:last-child),html.theme--catppuccin-latte .pagination:not(:last-child),html.theme--catppuccin-latte .message:not(:last-child),html.theme--catppuccin-latte .level:not(:last-child),html.theme--catppuccin-latte .breadcrumb:not(:last-child),html.theme--catppuccin-latte .block:not(:last-child),html.theme--catppuccin-latte .title:not(:last-child),html.theme--catppuccin-latte .subtitle:not(:last-child),html.theme--catppuccin-latte .table-container:not(:last-child),html.theme--catppuccin-latte .table:not(:last-child),html.theme--catppuccin-latte .progress:not(:last-child),html.theme--catppuccin-latte .notification:not(:last-child),html.theme--catppuccin-latte .content:not(:last-child),html.theme--catppuccin-latte .box:not(:last-child){margin-bottom:1.5rem}html.theme--catppuccin-latte .modal-close,html.theme--catppuccin-latte .delete{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,0.2);border:none;border-radius:9999px;cursor:pointer;pointer-events:auto;display:inline-block;flex-grow:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:none;position:relative;vertical-align:top;width:20px}html.theme--catppuccin-latte .modal-close::before,html.theme--catppuccin-latte .delete::before,html.theme--catppuccin-latte .modal-close::after,html.theme--catppuccin-latte .delete::after{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--catppuccin-latte .modal-close::before,html.theme--catppuccin-latte .delete::before{height:2px;width:50%}html.theme--catppuccin-latte .modal-close::after,html.theme--catppuccin-latte .delete::after{height:50%;width:2px}html.theme--catppuccin-latte .modal-close:hover,html.theme--catppuccin-latte .delete:hover,html.theme--catppuccin-latte .modal-close:focus,html.theme--catppuccin-latte .delete:focus{background-color:rgba(10,10,10,0.3)}html.theme--catppuccin-latte .modal-close:active,html.theme--catppuccin-latte .delete:active{background-color:rgba(10,10,10,0.4)}html.theme--catppuccin-latte .is-small.modal-close,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.modal-close,html.theme--catppuccin-latte .is-small.delete,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.delete{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}html.theme--catppuccin-latte .is-medium.modal-close,html.theme--catppuccin-latte .is-medium.delete{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}html.theme--catppuccin-latte .is-large.modal-close,html.theme--catppuccin-latte .is-large.delete{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}html.theme--catppuccin-latte .control.is-loading::after,html.theme--catppuccin-latte .select.is-loading::after,html.theme--catppuccin-latte .loader,html.theme--catppuccin-latte .button.is-loading::after{animation:spinAround 500ms infinite linear;border:2px solid #8c8fa1;border-radius:9999px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em}html.theme--catppuccin-latte .hero-video,html.theme--catppuccin-latte .modal-background,html.theme--catppuccin-latte .modal,html.theme--catppuccin-latte .image.is-square img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--catppuccin-latte .image.is-square .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--catppuccin-latte .image.is-1by1 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--catppuccin-latte .image.is-1by1 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--catppuccin-latte .image.is-5by4 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--catppuccin-latte .image.is-5by4 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--catppuccin-latte .image.is-4by3 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--catppuccin-latte .image.is-4by3 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--catppuccin-latte .image.is-3by2 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--catppuccin-latte .image.is-3by2 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--catppuccin-latte .image.is-5by3 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--catppuccin-latte .image.is-5by3 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--catppuccin-latte .image.is-16by9 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--catppuccin-latte .image.is-16by9 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--catppuccin-latte .image.is-2by1 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--catppuccin-latte .image.is-2by1 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--catppuccin-latte .image.is-3by1 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--catppuccin-latte .image.is-3by1 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--catppuccin-latte .image.is-4by5 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--catppuccin-latte .image.is-4by5 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--catppuccin-latte .image.is-3by4 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--catppuccin-latte .image.is-3by4 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--catppuccin-latte .image.is-2by3 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--catppuccin-latte .image.is-2by3 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--catppuccin-latte .image.is-3by5 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--catppuccin-latte .image.is-3by5 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--catppuccin-latte .image.is-9by16 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--catppuccin-latte .image.is-9by16 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--catppuccin-latte .image.is-1by2 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--catppuccin-latte .image.is-1by2 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--catppuccin-latte .image.is-1by3 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--catppuccin-latte .image.is-1by3 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio,.is-overlay{bottom:0;left:0;position:absolute;right:0;top:0}html.theme--catppuccin-latte .navbar-burger{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0}/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:inherit}.has-text-white{color:#fff !important}a.has-text-white:hover,a.has-text-white:focus{color:#e6e6e6 !important}.has-background-white{background-color:#fff !important}.has-text-black{color:#0a0a0a !important}a.has-text-black:hover,a.has-text-black:focus{color:#000 !important}.has-background-black{background-color:#0a0a0a !important}.has-text-light{color:#f5f5f5 !important}a.has-text-light:hover,a.has-text-light:focus{color:#dbdbdb !important}.has-background-light{background-color:#f5f5f5 !important}.has-text-dark{color:#ccd0da !important}a.has-text-dark:hover,a.has-text-dark:focus{color:#aeb5c5 !important}.has-background-dark{background-color:#ccd0da !important}.has-text-primary{color:#1e66f5 !important}a.has-text-primary:hover,a.has-text-primary:focus{color:#0a4ed6 !important}.has-background-primary{background-color:#1e66f5 !important}.has-text-primary-light{color:#ebf2fe !important}a.has-text-primary-light:hover,a.has-text-primary-light:focus{color:#bbd1fc !important}.has-background-primary-light{background-color:#ebf2fe !important}.has-text-primary-dark{color:#0a52e1 !important}a.has-text-primary-dark:hover,a.has-text-primary-dark:focus{color:#286df5 !important}.has-background-primary-dark{background-color:#0a52e1 !important}.has-text-link{color:#1e66f5 !important}a.has-text-link:hover,a.has-text-link:focus{color:#0a4ed6 !important}.has-background-link{background-color:#1e66f5 !important}.has-text-link-light{color:#ebf2fe !important}a.has-text-link-light:hover,a.has-text-link-light:focus{color:#bbd1fc !important}.has-background-link-light{background-color:#ebf2fe !important}.has-text-link-dark{color:#0a52e1 !important}a.has-text-link-dark:hover,a.has-text-link-dark:focus{color:#286df5 !important}.has-background-link-dark{background-color:#0a52e1 !important}.has-text-info{color:#179299 !important}a.has-text-info:hover,a.has-text-info:focus{color:#10686d !important}.has-background-info{background-color:#179299 !important}.has-text-info-light{color:#edfcfc !important}a.has-text-info-light:hover,a.has-text-info-light:focus{color:#c1f3f6 !important}.has-background-info-light{background-color:#edfcfc !important}.has-text-info-dark{color:#1cb2ba !important}a.has-text-info-dark:hover,a.has-text-info-dark:focus{color:#2ad5df !important}.has-background-info-dark{background-color:#1cb2ba !important}.has-text-success{color:#40a02b !important}a.has-text-success:hover,a.has-text-success:focus{color:#307820 !important}.has-background-success{background-color:#40a02b !important}.has-text-success-light{color:#f1fbef !important}a.has-text-success-light:hover,a.has-text-success-light:focus{color:#cef0c7 !important}.has-background-success-light{background-color:#f1fbef !important}.has-text-success-dark{color:#40a12b !important}a.has-text-success-dark:hover,a.has-text-success-dark:focus{color:#50c936 !important}.has-background-success-dark{background-color:#40a12b !important}.has-text-warning{color:#df8e1d !important}a.has-text-warning:hover,a.has-text-warning:focus{color:#b27117 !important}.has-background-warning{background-color:#df8e1d !important}.has-text-warning-light{color:#fdf6ed !important}a.has-text-warning-light:hover,a.has-text-warning-light:focus{color:#f7e0c0 !important}.has-background-warning-light{background-color:#fdf6ed !important}.has-text-warning-dark{color:#9e6515 !important}a.has-text-warning-dark:hover,a.has-text-warning-dark:focus{color:#cb811a !important}.has-background-warning-dark{background-color:#9e6515 !important}.has-text-danger{color:#d20f39 !important}a.has-text-danger:hover,a.has-text-danger:focus{color:#a20c2c !important}.has-background-danger{background-color:#d20f39 !important}.has-text-danger-light{color:#feecf0 !important}a.has-text-danger-light:hover,a.has-text-danger-light:focus{color:#fabcca !important}.has-background-danger-light{background-color:#feecf0 !important}.has-text-danger-dark{color:#e9113f !important}a.has-text-danger-dark:hover,a.has-text-danger-dark:focus{color:#f13c63 !important}.has-background-danger-dark{background-color:#e9113f !important}.has-text-black-bis{color:#121212 !important}.has-background-black-bis{background-color:#121212 !important}.has-text-black-ter{color:#242424 !important}.has-background-black-ter{background-color:#242424 !important}.has-text-grey-darker{color:#ccd0da !important}.has-background-grey-darker{background-color:#ccd0da !important}.has-text-grey-dark{color:#bcc0cc !important}.has-background-grey-dark{background-color:#bcc0cc !important}.has-text-grey{color:#acb0be !important}.has-background-grey{background-color:#acb0be !important}.has-text-grey-light{color:#9ca0b0 !important}.has-background-grey-light{background-color:#9ca0b0 !important}.has-text-grey-lighter{color:#8c8fa1 !important}.has-background-grey-lighter{background-color:#8c8fa1 !important}.has-text-white-ter{color:#f5f5f5 !important}.has-background-white-ter{background-color:#f5f5f5 !important}.has-text-white-bis{color:#fafafa !important}.has-background-white-bis{background-color:#fafafa !important}.is-flex-direction-row{flex-direction:row !important}.is-flex-direction-row-reverse{flex-direction:row-reverse !important}.is-flex-direction-column{flex-direction:column !important}.is-flex-direction-column-reverse{flex-direction:column-reverse !important}.is-flex-wrap-nowrap{flex-wrap:nowrap !important}.is-flex-wrap-wrap{flex-wrap:wrap !important}.is-flex-wrap-wrap-reverse{flex-wrap:wrap-reverse !important}.is-justify-content-flex-start{justify-content:flex-start !important}.is-justify-content-flex-end{justify-content:flex-end !important}.is-justify-content-center{justify-content:center !important}.is-justify-content-space-between{justify-content:space-between !important}.is-justify-content-space-around{justify-content:space-around !important}.is-justify-content-space-evenly{justify-content:space-evenly !important}.is-justify-content-start{justify-content:start !important}.is-justify-content-end{justify-content:end !important}.is-justify-content-left{justify-content:left !important}.is-justify-content-right{justify-content:right !important}.is-align-content-flex-start{align-content:flex-start !important}.is-align-content-flex-end{align-content:flex-end !important}.is-align-content-center{align-content:center !important}.is-align-content-space-between{align-content:space-between !important}.is-align-content-space-around{align-content:space-around !important}.is-align-content-space-evenly{align-content:space-evenly !important}.is-align-content-stretch{align-content:stretch !important}.is-align-content-start{align-content:start !important}.is-align-content-end{align-content:end !important}.is-align-content-baseline{align-content:baseline !important}.is-align-items-stretch{align-items:stretch !important}.is-align-items-flex-start{align-items:flex-start !important}.is-align-items-flex-end{align-items:flex-end !important}.is-align-items-center{align-items:center !important}.is-align-items-baseline{align-items:baseline !important}.is-align-items-start{align-items:start !important}.is-align-items-end{align-items:end !important}.is-align-items-self-start{align-items:self-start !important}.is-align-items-self-end{align-items:self-end !important}.is-align-self-auto{align-self:auto !important}.is-align-self-flex-start{align-self:flex-start !important}.is-align-self-flex-end{align-self:flex-end !important}.is-align-self-center{align-self:center !important}.is-align-self-baseline{align-self:baseline !important}.is-align-self-stretch{align-self:stretch !important}.is-flex-grow-0{flex-grow:0 !important}.is-flex-grow-1{flex-grow:1 !important}.is-flex-grow-2{flex-grow:2 !important}.is-flex-grow-3{flex-grow:3 !important}.is-flex-grow-4{flex-grow:4 !important}.is-flex-grow-5{flex-grow:5 !important}.is-flex-shrink-0{flex-shrink:0 !important}.is-flex-shrink-1{flex-shrink:1 !important}.is-flex-shrink-2{flex-shrink:2 !important}.is-flex-shrink-3{flex-shrink:3 !important}.is-flex-shrink-4{flex-shrink:4 !important}.is-flex-shrink-5{flex-shrink:5 !important}.is-clearfix::after{clear:both;content:" ";display:table}.is-pulled-left{float:left !important}.is-pulled-right{float:right !important}.is-radiusless{border-radius:0 !important}.is-shadowless{box-shadow:none !important}.is-clickable{cursor:pointer !important;pointer-events:all !important}.is-clipped{overflow:hidden !important}.is-relative{position:relative !important}.is-marginless{margin:0 !important}.is-paddingless{padding:0 !important}.m-0{margin:0 !important}.mt-0{margin-top:0 !important}.mr-0{margin-right:0 !important}.mb-0{margin-bottom:0 !important}.ml-0{margin-left:0 !important}.mx-0{margin-left:0 !important;margin-right:0 !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.m-1{margin:.25rem !important}.mt-1{margin-top:.25rem !important}.mr-1{margin-right:.25rem !important}.mb-1{margin-bottom:.25rem !important}.ml-1{margin-left:.25rem !important}.mx-1{margin-left:.25rem !important;margin-right:.25rem !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.m-2{margin:.5rem !important}.mt-2{margin-top:.5rem !important}.mr-2{margin-right:.5rem !important}.mb-2{margin-bottom:.5rem !important}.ml-2{margin-left:.5rem !important}.mx-2{margin-left:.5rem !important;margin-right:.5rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.m-3{margin:.75rem !important}.mt-3{margin-top:.75rem !important}.mr-3{margin-right:.75rem !important}.mb-3{margin-bottom:.75rem !important}.ml-3{margin-left:.75rem !important}.mx-3{margin-left:.75rem !important;margin-right:.75rem !important}.my-3{margin-top:.75rem !important;margin-bottom:.75rem !important}.m-4{margin:1rem !important}.mt-4{margin-top:1rem !important}.mr-4{margin-right:1rem !important}.mb-4{margin-bottom:1rem !important}.ml-4{margin-left:1rem !important}.mx-4{margin-left:1rem !important;margin-right:1rem !important}.my-4{margin-top:1rem !important;margin-bottom:1rem !important}.m-5{margin:1.5rem !important}.mt-5{margin-top:1.5rem !important}.mr-5{margin-right:1.5rem !important}.mb-5{margin-bottom:1.5rem !important}.ml-5{margin-left:1.5rem !important}.mx-5{margin-left:1.5rem !important;margin-right:1.5rem !important}.my-5{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.m-6{margin:3rem !important}.mt-6{margin-top:3rem !important}.mr-6{margin-right:3rem !important}.mb-6{margin-bottom:3rem !important}.ml-6{margin-left:3rem !important}.mx-6{margin-left:3rem !important;margin-right:3rem !important}.my-6{margin-top:3rem !important;margin-bottom:3rem !important}.m-auto{margin:auto !important}.mt-auto{margin-top:auto !important}.mr-auto{margin-right:auto !important}.mb-auto{margin-bottom:auto !important}.ml-auto{margin-left:auto !important}.mx-auto{margin-left:auto !important;margin-right:auto !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.p-0{padding:0 !important}.pt-0{padding-top:0 !important}.pr-0{padding-right:0 !important}.pb-0{padding-bottom:0 !important}.pl-0{padding-left:0 !important}.px-0{padding-left:0 !important;padding-right:0 !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.p-1{padding:.25rem !important}.pt-1{padding-top:.25rem !important}.pr-1{padding-right:.25rem !important}.pb-1{padding-bottom:.25rem !important}.pl-1{padding-left:.25rem !important}.px-1{padding-left:.25rem !important;padding-right:.25rem !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.p-2{padding:.5rem !important}.pt-2{padding-top:.5rem !important}.pr-2{padding-right:.5rem !important}.pb-2{padding-bottom:.5rem !important}.pl-2{padding-left:.5rem !important}.px-2{padding-left:.5rem !important;padding-right:.5rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.p-3{padding:.75rem !important}.pt-3{padding-top:.75rem !important}.pr-3{padding-right:.75rem !important}.pb-3{padding-bottom:.75rem !important}.pl-3{padding-left:.75rem !important}.px-3{padding-left:.75rem !important;padding-right:.75rem !important}.py-3{padding-top:.75rem !important;padding-bottom:.75rem !important}.p-4{padding:1rem !important}.pt-4{padding-top:1rem !important}.pr-4{padding-right:1rem !important}.pb-4{padding-bottom:1rem !important}.pl-4{padding-left:1rem !important}.px-4{padding-left:1rem !important;padding-right:1rem !important}.py-4{padding-top:1rem !important;padding-bottom:1rem !important}.p-5{padding:1.5rem !important}.pt-5{padding-top:1.5rem !important}.pr-5{padding-right:1.5rem !important}.pb-5{padding-bottom:1.5rem !important}.pl-5{padding-left:1.5rem !important}.px-5{padding-left:1.5rem !important;padding-right:1.5rem !important}.py-5{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.p-6{padding:3rem !important}.pt-6{padding-top:3rem !important}.pr-6{padding-right:3rem !important}.pb-6{padding-bottom:3rem !important}.pl-6{padding-left:3rem !important}.px-6{padding-left:3rem !important;padding-right:3rem !important}.py-6{padding-top:3rem !important;padding-bottom:3rem !important}.p-auto{padding:auto !important}.pt-auto{padding-top:auto !important}.pr-auto{padding-right:auto !important}.pb-auto{padding-bottom:auto !important}.pl-auto{padding-left:auto !important}.px-auto{padding-left:auto !important;padding-right:auto !important}.py-auto{padding-top:auto !important;padding-bottom:auto !important}.is-size-1{font-size:3rem !important}.is-size-2{font-size:2.5rem !important}.is-size-3{font-size:2rem !important}.is-size-4{font-size:1.5rem !important}.is-size-5{font-size:1.25rem !important}.is-size-6{font-size:1rem !important}.is-size-7,html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink{font-size:.75rem !important}@media screen and (max-width: 768px){.is-size-1-mobile{font-size:3rem !important}.is-size-2-mobile{font-size:2.5rem !important}.is-size-3-mobile{font-size:2rem !important}.is-size-4-mobile{font-size:1.5rem !important}.is-size-5-mobile{font-size:1.25rem !important}.is-size-6-mobile{font-size:1rem !important}.is-size-7-mobile{font-size:.75rem !important}}@media screen and (min-width: 769px),print{.is-size-1-tablet{font-size:3rem !important}.is-size-2-tablet{font-size:2.5rem !important}.is-size-3-tablet{font-size:2rem !important}.is-size-4-tablet{font-size:1.5rem !important}.is-size-5-tablet{font-size:1.25rem !important}.is-size-6-tablet{font-size:1rem !important}.is-size-7-tablet{font-size:.75rem !important}}@media screen and (max-width: 1055px){.is-size-1-touch{font-size:3rem !important}.is-size-2-touch{font-size:2.5rem !important}.is-size-3-touch{font-size:2rem !important}.is-size-4-touch{font-size:1.5rem !important}.is-size-5-touch{font-size:1.25rem !important}.is-size-6-touch{font-size:1rem !important}.is-size-7-touch{font-size:.75rem !important}}@media screen and (min-width: 1056px){.is-size-1-desktop{font-size:3rem !important}.is-size-2-desktop{font-size:2.5rem !important}.is-size-3-desktop{font-size:2rem !important}.is-size-4-desktop{font-size:1.5rem !important}.is-size-5-desktop{font-size:1.25rem !important}.is-size-6-desktop{font-size:1rem !important}.is-size-7-desktop{font-size:.75rem !important}}@media screen and (min-width: 1216px){.is-size-1-widescreen{font-size:3rem !important}.is-size-2-widescreen{font-size:2.5rem !important}.is-size-3-widescreen{font-size:2rem !important}.is-size-4-widescreen{font-size:1.5rem !important}.is-size-5-widescreen{font-size:1.25rem !important}.is-size-6-widescreen{font-size:1rem !important}.is-size-7-widescreen{font-size:.75rem !important}}@media screen and (min-width: 1408px){.is-size-1-fullhd{font-size:3rem !important}.is-size-2-fullhd{font-size:2.5rem !important}.is-size-3-fullhd{font-size:2rem !important}.is-size-4-fullhd{font-size:1.5rem !important}.is-size-5-fullhd{font-size:1.25rem !important}.is-size-6-fullhd{font-size:1rem !important}.is-size-7-fullhd{font-size:.75rem !important}}.has-text-centered{text-align:center !important}.has-text-justified{text-align:justify !important}.has-text-left{text-align:left !important}.has-text-right{text-align:right !important}@media screen and (max-width: 768px){.has-text-centered-mobile{text-align:center !important}}@media screen and (min-width: 769px),print{.has-text-centered-tablet{text-align:center !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-centered-tablet-only{text-align:center !important}}@media screen and (max-width: 1055px){.has-text-centered-touch{text-align:center !important}}@media screen and (min-width: 1056px){.has-text-centered-desktop{text-align:center !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-centered-desktop-only{text-align:center !important}}@media screen and (min-width: 1216px){.has-text-centered-widescreen{text-align:center !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-centered-widescreen-only{text-align:center !important}}@media screen and (min-width: 1408px){.has-text-centered-fullhd{text-align:center !important}}@media screen and (max-width: 768px){.has-text-justified-mobile{text-align:justify !important}}@media screen and (min-width: 769px),print{.has-text-justified-tablet{text-align:justify !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-justified-tablet-only{text-align:justify !important}}@media screen and (max-width: 1055px){.has-text-justified-touch{text-align:justify !important}}@media screen and (min-width: 1056px){.has-text-justified-desktop{text-align:justify !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-justified-desktop-only{text-align:justify !important}}@media screen and (min-width: 1216px){.has-text-justified-widescreen{text-align:justify !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-justified-widescreen-only{text-align:justify !important}}@media screen and (min-width: 1408px){.has-text-justified-fullhd{text-align:justify !important}}@media screen and (max-width: 768px){.has-text-left-mobile{text-align:left !important}}@media screen and (min-width: 769px),print{.has-text-left-tablet{text-align:left !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-left-tablet-only{text-align:left !important}}@media screen and (max-width: 1055px){.has-text-left-touch{text-align:left !important}}@media screen and (min-width: 1056px){.has-text-left-desktop{text-align:left !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-left-desktop-only{text-align:left !important}}@media screen and (min-width: 1216px){.has-text-left-widescreen{text-align:left !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-left-widescreen-only{text-align:left !important}}@media screen and (min-width: 1408px){.has-text-left-fullhd{text-align:left !important}}@media screen and (max-width: 768px){.has-text-right-mobile{text-align:right !important}}@media screen and (min-width: 769px),print{.has-text-right-tablet{text-align:right !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-right-tablet-only{text-align:right !important}}@media screen and (max-width: 1055px){.has-text-right-touch{text-align:right !important}}@media screen and (min-width: 1056px){.has-text-right-desktop{text-align:right !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-right-desktop-only{text-align:right !important}}@media screen and (min-width: 1216px){.has-text-right-widescreen{text-align:right !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-right-widescreen-only{text-align:right !important}}@media screen and (min-width: 1408px){.has-text-right-fullhd{text-align:right !important}}.is-capitalized{text-transform:capitalize !important}.is-lowercase{text-transform:lowercase !important}.is-uppercase{text-transform:uppercase !important}.is-italic{font-style:italic !important}.is-underlined{text-decoration:underline !important}.has-text-weight-light{font-weight:300 !important}.has-text-weight-normal{font-weight:400 !important}.has-text-weight-medium{font-weight:500 !important}.has-text-weight-semibold{font-weight:600 !important}.has-text-weight-bold{font-weight:700 !important}.is-family-primary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-secondary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-sans-serif{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-monospace{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-family-code{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-block{display:block !important}@media screen and (max-width: 768px){.is-block-mobile{display:block !important}}@media screen and (min-width: 769px),print{.is-block-tablet{display:block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-block-tablet-only{display:block !important}}@media screen and (max-width: 1055px){.is-block-touch{display:block !important}}@media screen and (min-width: 1056px){.is-block-desktop{display:block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-block-desktop-only{display:block !important}}@media screen and (min-width: 1216px){.is-block-widescreen{display:block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-block-widescreen-only{display:block !important}}@media screen and (min-width: 1408px){.is-block-fullhd{display:block !important}}.is-flex{display:flex !important}@media screen and (max-width: 768px){.is-flex-mobile{display:flex !important}}@media screen and (min-width: 769px),print{.is-flex-tablet{display:flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-flex-tablet-only{display:flex !important}}@media screen and (max-width: 1055px){.is-flex-touch{display:flex !important}}@media screen and (min-width: 1056px){.is-flex-desktop{display:flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-flex-desktop-only{display:flex !important}}@media screen and (min-width: 1216px){.is-flex-widescreen{display:flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-flex-widescreen-only{display:flex !important}}@media screen and (min-width: 1408px){.is-flex-fullhd{display:flex !important}}.is-inline{display:inline !important}@media screen and (max-width: 768px){.is-inline-mobile{display:inline !important}}@media screen and (min-width: 769px),print{.is-inline-tablet{display:inline !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-tablet-only{display:inline !important}}@media screen and (max-width: 1055px){.is-inline-touch{display:inline !important}}@media screen and (min-width: 1056px){.is-inline-desktop{display:inline !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-desktop-only{display:inline !important}}@media screen and (min-width: 1216px){.is-inline-widescreen{display:inline !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-widescreen-only{display:inline !important}}@media screen and (min-width: 1408px){.is-inline-fullhd{display:inline !important}}.is-inline-block{display:inline-block !important}@media screen and (max-width: 768px){.is-inline-block-mobile{display:inline-block !important}}@media screen and (min-width: 769px),print{.is-inline-block-tablet{display:inline-block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-block-tablet-only{display:inline-block !important}}@media screen and (max-width: 1055px){.is-inline-block-touch{display:inline-block !important}}@media screen and (min-width: 1056px){.is-inline-block-desktop{display:inline-block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-block-desktop-only{display:inline-block !important}}@media screen and (min-width: 1216px){.is-inline-block-widescreen{display:inline-block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-block-widescreen-only{display:inline-block !important}}@media screen and (min-width: 1408px){.is-inline-block-fullhd{display:inline-block !important}}.is-inline-flex{display:inline-flex !important}@media screen and (max-width: 768px){.is-inline-flex-mobile{display:inline-flex !important}}@media screen and (min-width: 769px),print{.is-inline-flex-tablet{display:inline-flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-flex-tablet-only{display:inline-flex !important}}@media screen and (max-width: 1055px){.is-inline-flex-touch{display:inline-flex !important}}@media screen and (min-width: 1056px){.is-inline-flex-desktop{display:inline-flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-flex-desktop-only{display:inline-flex !important}}@media screen and (min-width: 1216px){.is-inline-flex-widescreen{display:inline-flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-flex-widescreen-only{display:inline-flex !important}}@media screen and (min-width: 1408px){.is-inline-flex-fullhd{display:inline-flex !important}}.is-hidden{display:none !important}.is-sr-only{border:none !important;clip:rect(0, 0, 0, 0) !important;height:0.01em !important;overflow:hidden !important;padding:0 !important;position:absolute !important;white-space:nowrap !important;width:0.01em !important}@media screen and (max-width: 768px){.is-hidden-mobile{display:none !important}}@media screen and (min-width: 769px),print{.is-hidden-tablet{display:none !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-hidden-tablet-only{display:none !important}}@media screen and (max-width: 1055px){.is-hidden-touch{display:none !important}}@media screen and (min-width: 1056px){.is-hidden-desktop{display:none !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-hidden-desktop-only{display:none !important}}@media screen and (min-width: 1216px){.is-hidden-widescreen{display:none !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-hidden-widescreen-only{display:none !important}}@media screen and (min-width: 1408px){.is-hidden-fullhd{display:none !important}}.is-invisible{visibility:hidden !important}@media screen and (max-width: 768px){.is-invisible-mobile{visibility:hidden !important}}@media screen and (min-width: 769px),print{.is-invisible-tablet{visibility:hidden !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-invisible-tablet-only{visibility:hidden !important}}@media screen and (max-width: 1055px){.is-invisible-touch{visibility:hidden !important}}@media screen and (min-width: 1056px){.is-invisible-desktop{visibility:hidden !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-invisible-desktop-only{visibility:hidden !important}}@media screen and (min-width: 1216px){.is-invisible-widescreen{visibility:hidden !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-invisible-widescreen-only{visibility:hidden !important}}@media screen and (min-width: 1408px){.is-invisible-fullhd{visibility:hidden !important}}html.theme--catppuccin-latte html{background-color:#eff1f5;font-size:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--catppuccin-latte article,html.theme--catppuccin-latte aside,html.theme--catppuccin-latte figure,html.theme--catppuccin-latte footer,html.theme--catppuccin-latte header,html.theme--catppuccin-latte hgroup,html.theme--catppuccin-latte section{display:block}html.theme--catppuccin-latte body,html.theme--catppuccin-latte button,html.theme--catppuccin-latte input,html.theme--catppuccin-latte optgroup,html.theme--catppuccin-latte select,html.theme--catppuccin-latte textarea{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif}html.theme--catppuccin-latte code,html.theme--catppuccin-latte pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}html.theme--catppuccin-latte body{color:#4c4f69;font-size:1em;font-weight:400;line-height:1.5}html.theme--catppuccin-latte a{color:#1e66f5;cursor:pointer;text-decoration:none}html.theme--catppuccin-latte a strong{color:currentColor}html.theme--catppuccin-latte a:hover{color:#04a5e5}html.theme--catppuccin-latte code{background-color:#e6e9ef;color:#4c4f69;font-size:.875em;font-weight:normal;padding:.1em}html.theme--catppuccin-latte hr{background-color:#e6e9ef;border:none;display:block;height:2px;margin:1.5rem 0}html.theme--catppuccin-latte img{height:auto;max-width:100%}html.theme--catppuccin-latte input[type="checkbox"],html.theme--catppuccin-latte input[type="radio"]{vertical-align:baseline}html.theme--catppuccin-latte small{font-size:.875em}html.theme--catppuccin-latte span{font-style:inherit;font-weight:inherit}html.theme--catppuccin-latte strong{color:#41445a;font-weight:700}html.theme--catppuccin-latte fieldset{border:none}html.theme--catppuccin-latte pre{-webkit-overflow-scrolling:touch;background-color:#e6e9ef;color:#4c4f69;font-size:.875em;overflow-x:auto;padding:1.25rem 1.5rem;white-space:pre;word-wrap:normal}html.theme--catppuccin-latte pre code{background-color:transparent;color:currentColor;font-size:1em;padding:0}html.theme--catppuccin-latte table td,html.theme--catppuccin-latte table th{vertical-align:top}html.theme--catppuccin-latte table td:not([align]),html.theme--catppuccin-latte table th:not([align]){text-align:inherit}html.theme--catppuccin-latte table th{color:#41445a}html.theme--catppuccin-latte .box{background-color:#bcc0cc;border-radius:8px;box-shadow:none;color:#4c4f69;display:block;padding:1.25rem}html.theme--catppuccin-latte a.box:hover,html.theme--catppuccin-latte a.box:focus{box-shadow:0 0.5em 1em -0.125em rgba(10,10,10,0.1),0 0 0 1px #1e66f5}html.theme--catppuccin-latte a.box:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2),0 0 0 1px #1e66f5}html.theme--catppuccin-latte .button{background-color:#e6e9ef;border-color:#fff;border-width:1px;color:#1e66f5;cursor:pointer;justify-content:center;padding-bottom:calc(0.5em - 1px);padding-left:1em;padding-right:1em;padding-top:calc(0.5em - 1px);text-align:center;white-space:nowrap}html.theme--catppuccin-latte .button strong{color:inherit}html.theme--catppuccin-latte .button .icon,html.theme--catppuccin-latte .button .icon.is-small,html.theme--catppuccin-latte .button #documenter .docs-sidebar form.docs-search>input.icon,html.theme--catppuccin-latte #documenter .docs-sidebar .button form.docs-search>input.icon,html.theme--catppuccin-latte .button .icon.is-medium,html.theme--catppuccin-latte .button .icon.is-large{height:1.5em;width:1.5em}html.theme--catppuccin-latte .button .icon:first-child:not(:last-child){margin-left:calc(-0.5em - 1px);margin-right:.25em}html.theme--catppuccin-latte .button .icon:last-child:not(:first-child){margin-left:.25em;margin-right:calc(-0.5em - 1px)}html.theme--catppuccin-latte .button .icon:first-child:last-child{margin-left:calc(-0.5em - 1px);margin-right:calc(-0.5em - 1px)}html.theme--catppuccin-latte .button:hover,html.theme--catppuccin-latte .button.is-hovered{border-color:#9ca0b0;color:#41445a}html.theme--catppuccin-latte .button:focus,html.theme--catppuccin-latte .button.is-focused{border-color:#9ca0b0;color:#0b57ef}html.theme--catppuccin-latte .button:focus:not(:active),html.theme--catppuccin-latte .button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(30,102,245,0.25)}html.theme--catppuccin-latte .button:active,html.theme--catppuccin-latte .button.is-active{border-color:#bcc0cc;color:#41445a}html.theme--catppuccin-latte .button.is-text{background-color:transparent;border-color:transparent;color:#4c4f69;text-decoration:underline}html.theme--catppuccin-latte .button.is-text:hover,html.theme--catppuccin-latte .button.is-text.is-hovered,html.theme--catppuccin-latte .button.is-text:focus,html.theme--catppuccin-latte .button.is-text.is-focused{background-color:#e6e9ef;color:#41445a}html.theme--catppuccin-latte .button.is-text:active,html.theme--catppuccin-latte .button.is-text.is-active{background-color:#d6dbe5;color:#41445a}html.theme--catppuccin-latte .button.is-text[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-text{background-color:transparent;border-color:transparent;box-shadow:none}html.theme--catppuccin-latte .button.is-ghost{background:none;border-color:rgba(0,0,0,0);color:#1e66f5;text-decoration:none}html.theme--catppuccin-latte .button.is-ghost:hover,html.theme--catppuccin-latte .button.is-ghost.is-hovered{color:#1e66f5;text-decoration:underline}html.theme--catppuccin-latte .button.is-white{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-latte .button.is-white:hover,html.theme--catppuccin-latte .button.is-white.is-hovered{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-latte .button.is-white:focus,html.theme--catppuccin-latte .button.is-white.is-focused{border-color:transparent;color:#0a0a0a}html.theme--catppuccin-latte .button.is-white:focus:not(:active),html.theme--catppuccin-latte .button.is-white.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--catppuccin-latte .button.is-white:active,html.theme--catppuccin-latte .button.is-white.is-active{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-latte .button.is-white[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-white{background-color:#fff;border-color:#fff;box-shadow:none}html.theme--catppuccin-latte .button.is-white.is-inverted{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-latte .button.is-white.is-inverted:hover,html.theme--catppuccin-latte .button.is-white.is-inverted.is-hovered{background-color:#000}html.theme--catppuccin-latte .button.is-white.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-white.is-inverted{background-color:#0a0a0a;border-color:transparent;box-shadow:none;color:#fff}html.theme--catppuccin-latte .button.is-white.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--catppuccin-latte .button.is-white.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-latte .button.is-white.is-outlined:hover,html.theme--catppuccin-latte .button.is-white.is-outlined.is-hovered,html.theme--catppuccin-latte .button.is-white.is-outlined:focus,html.theme--catppuccin-latte .button.is-white.is-outlined.is-focused{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--catppuccin-latte .button.is-white.is-outlined.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-latte .button.is-white.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .button.is-white.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .button.is-white.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .button.is-white.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--catppuccin-latte .button.is-white.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-white.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-latte .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--catppuccin-latte .button.is-white.is-inverted.is-outlined:hover,html.theme--catppuccin-latte .button.is-white.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-latte .button.is-white.is-inverted.is-outlined:focus,html.theme--catppuccin-latte .button.is-white.is-inverted.is-outlined.is-focused{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-latte .button.is-white.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .button.is-white.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .button.is-white.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-latte .button.is-white.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--catppuccin-latte .button.is-black{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-black:hover,html.theme--catppuccin-latte .button.is-black.is-hovered{background-color:#040404;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-black:focus,html.theme--catppuccin-latte .button.is-black.is-focused{border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-black:focus:not(:active),html.theme--catppuccin-latte .button.is-black.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--catppuccin-latte .button.is-black:active,html.theme--catppuccin-latte .button.is-black.is-active{background-color:#000;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-black[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-black{background-color:#0a0a0a;border-color:#0a0a0a;box-shadow:none}html.theme--catppuccin-latte .button.is-black.is-inverted{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-latte .button.is-black.is-inverted:hover,html.theme--catppuccin-latte .button.is-black.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--catppuccin-latte .button.is-black.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-black.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#0a0a0a}html.theme--catppuccin-latte .button.is-black.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-latte .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--catppuccin-latte .button.is-black.is-outlined:hover,html.theme--catppuccin-latte .button.is-black.is-outlined.is-hovered,html.theme--catppuccin-latte .button.is-black.is-outlined:focus,html.theme--catppuccin-latte .button.is-black.is-outlined.is-focused{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--catppuccin-latte .button.is-black.is-outlined.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--catppuccin-latte .button.is-black.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .button.is-black.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .button.is-black.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .button.is-black.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-latte .button.is-black.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--catppuccin-latte .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-latte .button.is-black.is-inverted.is-outlined:hover,html.theme--catppuccin-latte .button.is-black.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-latte .button.is-black.is-inverted.is-outlined:focus,html.theme--catppuccin-latte .button.is-black.is-inverted.is-outlined.is-focused{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-latte .button.is-black.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .button.is-black.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .button.is-black.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--catppuccin-latte .button.is-black.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-latte .button.is-light{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .button.is-light:hover,html.theme--catppuccin-latte .button.is-light.is-hovered{background-color:#eee;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .button.is-light:focus,html.theme--catppuccin-latte .button.is-light.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .button.is-light:focus:not(:active),html.theme--catppuccin-latte .button.is-light.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}html.theme--catppuccin-latte .button.is-light:active,html.theme--catppuccin-latte .button.is-light.is-active{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .button.is-light[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-light{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none}html.theme--catppuccin-latte .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);color:#f5f5f5}html.theme--catppuccin-latte .button.is-light.is-inverted:hover,html.theme--catppuccin-latte .button.is-light.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .button.is-light.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#f5f5f5}html.theme--catppuccin-latte .button.is-light.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-latte .button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;color:#f5f5f5}html.theme--catppuccin-latte .button.is-light.is-outlined:hover,html.theme--catppuccin-latte .button.is-light.is-outlined.is-hovered,html.theme--catppuccin-latte .button.is-light.is-outlined:focus,html.theme--catppuccin-latte .button.is-light.is-outlined.is-focused{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .button.is-light.is-outlined.is-loading::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}html.theme--catppuccin-latte .button.is-light.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .button.is-light.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .button.is-light.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .button.is-light.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-latte .button.is-light.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;box-shadow:none;color:#f5f5f5}html.theme--catppuccin-latte .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .button.is-light.is-inverted.is-outlined:hover,html.theme--catppuccin-latte .button.is-light.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-latte .button.is-light.is-inverted.is-outlined:focus,html.theme--catppuccin-latte .button.is-light.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#f5f5f5}html.theme--catppuccin-latte .button.is-light.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .button.is-light.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .button.is-light.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}html.theme--catppuccin-latte .button.is-light.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .button.is-dark,html.theme--catppuccin-latte .content kbd.button{background-color:#ccd0da;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .button.is-dark:hover,html.theme--catppuccin-latte .content kbd.button:hover,html.theme--catppuccin-latte .button.is-dark.is-hovered,html.theme--catppuccin-latte .content kbd.button.is-hovered{background-color:#c5c9d5;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .button.is-dark:focus,html.theme--catppuccin-latte .content kbd.button:focus,html.theme--catppuccin-latte .button.is-dark.is-focused,html.theme--catppuccin-latte .content kbd.button.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .button.is-dark:focus:not(:active),html.theme--catppuccin-latte .content kbd.button:focus:not(:active),html.theme--catppuccin-latte .button.is-dark.is-focused:not(:active),html.theme--catppuccin-latte .content kbd.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(204,208,218,0.25)}html.theme--catppuccin-latte .button.is-dark:active,html.theme--catppuccin-latte .content kbd.button:active,html.theme--catppuccin-latte .button.is-dark.is-active,html.theme--catppuccin-latte .content kbd.button.is-active{background-color:#bdc2cf;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .button.is-dark[disabled],html.theme--catppuccin-latte .content kbd.button[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-dark,fieldset[disabled] html.theme--catppuccin-latte .content kbd.button{background-color:#ccd0da;border-color:#ccd0da;box-shadow:none}html.theme--catppuccin-latte .button.is-dark.is-inverted,html.theme--catppuccin-latte .content kbd.button.is-inverted{background-color:rgba(0,0,0,0.7);color:#ccd0da}html.theme--catppuccin-latte .button.is-dark.is-inverted:hover,html.theme--catppuccin-latte .content kbd.button.is-inverted:hover,html.theme--catppuccin-latte .button.is-dark.is-inverted.is-hovered,html.theme--catppuccin-latte .content kbd.button.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .button.is-dark.is-inverted[disabled],html.theme--catppuccin-latte .content kbd.button.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-dark.is-inverted,fieldset[disabled] html.theme--catppuccin-latte .content kbd.button.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#ccd0da}html.theme--catppuccin-latte .button.is-dark.is-loading::after,html.theme--catppuccin-latte .content kbd.button.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-latte .button.is-dark.is-outlined,html.theme--catppuccin-latte .content kbd.button.is-outlined{background-color:transparent;border-color:#ccd0da;color:#ccd0da}html.theme--catppuccin-latte .button.is-dark.is-outlined:hover,html.theme--catppuccin-latte .content kbd.button.is-outlined:hover,html.theme--catppuccin-latte .button.is-dark.is-outlined.is-hovered,html.theme--catppuccin-latte .content kbd.button.is-outlined.is-hovered,html.theme--catppuccin-latte .button.is-dark.is-outlined:focus,html.theme--catppuccin-latte .content kbd.button.is-outlined:focus,html.theme--catppuccin-latte .button.is-dark.is-outlined.is-focused,html.theme--catppuccin-latte .content kbd.button.is-outlined.is-focused{background-color:#ccd0da;border-color:#ccd0da;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .button.is-dark.is-outlined.is-loading::after,html.theme--catppuccin-latte .content kbd.button.is-outlined.is-loading::after{border-color:transparent transparent #ccd0da #ccd0da !important}html.theme--catppuccin-latte .button.is-dark.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .content kbd.button.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .button.is-dark.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .content kbd.button.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .button.is-dark.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .content kbd.button.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .button.is-dark.is-outlined.is-loading.is-focused::after,html.theme--catppuccin-latte .content kbd.button.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-latte .button.is-dark.is-outlined[disabled],html.theme--catppuccin-latte .content kbd.button.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-dark.is-outlined,fieldset[disabled] html.theme--catppuccin-latte .content kbd.button.is-outlined{background-color:transparent;border-color:#ccd0da;box-shadow:none;color:#ccd0da}html.theme--catppuccin-latte .button.is-dark.is-inverted.is-outlined,html.theme--catppuccin-latte .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .button.is-dark.is-inverted.is-outlined:hover,html.theme--catppuccin-latte .content kbd.button.is-inverted.is-outlined:hover,html.theme--catppuccin-latte .button.is-dark.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-latte .content kbd.button.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-latte .button.is-dark.is-inverted.is-outlined:focus,html.theme--catppuccin-latte .content kbd.button.is-inverted.is-outlined:focus,html.theme--catppuccin-latte .button.is-dark.is-inverted.is-outlined.is-focused,html.theme--catppuccin-latte .content kbd.button.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#ccd0da}html.theme--catppuccin-latte .button.is-dark.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .content kbd.button.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .content kbd.button.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .button.is-dark.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .content kbd.button.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--catppuccin-latte .content kbd.button.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #ccd0da #ccd0da !important}html.theme--catppuccin-latte .button.is-dark.is-inverted.is-outlined[disabled],html.theme--catppuccin-latte .content kbd.button.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-dark.is-inverted.is-outlined,fieldset[disabled] html.theme--catppuccin-latte .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .button.is-primary,html.theme--catppuccin-latte .docstring>section>a.button.docs-sourcelink{background-color:#1e66f5;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-primary:hover,html.theme--catppuccin-latte .docstring>section>a.button.docs-sourcelink:hover,html.theme--catppuccin-latte .button.is-primary.is-hovered,html.theme--catppuccin-latte .docstring>section>a.button.is-hovered.docs-sourcelink{background-color:#125ef4;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-primary:focus,html.theme--catppuccin-latte .docstring>section>a.button.docs-sourcelink:focus,html.theme--catppuccin-latte .button.is-primary.is-focused,html.theme--catppuccin-latte .docstring>section>a.button.is-focused.docs-sourcelink{border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-primary:focus:not(:active),html.theme--catppuccin-latte .docstring>section>a.button.docs-sourcelink:focus:not(:active),html.theme--catppuccin-latte .button.is-primary.is-focused:not(:active),html.theme--catppuccin-latte .docstring>section>a.button.is-focused.docs-sourcelink:not(:active){box-shadow:0 0 0 0.125em rgba(30,102,245,0.25)}html.theme--catppuccin-latte .button.is-primary:active,html.theme--catppuccin-latte .docstring>section>a.button.docs-sourcelink:active,html.theme--catppuccin-latte .button.is-primary.is-active,html.theme--catppuccin-latte .docstring>section>a.button.is-active.docs-sourcelink{background-color:#0b57ef;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-primary[disabled],html.theme--catppuccin-latte .docstring>section>a.button.docs-sourcelink[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-primary,fieldset[disabled] html.theme--catppuccin-latte .docstring>section>a.button.docs-sourcelink{background-color:#1e66f5;border-color:#1e66f5;box-shadow:none}html.theme--catppuccin-latte .button.is-primary.is-inverted,html.theme--catppuccin-latte .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;color:#1e66f5}html.theme--catppuccin-latte .button.is-primary.is-inverted:hover,html.theme--catppuccin-latte .docstring>section>a.button.is-inverted.docs-sourcelink:hover,html.theme--catppuccin-latte .button.is-primary.is-inverted.is-hovered,html.theme--catppuccin-latte .docstring>section>a.button.is-inverted.is-hovered.docs-sourcelink{background-color:#f2f2f2}html.theme--catppuccin-latte .button.is-primary.is-inverted[disabled],html.theme--catppuccin-latte .docstring>section>a.button.is-inverted.docs-sourcelink[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-primary.is-inverted,fieldset[disabled] html.theme--catppuccin-latte .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;border-color:transparent;box-shadow:none;color:#1e66f5}html.theme--catppuccin-latte .button.is-primary.is-loading::after,html.theme--catppuccin-latte .docstring>section>a.button.is-loading.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-latte .button.is-primary.is-outlined,html.theme--catppuccin-latte .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#1e66f5;color:#1e66f5}html.theme--catppuccin-latte .button.is-primary.is-outlined:hover,html.theme--catppuccin-latte .docstring>section>a.button.is-outlined.docs-sourcelink:hover,html.theme--catppuccin-latte .button.is-primary.is-outlined.is-hovered,html.theme--catppuccin-latte .docstring>section>a.button.is-outlined.is-hovered.docs-sourcelink,html.theme--catppuccin-latte .button.is-primary.is-outlined:focus,html.theme--catppuccin-latte .docstring>section>a.button.is-outlined.docs-sourcelink:focus,html.theme--catppuccin-latte .button.is-primary.is-outlined.is-focused,html.theme--catppuccin-latte .docstring>section>a.button.is-outlined.is-focused.docs-sourcelink{background-color:#1e66f5;border-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .button.is-primary.is-outlined.is-loading::after,html.theme--catppuccin-latte .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink::after{border-color:transparent transparent #1e66f5 #1e66f5 !important}html.theme--catppuccin-latte .button.is-primary.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--catppuccin-latte .button.is-primary.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .docstring>section>a.button.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--catppuccin-latte .button.is-primary.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--catppuccin-latte .button.is-primary.is-outlined.is-loading.is-focused::after,html.theme--catppuccin-latte .docstring>section>a.button.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-latte .button.is-primary.is-outlined[disabled],html.theme--catppuccin-latte .docstring>section>a.button.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-primary.is-outlined,fieldset[disabled] html.theme--catppuccin-latte .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#1e66f5;box-shadow:none;color:#1e66f5}html.theme--catppuccin-latte .button.is-primary.is-inverted.is-outlined,html.theme--catppuccin-latte .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-latte .button.is-primary.is-inverted.is-outlined:hover,html.theme--catppuccin-latte .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:hover,html.theme--catppuccin-latte .button.is-primary.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-latte .docstring>section>a.button.is-inverted.is-outlined.is-hovered.docs-sourcelink,html.theme--catppuccin-latte .button.is-primary.is-inverted.is-outlined:focus,html.theme--catppuccin-latte .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:focus,html.theme--catppuccin-latte .button.is-primary.is-inverted.is-outlined.is-focused,html.theme--catppuccin-latte .docstring>section>a.button.is-inverted.is-outlined.is-focused.docs-sourcelink{background-color:#fff;color:#1e66f5}html.theme--catppuccin-latte .button.is-primary.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--catppuccin-latte .button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--catppuccin-latte .button.is-primary.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--catppuccin-latte .button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--catppuccin-latte .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #1e66f5 #1e66f5 !important}html.theme--catppuccin-latte .button.is-primary.is-inverted.is-outlined[disabled],html.theme--catppuccin-latte .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-primary.is-inverted.is-outlined,fieldset[disabled] html.theme--catppuccin-latte .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-latte .button.is-primary.is-light,html.theme--catppuccin-latte .docstring>section>a.button.is-light.docs-sourcelink{background-color:#ebf2fe;color:#0a52e1}html.theme--catppuccin-latte .button.is-primary.is-light:hover,html.theme--catppuccin-latte .docstring>section>a.button.is-light.docs-sourcelink:hover,html.theme--catppuccin-latte .button.is-primary.is-light.is-hovered,html.theme--catppuccin-latte .docstring>section>a.button.is-light.is-hovered.docs-sourcelink{background-color:#dfe9fe;border-color:transparent;color:#0a52e1}html.theme--catppuccin-latte .button.is-primary.is-light:active,html.theme--catppuccin-latte .docstring>section>a.button.is-light.docs-sourcelink:active,html.theme--catppuccin-latte .button.is-primary.is-light.is-active,html.theme--catppuccin-latte .docstring>section>a.button.is-light.is-active.docs-sourcelink{background-color:#d3e1fd;border-color:transparent;color:#0a52e1}html.theme--catppuccin-latte .button.is-link{background-color:#1e66f5;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-link:hover,html.theme--catppuccin-latte .button.is-link.is-hovered{background-color:#125ef4;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-link:focus,html.theme--catppuccin-latte .button.is-link.is-focused{border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-link:focus:not(:active),html.theme--catppuccin-latte .button.is-link.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(30,102,245,0.25)}html.theme--catppuccin-latte .button.is-link:active,html.theme--catppuccin-latte .button.is-link.is-active{background-color:#0b57ef;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-link[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-link{background-color:#1e66f5;border-color:#1e66f5;box-shadow:none}html.theme--catppuccin-latte .button.is-link.is-inverted{background-color:#fff;color:#1e66f5}html.theme--catppuccin-latte .button.is-link.is-inverted:hover,html.theme--catppuccin-latte .button.is-link.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--catppuccin-latte .button.is-link.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-link.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#1e66f5}html.theme--catppuccin-latte .button.is-link.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-latte .button.is-link.is-outlined{background-color:transparent;border-color:#1e66f5;color:#1e66f5}html.theme--catppuccin-latte .button.is-link.is-outlined:hover,html.theme--catppuccin-latte .button.is-link.is-outlined.is-hovered,html.theme--catppuccin-latte .button.is-link.is-outlined:focus,html.theme--catppuccin-latte .button.is-link.is-outlined.is-focused{background-color:#1e66f5;border-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .button.is-link.is-outlined.is-loading::after{border-color:transparent transparent #1e66f5 #1e66f5 !important}html.theme--catppuccin-latte .button.is-link.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .button.is-link.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .button.is-link.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .button.is-link.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-latte .button.is-link.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-link.is-outlined{background-color:transparent;border-color:#1e66f5;box-shadow:none;color:#1e66f5}html.theme--catppuccin-latte .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-latte .button.is-link.is-inverted.is-outlined:hover,html.theme--catppuccin-latte .button.is-link.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-latte .button.is-link.is-inverted.is-outlined:focus,html.theme--catppuccin-latte .button.is-link.is-inverted.is-outlined.is-focused{background-color:#fff;color:#1e66f5}html.theme--catppuccin-latte .button.is-link.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .button.is-link.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .button.is-link.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #1e66f5 #1e66f5 !important}html.theme--catppuccin-latte .button.is-link.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-latte .button.is-link.is-light{background-color:#ebf2fe;color:#0a52e1}html.theme--catppuccin-latte .button.is-link.is-light:hover,html.theme--catppuccin-latte .button.is-link.is-light.is-hovered{background-color:#dfe9fe;border-color:transparent;color:#0a52e1}html.theme--catppuccin-latte .button.is-link.is-light:active,html.theme--catppuccin-latte .button.is-link.is-light.is-active{background-color:#d3e1fd;border-color:transparent;color:#0a52e1}html.theme--catppuccin-latte .button.is-info{background-color:#179299;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-info:hover,html.theme--catppuccin-latte .button.is-info.is-hovered{background-color:#15878e;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-info:focus,html.theme--catppuccin-latte .button.is-info.is-focused{border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-info:focus:not(:active),html.theme--catppuccin-latte .button.is-info.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(23,146,153,0.25)}html.theme--catppuccin-latte .button.is-info:active,html.theme--catppuccin-latte .button.is-info.is-active{background-color:#147d83;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-info[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-info{background-color:#179299;border-color:#179299;box-shadow:none}html.theme--catppuccin-latte .button.is-info.is-inverted{background-color:#fff;color:#179299}html.theme--catppuccin-latte .button.is-info.is-inverted:hover,html.theme--catppuccin-latte .button.is-info.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--catppuccin-latte .button.is-info.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-info.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#179299}html.theme--catppuccin-latte .button.is-info.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-latte .button.is-info.is-outlined{background-color:transparent;border-color:#179299;color:#179299}html.theme--catppuccin-latte .button.is-info.is-outlined:hover,html.theme--catppuccin-latte .button.is-info.is-outlined.is-hovered,html.theme--catppuccin-latte .button.is-info.is-outlined:focus,html.theme--catppuccin-latte .button.is-info.is-outlined.is-focused{background-color:#179299;border-color:#179299;color:#fff}html.theme--catppuccin-latte .button.is-info.is-outlined.is-loading::after{border-color:transparent transparent #179299 #179299 !important}html.theme--catppuccin-latte .button.is-info.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .button.is-info.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .button.is-info.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .button.is-info.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-latte .button.is-info.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-info.is-outlined{background-color:transparent;border-color:#179299;box-shadow:none;color:#179299}html.theme--catppuccin-latte .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-latte .button.is-info.is-inverted.is-outlined:hover,html.theme--catppuccin-latte .button.is-info.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-latte .button.is-info.is-inverted.is-outlined:focus,html.theme--catppuccin-latte .button.is-info.is-inverted.is-outlined.is-focused{background-color:#fff;color:#179299}html.theme--catppuccin-latte .button.is-info.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .button.is-info.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .button.is-info.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #179299 #179299 !important}html.theme--catppuccin-latte .button.is-info.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-latte .button.is-info.is-light{background-color:#edfcfc;color:#1cb2ba}html.theme--catppuccin-latte .button.is-info.is-light:hover,html.theme--catppuccin-latte .button.is-info.is-light.is-hovered{background-color:#e2f9fb;border-color:transparent;color:#1cb2ba}html.theme--catppuccin-latte .button.is-info.is-light:active,html.theme--catppuccin-latte .button.is-info.is-light.is-active{background-color:#d7f7f9;border-color:transparent;color:#1cb2ba}html.theme--catppuccin-latte .button.is-success{background-color:#40a02b;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-success:hover,html.theme--catppuccin-latte .button.is-success.is-hovered{background-color:#3c9628;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-success:focus,html.theme--catppuccin-latte .button.is-success.is-focused{border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-success:focus:not(:active),html.theme--catppuccin-latte .button.is-success.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(64,160,43,0.25)}html.theme--catppuccin-latte .button.is-success:active,html.theme--catppuccin-latte .button.is-success.is-active{background-color:#388c26;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-success[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-success{background-color:#40a02b;border-color:#40a02b;box-shadow:none}html.theme--catppuccin-latte .button.is-success.is-inverted{background-color:#fff;color:#40a02b}html.theme--catppuccin-latte .button.is-success.is-inverted:hover,html.theme--catppuccin-latte .button.is-success.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--catppuccin-latte .button.is-success.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-success.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#40a02b}html.theme--catppuccin-latte .button.is-success.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-latte .button.is-success.is-outlined{background-color:transparent;border-color:#40a02b;color:#40a02b}html.theme--catppuccin-latte .button.is-success.is-outlined:hover,html.theme--catppuccin-latte .button.is-success.is-outlined.is-hovered,html.theme--catppuccin-latte .button.is-success.is-outlined:focus,html.theme--catppuccin-latte .button.is-success.is-outlined.is-focused{background-color:#40a02b;border-color:#40a02b;color:#fff}html.theme--catppuccin-latte .button.is-success.is-outlined.is-loading::after{border-color:transparent transparent #40a02b #40a02b !important}html.theme--catppuccin-latte .button.is-success.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .button.is-success.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .button.is-success.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .button.is-success.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-latte .button.is-success.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-success.is-outlined{background-color:transparent;border-color:#40a02b;box-shadow:none;color:#40a02b}html.theme--catppuccin-latte .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-latte .button.is-success.is-inverted.is-outlined:hover,html.theme--catppuccin-latte .button.is-success.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-latte .button.is-success.is-inverted.is-outlined:focus,html.theme--catppuccin-latte .button.is-success.is-inverted.is-outlined.is-focused{background-color:#fff;color:#40a02b}html.theme--catppuccin-latte .button.is-success.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .button.is-success.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .button.is-success.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #40a02b #40a02b !important}html.theme--catppuccin-latte .button.is-success.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-latte .button.is-success.is-light{background-color:#f1fbef;color:#40a12b}html.theme--catppuccin-latte .button.is-success.is-light:hover,html.theme--catppuccin-latte .button.is-success.is-light.is-hovered{background-color:#e8f8e5;border-color:transparent;color:#40a12b}html.theme--catppuccin-latte .button.is-success.is-light:active,html.theme--catppuccin-latte .button.is-success.is-light.is-active{background-color:#e0f5db;border-color:transparent;color:#40a12b}html.theme--catppuccin-latte .button.is-warning{background-color:#df8e1d;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-warning:hover,html.theme--catppuccin-latte .button.is-warning.is-hovered{background-color:#d4871c;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-warning:focus,html.theme--catppuccin-latte .button.is-warning.is-focused{border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-warning:focus:not(:active),html.theme--catppuccin-latte .button.is-warning.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(223,142,29,0.25)}html.theme--catppuccin-latte .button.is-warning:active,html.theme--catppuccin-latte .button.is-warning.is-active{background-color:#c8801a;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-warning[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-warning{background-color:#df8e1d;border-color:#df8e1d;box-shadow:none}html.theme--catppuccin-latte .button.is-warning.is-inverted{background-color:#fff;color:#df8e1d}html.theme--catppuccin-latte .button.is-warning.is-inverted:hover,html.theme--catppuccin-latte .button.is-warning.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--catppuccin-latte .button.is-warning.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-warning.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#df8e1d}html.theme--catppuccin-latte .button.is-warning.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-latte .button.is-warning.is-outlined{background-color:transparent;border-color:#df8e1d;color:#df8e1d}html.theme--catppuccin-latte .button.is-warning.is-outlined:hover,html.theme--catppuccin-latte .button.is-warning.is-outlined.is-hovered,html.theme--catppuccin-latte .button.is-warning.is-outlined:focus,html.theme--catppuccin-latte .button.is-warning.is-outlined.is-focused{background-color:#df8e1d;border-color:#df8e1d;color:#fff}html.theme--catppuccin-latte .button.is-warning.is-outlined.is-loading::after{border-color:transparent transparent #df8e1d #df8e1d !important}html.theme--catppuccin-latte .button.is-warning.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .button.is-warning.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .button.is-warning.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .button.is-warning.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-latte .button.is-warning.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-warning.is-outlined{background-color:transparent;border-color:#df8e1d;box-shadow:none;color:#df8e1d}html.theme--catppuccin-latte .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-latte .button.is-warning.is-inverted.is-outlined:hover,html.theme--catppuccin-latte .button.is-warning.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-latte .button.is-warning.is-inverted.is-outlined:focus,html.theme--catppuccin-latte .button.is-warning.is-inverted.is-outlined.is-focused{background-color:#fff;color:#df8e1d}html.theme--catppuccin-latte .button.is-warning.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .button.is-warning.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #df8e1d #df8e1d !important}html.theme--catppuccin-latte .button.is-warning.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-latte .button.is-warning.is-light{background-color:#fdf6ed;color:#9e6515}html.theme--catppuccin-latte .button.is-warning.is-light:hover,html.theme--catppuccin-latte .button.is-warning.is-light.is-hovered{background-color:#fbf1e2;border-color:transparent;color:#9e6515}html.theme--catppuccin-latte .button.is-warning.is-light:active,html.theme--catppuccin-latte .button.is-warning.is-light.is-active{background-color:#faebd6;border-color:transparent;color:#9e6515}html.theme--catppuccin-latte .button.is-danger{background-color:#d20f39;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-danger:hover,html.theme--catppuccin-latte .button.is-danger.is-hovered{background-color:#c60e36;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-danger:focus,html.theme--catppuccin-latte .button.is-danger.is-focused{border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-danger:focus:not(:active),html.theme--catppuccin-latte .button.is-danger.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(210,15,57,0.25)}html.theme--catppuccin-latte .button.is-danger:active,html.theme--catppuccin-latte .button.is-danger.is-active{background-color:#ba0d33;border-color:transparent;color:#fff}html.theme--catppuccin-latte .button.is-danger[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-danger{background-color:#d20f39;border-color:#d20f39;box-shadow:none}html.theme--catppuccin-latte .button.is-danger.is-inverted{background-color:#fff;color:#d20f39}html.theme--catppuccin-latte .button.is-danger.is-inverted:hover,html.theme--catppuccin-latte .button.is-danger.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--catppuccin-latte .button.is-danger.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-danger.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#d20f39}html.theme--catppuccin-latte .button.is-danger.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-latte .button.is-danger.is-outlined{background-color:transparent;border-color:#d20f39;color:#d20f39}html.theme--catppuccin-latte .button.is-danger.is-outlined:hover,html.theme--catppuccin-latte .button.is-danger.is-outlined.is-hovered,html.theme--catppuccin-latte .button.is-danger.is-outlined:focus,html.theme--catppuccin-latte .button.is-danger.is-outlined.is-focused{background-color:#d20f39;border-color:#d20f39;color:#fff}html.theme--catppuccin-latte .button.is-danger.is-outlined.is-loading::after{border-color:transparent transparent #d20f39 #d20f39 !important}html.theme--catppuccin-latte .button.is-danger.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .button.is-danger.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .button.is-danger.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .button.is-danger.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-latte .button.is-danger.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-danger.is-outlined{background-color:transparent;border-color:#d20f39;box-shadow:none;color:#d20f39}html.theme--catppuccin-latte .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-latte .button.is-danger.is-inverted.is-outlined:hover,html.theme--catppuccin-latte .button.is-danger.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-latte .button.is-danger.is-inverted.is-outlined:focus,html.theme--catppuccin-latte .button.is-danger.is-inverted.is-outlined.is-focused{background-color:#fff;color:#d20f39}html.theme--catppuccin-latte .button.is-danger.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-latte .button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-latte .button.is-danger.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-latte .button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #d20f39 #d20f39 !important}html.theme--catppuccin-latte .button.is-danger.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-latte .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-latte .button.is-danger.is-light{background-color:#feecf0;color:#e9113f}html.theme--catppuccin-latte .button.is-danger.is-light:hover,html.theme--catppuccin-latte .button.is-danger.is-light.is-hovered{background-color:#fde0e6;border-color:transparent;color:#e9113f}html.theme--catppuccin-latte .button.is-danger.is-light:active,html.theme--catppuccin-latte .button.is-danger.is-light.is-active{background-color:#fcd4dd;border-color:transparent;color:#e9113f}html.theme--catppuccin-latte .button.is-small,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.button{font-size:.75rem}html.theme--catppuccin-latte .button.is-small:not(.is-rounded),html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.button:not(.is-rounded){border-radius:3px}html.theme--catppuccin-latte .button.is-normal{font-size:1rem}html.theme--catppuccin-latte .button.is-medium{font-size:1.25rem}html.theme--catppuccin-latte .button.is-large{font-size:1.5rem}html.theme--catppuccin-latte .button[disabled],fieldset[disabled] html.theme--catppuccin-latte .button{background-color:#9ca0b0;border-color:#acb0be;box-shadow:none;opacity:.5}html.theme--catppuccin-latte .button.is-fullwidth{display:flex;width:100%}html.theme--catppuccin-latte .button.is-loading{color:transparent !important;pointer-events:none}html.theme--catppuccin-latte .button.is-loading::after{position:absolute;left:calc(50% - (1em * 0.5));top:calc(50% - (1em * 0.5));position:absolute !important}html.theme--catppuccin-latte .button.is-static{background-color:#e6e9ef;border-color:#acb0be;color:#8c8fa1;box-shadow:none;pointer-events:none}html.theme--catppuccin-latte .button.is-rounded,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.button{border-radius:9999px;padding-left:calc(1em + 0.25em);padding-right:calc(1em + 0.25em)}html.theme--catppuccin-latte .buttons{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--catppuccin-latte .buttons .button{margin-bottom:0.5rem}html.theme--catppuccin-latte .buttons .button:not(:last-child):not(.is-fullwidth){margin-right:.5rem}html.theme--catppuccin-latte .buttons:last-child{margin-bottom:-0.5rem}html.theme--catppuccin-latte .buttons:not(:last-child){margin-bottom:1rem}html.theme--catppuccin-latte .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large){font-size:.75rem}html.theme--catppuccin-latte .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large):not(.is-rounded){border-radius:3px}html.theme--catppuccin-latte .buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large){font-size:1.25rem}html.theme--catppuccin-latte .buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium){font-size:1.5rem}html.theme--catppuccin-latte .buttons.has-addons .button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}html.theme--catppuccin-latte .buttons.has-addons .button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}html.theme--catppuccin-latte .buttons.has-addons .button:last-child{margin-right:0}html.theme--catppuccin-latte .buttons.has-addons .button:hover,html.theme--catppuccin-latte .buttons.has-addons .button.is-hovered{z-index:2}html.theme--catppuccin-latte .buttons.has-addons .button:focus,html.theme--catppuccin-latte .buttons.has-addons .button.is-focused,html.theme--catppuccin-latte .buttons.has-addons .button:active,html.theme--catppuccin-latte .buttons.has-addons .button.is-active,html.theme--catppuccin-latte .buttons.has-addons .button.is-selected{z-index:3}html.theme--catppuccin-latte .buttons.has-addons .button:focus:hover,html.theme--catppuccin-latte .buttons.has-addons .button.is-focused:hover,html.theme--catppuccin-latte .buttons.has-addons .button:active:hover,html.theme--catppuccin-latte .buttons.has-addons .button.is-active:hover,html.theme--catppuccin-latte .buttons.has-addons .button.is-selected:hover{z-index:4}html.theme--catppuccin-latte .buttons.has-addons .button.is-expanded{flex-grow:1;flex-shrink:1}html.theme--catppuccin-latte .buttons.is-centered{justify-content:center}html.theme--catppuccin-latte .buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}html.theme--catppuccin-latte .buttons.is-right{justify-content:flex-end}html.theme--catppuccin-latte .buttons.is-right:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}@media screen and (max-width: 768px){html.theme--catppuccin-latte .button.is-responsive.is-small,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.5625rem}html.theme--catppuccin-latte .button.is-responsive,html.theme--catppuccin-latte .button.is-responsive.is-normal{font-size:.65625rem}html.theme--catppuccin-latte .button.is-responsive.is-medium{font-size:.75rem}html.theme--catppuccin-latte .button.is-responsive.is-large{font-size:1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-latte .button.is-responsive.is-small,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.65625rem}html.theme--catppuccin-latte .button.is-responsive,html.theme--catppuccin-latte .button.is-responsive.is-normal{font-size:.75rem}html.theme--catppuccin-latte .button.is-responsive.is-medium{font-size:1rem}html.theme--catppuccin-latte .button.is-responsive.is-large{font-size:1.25rem}}html.theme--catppuccin-latte .container{flex-grow:1;margin:0 auto;position:relative;width:auto}html.theme--catppuccin-latte .container.is-fluid{max-width:none !important;padding-left:32px;padding-right:32px;width:100%}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .container{max-width:992px}}@media screen and (max-width: 1215px){html.theme--catppuccin-latte .container.is-widescreen:not(.is-max-desktop){max-width:1152px}}@media screen and (max-width: 1407px){html.theme--catppuccin-latte .container.is-fullhd:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}@media screen and (min-width: 1216px){html.theme--catppuccin-latte .container:not(.is-max-desktop){max-width:1152px}}@media screen and (min-width: 1408px){html.theme--catppuccin-latte .container:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}html.theme--catppuccin-latte .content li+li{margin-top:0.25em}html.theme--catppuccin-latte .content p:not(:last-child),html.theme--catppuccin-latte .content dl:not(:last-child),html.theme--catppuccin-latte .content ol:not(:last-child),html.theme--catppuccin-latte .content ul:not(:last-child),html.theme--catppuccin-latte .content blockquote:not(:last-child),html.theme--catppuccin-latte .content pre:not(:last-child),html.theme--catppuccin-latte .content table:not(:last-child){margin-bottom:1em}html.theme--catppuccin-latte .content h1,html.theme--catppuccin-latte .content h2,html.theme--catppuccin-latte .content h3,html.theme--catppuccin-latte .content h4,html.theme--catppuccin-latte .content h5,html.theme--catppuccin-latte .content h6{color:#4c4f69;font-weight:600;line-height:1.125}html.theme--catppuccin-latte .content h1{font-size:2em;margin-bottom:0.5em}html.theme--catppuccin-latte .content h1:not(:first-child){margin-top:1em}html.theme--catppuccin-latte .content h2{font-size:1.75em;margin-bottom:0.5714em}html.theme--catppuccin-latte .content h2:not(:first-child){margin-top:1.1428em}html.theme--catppuccin-latte .content h3{font-size:1.5em;margin-bottom:0.6666em}html.theme--catppuccin-latte .content h3:not(:first-child){margin-top:1.3333em}html.theme--catppuccin-latte .content h4{font-size:1.25em;margin-bottom:0.8em}html.theme--catppuccin-latte .content h5{font-size:1.125em;margin-bottom:0.8888em}html.theme--catppuccin-latte .content h6{font-size:1em;margin-bottom:1em}html.theme--catppuccin-latte .content blockquote{background-color:#e6e9ef;border-left:5px solid #acb0be;padding:1.25em 1.5em}html.theme--catppuccin-latte .content ol{list-style-position:outside;margin-left:2em;margin-top:1em}html.theme--catppuccin-latte .content ol:not([type]){list-style-type:decimal}html.theme--catppuccin-latte .content ol.is-lower-alpha:not([type]){list-style-type:lower-alpha}html.theme--catppuccin-latte .content ol.is-lower-roman:not([type]){list-style-type:lower-roman}html.theme--catppuccin-latte .content ol.is-upper-alpha:not([type]){list-style-type:upper-alpha}html.theme--catppuccin-latte .content ol.is-upper-roman:not([type]){list-style-type:upper-roman}html.theme--catppuccin-latte .content ul{list-style:disc outside;margin-left:2em;margin-top:1em}html.theme--catppuccin-latte .content ul ul{list-style-type:circle;margin-top:0.5em}html.theme--catppuccin-latte .content ul ul ul{list-style-type:square}html.theme--catppuccin-latte .content dd{margin-left:2em}html.theme--catppuccin-latte .content figure{margin-left:2em;margin-right:2em;text-align:center}html.theme--catppuccin-latte .content figure:not(:first-child){margin-top:2em}html.theme--catppuccin-latte .content figure:not(:last-child){margin-bottom:2em}html.theme--catppuccin-latte .content figure img{display:inline-block}html.theme--catppuccin-latte .content figure figcaption{font-style:italic}html.theme--catppuccin-latte .content pre{-webkit-overflow-scrolling:touch;overflow-x:auto;padding:0;white-space:pre;word-wrap:normal}html.theme--catppuccin-latte .content sup,html.theme--catppuccin-latte .content sub{font-size:75%}html.theme--catppuccin-latte .content table{width:100%}html.theme--catppuccin-latte .content table td,html.theme--catppuccin-latte .content table th{border:1px solid #acb0be;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--catppuccin-latte .content table th{color:#41445a}html.theme--catppuccin-latte .content table th:not([align]){text-align:inherit}html.theme--catppuccin-latte .content table thead td,html.theme--catppuccin-latte .content table thead th{border-width:0 0 2px;color:#41445a}html.theme--catppuccin-latte .content table tfoot td,html.theme--catppuccin-latte .content table tfoot th{border-width:2px 0 0;color:#41445a}html.theme--catppuccin-latte .content table tbody tr:last-child td,html.theme--catppuccin-latte .content table tbody tr:last-child th{border-bottom-width:0}html.theme--catppuccin-latte .content .tabs li+li{margin-top:0}html.theme--catppuccin-latte .content.is-small,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.content{font-size:.75rem}html.theme--catppuccin-latte .content.is-normal{font-size:1rem}html.theme--catppuccin-latte .content.is-medium{font-size:1.25rem}html.theme--catppuccin-latte .content.is-large{font-size:1.5rem}html.theme--catppuccin-latte .icon{align-items:center;display:inline-flex;justify-content:center;height:1.5rem;width:1.5rem}html.theme--catppuccin-latte .icon.is-small,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.icon{height:1rem;width:1rem}html.theme--catppuccin-latte .icon.is-medium{height:2rem;width:2rem}html.theme--catppuccin-latte .icon.is-large{height:3rem;width:3rem}html.theme--catppuccin-latte .icon-text{align-items:flex-start;color:inherit;display:inline-flex;flex-wrap:wrap;line-height:1.5rem;vertical-align:top}html.theme--catppuccin-latte .icon-text .icon{flex-grow:0;flex-shrink:0}html.theme--catppuccin-latte .icon-text .icon:not(:last-child){margin-right:.25em}html.theme--catppuccin-latte .icon-text .icon:not(:first-child){margin-left:.25em}html.theme--catppuccin-latte div.icon-text{display:flex}html.theme--catppuccin-latte .image,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img{display:block;position:relative}html.theme--catppuccin-latte .image img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img img{display:block;height:auto;width:100%}html.theme--catppuccin-latte .image img.is-rounded,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img img.is-rounded{border-radius:9999px}html.theme--catppuccin-latte .image.is-fullwidth,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-fullwidth{width:100%}html.theme--catppuccin-latte .image.is-square img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--catppuccin-latte .image.is-square .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--catppuccin-latte .image.is-1by1 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--catppuccin-latte .image.is-1by1 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--catppuccin-latte .image.is-5by4 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--catppuccin-latte .image.is-5by4 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--catppuccin-latte .image.is-4by3 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--catppuccin-latte .image.is-4by3 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--catppuccin-latte .image.is-3by2 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--catppuccin-latte .image.is-3by2 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--catppuccin-latte .image.is-5by3 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--catppuccin-latte .image.is-5by3 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--catppuccin-latte .image.is-16by9 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--catppuccin-latte .image.is-16by9 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--catppuccin-latte .image.is-2by1 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--catppuccin-latte .image.is-2by1 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--catppuccin-latte .image.is-3by1 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--catppuccin-latte .image.is-3by1 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--catppuccin-latte .image.is-4by5 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--catppuccin-latte .image.is-4by5 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--catppuccin-latte .image.is-3by4 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--catppuccin-latte .image.is-3by4 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--catppuccin-latte .image.is-2by3 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--catppuccin-latte .image.is-2by3 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--catppuccin-latte .image.is-3by5 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--catppuccin-latte .image.is-3by5 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--catppuccin-latte .image.is-9by16 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--catppuccin-latte .image.is-9by16 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--catppuccin-latte .image.is-1by2 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--catppuccin-latte .image.is-1by2 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--catppuccin-latte .image.is-1by3 img,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--catppuccin-latte .image.is-1by3 .has-ratio,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio{height:100%;width:100%}html.theme--catppuccin-latte .image.is-square,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-square,html.theme--catppuccin-latte .image.is-1by1,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-1by1{padding-top:100%}html.theme--catppuccin-latte .image.is-5by4,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-5by4{padding-top:80%}html.theme--catppuccin-latte .image.is-4by3,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-4by3{padding-top:75%}html.theme--catppuccin-latte .image.is-3by2,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by2{padding-top:66.6666%}html.theme--catppuccin-latte .image.is-5by3,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-5by3{padding-top:60%}html.theme--catppuccin-latte .image.is-16by9,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-16by9{padding-top:56.25%}html.theme--catppuccin-latte .image.is-2by1,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-2by1{padding-top:50%}html.theme--catppuccin-latte .image.is-3by1,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by1{padding-top:33.3333%}html.theme--catppuccin-latte .image.is-4by5,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-4by5{padding-top:125%}html.theme--catppuccin-latte .image.is-3by4,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by4{padding-top:133.3333%}html.theme--catppuccin-latte .image.is-2by3,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-2by3{padding-top:150%}html.theme--catppuccin-latte .image.is-3by5,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-3by5{padding-top:166.6666%}html.theme--catppuccin-latte .image.is-9by16,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-9by16{padding-top:177.7777%}html.theme--catppuccin-latte .image.is-1by2,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-1by2{padding-top:200%}html.theme--catppuccin-latte .image.is-1by3,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-1by3{padding-top:300%}html.theme--catppuccin-latte .image.is-16x16,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-16x16{height:16px;width:16px}html.theme--catppuccin-latte .image.is-24x24,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-24x24{height:24px;width:24px}html.theme--catppuccin-latte .image.is-32x32,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-32x32{height:32px;width:32px}html.theme--catppuccin-latte .image.is-48x48,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-48x48{height:48px;width:48px}html.theme--catppuccin-latte .image.is-64x64,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-64x64{height:64px;width:64px}html.theme--catppuccin-latte .image.is-96x96,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-96x96{height:96px;width:96px}html.theme--catppuccin-latte .image.is-128x128,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img.is-128x128{height:128px;width:128px}html.theme--catppuccin-latte .notification{background-color:#e6e9ef;border-radius:.4em;position:relative;padding:1.25rem 2.5rem 1.25rem 1.5rem}html.theme--catppuccin-latte .notification a:not(.button):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--catppuccin-latte .notification strong{color:currentColor}html.theme--catppuccin-latte .notification code,html.theme--catppuccin-latte .notification pre{background:#fff}html.theme--catppuccin-latte .notification pre code{background:transparent}html.theme--catppuccin-latte .notification>.delete{right:.5rem;position:absolute;top:0.5rem}html.theme--catppuccin-latte .notification .title,html.theme--catppuccin-latte .notification .subtitle,html.theme--catppuccin-latte .notification .content{color:currentColor}html.theme--catppuccin-latte .notification.is-white{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-latte .notification.is-black{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-latte .notification.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .notification.is-dark,html.theme--catppuccin-latte .content kbd.notification{background-color:#ccd0da;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .notification.is-primary,html.theme--catppuccin-latte .docstring>section>a.notification.docs-sourcelink{background-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .notification.is-primary.is-light,html.theme--catppuccin-latte .docstring>section>a.notification.is-light.docs-sourcelink{background-color:#ebf2fe;color:#0a52e1}html.theme--catppuccin-latte .notification.is-link{background-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .notification.is-link.is-light{background-color:#ebf2fe;color:#0a52e1}html.theme--catppuccin-latte .notification.is-info{background-color:#179299;color:#fff}html.theme--catppuccin-latte .notification.is-info.is-light{background-color:#edfcfc;color:#1cb2ba}html.theme--catppuccin-latte .notification.is-success{background-color:#40a02b;color:#fff}html.theme--catppuccin-latte .notification.is-success.is-light{background-color:#f1fbef;color:#40a12b}html.theme--catppuccin-latte .notification.is-warning{background-color:#df8e1d;color:#fff}html.theme--catppuccin-latte .notification.is-warning.is-light{background-color:#fdf6ed;color:#9e6515}html.theme--catppuccin-latte .notification.is-danger{background-color:#d20f39;color:#fff}html.theme--catppuccin-latte .notification.is-danger.is-light{background-color:#feecf0;color:#e9113f}html.theme--catppuccin-latte .progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:9999px;display:block;height:1rem;overflow:hidden;padding:0;width:100%}html.theme--catppuccin-latte .progress::-webkit-progress-bar{background-color:#bcc0cc}html.theme--catppuccin-latte .progress::-webkit-progress-value{background-color:#8c8fa1}html.theme--catppuccin-latte .progress::-moz-progress-bar{background-color:#8c8fa1}html.theme--catppuccin-latte .progress::-ms-fill{background-color:#8c8fa1;border:none}html.theme--catppuccin-latte .progress.is-white::-webkit-progress-value{background-color:#fff}html.theme--catppuccin-latte .progress.is-white::-moz-progress-bar{background-color:#fff}html.theme--catppuccin-latte .progress.is-white::-ms-fill{background-color:#fff}html.theme--catppuccin-latte .progress.is-white:indeterminate{background-image:linear-gradient(to right, #fff 30%, #bcc0cc 30%)}html.theme--catppuccin-latte .progress.is-black::-webkit-progress-value{background-color:#0a0a0a}html.theme--catppuccin-latte .progress.is-black::-moz-progress-bar{background-color:#0a0a0a}html.theme--catppuccin-latte .progress.is-black::-ms-fill{background-color:#0a0a0a}html.theme--catppuccin-latte .progress.is-black:indeterminate{background-image:linear-gradient(to right, #0a0a0a 30%, #bcc0cc 30%)}html.theme--catppuccin-latte .progress.is-light::-webkit-progress-value{background-color:#f5f5f5}html.theme--catppuccin-latte .progress.is-light::-moz-progress-bar{background-color:#f5f5f5}html.theme--catppuccin-latte .progress.is-light::-ms-fill{background-color:#f5f5f5}html.theme--catppuccin-latte .progress.is-light:indeterminate{background-image:linear-gradient(to right, #f5f5f5 30%, #bcc0cc 30%)}html.theme--catppuccin-latte .progress.is-dark::-webkit-progress-value,html.theme--catppuccin-latte .content kbd.progress::-webkit-progress-value{background-color:#ccd0da}html.theme--catppuccin-latte .progress.is-dark::-moz-progress-bar,html.theme--catppuccin-latte .content kbd.progress::-moz-progress-bar{background-color:#ccd0da}html.theme--catppuccin-latte .progress.is-dark::-ms-fill,html.theme--catppuccin-latte .content kbd.progress::-ms-fill{background-color:#ccd0da}html.theme--catppuccin-latte .progress.is-dark:indeterminate,html.theme--catppuccin-latte .content kbd.progress:indeterminate{background-image:linear-gradient(to right, #ccd0da 30%, #bcc0cc 30%)}html.theme--catppuccin-latte .progress.is-primary::-webkit-progress-value,html.theme--catppuccin-latte .docstring>section>a.progress.docs-sourcelink::-webkit-progress-value{background-color:#1e66f5}html.theme--catppuccin-latte .progress.is-primary::-moz-progress-bar,html.theme--catppuccin-latte .docstring>section>a.progress.docs-sourcelink::-moz-progress-bar{background-color:#1e66f5}html.theme--catppuccin-latte .progress.is-primary::-ms-fill,html.theme--catppuccin-latte .docstring>section>a.progress.docs-sourcelink::-ms-fill{background-color:#1e66f5}html.theme--catppuccin-latte .progress.is-primary:indeterminate,html.theme--catppuccin-latte .docstring>section>a.progress.docs-sourcelink:indeterminate{background-image:linear-gradient(to right, #1e66f5 30%, #bcc0cc 30%)}html.theme--catppuccin-latte .progress.is-link::-webkit-progress-value{background-color:#1e66f5}html.theme--catppuccin-latte .progress.is-link::-moz-progress-bar{background-color:#1e66f5}html.theme--catppuccin-latte .progress.is-link::-ms-fill{background-color:#1e66f5}html.theme--catppuccin-latte .progress.is-link:indeterminate{background-image:linear-gradient(to right, #1e66f5 30%, #bcc0cc 30%)}html.theme--catppuccin-latte .progress.is-info::-webkit-progress-value{background-color:#179299}html.theme--catppuccin-latte .progress.is-info::-moz-progress-bar{background-color:#179299}html.theme--catppuccin-latte .progress.is-info::-ms-fill{background-color:#179299}html.theme--catppuccin-latte .progress.is-info:indeterminate{background-image:linear-gradient(to right, #179299 30%, #bcc0cc 30%)}html.theme--catppuccin-latte .progress.is-success::-webkit-progress-value{background-color:#40a02b}html.theme--catppuccin-latte .progress.is-success::-moz-progress-bar{background-color:#40a02b}html.theme--catppuccin-latte .progress.is-success::-ms-fill{background-color:#40a02b}html.theme--catppuccin-latte .progress.is-success:indeterminate{background-image:linear-gradient(to right, #40a02b 30%, #bcc0cc 30%)}html.theme--catppuccin-latte .progress.is-warning::-webkit-progress-value{background-color:#df8e1d}html.theme--catppuccin-latte .progress.is-warning::-moz-progress-bar{background-color:#df8e1d}html.theme--catppuccin-latte .progress.is-warning::-ms-fill{background-color:#df8e1d}html.theme--catppuccin-latte .progress.is-warning:indeterminate{background-image:linear-gradient(to right, #df8e1d 30%, #bcc0cc 30%)}html.theme--catppuccin-latte .progress.is-danger::-webkit-progress-value{background-color:#d20f39}html.theme--catppuccin-latte .progress.is-danger::-moz-progress-bar{background-color:#d20f39}html.theme--catppuccin-latte .progress.is-danger::-ms-fill{background-color:#d20f39}html.theme--catppuccin-latte .progress.is-danger:indeterminate{background-image:linear-gradient(to right, #d20f39 30%, #bcc0cc 30%)}html.theme--catppuccin-latte .progress:indeterminate{animation-duration:1.5s;animation-iteration-count:infinite;animation-name:moveIndeterminate;animation-timing-function:linear;background-color:#bcc0cc;background-image:linear-gradient(to right, #4c4f69 30%, #bcc0cc 30%);background-position:top left;background-repeat:no-repeat;background-size:150% 150%}html.theme--catppuccin-latte .progress:indeterminate::-webkit-progress-bar{background-color:transparent}html.theme--catppuccin-latte .progress:indeterminate::-moz-progress-bar{background-color:transparent}html.theme--catppuccin-latte .progress:indeterminate::-ms-fill{animation-name:none}html.theme--catppuccin-latte .progress.is-small,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.progress{height:.75rem}html.theme--catppuccin-latte .progress.is-medium{height:1.25rem}html.theme--catppuccin-latte .progress.is-large{height:1.5rem}@keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}html.theme--catppuccin-latte .table{background-color:#bcc0cc;color:#4c4f69}html.theme--catppuccin-latte .table td,html.theme--catppuccin-latte .table th{border:1px solid #acb0be;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--catppuccin-latte .table td.is-white,html.theme--catppuccin-latte .table th.is-white{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--catppuccin-latte .table td.is-black,html.theme--catppuccin-latte .table th.is-black{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--catppuccin-latte .table td.is-light,html.theme--catppuccin-latte .table th.is-light{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .table td.is-dark,html.theme--catppuccin-latte .table th.is-dark{background-color:#ccd0da;border-color:#ccd0da;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .table td.is-primary,html.theme--catppuccin-latte .table th.is-primary{background-color:#1e66f5;border-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .table td.is-link,html.theme--catppuccin-latte .table th.is-link{background-color:#1e66f5;border-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .table td.is-info,html.theme--catppuccin-latte .table th.is-info{background-color:#179299;border-color:#179299;color:#fff}html.theme--catppuccin-latte .table td.is-success,html.theme--catppuccin-latte .table th.is-success{background-color:#40a02b;border-color:#40a02b;color:#fff}html.theme--catppuccin-latte .table td.is-warning,html.theme--catppuccin-latte .table th.is-warning{background-color:#df8e1d;border-color:#df8e1d;color:#fff}html.theme--catppuccin-latte .table td.is-danger,html.theme--catppuccin-latte .table th.is-danger{background-color:#d20f39;border-color:#d20f39;color:#fff}html.theme--catppuccin-latte .table td.is-narrow,html.theme--catppuccin-latte .table th.is-narrow{white-space:nowrap;width:1%}html.theme--catppuccin-latte .table td.is-selected,html.theme--catppuccin-latte .table th.is-selected{background-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .table td.is-selected a,html.theme--catppuccin-latte .table td.is-selected strong,html.theme--catppuccin-latte .table th.is-selected a,html.theme--catppuccin-latte .table th.is-selected strong{color:currentColor}html.theme--catppuccin-latte .table td.is-vcentered,html.theme--catppuccin-latte .table th.is-vcentered{vertical-align:middle}html.theme--catppuccin-latte .table th{color:#41445a}html.theme--catppuccin-latte .table th:not([align]){text-align:left}html.theme--catppuccin-latte .table tr.is-selected{background-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .table tr.is-selected a,html.theme--catppuccin-latte .table tr.is-selected strong{color:currentColor}html.theme--catppuccin-latte .table tr.is-selected td,html.theme--catppuccin-latte .table tr.is-selected th{border-color:#fff;color:currentColor}html.theme--catppuccin-latte .table thead{background-color:rgba(0,0,0,0)}html.theme--catppuccin-latte .table thead td,html.theme--catppuccin-latte .table thead th{border-width:0 0 2px;color:#41445a}html.theme--catppuccin-latte .table tfoot{background-color:rgba(0,0,0,0)}html.theme--catppuccin-latte .table tfoot td,html.theme--catppuccin-latte .table tfoot th{border-width:2px 0 0;color:#41445a}html.theme--catppuccin-latte .table tbody{background-color:rgba(0,0,0,0)}html.theme--catppuccin-latte .table tbody tr:last-child td,html.theme--catppuccin-latte .table tbody tr:last-child th{border-bottom-width:0}html.theme--catppuccin-latte .table.is-bordered td,html.theme--catppuccin-latte .table.is-bordered th{border-width:1px}html.theme--catppuccin-latte .table.is-bordered tr:last-child td,html.theme--catppuccin-latte .table.is-bordered tr:last-child th{border-bottom-width:1px}html.theme--catppuccin-latte .table.is-fullwidth{width:100%}html.theme--catppuccin-latte .table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#ccd0da}html.theme--catppuccin-latte .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover{background-color:#ccd0da}html.theme--catppuccin-latte .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even){background-color:#d2d5de}html.theme--catppuccin-latte .table.is-narrow td,html.theme--catppuccin-latte .table.is-narrow th{padding:0.25em 0.5em}html.theme--catppuccin-latte .table.is-striped tbody tr:not(.is-selected):nth-child(even){background-color:#ccd0da}html.theme--catppuccin-latte .table-container{-webkit-overflow-scrolling:touch;overflow:auto;overflow-y:hidden;max-width:100%}html.theme--catppuccin-latte .tags{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--catppuccin-latte .tags .tag,html.theme--catppuccin-latte .tags .content kbd,html.theme--catppuccin-latte .content .tags kbd,html.theme--catppuccin-latte .tags .docstring>section>a.docs-sourcelink{margin-bottom:0.5rem}html.theme--catppuccin-latte .tags .tag:not(:last-child),html.theme--catppuccin-latte .tags .content kbd:not(:last-child),html.theme--catppuccin-latte .content .tags kbd:not(:last-child),html.theme--catppuccin-latte .tags .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:.5rem}html.theme--catppuccin-latte .tags:last-child{margin-bottom:-0.5rem}html.theme--catppuccin-latte .tags:not(:last-child){margin-bottom:1rem}html.theme--catppuccin-latte .tags.are-medium .tag:not(.is-normal):not(.is-large),html.theme--catppuccin-latte .tags.are-medium .content kbd:not(.is-normal):not(.is-large),html.theme--catppuccin-latte .content .tags.are-medium kbd:not(.is-normal):not(.is-large),html.theme--catppuccin-latte .tags.are-medium .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-large){font-size:1rem}html.theme--catppuccin-latte .tags.are-large .tag:not(.is-normal):not(.is-medium),html.theme--catppuccin-latte .tags.are-large .content kbd:not(.is-normal):not(.is-medium),html.theme--catppuccin-latte .content .tags.are-large kbd:not(.is-normal):not(.is-medium),html.theme--catppuccin-latte .tags.are-large .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-medium){font-size:1.25rem}html.theme--catppuccin-latte .tags.is-centered{justify-content:center}html.theme--catppuccin-latte .tags.is-centered .tag,html.theme--catppuccin-latte .tags.is-centered .content kbd,html.theme--catppuccin-latte .content .tags.is-centered kbd,html.theme--catppuccin-latte .tags.is-centered .docstring>section>a.docs-sourcelink{margin-right:0.25rem;margin-left:0.25rem}html.theme--catppuccin-latte .tags.is-right{justify-content:flex-end}html.theme--catppuccin-latte .tags.is-right .tag:not(:first-child),html.theme--catppuccin-latte .tags.is-right .content kbd:not(:first-child),html.theme--catppuccin-latte .content .tags.is-right kbd:not(:first-child),html.theme--catppuccin-latte .tags.is-right .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0.5rem}html.theme--catppuccin-latte .tags.is-right .tag:not(:last-child),html.theme--catppuccin-latte .tags.is-right .content kbd:not(:last-child),html.theme--catppuccin-latte .content .tags.is-right kbd:not(:last-child),html.theme--catppuccin-latte .tags.is-right .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:0}html.theme--catppuccin-latte .tags.has-addons .tag,html.theme--catppuccin-latte .tags.has-addons .content kbd,html.theme--catppuccin-latte .content .tags.has-addons kbd,html.theme--catppuccin-latte .tags.has-addons .docstring>section>a.docs-sourcelink{margin-right:0}html.theme--catppuccin-latte .tags.has-addons .tag:not(:first-child),html.theme--catppuccin-latte .tags.has-addons .content kbd:not(:first-child),html.theme--catppuccin-latte .content .tags.has-addons kbd:not(:first-child),html.theme--catppuccin-latte .tags.has-addons .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0;border-top-left-radius:0;border-bottom-left-radius:0}html.theme--catppuccin-latte .tags.has-addons .tag:not(:last-child),html.theme--catppuccin-latte .tags.has-addons .content kbd:not(:last-child),html.theme--catppuccin-latte .content .tags.has-addons kbd:not(:last-child),html.theme--catppuccin-latte .tags.has-addons .docstring>section>a.docs-sourcelink:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}html.theme--catppuccin-latte .tag:not(body),html.theme--catppuccin-latte .content kbd:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink:not(body){align-items:center;background-color:#e6e9ef;border-radius:.4em;color:#4c4f69;display:inline-flex;font-size:.75rem;height:2em;justify-content:center;line-height:1.5;padding-left:0.75em;padding-right:0.75em;white-space:nowrap}html.theme--catppuccin-latte .tag:not(body) .delete,html.theme--catppuccin-latte .content kbd:not(body) .delete,html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink:not(body) .delete{margin-left:.25rem;margin-right:-.375rem}html.theme--catppuccin-latte .tag.is-white:not(body),html.theme--catppuccin-latte .content kbd.is-white:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-white:not(body){background-color:#fff;color:#0a0a0a}html.theme--catppuccin-latte .tag.is-black:not(body),html.theme--catppuccin-latte .content kbd.is-black:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-black:not(body){background-color:#0a0a0a;color:#fff}html.theme--catppuccin-latte .tag.is-light:not(body),html.theme--catppuccin-latte .content kbd.is-light:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .tag.is-dark:not(body),html.theme--catppuccin-latte .content kbd:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-dark:not(body),html.theme--catppuccin-latte .content .docstring>section>kbd:not(body){background-color:#ccd0da;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .tag.is-primary:not(body),html.theme--catppuccin-latte .content kbd.is-primary:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink:not(body){background-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .tag.is-primary.is-light:not(body),html.theme--catppuccin-latte .content kbd.is-primary.is-light:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#ebf2fe;color:#0a52e1}html.theme--catppuccin-latte .tag.is-link:not(body),html.theme--catppuccin-latte .content kbd.is-link:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-link:not(body){background-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .tag.is-link.is-light:not(body),html.theme--catppuccin-latte .content kbd.is-link.is-light:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-link.is-light:not(body){background-color:#ebf2fe;color:#0a52e1}html.theme--catppuccin-latte .tag.is-info:not(body),html.theme--catppuccin-latte .content kbd.is-info:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-info:not(body){background-color:#179299;color:#fff}html.theme--catppuccin-latte .tag.is-info.is-light:not(body),html.theme--catppuccin-latte .content kbd.is-info.is-light:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-info.is-light:not(body){background-color:#edfcfc;color:#1cb2ba}html.theme--catppuccin-latte .tag.is-success:not(body),html.theme--catppuccin-latte .content kbd.is-success:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-success:not(body){background-color:#40a02b;color:#fff}html.theme--catppuccin-latte .tag.is-success.is-light:not(body),html.theme--catppuccin-latte .content kbd.is-success.is-light:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-success.is-light:not(body){background-color:#f1fbef;color:#40a12b}html.theme--catppuccin-latte .tag.is-warning:not(body),html.theme--catppuccin-latte .content kbd.is-warning:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-warning:not(body){background-color:#df8e1d;color:#fff}html.theme--catppuccin-latte .tag.is-warning.is-light:not(body),html.theme--catppuccin-latte .content kbd.is-warning.is-light:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-warning.is-light:not(body){background-color:#fdf6ed;color:#9e6515}html.theme--catppuccin-latte .tag.is-danger:not(body),html.theme--catppuccin-latte .content kbd.is-danger:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-danger:not(body){background-color:#d20f39;color:#fff}html.theme--catppuccin-latte .tag.is-danger.is-light:not(body),html.theme--catppuccin-latte .content kbd.is-danger.is-light:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-danger.is-light:not(body){background-color:#feecf0;color:#e9113f}html.theme--catppuccin-latte .tag.is-normal:not(body),html.theme--catppuccin-latte .content kbd.is-normal:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-normal:not(body){font-size:.75rem}html.theme--catppuccin-latte .tag.is-medium:not(body),html.theme--catppuccin-latte .content kbd.is-medium:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-medium:not(body){font-size:1rem}html.theme--catppuccin-latte .tag.is-large:not(body),html.theme--catppuccin-latte .content kbd.is-large:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-large:not(body){font-size:1.25rem}html.theme--catppuccin-latte .tag:not(body) .icon:first-child:not(:last-child),html.theme--catppuccin-latte .content kbd:not(body) .icon:first-child:not(:last-child),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:not(:last-child){margin-left:-.375em;margin-right:.1875em}html.theme--catppuccin-latte .tag:not(body) .icon:last-child:not(:first-child),html.theme--catppuccin-latte .content kbd:not(body) .icon:last-child:not(:first-child),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink:not(body) .icon:last-child:not(:first-child){margin-left:.1875em;margin-right:-.375em}html.theme--catppuccin-latte .tag:not(body) .icon:first-child:last-child,html.theme--catppuccin-latte .content kbd:not(body) .icon:first-child:last-child,html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:last-child{margin-left:-.375em;margin-right:-.375em}html.theme--catppuccin-latte .tag.is-delete:not(body),html.theme--catppuccin-latte .content kbd.is-delete:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-delete:not(body){margin-left:1px;padding:0;position:relative;width:2em}html.theme--catppuccin-latte .tag.is-delete:not(body)::before,html.theme--catppuccin-latte .content kbd.is-delete:not(body)::before,html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-delete:not(body)::before,html.theme--catppuccin-latte .tag.is-delete:not(body)::after,html.theme--catppuccin-latte .content kbd.is-delete:not(body)::after,html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{background-color:currentColor;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--catppuccin-latte .tag.is-delete:not(body)::before,html.theme--catppuccin-latte .content kbd.is-delete:not(body)::before,html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-delete:not(body)::before{height:1px;width:50%}html.theme--catppuccin-latte .tag.is-delete:not(body)::after,html.theme--catppuccin-latte .content kbd.is-delete:not(body)::after,html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{height:50%;width:1px}html.theme--catppuccin-latte .tag.is-delete:not(body):hover,html.theme--catppuccin-latte .content kbd.is-delete:not(body):hover,html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-delete:not(body):hover,html.theme--catppuccin-latte .tag.is-delete:not(body):focus,html.theme--catppuccin-latte .content kbd.is-delete:not(body):focus,html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-delete:not(body):focus{background-color:#d6dbe5}html.theme--catppuccin-latte .tag.is-delete:not(body):active,html.theme--catppuccin-latte .content kbd.is-delete:not(body):active,html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-delete:not(body):active{background-color:#c7cedb}html.theme--catppuccin-latte .tag.is-rounded:not(body),html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input:not(body),html.theme--catppuccin-latte .content kbd.is-rounded:not(body),html.theme--catppuccin-latte #documenter .docs-sidebar .content form.docs-search>input:not(body),html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink.is-rounded:not(body){border-radius:9999px}html.theme--catppuccin-latte a.tag:hover,html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink:hover{text-decoration:underline}html.theme--catppuccin-latte .title,html.theme--catppuccin-latte .subtitle{word-break:break-word}html.theme--catppuccin-latte .title em,html.theme--catppuccin-latte .title span,html.theme--catppuccin-latte .subtitle em,html.theme--catppuccin-latte .subtitle span{font-weight:inherit}html.theme--catppuccin-latte .title sub,html.theme--catppuccin-latte .subtitle sub{font-size:.75em}html.theme--catppuccin-latte .title sup,html.theme--catppuccin-latte .subtitle sup{font-size:.75em}html.theme--catppuccin-latte .title .tag,html.theme--catppuccin-latte .title .content kbd,html.theme--catppuccin-latte .content .title kbd,html.theme--catppuccin-latte .title .docstring>section>a.docs-sourcelink,html.theme--catppuccin-latte .subtitle .tag,html.theme--catppuccin-latte .subtitle .content kbd,html.theme--catppuccin-latte .content .subtitle kbd,html.theme--catppuccin-latte .subtitle .docstring>section>a.docs-sourcelink{vertical-align:middle}html.theme--catppuccin-latte .title{color:#fff;font-size:2rem;font-weight:500;line-height:1.125}html.theme--catppuccin-latte .title strong{color:inherit;font-weight:inherit}html.theme--catppuccin-latte .title:not(.is-spaced)+.subtitle{margin-top:-1.25rem}html.theme--catppuccin-latte .title.is-1{font-size:3rem}html.theme--catppuccin-latte .title.is-2{font-size:2.5rem}html.theme--catppuccin-latte .title.is-3{font-size:2rem}html.theme--catppuccin-latte .title.is-4{font-size:1.5rem}html.theme--catppuccin-latte .title.is-5{font-size:1.25rem}html.theme--catppuccin-latte .title.is-6{font-size:1rem}html.theme--catppuccin-latte .title.is-7{font-size:.75rem}html.theme--catppuccin-latte .subtitle{color:#9ca0b0;font-size:1.25rem;font-weight:400;line-height:1.25}html.theme--catppuccin-latte .subtitle strong{color:#9ca0b0;font-weight:600}html.theme--catppuccin-latte .subtitle:not(.is-spaced)+.title{margin-top:-1.25rem}html.theme--catppuccin-latte .subtitle.is-1{font-size:3rem}html.theme--catppuccin-latte .subtitle.is-2{font-size:2.5rem}html.theme--catppuccin-latte .subtitle.is-3{font-size:2rem}html.theme--catppuccin-latte .subtitle.is-4{font-size:1.5rem}html.theme--catppuccin-latte .subtitle.is-5{font-size:1.25rem}html.theme--catppuccin-latte .subtitle.is-6{font-size:1rem}html.theme--catppuccin-latte .subtitle.is-7{font-size:.75rem}html.theme--catppuccin-latte .heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}html.theme--catppuccin-latte .number{align-items:center;background-color:#e6e9ef;border-radius:9999px;display:inline-flex;font-size:1.25rem;height:2em;justify-content:center;margin-right:1.5rem;min-width:2.5em;padding:0.25rem 0.5rem;text-align:center;vertical-align:top}html.theme--catppuccin-latte .select select,html.theme--catppuccin-latte .textarea,html.theme--catppuccin-latte .input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input{background-color:#eff1f5;border-color:#acb0be;border-radius:.4em;color:#8c8fa1}html.theme--catppuccin-latte .select select::-moz-placeholder,html.theme--catppuccin-latte .textarea::-moz-placeholder,html.theme--catppuccin-latte .input::-moz-placeholder,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:#868c98}html.theme--catppuccin-latte .select select::-webkit-input-placeholder,html.theme--catppuccin-latte .textarea::-webkit-input-placeholder,html.theme--catppuccin-latte .input::-webkit-input-placeholder,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:#868c98}html.theme--catppuccin-latte .select select:-moz-placeholder,html.theme--catppuccin-latte .textarea:-moz-placeholder,html.theme--catppuccin-latte .input:-moz-placeholder,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:#868c98}html.theme--catppuccin-latte .select select:-ms-input-placeholder,html.theme--catppuccin-latte .textarea:-ms-input-placeholder,html.theme--catppuccin-latte .input:-ms-input-placeholder,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:#868c98}html.theme--catppuccin-latte .select select:hover,html.theme--catppuccin-latte .textarea:hover,html.theme--catppuccin-latte .input:hover,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input:hover,html.theme--catppuccin-latte .select select.is-hovered,html.theme--catppuccin-latte .is-hovered.textarea,html.theme--catppuccin-latte .is-hovered.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-hovered{border-color:#9ca0b0}html.theme--catppuccin-latte .select select:focus,html.theme--catppuccin-latte .textarea:focus,html.theme--catppuccin-latte .input:focus,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input:focus,html.theme--catppuccin-latte .select select.is-focused,html.theme--catppuccin-latte .is-focused.textarea,html.theme--catppuccin-latte .is-focused.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-latte .select select:active,html.theme--catppuccin-latte .textarea:active,html.theme--catppuccin-latte .input:active,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input:active,html.theme--catppuccin-latte .select select.is-active,html.theme--catppuccin-latte .is-active.textarea,html.theme--catppuccin-latte .is-active.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-active{border-color:#1e66f5;box-shadow:0 0 0 0.125em rgba(30,102,245,0.25)}html.theme--catppuccin-latte .select select[disabled],html.theme--catppuccin-latte .textarea[disabled],html.theme--catppuccin-latte .input[disabled],html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input[disabled],fieldset[disabled] html.theme--catppuccin-latte .select select,fieldset[disabled] html.theme--catppuccin-latte .textarea,fieldset[disabled] html.theme--catppuccin-latte .input,fieldset[disabled] html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input{background-color:#9ca0b0;border-color:#e6e9ef;box-shadow:none;color:#616587}html.theme--catppuccin-latte .select select[disabled]::-moz-placeholder,html.theme--catppuccin-latte .textarea[disabled]::-moz-placeholder,html.theme--catppuccin-latte .input[disabled]::-moz-placeholder,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input[disabled]::-moz-placeholder,fieldset[disabled] html.theme--catppuccin-latte .select select::-moz-placeholder,fieldset[disabled] html.theme--catppuccin-latte .textarea::-moz-placeholder,fieldset[disabled] html.theme--catppuccin-latte .input::-moz-placeholder,fieldset[disabled] html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:rgba(97,101,135,0.3)}html.theme--catppuccin-latte .select select[disabled]::-webkit-input-placeholder,html.theme--catppuccin-latte .textarea[disabled]::-webkit-input-placeholder,html.theme--catppuccin-latte .input[disabled]::-webkit-input-placeholder,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input[disabled]::-webkit-input-placeholder,fieldset[disabled] html.theme--catppuccin-latte .select select::-webkit-input-placeholder,fieldset[disabled] html.theme--catppuccin-latte .textarea::-webkit-input-placeholder,fieldset[disabled] html.theme--catppuccin-latte .input::-webkit-input-placeholder,fieldset[disabled] html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:rgba(97,101,135,0.3)}html.theme--catppuccin-latte .select select[disabled]:-moz-placeholder,html.theme--catppuccin-latte .textarea[disabled]:-moz-placeholder,html.theme--catppuccin-latte .input[disabled]:-moz-placeholder,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input[disabled]:-moz-placeholder,fieldset[disabled] html.theme--catppuccin-latte .select select:-moz-placeholder,fieldset[disabled] html.theme--catppuccin-latte .textarea:-moz-placeholder,fieldset[disabled] html.theme--catppuccin-latte .input:-moz-placeholder,fieldset[disabled] html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:rgba(97,101,135,0.3)}html.theme--catppuccin-latte .select select[disabled]:-ms-input-placeholder,html.theme--catppuccin-latte .textarea[disabled]:-ms-input-placeholder,html.theme--catppuccin-latte .input[disabled]:-ms-input-placeholder,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input[disabled]:-ms-input-placeholder,fieldset[disabled] html.theme--catppuccin-latte .select select:-ms-input-placeholder,fieldset[disabled] html.theme--catppuccin-latte .textarea:-ms-input-placeholder,fieldset[disabled] html.theme--catppuccin-latte .input:-ms-input-placeholder,fieldset[disabled] html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:rgba(97,101,135,0.3)}html.theme--catppuccin-latte .textarea,html.theme--catppuccin-latte .input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input{box-shadow:inset 0 0.0625em 0.125em rgba(10,10,10,0.05);max-width:100%;width:100%}html.theme--catppuccin-latte .textarea[readonly],html.theme--catppuccin-latte .input[readonly],html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input[readonly]{box-shadow:none}html.theme--catppuccin-latte .is-white.textarea,html.theme--catppuccin-latte .is-white.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-white{border-color:#fff}html.theme--catppuccin-latte .is-white.textarea:focus,html.theme--catppuccin-latte .is-white.input:focus,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-white:focus,html.theme--catppuccin-latte .is-white.is-focused.textarea,html.theme--catppuccin-latte .is-white.is-focused.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-latte .is-white.textarea:active,html.theme--catppuccin-latte .is-white.input:active,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-white:active,html.theme--catppuccin-latte .is-white.is-active.textarea,html.theme--catppuccin-latte .is-white.is-active.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--catppuccin-latte .is-black.textarea,html.theme--catppuccin-latte .is-black.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-black{border-color:#0a0a0a}html.theme--catppuccin-latte .is-black.textarea:focus,html.theme--catppuccin-latte .is-black.input:focus,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-black:focus,html.theme--catppuccin-latte .is-black.is-focused.textarea,html.theme--catppuccin-latte .is-black.is-focused.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-latte .is-black.textarea:active,html.theme--catppuccin-latte .is-black.input:active,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-black:active,html.theme--catppuccin-latte .is-black.is-active.textarea,html.theme--catppuccin-latte .is-black.is-active.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--catppuccin-latte .is-light.textarea,html.theme--catppuccin-latte .is-light.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-light{border-color:#f5f5f5}html.theme--catppuccin-latte .is-light.textarea:focus,html.theme--catppuccin-latte .is-light.input:focus,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-light:focus,html.theme--catppuccin-latte .is-light.is-focused.textarea,html.theme--catppuccin-latte .is-light.is-focused.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-latte .is-light.textarea:active,html.theme--catppuccin-latte .is-light.input:active,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-light:active,html.theme--catppuccin-latte .is-light.is-active.textarea,html.theme--catppuccin-latte .is-light.is-active.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}html.theme--catppuccin-latte .is-dark.textarea,html.theme--catppuccin-latte .content kbd.textarea,html.theme--catppuccin-latte .is-dark.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-dark,html.theme--catppuccin-latte .content kbd.input{border-color:#ccd0da}html.theme--catppuccin-latte .is-dark.textarea:focus,html.theme--catppuccin-latte .content kbd.textarea:focus,html.theme--catppuccin-latte .is-dark.input:focus,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-dark:focus,html.theme--catppuccin-latte .content kbd.input:focus,html.theme--catppuccin-latte .is-dark.is-focused.textarea,html.theme--catppuccin-latte .content kbd.is-focused.textarea,html.theme--catppuccin-latte .is-dark.is-focused.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-latte .content kbd.is-focused.input,html.theme--catppuccin-latte #documenter .docs-sidebar .content form.docs-search>input.is-focused,html.theme--catppuccin-latte .is-dark.textarea:active,html.theme--catppuccin-latte .content kbd.textarea:active,html.theme--catppuccin-latte .is-dark.input:active,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-dark:active,html.theme--catppuccin-latte .content kbd.input:active,html.theme--catppuccin-latte .is-dark.is-active.textarea,html.theme--catppuccin-latte .content kbd.is-active.textarea,html.theme--catppuccin-latte .is-dark.is-active.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--catppuccin-latte .content kbd.is-active.input,html.theme--catppuccin-latte #documenter .docs-sidebar .content form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(204,208,218,0.25)}html.theme--catppuccin-latte .is-primary.textarea,html.theme--catppuccin-latte .docstring>section>a.textarea.docs-sourcelink,html.theme--catppuccin-latte .is-primary.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-primary,html.theme--catppuccin-latte .docstring>section>a.input.docs-sourcelink{border-color:#1e66f5}html.theme--catppuccin-latte .is-primary.textarea:focus,html.theme--catppuccin-latte .docstring>section>a.textarea.docs-sourcelink:focus,html.theme--catppuccin-latte .is-primary.input:focus,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-primary:focus,html.theme--catppuccin-latte .docstring>section>a.input.docs-sourcelink:focus,html.theme--catppuccin-latte .is-primary.is-focused.textarea,html.theme--catppuccin-latte .docstring>section>a.is-focused.textarea.docs-sourcelink,html.theme--catppuccin-latte .is-primary.is-focused.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-latte .docstring>section>a.is-focused.input.docs-sourcelink,html.theme--catppuccin-latte .is-primary.textarea:active,html.theme--catppuccin-latte .docstring>section>a.textarea.docs-sourcelink:active,html.theme--catppuccin-latte .is-primary.input:active,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-primary:active,html.theme--catppuccin-latte .docstring>section>a.input.docs-sourcelink:active,html.theme--catppuccin-latte .is-primary.is-active.textarea,html.theme--catppuccin-latte .docstring>section>a.is-active.textarea.docs-sourcelink,html.theme--catppuccin-latte .is-primary.is-active.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--catppuccin-latte .docstring>section>a.is-active.input.docs-sourcelink{box-shadow:0 0 0 0.125em rgba(30,102,245,0.25)}html.theme--catppuccin-latte .is-link.textarea,html.theme--catppuccin-latte .is-link.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-link{border-color:#1e66f5}html.theme--catppuccin-latte .is-link.textarea:focus,html.theme--catppuccin-latte .is-link.input:focus,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-link:focus,html.theme--catppuccin-latte .is-link.is-focused.textarea,html.theme--catppuccin-latte .is-link.is-focused.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-latte .is-link.textarea:active,html.theme--catppuccin-latte .is-link.input:active,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-link:active,html.theme--catppuccin-latte .is-link.is-active.textarea,html.theme--catppuccin-latte .is-link.is-active.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(30,102,245,0.25)}html.theme--catppuccin-latte .is-info.textarea,html.theme--catppuccin-latte .is-info.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-info{border-color:#179299}html.theme--catppuccin-latte .is-info.textarea:focus,html.theme--catppuccin-latte .is-info.input:focus,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-info:focus,html.theme--catppuccin-latte .is-info.is-focused.textarea,html.theme--catppuccin-latte .is-info.is-focused.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-latte .is-info.textarea:active,html.theme--catppuccin-latte .is-info.input:active,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-info:active,html.theme--catppuccin-latte .is-info.is-active.textarea,html.theme--catppuccin-latte .is-info.is-active.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(23,146,153,0.25)}html.theme--catppuccin-latte .is-success.textarea,html.theme--catppuccin-latte .is-success.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-success{border-color:#40a02b}html.theme--catppuccin-latte .is-success.textarea:focus,html.theme--catppuccin-latte .is-success.input:focus,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-success:focus,html.theme--catppuccin-latte .is-success.is-focused.textarea,html.theme--catppuccin-latte .is-success.is-focused.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-latte .is-success.textarea:active,html.theme--catppuccin-latte .is-success.input:active,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-success:active,html.theme--catppuccin-latte .is-success.is-active.textarea,html.theme--catppuccin-latte .is-success.is-active.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(64,160,43,0.25)}html.theme--catppuccin-latte .is-warning.textarea,html.theme--catppuccin-latte .is-warning.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-warning{border-color:#df8e1d}html.theme--catppuccin-latte .is-warning.textarea:focus,html.theme--catppuccin-latte .is-warning.input:focus,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-warning:focus,html.theme--catppuccin-latte .is-warning.is-focused.textarea,html.theme--catppuccin-latte .is-warning.is-focused.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-latte .is-warning.textarea:active,html.theme--catppuccin-latte .is-warning.input:active,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-warning:active,html.theme--catppuccin-latte .is-warning.is-active.textarea,html.theme--catppuccin-latte .is-warning.is-active.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(223,142,29,0.25)}html.theme--catppuccin-latte .is-danger.textarea,html.theme--catppuccin-latte .is-danger.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-danger{border-color:#d20f39}html.theme--catppuccin-latte .is-danger.textarea:focus,html.theme--catppuccin-latte .is-danger.input:focus,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-danger:focus,html.theme--catppuccin-latte .is-danger.is-focused.textarea,html.theme--catppuccin-latte .is-danger.is-focused.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-latte .is-danger.textarea:active,html.theme--catppuccin-latte .is-danger.input:active,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-danger:active,html.theme--catppuccin-latte .is-danger.is-active.textarea,html.theme--catppuccin-latte .is-danger.is-active.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(210,15,57,0.25)}html.theme--catppuccin-latte .is-small.textarea,html.theme--catppuccin-latte .is-small.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input{border-radius:3px;font-size:.75rem}html.theme--catppuccin-latte .is-medium.textarea,html.theme--catppuccin-latte .is-medium.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-medium{font-size:1.25rem}html.theme--catppuccin-latte .is-large.textarea,html.theme--catppuccin-latte .is-large.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-large{font-size:1.5rem}html.theme--catppuccin-latte .is-fullwidth.textarea,html.theme--catppuccin-latte .is-fullwidth.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-fullwidth{display:block;width:100%}html.theme--catppuccin-latte .is-inline.textarea,html.theme--catppuccin-latte .is-inline.input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-inline{display:inline;width:auto}html.theme--catppuccin-latte .input.is-rounded,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input{border-radius:9999px;padding-left:calc(calc(0.75em - 1px) + 0.375em);padding-right:calc(calc(0.75em - 1px) + 0.375em)}html.theme--catppuccin-latte .input.is-static,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-static{background-color:transparent;border-color:transparent;box-shadow:none;padding-left:0;padding-right:0}html.theme--catppuccin-latte .textarea{display:block;max-width:100%;min-width:100%;padding:calc(0.75em - 1px);resize:vertical}html.theme--catppuccin-latte .textarea:not([rows]){max-height:40em;min-height:8em}html.theme--catppuccin-latte .textarea[rows]{height:initial}html.theme--catppuccin-latte .textarea.has-fixed-size{resize:none}html.theme--catppuccin-latte .radio,html.theme--catppuccin-latte .checkbox{cursor:pointer;display:inline-block;line-height:1.25;position:relative}html.theme--catppuccin-latte .radio input,html.theme--catppuccin-latte .checkbox input{cursor:pointer}html.theme--catppuccin-latte .radio:hover,html.theme--catppuccin-latte .checkbox:hover{color:#04a5e5}html.theme--catppuccin-latte .radio[disabled],html.theme--catppuccin-latte .checkbox[disabled],fieldset[disabled] html.theme--catppuccin-latte .radio,fieldset[disabled] html.theme--catppuccin-latte .checkbox,html.theme--catppuccin-latte .radio input[disabled],html.theme--catppuccin-latte .checkbox input[disabled]{color:#616587;cursor:not-allowed}html.theme--catppuccin-latte .radio+.radio{margin-left:.5em}html.theme--catppuccin-latte .select{display:inline-block;max-width:100%;position:relative;vertical-align:top}html.theme--catppuccin-latte .select:not(.is-multiple){height:2.5em}html.theme--catppuccin-latte .select:not(.is-multiple):not(.is-loading)::after{border-color:#1e66f5;right:1.125em;z-index:4}html.theme--catppuccin-latte .select.is-rounded select,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.select select{border-radius:9999px;padding-left:1em}html.theme--catppuccin-latte .select select{cursor:pointer;display:block;font-size:1em;max-width:100%;outline:none}html.theme--catppuccin-latte .select select::-ms-expand{display:none}html.theme--catppuccin-latte .select select[disabled]:hover,fieldset[disabled] html.theme--catppuccin-latte .select select:hover{border-color:#e6e9ef}html.theme--catppuccin-latte .select select:not([multiple]){padding-right:2.5em}html.theme--catppuccin-latte .select select[multiple]{height:auto;padding:0}html.theme--catppuccin-latte .select select[multiple] option{padding:0.5em 1em}html.theme--catppuccin-latte .select:not(.is-multiple):not(.is-loading):hover::after{border-color:#04a5e5}html.theme--catppuccin-latte .select.is-white:not(:hover)::after{border-color:#fff}html.theme--catppuccin-latte .select.is-white select{border-color:#fff}html.theme--catppuccin-latte .select.is-white select:hover,html.theme--catppuccin-latte .select.is-white select.is-hovered{border-color:#f2f2f2}html.theme--catppuccin-latte .select.is-white select:focus,html.theme--catppuccin-latte .select.is-white select.is-focused,html.theme--catppuccin-latte .select.is-white select:active,html.theme--catppuccin-latte .select.is-white select.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--catppuccin-latte .select.is-black:not(:hover)::after{border-color:#0a0a0a}html.theme--catppuccin-latte .select.is-black select{border-color:#0a0a0a}html.theme--catppuccin-latte .select.is-black select:hover,html.theme--catppuccin-latte .select.is-black select.is-hovered{border-color:#000}html.theme--catppuccin-latte .select.is-black select:focus,html.theme--catppuccin-latte .select.is-black select.is-focused,html.theme--catppuccin-latte .select.is-black select:active,html.theme--catppuccin-latte .select.is-black select.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--catppuccin-latte .select.is-light:not(:hover)::after{border-color:#f5f5f5}html.theme--catppuccin-latte .select.is-light select{border-color:#f5f5f5}html.theme--catppuccin-latte .select.is-light select:hover,html.theme--catppuccin-latte .select.is-light select.is-hovered{border-color:#e8e8e8}html.theme--catppuccin-latte .select.is-light select:focus,html.theme--catppuccin-latte .select.is-light select.is-focused,html.theme--catppuccin-latte .select.is-light select:active,html.theme--catppuccin-latte .select.is-light select.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}html.theme--catppuccin-latte .select.is-dark:not(:hover)::after,html.theme--catppuccin-latte .content kbd.select:not(:hover)::after{border-color:#ccd0da}html.theme--catppuccin-latte .select.is-dark select,html.theme--catppuccin-latte .content kbd.select select{border-color:#ccd0da}html.theme--catppuccin-latte .select.is-dark select:hover,html.theme--catppuccin-latte .content kbd.select select:hover,html.theme--catppuccin-latte .select.is-dark select.is-hovered,html.theme--catppuccin-latte .content kbd.select select.is-hovered{border-color:#bdc2cf}html.theme--catppuccin-latte .select.is-dark select:focus,html.theme--catppuccin-latte .content kbd.select select:focus,html.theme--catppuccin-latte .select.is-dark select.is-focused,html.theme--catppuccin-latte .content kbd.select select.is-focused,html.theme--catppuccin-latte .select.is-dark select:active,html.theme--catppuccin-latte .content kbd.select select:active,html.theme--catppuccin-latte .select.is-dark select.is-active,html.theme--catppuccin-latte .content kbd.select select.is-active{box-shadow:0 0 0 0.125em rgba(204,208,218,0.25)}html.theme--catppuccin-latte .select.is-primary:not(:hover)::after,html.theme--catppuccin-latte .docstring>section>a.select.docs-sourcelink:not(:hover)::after{border-color:#1e66f5}html.theme--catppuccin-latte .select.is-primary select,html.theme--catppuccin-latte .docstring>section>a.select.docs-sourcelink select{border-color:#1e66f5}html.theme--catppuccin-latte .select.is-primary select:hover,html.theme--catppuccin-latte .docstring>section>a.select.docs-sourcelink select:hover,html.theme--catppuccin-latte .select.is-primary select.is-hovered,html.theme--catppuccin-latte .docstring>section>a.select.docs-sourcelink select.is-hovered{border-color:#0b57ef}html.theme--catppuccin-latte .select.is-primary select:focus,html.theme--catppuccin-latte .docstring>section>a.select.docs-sourcelink select:focus,html.theme--catppuccin-latte .select.is-primary select.is-focused,html.theme--catppuccin-latte .docstring>section>a.select.docs-sourcelink select.is-focused,html.theme--catppuccin-latte .select.is-primary select:active,html.theme--catppuccin-latte .docstring>section>a.select.docs-sourcelink select:active,html.theme--catppuccin-latte .select.is-primary select.is-active,html.theme--catppuccin-latte .docstring>section>a.select.docs-sourcelink select.is-active{box-shadow:0 0 0 0.125em rgba(30,102,245,0.25)}html.theme--catppuccin-latte .select.is-link:not(:hover)::after{border-color:#1e66f5}html.theme--catppuccin-latte .select.is-link select{border-color:#1e66f5}html.theme--catppuccin-latte .select.is-link select:hover,html.theme--catppuccin-latte .select.is-link select.is-hovered{border-color:#0b57ef}html.theme--catppuccin-latte .select.is-link select:focus,html.theme--catppuccin-latte .select.is-link select.is-focused,html.theme--catppuccin-latte .select.is-link select:active,html.theme--catppuccin-latte .select.is-link select.is-active{box-shadow:0 0 0 0.125em rgba(30,102,245,0.25)}html.theme--catppuccin-latte .select.is-info:not(:hover)::after{border-color:#179299}html.theme--catppuccin-latte .select.is-info select{border-color:#179299}html.theme--catppuccin-latte .select.is-info select:hover,html.theme--catppuccin-latte .select.is-info select.is-hovered{border-color:#147d83}html.theme--catppuccin-latte .select.is-info select:focus,html.theme--catppuccin-latte .select.is-info select.is-focused,html.theme--catppuccin-latte .select.is-info select:active,html.theme--catppuccin-latte .select.is-info select.is-active{box-shadow:0 0 0 0.125em rgba(23,146,153,0.25)}html.theme--catppuccin-latte .select.is-success:not(:hover)::after{border-color:#40a02b}html.theme--catppuccin-latte .select.is-success select{border-color:#40a02b}html.theme--catppuccin-latte .select.is-success select:hover,html.theme--catppuccin-latte .select.is-success select.is-hovered{border-color:#388c26}html.theme--catppuccin-latte .select.is-success select:focus,html.theme--catppuccin-latte .select.is-success select.is-focused,html.theme--catppuccin-latte .select.is-success select:active,html.theme--catppuccin-latte .select.is-success select.is-active{box-shadow:0 0 0 0.125em rgba(64,160,43,0.25)}html.theme--catppuccin-latte .select.is-warning:not(:hover)::after{border-color:#df8e1d}html.theme--catppuccin-latte .select.is-warning select{border-color:#df8e1d}html.theme--catppuccin-latte .select.is-warning select:hover,html.theme--catppuccin-latte .select.is-warning select.is-hovered{border-color:#c8801a}html.theme--catppuccin-latte .select.is-warning select:focus,html.theme--catppuccin-latte .select.is-warning select.is-focused,html.theme--catppuccin-latte .select.is-warning select:active,html.theme--catppuccin-latte .select.is-warning select.is-active{box-shadow:0 0 0 0.125em rgba(223,142,29,0.25)}html.theme--catppuccin-latte .select.is-danger:not(:hover)::after{border-color:#d20f39}html.theme--catppuccin-latte .select.is-danger select{border-color:#d20f39}html.theme--catppuccin-latte .select.is-danger select:hover,html.theme--catppuccin-latte .select.is-danger select.is-hovered{border-color:#ba0d33}html.theme--catppuccin-latte .select.is-danger select:focus,html.theme--catppuccin-latte .select.is-danger select.is-focused,html.theme--catppuccin-latte .select.is-danger select:active,html.theme--catppuccin-latte .select.is-danger select.is-active{box-shadow:0 0 0 0.125em rgba(210,15,57,0.25)}html.theme--catppuccin-latte .select.is-small,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.select{border-radius:3px;font-size:.75rem}html.theme--catppuccin-latte .select.is-medium{font-size:1.25rem}html.theme--catppuccin-latte .select.is-large{font-size:1.5rem}html.theme--catppuccin-latte .select.is-disabled::after{border-color:#616587 !important;opacity:0.5}html.theme--catppuccin-latte .select.is-fullwidth{width:100%}html.theme--catppuccin-latte .select.is-fullwidth select{width:100%}html.theme--catppuccin-latte .select.is-loading::after{margin-top:0;position:absolute;right:.625em;top:0.625em;transform:none}html.theme--catppuccin-latte .select.is-loading.is-small:after,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}html.theme--catppuccin-latte .select.is-loading.is-medium:after{font-size:1.25rem}html.theme--catppuccin-latte .select.is-loading.is-large:after{font-size:1.5rem}html.theme--catppuccin-latte .file{align-items:stretch;display:flex;justify-content:flex-start;position:relative}html.theme--catppuccin-latte .file.is-white .file-cta{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-latte .file.is-white:hover .file-cta,html.theme--catppuccin-latte .file.is-white.is-hovered .file-cta{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-latte .file.is-white:focus .file-cta,html.theme--catppuccin-latte .file.is-white.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,255,255,0.25);color:#0a0a0a}html.theme--catppuccin-latte .file.is-white:active .file-cta,html.theme--catppuccin-latte .file.is-white.is-active .file-cta{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-latte .file.is-black .file-cta{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-black:hover .file-cta,html.theme--catppuccin-latte .file.is-black.is-hovered .file-cta{background-color:#040404;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-black:focus .file-cta,html.theme--catppuccin-latte .file.is-black.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(10,10,10,0.25);color:#fff}html.theme--catppuccin-latte .file.is-black:active .file-cta,html.theme--catppuccin-latte .file.is-black.is-active .file-cta{background-color:#000;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-light .file-cta{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .file.is-light:hover .file-cta,html.theme--catppuccin-latte .file.is-light.is-hovered .file-cta{background-color:#eee;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .file.is-light:focus .file-cta,html.theme--catppuccin-latte .file.is-light.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(245,245,245,0.25);color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .file.is-light:active .file-cta,html.theme--catppuccin-latte .file.is-light.is-active .file-cta{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .file.is-dark .file-cta,html.theme--catppuccin-latte .content kbd.file .file-cta{background-color:#ccd0da;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .file.is-dark:hover .file-cta,html.theme--catppuccin-latte .content kbd.file:hover .file-cta,html.theme--catppuccin-latte .file.is-dark.is-hovered .file-cta,html.theme--catppuccin-latte .content kbd.file.is-hovered .file-cta{background-color:#c5c9d5;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .file.is-dark:focus .file-cta,html.theme--catppuccin-latte .content kbd.file:focus .file-cta,html.theme--catppuccin-latte .file.is-dark.is-focused .file-cta,html.theme--catppuccin-latte .content kbd.file.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(204,208,218,0.25);color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .file.is-dark:active .file-cta,html.theme--catppuccin-latte .content kbd.file:active .file-cta,html.theme--catppuccin-latte .file.is-dark.is-active .file-cta,html.theme--catppuccin-latte .content kbd.file.is-active .file-cta{background-color:#bdc2cf;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .file.is-primary .file-cta,html.theme--catppuccin-latte .docstring>section>a.file.docs-sourcelink .file-cta{background-color:#1e66f5;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-primary:hover .file-cta,html.theme--catppuccin-latte .docstring>section>a.file.docs-sourcelink:hover .file-cta,html.theme--catppuccin-latte .file.is-primary.is-hovered .file-cta,html.theme--catppuccin-latte .docstring>section>a.file.is-hovered.docs-sourcelink .file-cta{background-color:#125ef4;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-primary:focus .file-cta,html.theme--catppuccin-latte .docstring>section>a.file.docs-sourcelink:focus .file-cta,html.theme--catppuccin-latte .file.is-primary.is-focused .file-cta,html.theme--catppuccin-latte .docstring>section>a.file.is-focused.docs-sourcelink .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(30,102,245,0.25);color:#fff}html.theme--catppuccin-latte .file.is-primary:active .file-cta,html.theme--catppuccin-latte .docstring>section>a.file.docs-sourcelink:active .file-cta,html.theme--catppuccin-latte .file.is-primary.is-active .file-cta,html.theme--catppuccin-latte .docstring>section>a.file.is-active.docs-sourcelink .file-cta{background-color:#0b57ef;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-link .file-cta{background-color:#1e66f5;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-link:hover .file-cta,html.theme--catppuccin-latte .file.is-link.is-hovered .file-cta{background-color:#125ef4;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-link:focus .file-cta,html.theme--catppuccin-latte .file.is-link.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(30,102,245,0.25);color:#fff}html.theme--catppuccin-latte .file.is-link:active .file-cta,html.theme--catppuccin-latte .file.is-link.is-active .file-cta{background-color:#0b57ef;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-info .file-cta{background-color:#179299;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-info:hover .file-cta,html.theme--catppuccin-latte .file.is-info.is-hovered .file-cta{background-color:#15878e;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-info:focus .file-cta,html.theme--catppuccin-latte .file.is-info.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(23,146,153,0.25);color:#fff}html.theme--catppuccin-latte .file.is-info:active .file-cta,html.theme--catppuccin-latte .file.is-info.is-active .file-cta{background-color:#147d83;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-success .file-cta{background-color:#40a02b;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-success:hover .file-cta,html.theme--catppuccin-latte .file.is-success.is-hovered .file-cta{background-color:#3c9628;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-success:focus .file-cta,html.theme--catppuccin-latte .file.is-success.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(64,160,43,0.25);color:#fff}html.theme--catppuccin-latte .file.is-success:active .file-cta,html.theme--catppuccin-latte .file.is-success.is-active .file-cta{background-color:#388c26;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-warning .file-cta{background-color:#df8e1d;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-warning:hover .file-cta,html.theme--catppuccin-latte .file.is-warning.is-hovered .file-cta{background-color:#d4871c;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-warning:focus .file-cta,html.theme--catppuccin-latte .file.is-warning.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(223,142,29,0.25);color:#fff}html.theme--catppuccin-latte .file.is-warning:active .file-cta,html.theme--catppuccin-latte .file.is-warning.is-active .file-cta{background-color:#c8801a;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-danger .file-cta{background-color:#d20f39;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-danger:hover .file-cta,html.theme--catppuccin-latte .file.is-danger.is-hovered .file-cta{background-color:#c60e36;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-danger:focus .file-cta,html.theme--catppuccin-latte .file.is-danger.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(210,15,57,0.25);color:#fff}html.theme--catppuccin-latte .file.is-danger:active .file-cta,html.theme--catppuccin-latte .file.is-danger.is-active .file-cta{background-color:#ba0d33;border-color:transparent;color:#fff}html.theme--catppuccin-latte .file.is-small,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.file{font-size:.75rem}html.theme--catppuccin-latte .file.is-normal{font-size:1rem}html.theme--catppuccin-latte .file.is-medium{font-size:1.25rem}html.theme--catppuccin-latte .file.is-medium .file-icon .fa{font-size:21px}html.theme--catppuccin-latte .file.is-large{font-size:1.5rem}html.theme--catppuccin-latte .file.is-large .file-icon .fa{font-size:28px}html.theme--catppuccin-latte .file.has-name .file-cta{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--catppuccin-latte .file.has-name .file-name{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--catppuccin-latte .file.has-name.is-empty .file-cta{border-radius:.4em}html.theme--catppuccin-latte .file.has-name.is-empty .file-name{display:none}html.theme--catppuccin-latte .file.is-boxed .file-label{flex-direction:column}html.theme--catppuccin-latte .file.is-boxed .file-cta{flex-direction:column;height:auto;padding:1em 3em}html.theme--catppuccin-latte .file.is-boxed .file-name{border-width:0 1px 1px}html.theme--catppuccin-latte .file.is-boxed .file-icon{height:1.5em;width:1.5em}html.theme--catppuccin-latte .file.is-boxed .file-icon .fa{font-size:21px}html.theme--catppuccin-latte .file.is-boxed.is-small .file-icon .fa,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-boxed .file-icon .fa{font-size:14px}html.theme--catppuccin-latte .file.is-boxed.is-medium .file-icon .fa{font-size:28px}html.theme--catppuccin-latte .file.is-boxed.is-large .file-icon .fa{font-size:35px}html.theme--catppuccin-latte .file.is-boxed.has-name .file-cta{border-radius:.4em .4em 0 0}html.theme--catppuccin-latte .file.is-boxed.has-name .file-name{border-radius:0 0 .4em .4em;border-width:0 1px 1px}html.theme--catppuccin-latte .file.is-centered{justify-content:center}html.theme--catppuccin-latte .file.is-fullwidth .file-label{width:100%}html.theme--catppuccin-latte .file.is-fullwidth .file-name{flex-grow:1;max-width:none}html.theme--catppuccin-latte .file.is-right{justify-content:flex-end}html.theme--catppuccin-latte .file.is-right .file-cta{border-radius:0 .4em .4em 0}html.theme--catppuccin-latte .file.is-right .file-name{border-radius:.4em 0 0 .4em;border-width:1px 0 1px 1px;order:-1}html.theme--catppuccin-latte .file-label{align-items:stretch;display:flex;cursor:pointer;justify-content:flex-start;overflow:hidden;position:relative}html.theme--catppuccin-latte .file-label:hover .file-cta{background-color:#c5c9d5;color:#41445a}html.theme--catppuccin-latte .file-label:hover .file-name{border-color:#a5a9b8}html.theme--catppuccin-latte .file-label:active .file-cta{background-color:#bdc2cf;color:#41445a}html.theme--catppuccin-latte .file-label:active .file-name{border-color:#9ea2b3}html.theme--catppuccin-latte .file-input{height:100%;left:0;opacity:0;outline:none;position:absolute;top:0;width:100%}html.theme--catppuccin-latte .file-cta,html.theme--catppuccin-latte .file-name{border-color:#acb0be;border-radius:.4em;font-size:1em;padding-left:1em;padding-right:1em;white-space:nowrap}html.theme--catppuccin-latte .file-cta{background-color:#ccd0da;color:#4c4f69}html.theme--catppuccin-latte .file-name{border-color:#acb0be;border-style:solid;border-width:1px 1px 1px 0;display:block;max-width:16em;overflow:hidden;text-align:inherit;text-overflow:ellipsis}html.theme--catppuccin-latte .file-icon{align-items:center;display:flex;height:1em;justify-content:center;margin-right:.5em;width:1em}html.theme--catppuccin-latte .file-icon .fa{font-size:14px}html.theme--catppuccin-latte .label{color:#41445a;display:block;font-size:1rem;font-weight:700}html.theme--catppuccin-latte .label:not(:last-child){margin-bottom:0.5em}html.theme--catppuccin-latte .label.is-small,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.label{font-size:.75rem}html.theme--catppuccin-latte .label.is-medium{font-size:1.25rem}html.theme--catppuccin-latte .label.is-large{font-size:1.5rem}html.theme--catppuccin-latte .help{display:block;font-size:.75rem;margin-top:0.25rem}html.theme--catppuccin-latte .help.is-white{color:#fff}html.theme--catppuccin-latte .help.is-black{color:#0a0a0a}html.theme--catppuccin-latte .help.is-light{color:#f5f5f5}html.theme--catppuccin-latte .help.is-dark,html.theme--catppuccin-latte .content kbd.help{color:#ccd0da}html.theme--catppuccin-latte .help.is-primary,html.theme--catppuccin-latte .docstring>section>a.help.docs-sourcelink{color:#1e66f5}html.theme--catppuccin-latte .help.is-link{color:#1e66f5}html.theme--catppuccin-latte .help.is-info{color:#179299}html.theme--catppuccin-latte .help.is-success{color:#40a02b}html.theme--catppuccin-latte .help.is-warning{color:#df8e1d}html.theme--catppuccin-latte .help.is-danger{color:#d20f39}html.theme--catppuccin-latte .field:not(:last-child){margin-bottom:0.75rem}html.theme--catppuccin-latte .field.has-addons{display:flex;justify-content:flex-start}html.theme--catppuccin-latte .field.has-addons .control:not(:last-child){margin-right:-1px}html.theme--catppuccin-latte .field.has-addons .control:not(:first-child):not(:last-child) .button,html.theme--catppuccin-latte .field.has-addons .control:not(:first-child):not(:last-child) .input,html.theme--catppuccin-latte .field.has-addons .control:not(:first-child):not(:last-child) #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-latte #documenter .docs-sidebar .field.has-addons .control:not(:first-child):not(:last-child) form.docs-search>input,html.theme--catppuccin-latte .field.has-addons .control:not(:first-child):not(:last-child) .select select{border-radius:0}html.theme--catppuccin-latte .field.has-addons .control:first-child:not(:only-child) .button,html.theme--catppuccin-latte .field.has-addons .control:first-child:not(:only-child) .input,html.theme--catppuccin-latte .field.has-addons .control:first-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-latte #documenter .docs-sidebar .field.has-addons .control:first-child:not(:only-child) form.docs-search>input,html.theme--catppuccin-latte .field.has-addons .control:first-child:not(:only-child) .select select{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--catppuccin-latte .field.has-addons .control:last-child:not(:only-child) .button,html.theme--catppuccin-latte .field.has-addons .control:last-child:not(:only-child) .input,html.theme--catppuccin-latte .field.has-addons .control:last-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-latte #documenter .docs-sidebar .field.has-addons .control:last-child:not(:only-child) form.docs-search>input,html.theme--catppuccin-latte .field.has-addons .control:last-child:not(:only-child) .select select{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--catppuccin-latte .field.has-addons .control .button:not([disabled]):hover,html.theme--catppuccin-latte .field.has-addons .control .button.is-hovered:not([disabled]),html.theme--catppuccin-latte .field.has-addons .control .input:not([disabled]):hover,html.theme--catppuccin-latte .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):hover,html.theme--catppuccin-latte #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):hover,html.theme--catppuccin-latte .field.has-addons .control .input.is-hovered:not([disabled]),html.theme--catppuccin-latte .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-hovered:not([disabled]),html.theme--catppuccin-latte #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-hovered:not([disabled]),html.theme--catppuccin-latte .field.has-addons .control .select select:not([disabled]):hover,html.theme--catppuccin-latte .field.has-addons .control .select select.is-hovered:not([disabled]){z-index:2}html.theme--catppuccin-latte .field.has-addons .control .button:not([disabled]):focus,html.theme--catppuccin-latte .field.has-addons .control .button.is-focused:not([disabled]),html.theme--catppuccin-latte .field.has-addons .control .button:not([disabled]):active,html.theme--catppuccin-latte .field.has-addons .control .button.is-active:not([disabled]),html.theme--catppuccin-latte .field.has-addons .control .input:not([disabled]):focus,html.theme--catppuccin-latte .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus,html.theme--catppuccin-latte #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus,html.theme--catppuccin-latte .field.has-addons .control .input.is-focused:not([disabled]),html.theme--catppuccin-latte .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]),html.theme--catppuccin-latte #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]),html.theme--catppuccin-latte .field.has-addons .control .input:not([disabled]):active,html.theme--catppuccin-latte .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active,html.theme--catppuccin-latte #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active,html.theme--catppuccin-latte .field.has-addons .control .input.is-active:not([disabled]),html.theme--catppuccin-latte .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]),html.theme--catppuccin-latte #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]),html.theme--catppuccin-latte .field.has-addons .control .select select:not([disabled]):focus,html.theme--catppuccin-latte .field.has-addons .control .select select.is-focused:not([disabled]),html.theme--catppuccin-latte .field.has-addons .control .select select:not([disabled]):active,html.theme--catppuccin-latte .field.has-addons .control .select select.is-active:not([disabled]){z-index:3}html.theme--catppuccin-latte .field.has-addons .control .button:not([disabled]):focus:hover,html.theme--catppuccin-latte .field.has-addons .control .button.is-focused:not([disabled]):hover,html.theme--catppuccin-latte .field.has-addons .control .button:not([disabled]):active:hover,html.theme--catppuccin-latte .field.has-addons .control .button.is-active:not([disabled]):hover,html.theme--catppuccin-latte .field.has-addons .control .input:not([disabled]):focus:hover,html.theme--catppuccin-latte .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus:hover,html.theme--catppuccin-latte #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus:hover,html.theme--catppuccin-latte .field.has-addons .control .input.is-focused:not([disabled]):hover,html.theme--catppuccin-latte .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]):hover,html.theme--catppuccin-latte #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]):hover,html.theme--catppuccin-latte .field.has-addons .control .input:not([disabled]):active:hover,html.theme--catppuccin-latte .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active:hover,html.theme--catppuccin-latte #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active:hover,html.theme--catppuccin-latte .field.has-addons .control .input.is-active:not([disabled]):hover,html.theme--catppuccin-latte .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]):hover,html.theme--catppuccin-latte #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]):hover,html.theme--catppuccin-latte .field.has-addons .control .select select:not([disabled]):focus:hover,html.theme--catppuccin-latte .field.has-addons .control .select select.is-focused:not([disabled]):hover,html.theme--catppuccin-latte .field.has-addons .control .select select:not([disabled]):active:hover,html.theme--catppuccin-latte .field.has-addons .control .select select.is-active:not([disabled]):hover{z-index:4}html.theme--catppuccin-latte .field.has-addons .control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--catppuccin-latte .field.has-addons.has-addons-centered{justify-content:center}html.theme--catppuccin-latte .field.has-addons.has-addons-right{justify-content:flex-end}html.theme--catppuccin-latte .field.has-addons.has-addons-fullwidth .control{flex-grow:1;flex-shrink:0}html.theme--catppuccin-latte .field.is-grouped{display:flex;justify-content:flex-start}html.theme--catppuccin-latte .field.is-grouped>.control{flex-shrink:0}html.theme--catppuccin-latte .field.is-grouped>.control:not(:last-child){margin-bottom:0;margin-right:.75rem}html.theme--catppuccin-latte .field.is-grouped>.control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--catppuccin-latte .field.is-grouped.is-grouped-centered{justify-content:center}html.theme--catppuccin-latte .field.is-grouped.is-grouped-right{justify-content:flex-end}html.theme--catppuccin-latte .field.is-grouped.is-grouped-multiline{flex-wrap:wrap}html.theme--catppuccin-latte .field.is-grouped.is-grouped-multiline>.control:last-child,html.theme--catppuccin-latte .field.is-grouped.is-grouped-multiline>.control:not(:last-child){margin-bottom:0.75rem}html.theme--catppuccin-latte .field.is-grouped.is-grouped-multiline:last-child{margin-bottom:-0.75rem}html.theme--catppuccin-latte .field.is-grouped.is-grouped-multiline:not(:last-child){margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .field.is-horizontal{display:flex}}html.theme--catppuccin-latte .field-label .label{font-size:inherit}@media screen and (max-width: 768px){html.theme--catppuccin-latte .field-label{margin-bottom:0.5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .field-label{flex-basis:0;flex-grow:1;flex-shrink:0;margin-right:1.5rem;text-align:right}html.theme--catppuccin-latte .field-label.is-small,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.field-label{font-size:.75rem;padding-top:0.375em}html.theme--catppuccin-latte .field-label.is-normal{padding-top:0.375em}html.theme--catppuccin-latte .field-label.is-medium{font-size:1.25rem;padding-top:0.375em}html.theme--catppuccin-latte .field-label.is-large{font-size:1.5rem;padding-top:0.375em}}html.theme--catppuccin-latte .field-body .field .field{margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .field-body{display:flex;flex-basis:0;flex-grow:5;flex-shrink:1}html.theme--catppuccin-latte .field-body .field{margin-bottom:0}html.theme--catppuccin-latte .field-body>.field{flex-shrink:1}html.theme--catppuccin-latte .field-body>.field:not(.is-narrow){flex-grow:1}html.theme--catppuccin-latte .field-body>.field:not(:last-child){margin-right:.75rem}}html.theme--catppuccin-latte .control{box-sizing:border-box;clear:both;font-size:1rem;position:relative;text-align:inherit}html.theme--catppuccin-latte .control.has-icons-left .input:focus~.icon,html.theme--catppuccin-latte .control.has-icons-left #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--catppuccin-latte #documenter .docs-sidebar .control.has-icons-left form.docs-search>input:focus~.icon,html.theme--catppuccin-latte .control.has-icons-left .select:focus~.icon,html.theme--catppuccin-latte .control.has-icons-right .input:focus~.icon,html.theme--catppuccin-latte .control.has-icons-right #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--catppuccin-latte #documenter .docs-sidebar .control.has-icons-right form.docs-search>input:focus~.icon,html.theme--catppuccin-latte .control.has-icons-right .select:focus~.icon{color:#ccd0da}html.theme--catppuccin-latte .control.has-icons-left .input.is-small~.icon,html.theme--catppuccin-latte .control.has-icons-left #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--catppuccin-latte #documenter .docs-sidebar .control.has-icons-left form.docs-search>input~.icon,html.theme--catppuccin-latte .control.has-icons-left .select.is-small~.icon,html.theme--catppuccin-latte .control.has-icons-right .input.is-small~.icon,html.theme--catppuccin-latte .control.has-icons-right #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--catppuccin-latte #documenter .docs-sidebar .control.has-icons-right form.docs-search>input~.icon,html.theme--catppuccin-latte .control.has-icons-right .select.is-small~.icon{font-size:.75rem}html.theme--catppuccin-latte .control.has-icons-left .input.is-medium~.icon,html.theme--catppuccin-latte .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--catppuccin-latte #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-medium~.icon,html.theme--catppuccin-latte .control.has-icons-left .select.is-medium~.icon,html.theme--catppuccin-latte .control.has-icons-right .input.is-medium~.icon,html.theme--catppuccin-latte .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--catppuccin-latte #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-medium~.icon,html.theme--catppuccin-latte .control.has-icons-right .select.is-medium~.icon{font-size:1.25rem}html.theme--catppuccin-latte .control.has-icons-left .input.is-large~.icon,html.theme--catppuccin-latte .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--catppuccin-latte #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-large~.icon,html.theme--catppuccin-latte .control.has-icons-left .select.is-large~.icon,html.theme--catppuccin-latte .control.has-icons-right .input.is-large~.icon,html.theme--catppuccin-latte .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--catppuccin-latte #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-large~.icon,html.theme--catppuccin-latte .control.has-icons-right .select.is-large~.icon{font-size:1.5rem}html.theme--catppuccin-latte .control.has-icons-left .icon,html.theme--catppuccin-latte .control.has-icons-right .icon{color:#acb0be;height:2.5em;pointer-events:none;position:absolute;top:0;width:2.5em;z-index:4}html.theme--catppuccin-latte .control.has-icons-left .input,html.theme--catppuccin-latte .control.has-icons-left #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-latte #documenter .docs-sidebar .control.has-icons-left form.docs-search>input,html.theme--catppuccin-latte .control.has-icons-left .select select{padding-left:2.5em}html.theme--catppuccin-latte .control.has-icons-left .icon.is-left{left:0}html.theme--catppuccin-latte .control.has-icons-right .input,html.theme--catppuccin-latte .control.has-icons-right #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-latte #documenter .docs-sidebar .control.has-icons-right form.docs-search>input,html.theme--catppuccin-latte .control.has-icons-right .select select{padding-right:2.5em}html.theme--catppuccin-latte .control.has-icons-right .icon.is-right{right:0}html.theme--catppuccin-latte .control.is-loading::after{position:absolute !important;right:.625em;top:0.625em;z-index:4}html.theme--catppuccin-latte .control.is-loading.is-small:after,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}html.theme--catppuccin-latte .control.is-loading.is-medium:after{font-size:1.25rem}html.theme--catppuccin-latte .control.is-loading.is-large:after{font-size:1.5rem}html.theme--catppuccin-latte .breadcrumb{font-size:1rem;white-space:nowrap}html.theme--catppuccin-latte .breadcrumb a{align-items:center;color:#1e66f5;display:flex;justify-content:center;padding:0 .75em}html.theme--catppuccin-latte .breadcrumb a:hover{color:#04a5e5}html.theme--catppuccin-latte .breadcrumb li{align-items:center;display:flex}html.theme--catppuccin-latte .breadcrumb li:first-child a{padding-left:0}html.theme--catppuccin-latte .breadcrumb li.is-active a{color:#41445a;cursor:default;pointer-events:none}html.theme--catppuccin-latte .breadcrumb li+li::before{color:#9ca0b0;content:"\0002f"}html.theme--catppuccin-latte .breadcrumb ul,html.theme--catppuccin-latte .breadcrumb ol{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--catppuccin-latte .breadcrumb .icon:first-child{margin-right:.5em}html.theme--catppuccin-latte .breadcrumb .icon:last-child{margin-left:.5em}html.theme--catppuccin-latte .breadcrumb.is-centered ol,html.theme--catppuccin-latte .breadcrumb.is-centered ul{justify-content:center}html.theme--catppuccin-latte .breadcrumb.is-right ol,html.theme--catppuccin-latte .breadcrumb.is-right ul{justify-content:flex-end}html.theme--catppuccin-latte .breadcrumb.is-small,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.breadcrumb{font-size:.75rem}html.theme--catppuccin-latte .breadcrumb.is-medium{font-size:1.25rem}html.theme--catppuccin-latte .breadcrumb.is-large{font-size:1.5rem}html.theme--catppuccin-latte .breadcrumb.has-arrow-separator li+li::before{content:"\02192"}html.theme--catppuccin-latte .breadcrumb.has-bullet-separator li+li::before{content:"\02022"}html.theme--catppuccin-latte .breadcrumb.has-dot-separator li+li::before{content:"\000b7"}html.theme--catppuccin-latte .breadcrumb.has-succeeds-separator li+li::before{content:"\0227B"}html.theme--catppuccin-latte .card{background-color:#fff;border-radius:.25rem;box-shadow:#171717;color:#4c4f69;max-width:100%;position:relative}html.theme--catppuccin-latte .card-footer:first-child,html.theme--catppuccin-latte .card-content:first-child,html.theme--catppuccin-latte .card-header:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}html.theme--catppuccin-latte .card-footer:last-child,html.theme--catppuccin-latte .card-content:last-child,html.theme--catppuccin-latte .card-header:last-child{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}html.theme--catppuccin-latte .card-header{background-color:rgba(0,0,0,0);align-items:stretch;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);display:flex}html.theme--catppuccin-latte .card-header-title{align-items:center;color:#41445a;display:flex;flex-grow:1;font-weight:700;padding:0.75rem 1rem}html.theme--catppuccin-latte .card-header-title.is-centered{justify-content:center}html.theme--catppuccin-latte .card-header-icon{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0;align-items:center;cursor:pointer;display:flex;justify-content:center;padding:0.75rem 1rem}html.theme--catppuccin-latte .card-image{display:block;position:relative}html.theme--catppuccin-latte .card-image:first-child img{border-top-left-radius:.25rem;border-top-right-radius:.25rem}html.theme--catppuccin-latte .card-image:last-child img{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}html.theme--catppuccin-latte .card-content{background-color:rgba(0,0,0,0);padding:1.5rem}html.theme--catppuccin-latte .card-footer{background-color:rgba(0,0,0,0);border-top:1px solid #ededed;align-items:stretch;display:flex}html.theme--catppuccin-latte .card-footer-item{align-items:center;display:flex;flex-basis:0;flex-grow:1;flex-shrink:0;justify-content:center;padding:.75rem}html.theme--catppuccin-latte .card-footer-item:not(:last-child){border-right:1px solid #ededed}html.theme--catppuccin-latte .card .media:not(:last-child){margin-bottom:1.5rem}html.theme--catppuccin-latte .dropdown{display:inline-flex;position:relative;vertical-align:top}html.theme--catppuccin-latte .dropdown.is-active .dropdown-menu,html.theme--catppuccin-latte .dropdown.is-hoverable:hover .dropdown-menu{display:block}html.theme--catppuccin-latte .dropdown.is-right .dropdown-menu{left:auto;right:0}html.theme--catppuccin-latte .dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:initial;top:auto}html.theme--catppuccin-latte .dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:20}html.theme--catppuccin-latte .dropdown-content{background-color:#e6e9ef;border-radius:.4em;box-shadow:#171717;padding-bottom:.5rem;padding-top:.5rem}html.theme--catppuccin-latte .dropdown-item{color:#4c4f69;display:block;font-size:0.875rem;line-height:1.5;padding:0.375rem 1rem;position:relative}html.theme--catppuccin-latte a.dropdown-item,html.theme--catppuccin-latte button.dropdown-item{padding-right:3rem;text-align:inherit;white-space:nowrap;width:100%}html.theme--catppuccin-latte a.dropdown-item:hover,html.theme--catppuccin-latte button.dropdown-item:hover{background-color:#e6e9ef;color:#0a0a0a}html.theme--catppuccin-latte a.dropdown-item.is-active,html.theme--catppuccin-latte button.dropdown-item.is-active{background-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .dropdown-divider{background-color:#ededed;border:none;display:block;height:1px;margin:0.5rem 0}html.theme--catppuccin-latte .level{align-items:center;justify-content:space-between}html.theme--catppuccin-latte .level code{border-radius:.4em}html.theme--catppuccin-latte .level img{display:inline-block;vertical-align:top}html.theme--catppuccin-latte .level.is-mobile{display:flex}html.theme--catppuccin-latte .level.is-mobile .level-left,html.theme--catppuccin-latte .level.is-mobile .level-right{display:flex}html.theme--catppuccin-latte .level.is-mobile .level-left+.level-right{margin-top:0}html.theme--catppuccin-latte .level.is-mobile .level-item:not(:last-child){margin-bottom:0;margin-right:.75rem}html.theme--catppuccin-latte .level.is-mobile .level-item:not(.is-narrow){flex-grow:1}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .level{display:flex}html.theme--catppuccin-latte .level>.level-item:not(.is-narrow){flex-grow:1}}html.theme--catppuccin-latte .level-item{align-items:center;display:flex;flex-basis:auto;flex-grow:0;flex-shrink:0;justify-content:center}html.theme--catppuccin-latte .level-item .title,html.theme--catppuccin-latte .level-item .subtitle{margin-bottom:0}@media screen and (max-width: 768px){html.theme--catppuccin-latte .level-item:not(:last-child){margin-bottom:.75rem}}html.theme--catppuccin-latte .level-left,html.theme--catppuccin-latte .level-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--catppuccin-latte .level-left .level-item.is-flexible,html.theme--catppuccin-latte .level-right .level-item.is-flexible{flex-grow:1}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .level-left .level-item:not(:last-child),html.theme--catppuccin-latte .level-right .level-item:not(:last-child){margin-right:.75rem}}html.theme--catppuccin-latte .level-left{align-items:center;justify-content:flex-start}@media screen and (max-width: 768px){html.theme--catppuccin-latte .level-left+.level-right{margin-top:1.5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .level-left{display:flex}}html.theme--catppuccin-latte .level-right{align-items:center;justify-content:flex-end}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .level-right{display:flex}}html.theme--catppuccin-latte .media{align-items:flex-start;display:flex;text-align:inherit}html.theme--catppuccin-latte .media .content:not(:last-child){margin-bottom:.75rem}html.theme--catppuccin-latte .media .media{border-top:1px solid rgba(172,176,190,0.5);display:flex;padding-top:.75rem}html.theme--catppuccin-latte .media .media .content:not(:last-child),html.theme--catppuccin-latte .media .media .control:not(:last-child){margin-bottom:.5rem}html.theme--catppuccin-latte .media .media .media{padding-top:.5rem}html.theme--catppuccin-latte .media .media .media+.media{margin-top:.5rem}html.theme--catppuccin-latte .media+.media{border-top:1px solid rgba(172,176,190,0.5);margin-top:1rem;padding-top:1rem}html.theme--catppuccin-latte .media.is-large+.media{margin-top:1.5rem;padding-top:1.5rem}html.theme--catppuccin-latte .media-left,html.theme--catppuccin-latte .media-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--catppuccin-latte .media-left{margin-right:1rem}html.theme--catppuccin-latte .media-right{margin-left:1rem}html.theme--catppuccin-latte .media-content{flex-basis:auto;flex-grow:1;flex-shrink:1;text-align:inherit}@media screen and (max-width: 768px){html.theme--catppuccin-latte .media-content{overflow-x:auto}}html.theme--catppuccin-latte .menu{font-size:1rem}html.theme--catppuccin-latte .menu.is-small,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.menu{font-size:.75rem}html.theme--catppuccin-latte .menu.is-medium{font-size:1.25rem}html.theme--catppuccin-latte .menu.is-large{font-size:1.5rem}html.theme--catppuccin-latte .menu-list{line-height:1.25}html.theme--catppuccin-latte .menu-list a{border-radius:3px;color:#4c4f69;display:block;padding:0.5em 0.75em}html.theme--catppuccin-latte .menu-list a:hover{background-color:#e6e9ef;color:#41445a}html.theme--catppuccin-latte .menu-list a.is-active{background-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .menu-list li ul{border-left:1px solid #acb0be;margin:.75em;padding-left:.75em}html.theme--catppuccin-latte .menu-label{color:#616587;font-size:.75em;letter-spacing:.1em;text-transform:uppercase}html.theme--catppuccin-latte .menu-label:not(:first-child){margin-top:1em}html.theme--catppuccin-latte .menu-label:not(:last-child){margin-bottom:1em}html.theme--catppuccin-latte .message{background-color:#e6e9ef;border-radius:.4em;font-size:1rem}html.theme--catppuccin-latte .message strong{color:currentColor}html.theme--catppuccin-latte .message a:not(.button):not(.tag):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--catppuccin-latte .message.is-small,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.message{font-size:.75rem}html.theme--catppuccin-latte .message.is-medium{font-size:1.25rem}html.theme--catppuccin-latte .message.is-large{font-size:1.5rem}html.theme--catppuccin-latte .message.is-white{background-color:#fff}html.theme--catppuccin-latte .message.is-white .message-header{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-latte .message.is-white .message-body{border-color:#fff}html.theme--catppuccin-latte .message.is-black{background-color:#fafafa}html.theme--catppuccin-latte .message.is-black .message-header{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-latte .message.is-black .message-body{border-color:#0a0a0a}html.theme--catppuccin-latte .message.is-light{background-color:#fafafa}html.theme--catppuccin-latte .message.is-light .message-header{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .message.is-light .message-body{border-color:#f5f5f5}html.theme--catppuccin-latte .message.is-dark,html.theme--catppuccin-latte .content kbd.message{background-color:#f9fafb}html.theme--catppuccin-latte .message.is-dark .message-header,html.theme--catppuccin-latte .content kbd.message .message-header{background-color:#ccd0da;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .message.is-dark .message-body,html.theme--catppuccin-latte .content kbd.message .message-body{border-color:#ccd0da}html.theme--catppuccin-latte .message.is-primary,html.theme--catppuccin-latte .docstring>section>a.message.docs-sourcelink{background-color:#ebf2fe}html.theme--catppuccin-latte .message.is-primary .message-header,html.theme--catppuccin-latte .docstring>section>a.message.docs-sourcelink .message-header{background-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .message.is-primary .message-body,html.theme--catppuccin-latte .docstring>section>a.message.docs-sourcelink .message-body{border-color:#1e66f5;color:#0a52e1}html.theme--catppuccin-latte .message.is-link{background-color:#ebf2fe}html.theme--catppuccin-latte .message.is-link .message-header{background-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .message.is-link .message-body{border-color:#1e66f5;color:#0a52e1}html.theme--catppuccin-latte .message.is-info{background-color:#edfcfc}html.theme--catppuccin-latte .message.is-info .message-header{background-color:#179299;color:#fff}html.theme--catppuccin-latte .message.is-info .message-body{border-color:#179299;color:#1cb2ba}html.theme--catppuccin-latte .message.is-success{background-color:#f1fbef}html.theme--catppuccin-latte .message.is-success .message-header{background-color:#40a02b;color:#fff}html.theme--catppuccin-latte .message.is-success .message-body{border-color:#40a02b;color:#40a12b}html.theme--catppuccin-latte .message.is-warning{background-color:#fdf6ed}html.theme--catppuccin-latte .message.is-warning .message-header{background-color:#df8e1d;color:#fff}html.theme--catppuccin-latte .message.is-warning .message-body{border-color:#df8e1d;color:#9e6515}html.theme--catppuccin-latte .message.is-danger{background-color:#feecf0}html.theme--catppuccin-latte .message.is-danger .message-header{background-color:#d20f39;color:#fff}html.theme--catppuccin-latte .message.is-danger .message-body{border-color:#d20f39;color:#e9113f}html.theme--catppuccin-latte .message-header{align-items:center;background-color:#4c4f69;border-radius:.4em .4em 0 0;color:#fff;display:flex;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.75em 1em;position:relative}html.theme--catppuccin-latte .message-header .delete{flex-grow:0;flex-shrink:0;margin-left:.75em}html.theme--catppuccin-latte .message-header+.message-body{border-width:0;border-top-left-radius:0;border-top-right-radius:0}html.theme--catppuccin-latte .message-body{border-color:#acb0be;border-radius:.4em;border-style:solid;border-width:0 0 0 4px;color:#4c4f69;padding:1.25em 1.5em}html.theme--catppuccin-latte .message-body code,html.theme--catppuccin-latte .message-body pre{background-color:#fff}html.theme--catppuccin-latte .message-body pre code{background-color:rgba(0,0,0,0)}html.theme--catppuccin-latte .modal{align-items:center;display:none;flex-direction:column;justify-content:center;overflow:hidden;position:fixed;z-index:40}html.theme--catppuccin-latte .modal.is-active{display:flex}html.theme--catppuccin-latte .modal-background{background-color:rgba(10,10,10,0.86)}html.theme--catppuccin-latte .modal-content,html.theme--catppuccin-latte .modal-card{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width: 769px){html.theme--catppuccin-latte .modal-content,html.theme--catppuccin-latte .modal-card{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}html.theme--catppuccin-latte .modal-close{background:none;height:40px;position:fixed;right:20px;top:20px;width:40px}html.theme--catppuccin-latte .modal-card{display:flex;flex-direction:column;max-height:calc(100vh - 40px);overflow:hidden;-ms-overflow-y:visible}html.theme--catppuccin-latte .modal-card-head,html.theme--catppuccin-latte .modal-card-foot{align-items:center;background-color:#e6e9ef;display:flex;flex-shrink:0;justify-content:flex-start;padding:20px;position:relative}html.theme--catppuccin-latte .modal-card-head{border-bottom:1px solid #acb0be;border-top-left-radius:8px;border-top-right-radius:8px}html.theme--catppuccin-latte .modal-card-title{color:#4c4f69;flex-grow:1;flex-shrink:0;font-size:1.5rem;line-height:1}html.theme--catppuccin-latte .modal-card-foot{border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid #acb0be}html.theme--catppuccin-latte .modal-card-foot .button:not(:last-child){margin-right:.5em}html.theme--catppuccin-latte .modal-card-body{-webkit-overflow-scrolling:touch;background-color:#eff1f5;flex-grow:1;flex-shrink:1;overflow:auto;padding:20px}html.theme--catppuccin-latte .navbar{background-color:#1e66f5;min-height:4rem;position:relative;z-index:30}html.theme--catppuccin-latte .navbar.is-white{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-latte .navbar.is-white .navbar-brand>.navbar-item,html.theme--catppuccin-latte .navbar.is-white .navbar-brand .navbar-link{color:#0a0a0a}html.theme--catppuccin-latte .navbar.is-white .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-white .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-white .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-white .navbar-brand .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-white .navbar-brand .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-white .navbar-brand .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--catppuccin-latte .navbar.is-white .navbar-brand .navbar-link::after{border-color:#0a0a0a}html.theme--catppuccin-latte .navbar.is-white .navbar-burger{color:#0a0a0a}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .navbar.is-white .navbar-start>.navbar-item,html.theme--catppuccin-latte .navbar.is-white .navbar-start .navbar-link,html.theme--catppuccin-latte .navbar.is-white .navbar-end>.navbar-item,html.theme--catppuccin-latte .navbar.is-white .navbar-end .navbar-link{color:#0a0a0a}html.theme--catppuccin-latte .navbar.is-white .navbar-start>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-white .navbar-start>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-white .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-white .navbar-start .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-white .navbar-start .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-white .navbar-start .navbar-link.is-active,html.theme--catppuccin-latte .navbar.is-white .navbar-end>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-white .navbar-end>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-white .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-white .navbar-end .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-white .navbar-end .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-white .navbar-end .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--catppuccin-latte .navbar.is-white .navbar-start .navbar-link::after,html.theme--catppuccin-latte .navbar.is-white .navbar-end .navbar-link::after{border-color:#0a0a0a}html.theme--catppuccin-latte .navbar.is-white .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-latte .navbar.is-white .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-latte .navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link{background-color:#f2f2f2;color:#0a0a0a}html.theme--catppuccin-latte .navbar.is-white .navbar-dropdown a.navbar-item.is-active{background-color:#fff;color:#0a0a0a}}html.theme--catppuccin-latte .navbar.is-black{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-latte .navbar.is-black .navbar-brand>.navbar-item,html.theme--catppuccin-latte .navbar.is-black .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-latte .navbar.is-black .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-black .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-black .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-black .navbar-brand .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-black .navbar-brand .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-black .navbar-brand .navbar-link.is-active{background-color:#000;color:#fff}html.theme--catppuccin-latte .navbar.is-black .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-latte .navbar.is-black .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .navbar.is-black .navbar-start>.navbar-item,html.theme--catppuccin-latte .navbar.is-black .navbar-start .navbar-link,html.theme--catppuccin-latte .navbar.is-black .navbar-end>.navbar-item,html.theme--catppuccin-latte .navbar.is-black .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-latte .navbar.is-black .navbar-start>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-black .navbar-start>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-black .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-black .navbar-start .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-black .navbar-start .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-black .navbar-start .navbar-link.is-active,html.theme--catppuccin-latte .navbar.is-black .navbar-end>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-black .navbar-end>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-black .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-black .navbar-end .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-black .navbar-end .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-black .navbar-end .navbar-link.is-active{background-color:#000;color:#fff}html.theme--catppuccin-latte .navbar.is-black .navbar-start .navbar-link::after,html.theme--catppuccin-latte .navbar.is-black .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-latte .navbar.is-black .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-latte .navbar.is-black .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-latte .navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link{background-color:#000;color:#fff}html.theme--catppuccin-latte .navbar.is-black .navbar-dropdown a.navbar-item.is-active{background-color:#0a0a0a;color:#fff}}html.theme--catppuccin-latte .navbar.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .navbar.is-light .navbar-brand>.navbar-item,html.theme--catppuccin-latte .navbar.is-light .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .navbar.is-light .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-light .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-light .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-light .navbar-brand .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-light .navbar-brand .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-light .navbar-brand .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .navbar.is-light .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .navbar.is-light .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .navbar.is-light .navbar-start>.navbar-item,html.theme--catppuccin-latte .navbar.is-light .navbar-start .navbar-link,html.theme--catppuccin-latte .navbar.is-light .navbar-end>.navbar-item,html.theme--catppuccin-latte .navbar.is-light .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .navbar.is-light .navbar-start>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-light .navbar-start>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-light .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-light .navbar-start .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-light .navbar-start .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-light .navbar-start .navbar-link.is-active,html.theme--catppuccin-latte .navbar.is-light .navbar-end>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-light .navbar-end>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-light .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-light .navbar-end .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-light .navbar-end .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-light .navbar-end .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .navbar.is-light .navbar-start .navbar-link::after,html.theme--catppuccin-latte .navbar.is-light .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .navbar.is-light .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-latte .navbar.is-light .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-latte .navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .navbar.is-light .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}}html.theme--catppuccin-latte .navbar.is-dark,html.theme--catppuccin-latte .content kbd.navbar{background-color:#ccd0da;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .navbar.is-dark .navbar-brand>.navbar-item,html.theme--catppuccin-latte .content kbd.navbar .navbar-brand>.navbar-item,html.theme--catppuccin-latte .navbar.is-dark .navbar-brand .navbar-link,html.theme--catppuccin-latte .content kbd.navbar .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .navbar.is-dark .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-latte .content kbd.navbar .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-dark .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-latte .content kbd.navbar .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-dark .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-latte .content kbd.navbar .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-dark .navbar-brand .navbar-link:focus,html.theme--catppuccin-latte .content kbd.navbar .navbar-brand .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-dark .navbar-brand .navbar-link:hover,html.theme--catppuccin-latte .content kbd.navbar .navbar-brand .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-dark .navbar-brand .navbar-link.is-active,html.theme--catppuccin-latte .content kbd.navbar .navbar-brand .navbar-link.is-active{background-color:#bdc2cf;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .navbar.is-dark .navbar-brand .navbar-link::after,html.theme--catppuccin-latte .content kbd.navbar .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .navbar.is-dark .navbar-burger,html.theme--catppuccin-latte .content kbd.navbar .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .navbar.is-dark .navbar-start>.navbar-item,html.theme--catppuccin-latte .content kbd.navbar .navbar-start>.navbar-item,html.theme--catppuccin-latte .navbar.is-dark .navbar-start .navbar-link,html.theme--catppuccin-latte .content kbd.navbar .navbar-start .navbar-link,html.theme--catppuccin-latte .navbar.is-dark .navbar-end>.navbar-item,html.theme--catppuccin-latte .content kbd.navbar .navbar-end>.navbar-item,html.theme--catppuccin-latte .navbar.is-dark .navbar-end .navbar-link,html.theme--catppuccin-latte .content kbd.navbar .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .navbar.is-dark .navbar-start>a.navbar-item:focus,html.theme--catppuccin-latte .content kbd.navbar .navbar-start>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-dark .navbar-start>a.navbar-item:hover,html.theme--catppuccin-latte .content kbd.navbar .navbar-start>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-dark .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-latte .content kbd.navbar .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-dark .navbar-start .navbar-link:focus,html.theme--catppuccin-latte .content kbd.navbar .navbar-start .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-dark .navbar-start .navbar-link:hover,html.theme--catppuccin-latte .content kbd.navbar .navbar-start .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-dark .navbar-start .navbar-link.is-active,html.theme--catppuccin-latte .content kbd.navbar .navbar-start .navbar-link.is-active,html.theme--catppuccin-latte .navbar.is-dark .navbar-end>a.navbar-item:focus,html.theme--catppuccin-latte .content kbd.navbar .navbar-end>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-dark .navbar-end>a.navbar-item:hover,html.theme--catppuccin-latte .content kbd.navbar .navbar-end>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-dark .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-latte .content kbd.navbar .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-dark .navbar-end .navbar-link:focus,html.theme--catppuccin-latte .content kbd.navbar .navbar-end .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-dark .navbar-end .navbar-link:hover,html.theme--catppuccin-latte .content kbd.navbar .navbar-end .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-dark .navbar-end .navbar-link.is-active,html.theme--catppuccin-latte .content kbd.navbar .navbar-end .navbar-link.is-active{background-color:#bdc2cf;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .navbar.is-dark .navbar-start .navbar-link::after,html.theme--catppuccin-latte .content kbd.navbar .navbar-start .navbar-link::after,html.theme--catppuccin-latte .navbar.is-dark .navbar-end .navbar-link::after,html.theme--catppuccin-latte .content kbd.navbar .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-latte .content kbd.navbar .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-latte .navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-latte .content kbd.navbar .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-latte .navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link,html.theme--catppuccin-latte .content kbd.navbar .navbar-item.has-dropdown.is-active .navbar-link{background-color:#bdc2cf;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .navbar.is-dark .navbar-dropdown a.navbar-item.is-active,html.theme--catppuccin-latte .content kbd.navbar .navbar-dropdown a.navbar-item.is-active{background-color:#ccd0da;color:rgba(0,0,0,0.7)}}html.theme--catppuccin-latte .navbar.is-primary,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink{background-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .navbar.is-primary .navbar-brand>.navbar-item,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-brand>.navbar-item,html.theme--catppuccin-latte .navbar.is-primary .navbar-brand .navbar-link,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-latte .navbar.is-primary .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-primary .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-primary .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-primary .navbar-brand .navbar-link:focus,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-primary .navbar-brand .navbar-link:hover,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-primary .navbar-brand .navbar-link.is-active,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link.is-active{background-color:#0b57ef;color:#fff}html.theme--catppuccin-latte .navbar.is-primary .navbar-brand .navbar-link::after,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-latte .navbar.is-primary .navbar-burger,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .navbar.is-primary .navbar-start>.navbar-item,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-start>.navbar-item,html.theme--catppuccin-latte .navbar.is-primary .navbar-start .navbar-link,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link,html.theme--catppuccin-latte .navbar.is-primary .navbar-end>.navbar-item,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-end>.navbar-item,html.theme--catppuccin-latte .navbar.is-primary .navbar-end .navbar-link,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-latte .navbar.is-primary .navbar-start>a.navbar-item:focus,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-primary .navbar-start>a.navbar-item:hover,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-primary .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-primary .navbar-start .navbar-link:focus,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-primary .navbar-start .navbar-link:hover,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-primary .navbar-start .navbar-link.is-active,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link.is-active,html.theme--catppuccin-latte .navbar.is-primary .navbar-end>a.navbar-item:focus,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-primary .navbar-end>a.navbar-item:hover,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-primary .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-primary .navbar-end .navbar-link:focus,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-primary .navbar-end .navbar-link:hover,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-primary .navbar-end .navbar-link.is-active,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link.is-active{background-color:#0b57ef;color:#fff}html.theme--catppuccin-latte .navbar.is-primary .navbar-start .navbar-link::after,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link::after,html.theme--catppuccin-latte .navbar.is-primary .navbar-end .navbar-link::after,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-latte .navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-latte .navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-latte .navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown.is-active .navbar-link{background-color:#0b57ef;color:#fff}html.theme--catppuccin-latte .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#1e66f5;color:#fff}}html.theme--catppuccin-latte .navbar.is-link{background-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .navbar.is-link .navbar-brand>.navbar-item,html.theme--catppuccin-latte .navbar.is-link .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-latte .navbar.is-link .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-link .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-link .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-link .navbar-brand .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-link .navbar-brand .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-link .navbar-brand .navbar-link.is-active{background-color:#0b57ef;color:#fff}html.theme--catppuccin-latte .navbar.is-link .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-latte .navbar.is-link .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .navbar.is-link .navbar-start>.navbar-item,html.theme--catppuccin-latte .navbar.is-link .navbar-start .navbar-link,html.theme--catppuccin-latte .navbar.is-link .navbar-end>.navbar-item,html.theme--catppuccin-latte .navbar.is-link .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-latte .navbar.is-link .navbar-start>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-link .navbar-start>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-link .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-link .navbar-start .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-link .navbar-start .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-link .navbar-start .navbar-link.is-active,html.theme--catppuccin-latte .navbar.is-link .navbar-end>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-link .navbar-end>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-link .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-link .navbar-end .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-link .navbar-end .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-link .navbar-end .navbar-link.is-active{background-color:#0b57ef;color:#fff}html.theme--catppuccin-latte .navbar.is-link .navbar-start .navbar-link::after,html.theme--catppuccin-latte .navbar.is-link .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-latte .navbar.is-link .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-latte .navbar.is-link .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-latte .navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link{background-color:#0b57ef;color:#fff}html.theme--catppuccin-latte .navbar.is-link .navbar-dropdown a.navbar-item.is-active{background-color:#1e66f5;color:#fff}}html.theme--catppuccin-latte .navbar.is-info{background-color:#179299;color:#fff}html.theme--catppuccin-latte .navbar.is-info .navbar-brand>.navbar-item,html.theme--catppuccin-latte .navbar.is-info .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-latte .navbar.is-info .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-info .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-info .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-info .navbar-brand .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-info .navbar-brand .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-info .navbar-brand .navbar-link.is-active{background-color:#147d83;color:#fff}html.theme--catppuccin-latte .navbar.is-info .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-latte .navbar.is-info .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .navbar.is-info .navbar-start>.navbar-item,html.theme--catppuccin-latte .navbar.is-info .navbar-start .navbar-link,html.theme--catppuccin-latte .navbar.is-info .navbar-end>.navbar-item,html.theme--catppuccin-latte .navbar.is-info .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-latte .navbar.is-info .navbar-start>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-info .navbar-start>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-info .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-info .navbar-start .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-info .navbar-start .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-info .navbar-start .navbar-link.is-active,html.theme--catppuccin-latte .navbar.is-info .navbar-end>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-info .navbar-end>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-info .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-info .navbar-end .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-info .navbar-end .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-info .navbar-end .navbar-link.is-active{background-color:#147d83;color:#fff}html.theme--catppuccin-latte .navbar.is-info .navbar-start .navbar-link::after,html.theme--catppuccin-latte .navbar.is-info .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-latte .navbar.is-info .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-latte .navbar.is-info .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-latte .navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link{background-color:#147d83;color:#fff}html.theme--catppuccin-latte .navbar.is-info .navbar-dropdown a.navbar-item.is-active{background-color:#179299;color:#fff}}html.theme--catppuccin-latte .navbar.is-success{background-color:#40a02b;color:#fff}html.theme--catppuccin-latte .navbar.is-success .navbar-brand>.navbar-item,html.theme--catppuccin-latte .navbar.is-success .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-latte .navbar.is-success .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-success .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-success .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-success .navbar-brand .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-success .navbar-brand .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-success .navbar-brand .navbar-link.is-active{background-color:#388c26;color:#fff}html.theme--catppuccin-latte .navbar.is-success .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-latte .navbar.is-success .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .navbar.is-success .navbar-start>.navbar-item,html.theme--catppuccin-latte .navbar.is-success .navbar-start .navbar-link,html.theme--catppuccin-latte .navbar.is-success .navbar-end>.navbar-item,html.theme--catppuccin-latte .navbar.is-success .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-latte .navbar.is-success .navbar-start>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-success .navbar-start>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-success .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-success .navbar-start .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-success .navbar-start .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-success .navbar-start .navbar-link.is-active,html.theme--catppuccin-latte .navbar.is-success .navbar-end>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-success .navbar-end>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-success .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-success .navbar-end .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-success .navbar-end .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-success .navbar-end .navbar-link.is-active{background-color:#388c26;color:#fff}html.theme--catppuccin-latte .navbar.is-success .navbar-start .navbar-link::after,html.theme--catppuccin-latte .navbar.is-success .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-latte .navbar.is-success .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-latte .navbar.is-success .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-latte .navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link{background-color:#388c26;color:#fff}html.theme--catppuccin-latte .navbar.is-success .navbar-dropdown a.navbar-item.is-active{background-color:#40a02b;color:#fff}}html.theme--catppuccin-latte .navbar.is-warning{background-color:#df8e1d;color:#fff}html.theme--catppuccin-latte .navbar.is-warning .navbar-brand>.navbar-item,html.theme--catppuccin-latte .navbar.is-warning .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-latte .navbar.is-warning .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-warning .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-warning .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-warning .navbar-brand .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-warning .navbar-brand .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-warning .navbar-brand .navbar-link.is-active{background-color:#c8801a;color:#fff}html.theme--catppuccin-latte .navbar.is-warning .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-latte .navbar.is-warning .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .navbar.is-warning .navbar-start>.navbar-item,html.theme--catppuccin-latte .navbar.is-warning .navbar-start .navbar-link,html.theme--catppuccin-latte .navbar.is-warning .navbar-end>.navbar-item,html.theme--catppuccin-latte .navbar.is-warning .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-latte .navbar.is-warning .navbar-start>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-warning .navbar-start>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-warning .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-warning .navbar-start .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-warning .navbar-start .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-warning .navbar-start .navbar-link.is-active,html.theme--catppuccin-latte .navbar.is-warning .navbar-end>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-warning .navbar-end>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-warning .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-warning .navbar-end .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-warning .navbar-end .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-warning .navbar-end .navbar-link.is-active{background-color:#c8801a;color:#fff}html.theme--catppuccin-latte .navbar.is-warning .navbar-start .navbar-link::after,html.theme--catppuccin-latte .navbar.is-warning .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-latte .navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-latte .navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-latte .navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link{background-color:#c8801a;color:#fff}html.theme--catppuccin-latte .navbar.is-warning .navbar-dropdown a.navbar-item.is-active{background-color:#df8e1d;color:#fff}}html.theme--catppuccin-latte .navbar.is-danger{background-color:#d20f39;color:#fff}html.theme--catppuccin-latte .navbar.is-danger .navbar-brand>.navbar-item,html.theme--catppuccin-latte .navbar.is-danger .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-latte .navbar.is-danger .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-danger .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-danger .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-danger .navbar-brand .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-danger .navbar-brand .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-danger .navbar-brand .navbar-link.is-active{background-color:#ba0d33;color:#fff}html.theme--catppuccin-latte .navbar.is-danger .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-latte .navbar.is-danger .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .navbar.is-danger .navbar-start>.navbar-item,html.theme--catppuccin-latte .navbar.is-danger .navbar-start .navbar-link,html.theme--catppuccin-latte .navbar.is-danger .navbar-end>.navbar-item,html.theme--catppuccin-latte .navbar.is-danger .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-latte .navbar.is-danger .navbar-start>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-danger .navbar-start>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-danger .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-danger .navbar-start .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-danger .navbar-start .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-danger .navbar-start .navbar-link.is-active,html.theme--catppuccin-latte .navbar.is-danger .navbar-end>a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-danger .navbar-end>a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-danger .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-danger .navbar-end .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-danger .navbar-end .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-danger .navbar-end .navbar-link.is-active{background-color:#ba0d33;color:#fff}html.theme--catppuccin-latte .navbar.is-danger .navbar-start .navbar-link::after,html.theme--catppuccin-latte .navbar.is-danger .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-latte .navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-latte .navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-latte .navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link{background-color:#ba0d33;color:#fff}html.theme--catppuccin-latte .navbar.is-danger .navbar-dropdown a.navbar-item.is-active{background-color:#d20f39;color:#fff}}html.theme--catppuccin-latte .navbar>.container{align-items:stretch;display:flex;min-height:4rem;width:100%}html.theme--catppuccin-latte .navbar.has-shadow{box-shadow:0 2px 0 0 #e6e9ef}html.theme--catppuccin-latte .navbar.is-fixed-bottom,html.theme--catppuccin-latte .navbar.is-fixed-top{left:0;position:fixed;right:0;z-index:30}html.theme--catppuccin-latte .navbar.is-fixed-bottom{bottom:0}html.theme--catppuccin-latte .navbar.is-fixed-bottom.has-shadow{box-shadow:0 -2px 0 0 #e6e9ef}html.theme--catppuccin-latte .navbar.is-fixed-top{top:0}html.theme--catppuccin-latte html.has-navbar-fixed-top,html.theme--catppuccin-latte body.has-navbar-fixed-top{padding-top:4rem}html.theme--catppuccin-latte html.has-navbar-fixed-bottom,html.theme--catppuccin-latte body.has-navbar-fixed-bottom{padding-bottom:4rem}html.theme--catppuccin-latte .navbar-brand,html.theme--catppuccin-latte .navbar-tabs{align-items:stretch;display:flex;flex-shrink:0;min-height:4rem}html.theme--catppuccin-latte .navbar-brand a.navbar-item:focus,html.theme--catppuccin-latte .navbar-brand a.navbar-item:hover{background-color:transparent}html.theme--catppuccin-latte .navbar-tabs{-webkit-overflow-scrolling:touch;max-width:100vw;overflow-x:auto;overflow-y:hidden}html.theme--catppuccin-latte .navbar-burger{color:#4c4f69;-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;cursor:pointer;display:block;height:4rem;position:relative;width:4rem;margin-left:auto}html.theme--catppuccin-latte .navbar-burger span{background-color:currentColor;display:block;height:1px;left:calc(50% - 8px);position:absolute;transform-origin:center;transition-duration:86ms;transition-property:background-color, opacity, transform;transition-timing-function:ease-out;width:16px}html.theme--catppuccin-latte .navbar-burger span:nth-child(1){top:calc(50% - 6px)}html.theme--catppuccin-latte .navbar-burger span:nth-child(2){top:calc(50% - 1px)}html.theme--catppuccin-latte .navbar-burger span:nth-child(3){top:calc(50% + 4px)}html.theme--catppuccin-latte .navbar-burger:hover{background-color:rgba(0,0,0,0.05)}html.theme--catppuccin-latte .navbar-burger.is-active span:nth-child(1){transform:translateY(5px) rotate(45deg)}html.theme--catppuccin-latte .navbar-burger.is-active span:nth-child(2){opacity:0}html.theme--catppuccin-latte .navbar-burger.is-active span:nth-child(3){transform:translateY(-5px) rotate(-45deg)}html.theme--catppuccin-latte .navbar-menu{display:none}html.theme--catppuccin-latte .navbar-item,html.theme--catppuccin-latte .navbar-link{color:#4c4f69;display:block;line-height:1.5;padding:0.5rem 0.75rem;position:relative}html.theme--catppuccin-latte .navbar-item .icon:only-child,html.theme--catppuccin-latte .navbar-link .icon:only-child{margin-left:-0.25rem;margin-right:-0.25rem}html.theme--catppuccin-latte a.navbar-item,html.theme--catppuccin-latte .navbar-link{cursor:pointer}html.theme--catppuccin-latte a.navbar-item:focus,html.theme--catppuccin-latte a.navbar-item:focus-within,html.theme--catppuccin-latte a.navbar-item:hover,html.theme--catppuccin-latte a.navbar-item.is-active,html.theme--catppuccin-latte .navbar-link:focus,html.theme--catppuccin-latte .navbar-link:focus-within,html.theme--catppuccin-latte .navbar-link:hover,html.theme--catppuccin-latte .navbar-link.is-active{background-color:rgba(0,0,0,0);color:#1e66f5}html.theme--catppuccin-latte .navbar-item{flex-grow:0;flex-shrink:0}html.theme--catppuccin-latte .navbar-item img{max-height:1.75rem}html.theme--catppuccin-latte .navbar-item.has-dropdown{padding:0}html.theme--catppuccin-latte .navbar-item.is-expanded{flex-grow:1;flex-shrink:1}html.theme--catppuccin-latte .navbar-item.is-tab{border-bottom:1px solid transparent;min-height:4rem;padding-bottom:calc(0.5rem - 1px)}html.theme--catppuccin-latte .navbar-item.is-tab:focus,html.theme--catppuccin-latte .navbar-item.is-tab:hover{background-color:rgba(0,0,0,0);border-bottom-color:#1e66f5}html.theme--catppuccin-latte .navbar-item.is-tab.is-active{background-color:rgba(0,0,0,0);border-bottom-color:#1e66f5;border-bottom-style:solid;border-bottom-width:3px;color:#1e66f5;padding-bottom:calc(0.5rem - 3px)}html.theme--catppuccin-latte .navbar-content{flex-grow:1;flex-shrink:1}html.theme--catppuccin-latte .navbar-link:not(.is-arrowless){padding-right:2.5em}html.theme--catppuccin-latte .navbar-link:not(.is-arrowless)::after{border-color:#fff;margin-top:-0.375em;right:1.125em}html.theme--catppuccin-latte .navbar-dropdown{font-size:0.875rem;padding-bottom:0.5rem;padding-top:0.5rem}html.theme--catppuccin-latte .navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}html.theme--catppuccin-latte .navbar-divider{background-color:rgba(0,0,0,0.2);border:none;display:none;height:2px;margin:0.5rem 0}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .navbar>.container{display:block}html.theme--catppuccin-latte .navbar-brand .navbar-item,html.theme--catppuccin-latte .navbar-tabs .navbar-item{align-items:center;display:flex}html.theme--catppuccin-latte .navbar-link::after{display:none}html.theme--catppuccin-latte .navbar-menu{background-color:#1e66f5;box-shadow:0 8px 16px rgba(10,10,10,0.1);padding:0.5rem 0}html.theme--catppuccin-latte .navbar-menu.is-active{display:block}html.theme--catppuccin-latte .navbar.is-fixed-bottom-touch,html.theme--catppuccin-latte .navbar.is-fixed-top-touch{left:0;position:fixed;right:0;z-index:30}html.theme--catppuccin-latte .navbar.is-fixed-bottom-touch{bottom:0}html.theme--catppuccin-latte .navbar.is-fixed-bottom-touch.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--catppuccin-latte .navbar.is-fixed-top-touch{top:0}html.theme--catppuccin-latte .navbar.is-fixed-top .navbar-menu,html.theme--catppuccin-latte .navbar.is-fixed-top-touch .navbar-menu{-webkit-overflow-scrolling:touch;max-height:calc(100vh - 4rem);overflow:auto}html.theme--catppuccin-latte html.has-navbar-fixed-top-touch,html.theme--catppuccin-latte body.has-navbar-fixed-top-touch{padding-top:4rem}html.theme--catppuccin-latte html.has-navbar-fixed-bottom-touch,html.theme--catppuccin-latte body.has-navbar-fixed-bottom-touch{padding-bottom:4rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .navbar,html.theme--catppuccin-latte .navbar-menu,html.theme--catppuccin-latte .navbar-start,html.theme--catppuccin-latte .navbar-end{align-items:stretch;display:flex}html.theme--catppuccin-latte .navbar{min-height:4rem}html.theme--catppuccin-latte .navbar.is-spaced{padding:1rem 2rem}html.theme--catppuccin-latte .navbar.is-spaced .navbar-start,html.theme--catppuccin-latte .navbar.is-spaced .navbar-end{align-items:center}html.theme--catppuccin-latte .navbar.is-spaced a.navbar-item,html.theme--catppuccin-latte .navbar.is-spaced .navbar-link{border-radius:.4em}html.theme--catppuccin-latte .navbar.is-transparent a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-transparent a.navbar-item:hover,html.theme--catppuccin-latte .navbar.is-transparent a.navbar-item.is-active,html.theme--catppuccin-latte .navbar.is-transparent .navbar-link:focus,html.theme--catppuccin-latte .navbar.is-transparent .navbar-link:hover,html.theme--catppuccin-latte .navbar.is-transparent .navbar-link.is-active{background-color:transparent !important}html.theme--catppuccin-latte .navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link,html.theme--catppuccin-latte .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link,html.theme--catppuccin-latte .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link,html.theme--catppuccin-latte .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link{background-color:transparent !important}html.theme--catppuccin-latte .navbar.is-transparent .navbar-dropdown a.navbar-item:focus,html.theme--catppuccin-latte .navbar.is-transparent .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#8c8fa1}html.theme--catppuccin-latte .navbar.is-transparent .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#1e66f5}html.theme--catppuccin-latte .navbar-burger{display:none}html.theme--catppuccin-latte .navbar-item,html.theme--catppuccin-latte .navbar-link{align-items:center;display:flex}html.theme--catppuccin-latte .navbar-item.has-dropdown{align-items:stretch}html.theme--catppuccin-latte .navbar-item.has-dropdown-up .navbar-link::after{transform:rotate(135deg) translate(0.25em, -0.25em)}html.theme--catppuccin-latte .navbar-item.has-dropdown-up .navbar-dropdown{border-bottom:1px solid rgba(0,0,0,0.2);border-radius:8px 8px 0 0;border-top:none;bottom:100%;box-shadow:0 -8px 8px rgba(10,10,10,0.1);top:auto}html.theme--catppuccin-latte .navbar-item.is-active .navbar-dropdown,html.theme--catppuccin-latte .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--catppuccin-latte .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--catppuccin-latte .navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar.is-spaced html.theme--catppuccin-latte .navbar-item.is-active .navbar-dropdown,html.theme--catppuccin-latte .navbar-item.is-active .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--catppuccin-latte .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--catppuccin-latte .navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--catppuccin-latte .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--catppuccin-latte .navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--catppuccin-latte .navbar-item.is-hoverable:hover .navbar-dropdown,html.theme--catppuccin-latte .navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed{opacity:1;pointer-events:auto;transform:translateY(0)}html.theme--catppuccin-latte .navbar-menu{flex-grow:1;flex-shrink:0}html.theme--catppuccin-latte .navbar-start{justify-content:flex-start;margin-right:auto}html.theme--catppuccin-latte .navbar-end{justify-content:flex-end;margin-left:auto}html.theme--catppuccin-latte .navbar-dropdown{background-color:#1e66f5;border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid rgba(0,0,0,0.2);box-shadow:0 8px 8px rgba(10,10,10,0.1);display:none;font-size:0.875rem;left:0;min-width:100%;position:absolute;top:100%;z-index:20}html.theme--catppuccin-latte .navbar-dropdown .navbar-item{padding:0.375rem 1rem;white-space:nowrap}html.theme--catppuccin-latte .navbar-dropdown a.navbar-item{padding-right:3rem}html.theme--catppuccin-latte .navbar-dropdown a.navbar-item:focus,html.theme--catppuccin-latte .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#8c8fa1}html.theme--catppuccin-latte .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#1e66f5}.navbar.is-spaced html.theme--catppuccin-latte .navbar-dropdown,html.theme--catppuccin-latte .navbar-dropdown.is-boxed{border-radius:8px;border-top:none;box-shadow:0 8px 8px rgba(10,10,10,0.1), 0 0 0 1px rgba(10,10,10,0.1);display:block;opacity:0;pointer-events:none;top:calc(100% + (-4px));transform:translateY(-5px);transition-duration:86ms;transition-property:opacity, transform}html.theme--catppuccin-latte .navbar-dropdown.is-right{left:auto;right:0}html.theme--catppuccin-latte .navbar-divider{display:block}html.theme--catppuccin-latte .navbar>.container .navbar-brand,html.theme--catppuccin-latte .container>.navbar .navbar-brand{margin-left:-.75rem}html.theme--catppuccin-latte .navbar>.container .navbar-menu,html.theme--catppuccin-latte .container>.navbar .navbar-menu{margin-right:-.75rem}html.theme--catppuccin-latte .navbar.is-fixed-bottom-desktop,html.theme--catppuccin-latte .navbar.is-fixed-top-desktop{left:0;position:fixed;right:0;z-index:30}html.theme--catppuccin-latte .navbar.is-fixed-bottom-desktop{bottom:0}html.theme--catppuccin-latte .navbar.is-fixed-bottom-desktop.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--catppuccin-latte .navbar.is-fixed-top-desktop{top:0}html.theme--catppuccin-latte html.has-navbar-fixed-top-desktop,html.theme--catppuccin-latte body.has-navbar-fixed-top-desktop{padding-top:4rem}html.theme--catppuccin-latte html.has-navbar-fixed-bottom-desktop,html.theme--catppuccin-latte body.has-navbar-fixed-bottom-desktop{padding-bottom:4rem}html.theme--catppuccin-latte html.has-spaced-navbar-fixed-top,html.theme--catppuccin-latte body.has-spaced-navbar-fixed-top{padding-top:6rem}html.theme--catppuccin-latte html.has-spaced-navbar-fixed-bottom,html.theme--catppuccin-latte body.has-spaced-navbar-fixed-bottom{padding-bottom:6rem}html.theme--catppuccin-latte a.navbar-item.is-active,html.theme--catppuccin-latte .navbar-link.is-active{color:#1e66f5}html.theme--catppuccin-latte a.navbar-item.is-active:not(:focus):not(:hover),html.theme--catppuccin-latte .navbar-link.is-active:not(:focus):not(:hover){background-color:rgba(0,0,0,0)}html.theme--catppuccin-latte .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-latte .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-latte .navbar-item.has-dropdown.is-active .navbar-link{background-color:rgba(0,0,0,0)}}html.theme--catppuccin-latte .hero.is-fullheight-with-navbar{min-height:calc(100vh - 4rem)}html.theme--catppuccin-latte .pagination{font-size:1rem;margin:-.25rem}html.theme--catppuccin-latte .pagination.is-small,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.pagination{font-size:.75rem}html.theme--catppuccin-latte .pagination.is-medium{font-size:1.25rem}html.theme--catppuccin-latte .pagination.is-large{font-size:1.5rem}html.theme--catppuccin-latte .pagination.is-rounded .pagination-previous,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.pagination .pagination-previous,html.theme--catppuccin-latte .pagination.is-rounded .pagination-next,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.pagination .pagination-next{padding-left:1em;padding-right:1em;border-radius:9999px}html.theme--catppuccin-latte .pagination.is-rounded .pagination-link,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.pagination .pagination-link{border-radius:9999px}html.theme--catppuccin-latte .pagination,html.theme--catppuccin-latte .pagination-list{align-items:center;display:flex;justify-content:center;text-align:center}html.theme--catppuccin-latte .pagination-previous,html.theme--catppuccin-latte .pagination-next,html.theme--catppuccin-latte .pagination-link,html.theme--catppuccin-latte .pagination-ellipsis{font-size:1em;justify-content:center;margin:.25rem;padding-left:.5em;padding-right:.5em;text-align:center}html.theme--catppuccin-latte .pagination-previous,html.theme--catppuccin-latte .pagination-next,html.theme--catppuccin-latte .pagination-link{border-color:#acb0be;color:#1e66f5;min-width:2.5em}html.theme--catppuccin-latte .pagination-previous:hover,html.theme--catppuccin-latte .pagination-next:hover,html.theme--catppuccin-latte .pagination-link:hover{border-color:#9ca0b0;color:#04a5e5}html.theme--catppuccin-latte .pagination-previous:focus,html.theme--catppuccin-latte .pagination-next:focus,html.theme--catppuccin-latte .pagination-link:focus{border-color:#9ca0b0}html.theme--catppuccin-latte .pagination-previous:active,html.theme--catppuccin-latte .pagination-next:active,html.theme--catppuccin-latte .pagination-link:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2)}html.theme--catppuccin-latte .pagination-previous[disabled],html.theme--catppuccin-latte .pagination-previous.is-disabled,html.theme--catppuccin-latte .pagination-next[disabled],html.theme--catppuccin-latte .pagination-next.is-disabled,html.theme--catppuccin-latte .pagination-link[disabled],html.theme--catppuccin-latte .pagination-link.is-disabled{background-color:#acb0be;border-color:#acb0be;box-shadow:none;color:#616587;opacity:0.5}html.theme--catppuccin-latte .pagination-previous,html.theme--catppuccin-latte .pagination-next{padding-left:.75em;padding-right:.75em;white-space:nowrap}html.theme--catppuccin-latte .pagination-link.is-current{background-color:#1e66f5;border-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .pagination-ellipsis{color:#9ca0b0;pointer-events:none}html.theme--catppuccin-latte .pagination-list{flex-wrap:wrap}html.theme--catppuccin-latte .pagination-list li{list-style:none}@media screen and (max-width: 768px){html.theme--catppuccin-latte .pagination{flex-wrap:wrap}html.theme--catppuccin-latte .pagination-previous,html.theme--catppuccin-latte .pagination-next{flex-grow:1;flex-shrink:1}html.theme--catppuccin-latte .pagination-list li{flex-grow:1;flex-shrink:1}}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .pagination-list{flex-grow:1;flex-shrink:1;justify-content:flex-start;order:1}html.theme--catppuccin-latte .pagination-previous,html.theme--catppuccin-latte .pagination-next,html.theme--catppuccin-latte .pagination-link,html.theme--catppuccin-latte .pagination-ellipsis{margin-bottom:0;margin-top:0}html.theme--catppuccin-latte .pagination-previous{order:2}html.theme--catppuccin-latte .pagination-next{order:3}html.theme--catppuccin-latte .pagination{justify-content:space-between;margin-bottom:0;margin-top:0}html.theme--catppuccin-latte .pagination.is-centered .pagination-previous{order:1}html.theme--catppuccin-latte .pagination.is-centered .pagination-list{justify-content:center;order:2}html.theme--catppuccin-latte .pagination.is-centered .pagination-next{order:3}html.theme--catppuccin-latte .pagination.is-right .pagination-previous{order:1}html.theme--catppuccin-latte .pagination.is-right .pagination-next{order:2}html.theme--catppuccin-latte .pagination.is-right .pagination-list{justify-content:flex-end;order:3}}html.theme--catppuccin-latte .panel{border-radius:8px;box-shadow:#171717;font-size:1rem}html.theme--catppuccin-latte .panel:not(:last-child){margin-bottom:1.5rem}html.theme--catppuccin-latte .panel.is-white .panel-heading{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-latte .panel.is-white .panel-tabs a.is-active{border-bottom-color:#fff}html.theme--catppuccin-latte .panel.is-white .panel-block.is-active .panel-icon{color:#fff}html.theme--catppuccin-latte .panel.is-black .panel-heading{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-latte .panel.is-black .panel-tabs a.is-active{border-bottom-color:#0a0a0a}html.theme--catppuccin-latte .panel.is-black .panel-block.is-active .panel-icon{color:#0a0a0a}html.theme--catppuccin-latte .panel.is-light .panel-heading{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .panel.is-light .panel-tabs a.is-active{border-bottom-color:#f5f5f5}html.theme--catppuccin-latte .panel.is-light .panel-block.is-active .panel-icon{color:#f5f5f5}html.theme--catppuccin-latte .panel.is-dark .panel-heading,html.theme--catppuccin-latte .content kbd.panel .panel-heading{background-color:#ccd0da;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .panel.is-dark .panel-tabs a.is-active,html.theme--catppuccin-latte .content kbd.panel .panel-tabs a.is-active{border-bottom-color:#ccd0da}html.theme--catppuccin-latte .panel.is-dark .panel-block.is-active .panel-icon,html.theme--catppuccin-latte .content kbd.panel .panel-block.is-active .panel-icon{color:#ccd0da}html.theme--catppuccin-latte .panel.is-primary .panel-heading,html.theme--catppuccin-latte .docstring>section>a.panel.docs-sourcelink .panel-heading{background-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .panel.is-primary .panel-tabs a.is-active,html.theme--catppuccin-latte .docstring>section>a.panel.docs-sourcelink .panel-tabs a.is-active{border-bottom-color:#1e66f5}html.theme--catppuccin-latte .panel.is-primary .panel-block.is-active .panel-icon,html.theme--catppuccin-latte .docstring>section>a.panel.docs-sourcelink .panel-block.is-active .panel-icon{color:#1e66f5}html.theme--catppuccin-latte .panel.is-link .panel-heading{background-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .panel.is-link .panel-tabs a.is-active{border-bottom-color:#1e66f5}html.theme--catppuccin-latte .panel.is-link .panel-block.is-active .panel-icon{color:#1e66f5}html.theme--catppuccin-latte .panel.is-info .panel-heading{background-color:#179299;color:#fff}html.theme--catppuccin-latte .panel.is-info .panel-tabs a.is-active{border-bottom-color:#179299}html.theme--catppuccin-latte .panel.is-info .panel-block.is-active .panel-icon{color:#179299}html.theme--catppuccin-latte .panel.is-success .panel-heading{background-color:#40a02b;color:#fff}html.theme--catppuccin-latte .panel.is-success .panel-tabs a.is-active{border-bottom-color:#40a02b}html.theme--catppuccin-latte .panel.is-success .panel-block.is-active .panel-icon{color:#40a02b}html.theme--catppuccin-latte .panel.is-warning .panel-heading{background-color:#df8e1d;color:#fff}html.theme--catppuccin-latte .panel.is-warning .panel-tabs a.is-active{border-bottom-color:#df8e1d}html.theme--catppuccin-latte .panel.is-warning .panel-block.is-active .panel-icon{color:#df8e1d}html.theme--catppuccin-latte .panel.is-danger .panel-heading{background-color:#d20f39;color:#fff}html.theme--catppuccin-latte .panel.is-danger .panel-tabs a.is-active{border-bottom-color:#d20f39}html.theme--catppuccin-latte .panel.is-danger .panel-block.is-active .panel-icon{color:#d20f39}html.theme--catppuccin-latte .panel-tabs:not(:last-child),html.theme--catppuccin-latte .panel-block:not(:last-child){border-bottom:1px solid #ededed}html.theme--catppuccin-latte .panel-heading{background-color:#bcc0cc;border-radius:8px 8px 0 0;color:#41445a;font-size:1.25em;font-weight:700;line-height:1.25;padding:0.75em 1em}html.theme--catppuccin-latte .panel-tabs{align-items:flex-end;display:flex;font-size:.875em;justify-content:center}html.theme--catppuccin-latte .panel-tabs a{border-bottom:1px solid #acb0be;margin-bottom:-1px;padding:0.5em}html.theme--catppuccin-latte .panel-tabs a.is-active{border-bottom-color:#bcc0cc;color:#0b57ef}html.theme--catppuccin-latte .panel-list a{color:#4c4f69}html.theme--catppuccin-latte .panel-list a:hover{color:#1e66f5}html.theme--catppuccin-latte .panel-block{align-items:center;color:#41445a;display:flex;justify-content:flex-start;padding:0.5em 0.75em}html.theme--catppuccin-latte .panel-block input[type="checkbox"]{margin-right:.75em}html.theme--catppuccin-latte .panel-block>.control{flex-grow:1;flex-shrink:1;width:100%}html.theme--catppuccin-latte .panel-block.is-wrapped{flex-wrap:wrap}html.theme--catppuccin-latte .panel-block.is-active{border-left-color:#1e66f5;color:#0b57ef}html.theme--catppuccin-latte .panel-block.is-active .panel-icon{color:#1e66f5}html.theme--catppuccin-latte .panel-block:last-child{border-bottom-left-radius:8px;border-bottom-right-radius:8px}html.theme--catppuccin-latte a.panel-block,html.theme--catppuccin-latte label.panel-block{cursor:pointer}html.theme--catppuccin-latte a.panel-block:hover,html.theme--catppuccin-latte label.panel-block:hover{background-color:#e6e9ef}html.theme--catppuccin-latte .panel-icon{display:inline-block;font-size:14px;height:1em;line-height:1em;text-align:center;vertical-align:top;width:1em;color:#616587;margin-right:.75em}html.theme--catppuccin-latte .panel-icon .fa{font-size:inherit;line-height:inherit}html.theme--catppuccin-latte .tabs{-webkit-overflow-scrolling:touch;align-items:stretch;display:flex;font-size:1rem;justify-content:space-between;overflow:hidden;overflow-x:auto;white-space:nowrap}html.theme--catppuccin-latte .tabs a{align-items:center;border-bottom-color:#acb0be;border-bottom-style:solid;border-bottom-width:1px;color:#4c4f69;display:flex;justify-content:center;margin-bottom:-1px;padding:0.5em 1em;vertical-align:top}html.theme--catppuccin-latte .tabs a:hover{border-bottom-color:#41445a;color:#41445a}html.theme--catppuccin-latte .tabs li{display:block}html.theme--catppuccin-latte .tabs li.is-active a{border-bottom-color:#1e66f5;color:#1e66f5}html.theme--catppuccin-latte .tabs ul{align-items:center;border-bottom-color:#acb0be;border-bottom-style:solid;border-bottom-width:1px;display:flex;flex-grow:1;flex-shrink:0;justify-content:flex-start}html.theme--catppuccin-latte .tabs ul.is-left{padding-right:0.75em}html.theme--catppuccin-latte .tabs ul.is-center{flex:none;justify-content:center;padding-left:0.75em;padding-right:0.75em}html.theme--catppuccin-latte .tabs ul.is-right{justify-content:flex-end;padding-left:0.75em}html.theme--catppuccin-latte .tabs .icon:first-child{margin-right:.5em}html.theme--catppuccin-latte .tabs .icon:last-child{margin-left:.5em}html.theme--catppuccin-latte .tabs.is-centered ul{justify-content:center}html.theme--catppuccin-latte .tabs.is-right ul{justify-content:flex-end}html.theme--catppuccin-latte .tabs.is-boxed a{border:1px solid transparent;border-radius:.4em .4em 0 0}html.theme--catppuccin-latte .tabs.is-boxed a:hover{background-color:#e6e9ef;border-bottom-color:#acb0be}html.theme--catppuccin-latte .tabs.is-boxed li.is-active a{background-color:#fff;border-color:#acb0be;border-bottom-color:rgba(0,0,0,0) !important}html.theme--catppuccin-latte .tabs.is-fullwidth li{flex-grow:1;flex-shrink:0}html.theme--catppuccin-latte .tabs.is-toggle a{border-color:#acb0be;border-style:solid;border-width:1px;margin-bottom:0;position:relative}html.theme--catppuccin-latte .tabs.is-toggle a:hover{background-color:#e6e9ef;border-color:#9ca0b0;z-index:2}html.theme--catppuccin-latte .tabs.is-toggle li+li{margin-left:-1px}html.theme--catppuccin-latte .tabs.is-toggle li:first-child a{border-top-left-radius:.4em;border-bottom-left-radius:.4em}html.theme--catppuccin-latte .tabs.is-toggle li:last-child a{border-top-right-radius:.4em;border-bottom-right-radius:.4em}html.theme--catppuccin-latte .tabs.is-toggle li.is-active a{background-color:#1e66f5;border-color:#1e66f5;color:#fff;z-index:1}html.theme--catppuccin-latte .tabs.is-toggle ul{border-bottom:none}html.theme--catppuccin-latte .tabs.is-toggle.is-toggle-rounded li:first-child a{border-bottom-left-radius:9999px;border-top-left-radius:9999px;padding-left:1.25em}html.theme--catppuccin-latte .tabs.is-toggle.is-toggle-rounded li:last-child a{border-bottom-right-radius:9999px;border-top-right-radius:9999px;padding-right:1.25em}html.theme--catppuccin-latte .tabs.is-small,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.tabs{font-size:.75rem}html.theme--catppuccin-latte .tabs.is-medium{font-size:1.25rem}html.theme--catppuccin-latte .tabs.is-large{font-size:1.5rem}html.theme--catppuccin-latte .column{display:block;flex-basis:0;flex-grow:1;flex-shrink:1;padding:.75rem}.columns.is-mobile>html.theme--catppuccin-latte .column.is-narrow{flex:none;width:unset}.columns.is-mobile>html.theme--catppuccin-latte .column.is-full{flex:none;width:100%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-three-quarters{flex:none;width:75%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-two-thirds{flex:none;width:66.6666%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-half{flex:none;width:50%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-one-third{flex:none;width:33.3333%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-one-quarter{flex:none;width:25%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-one-fifth{flex:none;width:20%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-two-fifths{flex:none;width:40%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-three-fifths{flex:none;width:60%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-four-fifths{flex:none;width:80%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-three-quarters{margin-left:75%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-two-thirds{margin-left:66.6666%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-half{margin-left:50%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-one-third{margin-left:33.3333%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-one-quarter{margin-left:25%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-one-fifth{margin-left:20%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-two-fifths{margin-left:40%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-three-fifths{margin-left:60%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-four-fifths{margin-left:80%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-0{flex:none;width:0%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-0{margin-left:0%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-1{flex:none;width:8.33333337%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-1{margin-left:8.33333337%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-2{flex:none;width:16.66666674%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-2{margin-left:16.66666674%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-3{flex:none;width:25%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-3{margin-left:25%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-4{flex:none;width:33.33333337%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-4{margin-left:33.33333337%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-5{flex:none;width:41.66666674%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-5{margin-left:41.66666674%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-6{flex:none;width:50%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-6{margin-left:50%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-7{flex:none;width:58.33333337%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-7{margin-left:58.33333337%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-8{flex:none;width:66.66666674%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-8{margin-left:66.66666674%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-9{flex:none;width:75%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-9{margin-left:75%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-10{flex:none;width:83.33333337%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-10{margin-left:83.33333337%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-11{flex:none;width:91.66666674%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-11{margin-left:91.66666674%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-12{flex:none;width:100%}.columns.is-mobile>html.theme--catppuccin-latte .column.is-offset-12{margin-left:100%}@media screen and (max-width: 768px){html.theme--catppuccin-latte .column.is-narrow-mobile{flex:none;width:unset}html.theme--catppuccin-latte .column.is-full-mobile{flex:none;width:100%}html.theme--catppuccin-latte .column.is-three-quarters-mobile{flex:none;width:75%}html.theme--catppuccin-latte .column.is-two-thirds-mobile{flex:none;width:66.6666%}html.theme--catppuccin-latte .column.is-half-mobile{flex:none;width:50%}html.theme--catppuccin-latte .column.is-one-third-mobile{flex:none;width:33.3333%}html.theme--catppuccin-latte .column.is-one-quarter-mobile{flex:none;width:25%}html.theme--catppuccin-latte .column.is-one-fifth-mobile{flex:none;width:20%}html.theme--catppuccin-latte .column.is-two-fifths-mobile{flex:none;width:40%}html.theme--catppuccin-latte .column.is-three-fifths-mobile{flex:none;width:60%}html.theme--catppuccin-latte .column.is-four-fifths-mobile{flex:none;width:80%}html.theme--catppuccin-latte .column.is-offset-three-quarters-mobile{margin-left:75%}html.theme--catppuccin-latte .column.is-offset-two-thirds-mobile{margin-left:66.6666%}html.theme--catppuccin-latte .column.is-offset-half-mobile{margin-left:50%}html.theme--catppuccin-latte .column.is-offset-one-third-mobile{margin-left:33.3333%}html.theme--catppuccin-latte .column.is-offset-one-quarter-mobile{margin-left:25%}html.theme--catppuccin-latte .column.is-offset-one-fifth-mobile{margin-left:20%}html.theme--catppuccin-latte .column.is-offset-two-fifths-mobile{margin-left:40%}html.theme--catppuccin-latte .column.is-offset-three-fifths-mobile{margin-left:60%}html.theme--catppuccin-latte .column.is-offset-four-fifths-mobile{margin-left:80%}html.theme--catppuccin-latte .column.is-0-mobile{flex:none;width:0%}html.theme--catppuccin-latte .column.is-offset-0-mobile{margin-left:0%}html.theme--catppuccin-latte .column.is-1-mobile{flex:none;width:8.33333337%}html.theme--catppuccin-latte .column.is-offset-1-mobile{margin-left:8.33333337%}html.theme--catppuccin-latte .column.is-2-mobile{flex:none;width:16.66666674%}html.theme--catppuccin-latte .column.is-offset-2-mobile{margin-left:16.66666674%}html.theme--catppuccin-latte .column.is-3-mobile{flex:none;width:25%}html.theme--catppuccin-latte .column.is-offset-3-mobile{margin-left:25%}html.theme--catppuccin-latte .column.is-4-mobile{flex:none;width:33.33333337%}html.theme--catppuccin-latte .column.is-offset-4-mobile{margin-left:33.33333337%}html.theme--catppuccin-latte .column.is-5-mobile{flex:none;width:41.66666674%}html.theme--catppuccin-latte .column.is-offset-5-mobile{margin-left:41.66666674%}html.theme--catppuccin-latte .column.is-6-mobile{flex:none;width:50%}html.theme--catppuccin-latte .column.is-offset-6-mobile{margin-left:50%}html.theme--catppuccin-latte .column.is-7-mobile{flex:none;width:58.33333337%}html.theme--catppuccin-latte .column.is-offset-7-mobile{margin-left:58.33333337%}html.theme--catppuccin-latte .column.is-8-mobile{flex:none;width:66.66666674%}html.theme--catppuccin-latte .column.is-offset-8-mobile{margin-left:66.66666674%}html.theme--catppuccin-latte .column.is-9-mobile{flex:none;width:75%}html.theme--catppuccin-latte .column.is-offset-9-mobile{margin-left:75%}html.theme--catppuccin-latte .column.is-10-mobile{flex:none;width:83.33333337%}html.theme--catppuccin-latte .column.is-offset-10-mobile{margin-left:83.33333337%}html.theme--catppuccin-latte .column.is-11-mobile{flex:none;width:91.66666674%}html.theme--catppuccin-latte .column.is-offset-11-mobile{margin-left:91.66666674%}html.theme--catppuccin-latte .column.is-12-mobile{flex:none;width:100%}html.theme--catppuccin-latte .column.is-offset-12-mobile{margin-left:100%}}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .column.is-narrow,html.theme--catppuccin-latte .column.is-narrow-tablet{flex:none;width:unset}html.theme--catppuccin-latte .column.is-full,html.theme--catppuccin-latte .column.is-full-tablet{flex:none;width:100%}html.theme--catppuccin-latte .column.is-three-quarters,html.theme--catppuccin-latte .column.is-three-quarters-tablet{flex:none;width:75%}html.theme--catppuccin-latte .column.is-two-thirds,html.theme--catppuccin-latte .column.is-two-thirds-tablet{flex:none;width:66.6666%}html.theme--catppuccin-latte .column.is-half,html.theme--catppuccin-latte .column.is-half-tablet{flex:none;width:50%}html.theme--catppuccin-latte .column.is-one-third,html.theme--catppuccin-latte .column.is-one-third-tablet{flex:none;width:33.3333%}html.theme--catppuccin-latte .column.is-one-quarter,html.theme--catppuccin-latte .column.is-one-quarter-tablet{flex:none;width:25%}html.theme--catppuccin-latte .column.is-one-fifth,html.theme--catppuccin-latte .column.is-one-fifth-tablet{flex:none;width:20%}html.theme--catppuccin-latte .column.is-two-fifths,html.theme--catppuccin-latte .column.is-two-fifths-tablet{flex:none;width:40%}html.theme--catppuccin-latte .column.is-three-fifths,html.theme--catppuccin-latte .column.is-three-fifths-tablet{flex:none;width:60%}html.theme--catppuccin-latte .column.is-four-fifths,html.theme--catppuccin-latte .column.is-four-fifths-tablet{flex:none;width:80%}html.theme--catppuccin-latte .column.is-offset-three-quarters,html.theme--catppuccin-latte .column.is-offset-three-quarters-tablet{margin-left:75%}html.theme--catppuccin-latte .column.is-offset-two-thirds,html.theme--catppuccin-latte .column.is-offset-two-thirds-tablet{margin-left:66.6666%}html.theme--catppuccin-latte .column.is-offset-half,html.theme--catppuccin-latte .column.is-offset-half-tablet{margin-left:50%}html.theme--catppuccin-latte .column.is-offset-one-third,html.theme--catppuccin-latte .column.is-offset-one-third-tablet{margin-left:33.3333%}html.theme--catppuccin-latte .column.is-offset-one-quarter,html.theme--catppuccin-latte .column.is-offset-one-quarter-tablet{margin-left:25%}html.theme--catppuccin-latte .column.is-offset-one-fifth,html.theme--catppuccin-latte .column.is-offset-one-fifth-tablet{margin-left:20%}html.theme--catppuccin-latte .column.is-offset-two-fifths,html.theme--catppuccin-latte .column.is-offset-two-fifths-tablet{margin-left:40%}html.theme--catppuccin-latte .column.is-offset-three-fifths,html.theme--catppuccin-latte .column.is-offset-three-fifths-tablet{margin-left:60%}html.theme--catppuccin-latte .column.is-offset-four-fifths,html.theme--catppuccin-latte .column.is-offset-four-fifths-tablet{margin-left:80%}html.theme--catppuccin-latte .column.is-0,html.theme--catppuccin-latte .column.is-0-tablet{flex:none;width:0%}html.theme--catppuccin-latte .column.is-offset-0,html.theme--catppuccin-latte .column.is-offset-0-tablet{margin-left:0%}html.theme--catppuccin-latte .column.is-1,html.theme--catppuccin-latte .column.is-1-tablet{flex:none;width:8.33333337%}html.theme--catppuccin-latte .column.is-offset-1,html.theme--catppuccin-latte .column.is-offset-1-tablet{margin-left:8.33333337%}html.theme--catppuccin-latte .column.is-2,html.theme--catppuccin-latte .column.is-2-tablet{flex:none;width:16.66666674%}html.theme--catppuccin-latte .column.is-offset-2,html.theme--catppuccin-latte .column.is-offset-2-tablet{margin-left:16.66666674%}html.theme--catppuccin-latte .column.is-3,html.theme--catppuccin-latte .column.is-3-tablet{flex:none;width:25%}html.theme--catppuccin-latte .column.is-offset-3,html.theme--catppuccin-latte .column.is-offset-3-tablet{margin-left:25%}html.theme--catppuccin-latte .column.is-4,html.theme--catppuccin-latte .column.is-4-tablet{flex:none;width:33.33333337%}html.theme--catppuccin-latte .column.is-offset-4,html.theme--catppuccin-latte .column.is-offset-4-tablet{margin-left:33.33333337%}html.theme--catppuccin-latte .column.is-5,html.theme--catppuccin-latte .column.is-5-tablet{flex:none;width:41.66666674%}html.theme--catppuccin-latte .column.is-offset-5,html.theme--catppuccin-latte .column.is-offset-5-tablet{margin-left:41.66666674%}html.theme--catppuccin-latte .column.is-6,html.theme--catppuccin-latte .column.is-6-tablet{flex:none;width:50%}html.theme--catppuccin-latte .column.is-offset-6,html.theme--catppuccin-latte .column.is-offset-6-tablet{margin-left:50%}html.theme--catppuccin-latte .column.is-7,html.theme--catppuccin-latte .column.is-7-tablet{flex:none;width:58.33333337%}html.theme--catppuccin-latte .column.is-offset-7,html.theme--catppuccin-latte .column.is-offset-7-tablet{margin-left:58.33333337%}html.theme--catppuccin-latte .column.is-8,html.theme--catppuccin-latte .column.is-8-tablet{flex:none;width:66.66666674%}html.theme--catppuccin-latte .column.is-offset-8,html.theme--catppuccin-latte .column.is-offset-8-tablet{margin-left:66.66666674%}html.theme--catppuccin-latte .column.is-9,html.theme--catppuccin-latte .column.is-9-tablet{flex:none;width:75%}html.theme--catppuccin-latte .column.is-offset-9,html.theme--catppuccin-latte .column.is-offset-9-tablet{margin-left:75%}html.theme--catppuccin-latte .column.is-10,html.theme--catppuccin-latte .column.is-10-tablet{flex:none;width:83.33333337%}html.theme--catppuccin-latte .column.is-offset-10,html.theme--catppuccin-latte .column.is-offset-10-tablet{margin-left:83.33333337%}html.theme--catppuccin-latte .column.is-11,html.theme--catppuccin-latte .column.is-11-tablet{flex:none;width:91.66666674%}html.theme--catppuccin-latte .column.is-offset-11,html.theme--catppuccin-latte .column.is-offset-11-tablet{margin-left:91.66666674%}html.theme--catppuccin-latte .column.is-12,html.theme--catppuccin-latte .column.is-12-tablet{flex:none;width:100%}html.theme--catppuccin-latte .column.is-offset-12,html.theme--catppuccin-latte .column.is-offset-12-tablet{margin-left:100%}}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .column.is-narrow-touch{flex:none;width:unset}html.theme--catppuccin-latte .column.is-full-touch{flex:none;width:100%}html.theme--catppuccin-latte .column.is-three-quarters-touch{flex:none;width:75%}html.theme--catppuccin-latte .column.is-two-thirds-touch{flex:none;width:66.6666%}html.theme--catppuccin-latte .column.is-half-touch{flex:none;width:50%}html.theme--catppuccin-latte .column.is-one-third-touch{flex:none;width:33.3333%}html.theme--catppuccin-latte .column.is-one-quarter-touch{flex:none;width:25%}html.theme--catppuccin-latte .column.is-one-fifth-touch{flex:none;width:20%}html.theme--catppuccin-latte .column.is-two-fifths-touch{flex:none;width:40%}html.theme--catppuccin-latte .column.is-three-fifths-touch{flex:none;width:60%}html.theme--catppuccin-latte .column.is-four-fifths-touch{flex:none;width:80%}html.theme--catppuccin-latte .column.is-offset-three-quarters-touch{margin-left:75%}html.theme--catppuccin-latte .column.is-offset-two-thirds-touch{margin-left:66.6666%}html.theme--catppuccin-latte .column.is-offset-half-touch{margin-left:50%}html.theme--catppuccin-latte .column.is-offset-one-third-touch{margin-left:33.3333%}html.theme--catppuccin-latte .column.is-offset-one-quarter-touch{margin-left:25%}html.theme--catppuccin-latte .column.is-offset-one-fifth-touch{margin-left:20%}html.theme--catppuccin-latte .column.is-offset-two-fifths-touch{margin-left:40%}html.theme--catppuccin-latte .column.is-offset-three-fifths-touch{margin-left:60%}html.theme--catppuccin-latte .column.is-offset-four-fifths-touch{margin-left:80%}html.theme--catppuccin-latte .column.is-0-touch{flex:none;width:0%}html.theme--catppuccin-latte .column.is-offset-0-touch{margin-left:0%}html.theme--catppuccin-latte .column.is-1-touch{flex:none;width:8.33333337%}html.theme--catppuccin-latte .column.is-offset-1-touch{margin-left:8.33333337%}html.theme--catppuccin-latte .column.is-2-touch{flex:none;width:16.66666674%}html.theme--catppuccin-latte .column.is-offset-2-touch{margin-left:16.66666674%}html.theme--catppuccin-latte .column.is-3-touch{flex:none;width:25%}html.theme--catppuccin-latte .column.is-offset-3-touch{margin-left:25%}html.theme--catppuccin-latte .column.is-4-touch{flex:none;width:33.33333337%}html.theme--catppuccin-latte .column.is-offset-4-touch{margin-left:33.33333337%}html.theme--catppuccin-latte .column.is-5-touch{flex:none;width:41.66666674%}html.theme--catppuccin-latte .column.is-offset-5-touch{margin-left:41.66666674%}html.theme--catppuccin-latte .column.is-6-touch{flex:none;width:50%}html.theme--catppuccin-latte .column.is-offset-6-touch{margin-left:50%}html.theme--catppuccin-latte .column.is-7-touch{flex:none;width:58.33333337%}html.theme--catppuccin-latte .column.is-offset-7-touch{margin-left:58.33333337%}html.theme--catppuccin-latte .column.is-8-touch{flex:none;width:66.66666674%}html.theme--catppuccin-latte .column.is-offset-8-touch{margin-left:66.66666674%}html.theme--catppuccin-latte .column.is-9-touch{flex:none;width:75%}html.theme--catppuccin-latte .column.is-offset-9-touch{margin-left:75%}html.theme--catppuccin-latte .column.is-10-touch{flex:none;width:83.33333337%}html.theme--catppuccin-latte .column.is-offset-10-touch{margin-left:83.33333337%}html.theme--catppuccin-latte .column.is-11-touch{flex:none;width:91.66666674%}html.theme--catppuccin-latte .column.is-offset-11-touch{margin-left:91.66666674%}html.theme--catppuccin-latte .column.is-12-touch{flex:none;width:100%}html.theme--catppuccin-latte .column.is-offset-12-touch{margin-left:100%}}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .column.is-narrow-desktop{flex:none;width:unset}html.theme--catppuccin-latte .column.is-full-desktop{flex:none;width:100%}html.theme--catppuccin-latte .column.is-three-quarters-desktop{flex:none;width:75%}html.theme--catppuccin-latte .column.is-two-thirds-desktop{flex:none;width:66.6666%}html.theme--catppuccin-latte .column.is-half-desktop{flex:none;width:50%}html.theme--catppuccin-latte .column.is-one-third-desktop{flex:none;width:33.3333%}html.theme--catppuccin-latte .column.is-one-quarter-desktop{flex:none;width:25%}html.theme--catppuccin-latte .column.is-one-fifth-desktop{flex:none;width:20%}html.theme--catppuccin-latte .column.is-two-fifths-desktop{flex:none;width:40%}html.theme--catppuccin-latte .column.is-three-fifths-desktop{flex:none;width:60%}html.theme--catppuccin-latte .column.is-four-fifths-desktop{flex:none;width:80%}html.theme--catppuccin-latte .column.is-offset-three-quarters-desktop{margin-left:75%}html.theme--catppuccin-latte .column.is-offset-two-thirds-desktop{margin-left:66.6666%}html.theme--catppuccin-latte .column.is-offset-half-desktop{margin-left:50%}html.theme--catppuccin-latte .column.is-offset-one-third-desktop{margin-left:33.3333%}html.theme--catppuccin-latte .column.is-offset-one-quarter-desktop{margin-left:25%}html.theme--catppuccin-latte .column.is-offset-one-fifth-desktop{margin-left:20%}html.theme--catppuccin-latte .column.is-offset-two-fifths-desktop{margin-left:40%}html.theme--catppuccin-latte .column.is-offset-three-fifths-desktop{margin-left:60%}html.theme--catppuccin-latte .column.is-offset-four-fifths-desktop{margin-left:80%}html.theme--catppuccin-latte .column.is-0-desktop{flex:none;width:0%}html.theme--catppuccin-latte .column.is-offset-0-desktop{margin-left:0%}html.theme--catppuccin-latte .column.is-1-desktop{flex:none;width:8.33333337%}html.theme--catppuccin-latte .column.is-offset-1-desktop{margin-left:8.33333337%}html.theme--catppuccin-latte .column.is-2-desktop{flex:none;width:16.66666674%}html.theme--catppuccin-latte .column.is-offset-2-desktop{margin-left:16.66666674%}html.theme--catppuccin-latte .column.is-3-desktop{flex:none;width:25%}html.theme--catppuccin-latte .column.is-offset-3-desktop{margin-left:25%}html.theme--catppuccin-latte .column.is-4-desktop{flex:none;width:33.33333337%}html.theme--catppuccin-latte .column.is-offset-4-desktop{margin-left:33.33333337%}html.theme--catppuccin-latte .column.is-5-desktop{flex:none;width:41.66666674%}html.theme--catppuccin-latte .column.is-offset-5-desktop{margin-left:41.66666674%}html.theme--catppuccin-latte .column.is-6-desktop{flex:none;width:50%}html.theme--catppuccin-latte .column.is-offset-6-desktop{margin-left:50%}html.theme--catppuccin-latte .column.is-7-desktop{flex:none;width:58.33333337%}html.theme--catppuccin-latte .column.is-offset-7-desktop{margin-left:58.33333337%}html.theme--catppuccin-latte .column.is-8-desktop{flex:none;width:66.66666674%}html.theme--catppuccin-latte .column.is-offset-8-desktop{margin-left:66.66666674%}html.theme--catppuccin-latte .column.is-9-desktop{flex:none;width:75%}html.theme--catppuccin-latte .column.is-offset-9-desktop{margin-left:75%}html.theme--catppuccin-latte .column.is-10-desktop{flex:none;width:83.33333337%}html.theme--catppuccin-latte .column.is-offset-10-desktop{margin-left:83.33333337%}html.theme--catppuccin-latte .column.is-11-desktop{flex:none;width:91.66666674%}html.theme--catppuccin-latte .column.is-offset-11-desktop{margin-left:91.66666674%}html.theme--catppuccin-latte .column.is-12-desktop{flex:none;width:100%}html.theme--catppuccin-latte .column.is-offset-12-desktop{margin-left:100%}}@media screen and (min-width: 1216px){html.theme--catppuccin-latte .column.is-narrow-widescreen{flex:none;width:unset}html.theme--catppuccin-latte .column.is-full-widescreen{flex:none;width:100%}html.theme--catppuccin-latte .column.is-three-quarters-widescreen{flex:none;width:75%}html.theme--catppuccin-latte .column.is-two-thirds-widescreen{flex:none;width:66.6666%}html.theme--catppuccin-latte .column.is-half-widescreen{flex:none;width:50%}html.theme--catppuccin-latte .column.is-one-third-widescreen{flex:none;width:33.3333%}html.theme--catppuccin-latte .column.is-one-quarter-widescreen{flex:none;width:25%}html.theme--catppuccin-latte .column.is-one-fifth-widescreen{flex:none;width:20%}html.theme--catppuccin-latte .column.is-two-fifths-widescreen{flex:none;width:40%}html.theme--catppuccin-latte .column.is-three-fifths-widescreen{flex:none;width:60%}html.theme--catppuccin-latte .column.is-four-fifths-widescreen{flex:none;width:80%}html.theme--catppuccin-latte .column.is-offset-three-quarters-widescreen{margin-left:75%}html.theme--catppuccin-latte .column.is-offset-two-thirds-widescreen{margin-left:66.6666%}html.theme--catppuccin-latte .column.is-offset-half-widescreen{margin-left:50%}html.theme--catppuccin-latte .column.is-offset-one-third-widescreen{margin-left:33.3333%}html.theme--catppuccin-latte .column.is-offset-one-quarter-widescreen{margin-left:25%}html.theme--catppuccin-latte .column.is-offset-one-fifth-widescreen{margin-left:20%}html.theme--catppuccin-latte .column.is-offset-two-fifths-widescreen{margin-left:40%}html.theme--catppuccin-latte .column.is-offset-three-fifths-widescreen{margin-left:60%}html.theme--catppuccin-latte .column.is-offset-four-fifths-widescreen{margin-left:80%}html.theme--catppuccin-latte .column.is-0-widescreen{flex:none;width:0%}html.theme--catppuccin-latte .column.is-offset-0-widescreen{margin-left:0%}html.theme--catppuccin-latte .column.is-1-widescreen{flex:none;width:8.33333337%}html.theme--catppuccin-latte .column.is-offset-1-widescreen{margin-left:8.33333337%}html.theme--catppuccin-latte .column.is-2-widescreen{flex:none;width:16.66666674%}html.theme--catppuccin-latte .column.is-offset-2-widescreen{margin-left:16.66666674%}html.theme--catppuccin-latte .column.is-3-widescreen{flex:none;width:25%}html.theme--catppuccin-latte .column.is-offset-3-widescreen{margin-left:25%}html.theme--catppuccin-latte .column.is-4-widescreen{flex:none;width:33.33333337%}html.theme--catppuccin-latte .column.is-offset-4-widescreen{margin-left:33.33333337%}html.theme--catppuccin-latte .column.is-5-widescreen{flex:none;width:41.66666674%}html.theme--catppuccin-latte .column.is-offset-5-widescreen{margin-left:41.66666674%}html.theme--catppuccin-latte .column.is-6-widescreen{flex:none;width:50%}html.theme--catppuccin-latte .column.is-offset-6-widescreen{margin-left:50%}html.theme--catppuccin-latte .column.is-7-widescreen{flex:none;width:58.33333337%}html.theme--catppuccin-latte .column.is-offset-7-widescreen{margin-left:58.33333337%}html.theme--catppuccin-latte .column.is-8-widescreen{flex:none;width:66.66666674%}html.theme--catppuccin-latte .column.is-offset-8-widescreen{margin-left:66.66666674%}html.theme--catppuccin-latte .column.is-9-widescreen{flex:none;width:75%}html.theme--catppuccin-latte .column.is-offset-9-widescreen{margin-left:75%}html.theme--catppuccin-latte .column.is-10-widescreen{flex:none;width:83.33333337%}html.theme--catppuccin-latte .column.is-offset-10-widescreen{margin-left:83.33333337%}html.theme--catppuccin-latte .column.is-11-widescreen{flex:none;width:91.66666674%}html.theme--catppuccin-latte .column.is-offset-11-widescreen{margin-left:91.66666674%}html.theme--catppuccin-latte .column.is-12-widescreen{flex:none;width:100%}html.theme--catppuccin-latte .column.is-offset-12-widescreen{margin-left:100%}}@media screen and (min-width: 1408px){html.theme--catppuccin-latte .column.is-narrow-fullhd{flex:none;width:unset}html.theme--catppuccin-latte .column.is-full-fullhd{flex:none;width:100%}html.theme--catppuccin-latte .column.is-three-quarters-fullhd{flex:none;width:75%}html.theme--catppuccin-latte .column.is-two-thirds-fullhd{flex:none;width:66.6666%}html.theme--catppuccin-latte .column.is-half-fullhd{flex:none;width:50%}html.theme--catppuccin-latte .column.is-one-third-fullhd{flex:none;width:33.3333%}html.theme--catppuccin-latte .column.is-one-quarter-fullhd{flex:none;width:25%}html.theme--catppuccin-latte .column.is-one-fifth-fullhd{flex:none;width:20%}html.theme--catppuccin-latte .column.is-two-fifths-fullhd{flex:none;width:40%}html.theme--catppuccin-latte .column.is-three-fifths-fullhd{flex:none;width:60%}html.theme--catppuccin-latte .column.is-four-fifths-fullhd{flex:none;width:80%}html.theme--catppuccin-latte .column.is-offset-three-quarters-fullhd{margin-left:75%}html.theme--catppuccin-latte .column.is-offset-two-thirds-fullhd{margin-left:66.6666%}html.theme--catppuccin-latte .column.is-offset-half-fullhd{margin-left:50%}html.theme--catppuccin-latte .column.is-offset-one-third-fullhd{margin-left:33.3333%}html.theme--catppuccin-latte .column.is-offset-one-quarter-fullhd{margin-left:25%}html.theme--catppuccin-latte .column.is-offset-one-fifth-fullhd{margin-left:20%}html.theme--catppuccin-latte .column.is-offset-two-fifths-fullhd{margin-left:40%}html.theme--catppuccin-latte .column.is-offset-three-fifths-fullhd{margin-left:60%}html.theme--catppuccin-latte .column.is-offset-four-fifths-fullhd{margin-left:80%}html.theme--catppuccin-latte .column.is-0-fullhd{flex:none;width:0%}html.theme--catppuccin-latte .column.is-offset-0-fullhd{margin-left:0%}html.theme--catppuccin-latte .column.is-1-fullhd{flex:none;width:8.33333337%}html.theme--catppuccin-latte .column.is-offset-1-fullhd{margin-left:8.33333337%}html.theme--catppuccin-latte .column.is-2-fullhd{flex:none;width:16.66666674%}html.theme--catppuccin-latte .column.is-offset-2-fullhd{margin-left:16.66666674%}html.theme--catppuccin-latte .column.is-3-fullhd{flex:none;width:25%}html.theme--catppuccin-latte .column.is-offset-3-fullhd{margin-left:25%}html.theme--catppuccin-latte .column.is-4-fullhd{flex:none;width:33.33333337%}html.theme--catppuccin-latte .column.is-offset-4-fullhd{margin-left:33.33333337%}html.theme--catppuccin-latte .column.is-5-fullhd{flex:none;width:41.66666674%}html.theme--catppuccin-latte .column.is-offset-5-fullhd{margin-left:41.66666674%}html.theme--catppuccin-latte .column.is-6-fullhd{flex:none;width:50%}html.theme--catppuccin-latte .column.is-offset-6-fullhd{margin-left:50%}html.theme--catppuccin-latte .column.is-7-fullhd{flex:none;width:58.33333337%}html.theme--catppuccin-latte .column.is-offset-7-fullhd{margin-left:58.33333337%}html.theme--catppuccin-latte .column.is-8-fullhd{flex:none;width:66.66666674%}html.theme--catppuccin-latte .column.is-offset-8-fullhd{margin-left:66.66666674%}html.theme--catppuccin-latte .column.is-9-fullhd{flex:none;width:75%}html.theme--catppuccin-latte .column.is-offset-9-fullhd{margin-left:75%}html.theme--catppuccin-latte .column.is-10-fullhd{flex:none;width:83.33333337%}html.theme--catppuccin-latte .column.is-offset-10-fullhd{margin-left:83.33333337%}html.theme--catppuccin-latte .column.is-11-fullhd{flex:none;width:91.66666674%}html.theme--catppuccin-latte .column.is-offset-11-fullhd{margin-left:91.66666674%}html.theme--catppuccin-latte .column.is-12-fullhd{flex:none;width:100%}html.theme--catppuccin-latte .column.is-offset-12-fullhd{margin-left:100%}}html.theme--catppuccin-latte .columns{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--catppuccin-latte .columns:last-child{margin-bottom:-.75rem}html.theme--catppuccin-latte .columns:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}html.theme--catppuccin-latte .columns.is-centered{justify-content:center}html.theme--catppuccin-latte .columns.is-gapless{margin-left:0;margin-right:0;margin-top:0}html.theme--catppuccin-latte .columns.is-gapless>.column{margin:0;padding:0 !important}html.theme--catppuccin-latte .columns.is-gapless:not(:last-child){margin-bottom:1.5rem}html.theme--catppuccin-latte .columns.is-gapless:last-child{margin-bottom:0}html.theme--catppuccin-latte .columns.is-mobile{display:flex}html.theme--catppuccin-latte .columns.is-multiline{flex-wrap:wrap}html.theme--catppuccin-latte .columns.is-vcentered{align-items:center}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .columns:not(.is-desktop){display:flex}}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .columns.is-desktop{display:flex}}html.theme--catppuccin-latte .columns.is-variable{--columnGap: 0.75rem;margin-left:calc(-1 * var(--columnGap));margin-right:calc(-1 * var(--columnGap))}html.theme--catppuccin-latte .columns.is-variable>.column{padding-left:var(--columnGap);padding-right:var(--columnGap)}html.theme--catppuccin-latte .columns.is-variable.is-0{--columnGap: 0rem}@media screen and (max-width: 768px){html.theme--catppuccin-latte .columns.is-variable.is-0-mobile{--columnGap: 0rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .columns.is-variable.is-0-tablet{--columnGap: 0rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-latte .columns.is-variable.is-0-tablet-only{--columnGap: 0rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .columns.is-variable.is-0-touch{--columnGap: 0rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .columns.is-variable.is-0-desktop{--columnGap: 0rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-latte .columns.is-variable.is-0-desktop-only{--columnGap: 0rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-latte .columns.is-variable.is-0-widescreen{--columnGap: 0rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-latte .columns.is-variable.is-0-widescreen-only{--columnGap: 0rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-latte .columns.is-variable.is-0-fullhd{--columnGap: 0rem}}html.theme--catppuccin-latte .columns.is-variable.is-1{--columnGap: .25rem}@media screen and (max-width: 768px){html.theme--catppuccin-latte .columns.is-variable.is-1-mobile{--columnGap: .25rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .columns.is-variable.is-1-tablet{--columnGap: .25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-latte .columns.is-variable.is-1-tablet-only{--columnGap: .25rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .columns.is-variable.is-1-touch{--columnGap: .25rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .columns.is-variable.is-1-desktop{--columnGap: .25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-latte .columns.is-variable.is-1-desktop-only{--columnGap: .25rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-latte .columns.is-variable.is-1-widescreen{--columnGap: .25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-latte .columns.is-variable.is-1-widescreen-only{--columnGap: .25rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-latte .columns.is-variable.is-1-fullhd{--columnGap: .25rem}}html.theme--catppuccin-latte .columns.is-variable.is-2{--columnGap: .5rem}@media screen and (max-width: 768px){html.theme--catppuccin-latte .columns.is-variable.is-2-mobile{--columnGap: .5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .columns.is-variable.is-2-tablet{--columnGap: .5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-latte .columns.is-variable.is-2-tablet-only{--columnGap: .5rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .columns.is-variable.is-2-touch{--columnGap: .5rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .columns.is-variable.is-2-desktop{--columnGap: .5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-latte .columns.is-variable.is-2-desktop-only{--columnGap: .5rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-latte .columns.is-variable.is-2-widescreen{--columnGap: .5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-latte .columns.is-variable.is-2-widescreen-only{--columnGap: .5rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-latte .columns.is-variable.is-2-fullhd{--columnGap: .5rem}}html.theme--catppuccin-latte .columns.is-variable.is-3{--columnGap: .75rem}@media screen and (max-width: 768px){html.theme--catppuccin-latte .columns.is-variable.is-3-mobile{--columnGap: .75rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .columns.is-variable.is-3-tablet{--columnGap: .75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-latte .columns.is-variable.is-3-tablet-only{--columnGap: .75rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .columns.is-variable.is-3-touch{--columnGap: .75rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .columns.is-variable.is-3-desktop{--columnGap: .75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-latte .columns.is-variable.is-3-desktop-only{--columnGap: .75rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-latte .columns.is-variable.is-3-widescreen{--columnGap: .75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-latte .columns.is-variable.is-3-widescreen-only{--columnGap: .75rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-latte .columns.is-variable.is-3-fullhd{--columnGap: .75rem}}html.theme--catppuccin-latte .columns.is-variable.is-4{--columnGap: 1rem}@media screen and (max-width: 768px){html.theme--catppuccin-latte .columns.is-variable.is-4-mobile{--columnGap: 1rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .columns.is-variable.is-4-tablet{--columnGap: 1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-latte .columns.is-variable.is-4-tablet-only{--columnGap: 1rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .columns.is-variable.is-4-touch{--columnGap: 1rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .columns.is-variable.is-4-desktop{--columnGap: 1rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-latte .columns.is-variable.is-4-desktop-only{--columnGap: 1rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-latte .columns.is-variable.is-4-widescreen{--columnGap: 1rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-latte .columns.is-variable.is-4-widescreen-only{--columnGap: 1rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-latte .columns.is-variable.is-4-fullhd{--columnGap: 1rem}}html.theme--catppuccin-latte .columns.is-variable.is-5{--columnGap: 1.25rem}@media screen and (max-width: 768px){html.theme--catppuccin-latte .columns.is-variable.is-5-mobile{--columnGap: 1.25rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .columns.is-variable.is-5-tablet{--columnGap: 1.25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-latte .columns.is-variable.is-5-tablet-only{--columnGap: 1.25rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .columns.is-variable.is-5-touch{--columnGap: 1.25rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .columns.is-variable.is-5-desktop{--columnGap: 1.25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-latte .columns.is-variable.is-5-desktop-only{--columnGap: 1.25rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-latte .columns.is-variable.is-5-widescreen{--columnGap: 1.25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-latte .columns.is-variable.is-5-widescreen-only{--columnGap: 1.25rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-latte .columns.is-variable.is-5-fullhd{--columnGap: 1.25rem}}html.theme--catppuccin-latte .columns.is-variable.is-6{--columnGap: 1.5rem}@media screen and (max-width: 768px){html.theme--catppuccin-latte .columns.is-variable.is-6-mobile{--columnGap: 1.5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .columns.is-variable.is-6-tablet{--columnGap: 1.5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-latte .columns.is-variable.is-6-tablet-only{--columnGap: 1.5rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .columns.is-variable.is-6-touch{--columnGap: 1.5rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .columns.is-variable.is-6-desktop{--columnGap: 1.5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-latte .columns.is-variable.is-6-desktop-only{--columnGap: 1.5rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-latte .columns.is-variable.is-6-widescreen{--columnGap: 1.5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-latte .columns.is-variable.is-6-widescreen-only{--columnGap: 1.5rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-latte .columns.is-variable.is-6-fullhd{--columnGap: 1.5rem}}html.theme--catppuccin-latte .columns.is-variable.is-7{--columnGap: 1.75rem}@media screen and (max-width: 768px){html.theme--catppuccin-latte .columns.is-variable.is-7-mobile{--columnGap: 1.75rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .columns.is-variable.is-7-tablet{--columnGap: 1.75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-latte .columns.is-variable.is-7-tablet-only{--columnGap: 1.75rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .columns.is-variable.is-7-touch{--columnGap: 1.75rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .columns.is-variable.is-7-desktop{--columnGap: 1.75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-latte .columns.is-variable.is-7-desktop-only{--columnGap: 1.75rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-latte .columns.is-variable.is-7-widescreen{--columnGap: 1.75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-latte .columns.is-variable.is-7-widescreen-only{--columnGap: 1.75rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-latte .columns.is-variable.is-7-fullhd{--columnGap: 1.75rem}}html.theme--catppuccin-latte .columns.is-variable.is-8{--columnGap: 2rem}@media screen and (max-width: 768px){html.theme--catppuccin-latte .columns.is-variable.is-8-mobile{--columnGap: 2rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .columns.is-variable.is-8-tablet{--columnGap: 2rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-latte .columns.is-variable.is-8-tablet-only{--columnGap: 2rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .columns.is-variable.is-8-touch{--columnGap: 2rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .columns.is-variable.is-8-desktop{--columnGap: 2rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-latte .columns.is-variable.is-8-desktop-only{--columnGap: 2rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-latte .columns.is-variable.is-8-widescreen{--columnGap: 2rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-latte .columns.is-variable.is-8-widescreen-only{--columnGap: 2rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-latte .columns.is-variable.is-8-fullhd{--columnGap: 2rem}}html.theme--catppuccin-latte .tile{align-items:stretch;display:block;flex-basis:0;flex-grow:1;flex-shrink:1;min-height:min-content}html.theme--catppuccin-latte .tile.is-ancestor{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--catppuccin-latte .tile.is-ancestor:last-child{margin-bottom:-.75rem}html.theme--catppuccin-latte .tile.is-ancestor:not(:last-child){margin-bottom:.75rem}html.theme--catppuccin-latte .tile.is-child{margin:0 !important}html.theme--catppuccin-latte .tile.is-parent{padding:.75rem}html.theme--catppuccin-latte .tile.is-vertical{flex-direction:column}html.theme--catppuccin-latte .tile.is-vertical>.tile.is-child:not(:last-child){margin-bottom:1.5rem !important}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .tile:not(.is-child){display:flex}html.theme--catppuccin-latte .tile.is-1{flex:none;width:8.33333337%}html.theme--catppuccin-latte .tile.is-2{flex:none;width:16.66666674%}html.theme--catppuccin-latte .tile.is-3{flex:none;width:25%}html.theme--catppuccin-latte .tile.is-4{flex:none;width:33.33333337%}html.theme--catppuccin-latte .tile.is-5{flex:none;width:41.66666674%}html.theme--catppuccin-latte .tile.is-6{flex:none;width:50%}html.theme--catppuccin-latte .tile.is-7{flex:none;width:58.33333337%}html.theme--catppuccin-latte .tile.is-8{flex:none;width:66.66666674%}html.theme--catppuccin-latte .tile.is-9{flex:none;width:75%}html.theme--catppuccin-latte .tile.is-10{flex:none;width:83.33333337%}html.theme--catppuccin-latte .tile.is-11{flex:none;width:91.66666674%}html.theme--catppuccin-latte .tile.is-12{flex:none;width:100%}}html.theme--catppuccin-latte .hero{align-items:stretch;display:flex;flex-direction:column;justify-content:space-between}html.theme--catppuccin-latte .hero .navbar{background:none}html.theme--catppuccin-latte .hero .tabs ul{border-bottom:none}html.theme--catppuccin-latte .hero.is-white{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-latte .hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-latte .hero.is-white strong{color:inherit}html.theme--catppuccin-latte .hero.is-white .title{color:#0a0a0a}html.theme--catppuccin-latte .hero.is-white .subtitle{color:rgba(10,10,10,0.9)}html.theme--catppuccin-latte .hero.is-white .subtitle a:not(.button),html.theme--catppuccin-latte .hero.is-white .subtitle strong{color:#0a0a0a}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .hero.is-white .navbar-menu{background-color:#fff}}html.theme--catppuccin-latte .hero.is-white .navbar-item,html.theme--catppuccin-latte .hero.is-white .navbar-link{color:rgba(10,10,10,0.7)}html.theme--catppuccin-latte .hero.is-white a.navbar-item:hover,html.theme--catppuccin-latte .hero.is-white a.navbar-item.is-active,html.theme--catppuccin-latte .hero.is-white .navbar-link:hover,html.theme--catppuccin-latte .hero.is-white .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--catppuccin-latte .hero.is-white .tabs a{color:#0a0a0a;opacity:0.9}html.theme--catppuccin-latte .hero.is-white .tabs a:hover{opacity:1}html.theme--catppuccin-latte .hero.is-white .tabs li.is-active a{color:#fff !important;opacity:1}html.theme--catppuccin-latte .hero.is-white .tabs.is-boxed a,html.theme--catppuccin-latte .hero.is-white .tabs.is-toggle a{color:#0a0a0a}html.theme--catppuccin-latte .hero.is-white .tabs.is-boxed a:hover,html.theme--catppuccin-latte .hero.is-white .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-latte .hero.is-white .tabs.is-boxed li.is-active a,html.theme--catppuccin-latte .hero.is-white .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-latte .hero.is-white .tabs.is-toggle li.is-active a,html.theme--catppuccin-latte .hero.is-white .tabs.is-toggle li.is-active a:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--catppuccin-latte .hero.is-white.is-bold{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-latte .hero.is-white.is-bold .navbar-menu{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}}html.theme--catppuccin-latte .hero.is-black{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-latte .hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-latte .hero.is-black strong{color:inherit}html.theme--catppuccin-latte .hero.is-black .title{color:#fff}html.theme--catppuccin-latte .hero.is-black .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-latte .hero.is-black .subtitle a:not(.button),html.theme--catppuccin-latte .hero.is-black .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .hero.is-black .navbar-menu{background-color:#0a0a0a}}html.theme--catppuccin-latte .hero.is-black .navbar-item,html.theme--catppuccin-latte .hero.is-black .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-latte .hero.is-black a.navbar-item:hover,html.theme--catppuccin-latte .hero.is-black a.navbar-item.is-active,html.theme--catppuccin-latte .hero.is-black .navbar-link:hover,html.theme--catppuccin-latte .hero.is-black .navbar-link.is-active{background-color:#000;color:#fff}html.theme--catppuccin-latte .hero.is-black .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-latte .hero.is-black .tabs a:hover{opacity:1}html.theme--catppuccin-latte .hero.is-black .tabs li.is-active a{color:#0a0a0a !important;opacity:1}html.theme--catppuccin-latte .hero.is-black .tabs.is-boxed a,html.theme--catppuccin-latte .hero.is-black .tabs.is-toggle a{color:#fff}html.theme--catppuccin-latte .hero.is-black .tabs.is-boxed a:hover,html.theme--catppuccin-latte .hero.is-black .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-latte .hero.is-black .tabs.is-boxed li.is-active a,html.theme--catppuccin-latte .hero.is-black .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-latte .hero.is-black .tabs.is-toggle li.is-active a,html.theme--catppuccin-latte .hero.is-black .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--catppuccin-latte .hero.is-black.is-bold{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-latte .hero.is-black.is-bold .navbar-menu{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}}html.theme--catppuccin-latte .hero.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-latte .hero.is-light strong{color:inherit}html.theme--catppuccin-latte .hero.is-light .title{color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .hero.is-light .subtitle{color:rgba(0,0,0,0.9)}html.theme--catppuccin-latte .hero.is-light .subtitle a:not(.button),html.theme--catppuccin-latte .hero.is-light .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .hero.is-light .navbar-menu{background-color:#f5f5f5}}html.theme--catppuccin-latte .hero.is-light .navbar-item,html.theme--catppuccin-latte .hero.is-light .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .hero.is-light a.navbar-item:hover,html.theme--catppuccin-latte .hero.is-light a.navbar-item.is-active,html.theme--catppuccin-latte .hero.is-light .navbar-link:hover,html.theme--catppuccin-latte .hero.is-light .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .hero.is-light .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--catppuccin-latte .hero.is-light .tabs a:hover{opacity:1}html.theme--catppuccin-latte .hero.is-light .tabs li.is-active a{color:#f5f5f5 !important;opacity:1}html.theme--catppuccin-latte .hero.is-light .tabs.is-boxed a,html.theme--catppuccin-latte .hero.is-light .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .hero.is-light .tabs.is-boxed a:hover,html.theme--catppuccin-latte .hero.is-light .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-latte .hero.is-light .tabs.is-boxed li.is-active a,html.theme--catppuccin-latte .hero.is-light .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-latte .hero.is-light .tabs.is-toggle li.is-active a,html.theme--catppuccin-latte .hero.is-light .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#f5f5f5}html.theme--catppuccin-latte .hero.is-light.is-bold{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-latte .hero.is-light.is-bold .navbar-menu{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}}html.theme--catppuccin-latte .hero.is-dark,html.theme--catppuccin-latte .content kbd.hero{background-color:#ccd0da;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-latte .content kbd.hero a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-latte .hero.is-dark strong,html.theme--catppuccin-latte .content kbd.hero strong{color:inherit}html.theme--catppuccin-latte .hero.is-dark .title,html.theme--catppuccin-latte .content kbd.hero .title{color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .hero.is-dark .subtitle,html.theme--catppuccin-latte .content kbd.hero .subtitle{color:rgba(0,0,0,0.9)}html.theme--catppuccin-latte .hero.is-dark .subtitle a:not(.button),html.theme--catppuccin-latte .content kbd.hero .subtitle a:not(.button),html.theme--catppuccin-latte .hero.is-dark .subtitle strong,html.theme--catppuccin-latte .content kbd.hero .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .hero.is-dark .navbar-menu,html.theme--catppuccin-latte .content kbd.hero .navbar-menu{background-color:#ccd0da}}html.theme--catppuccin-latte .hero.is-dark .navbar-item,html.theme--catppuccin-latte .content kbd.hero .navbar-item,html.theme--catppuccin-latte .hero.is-dark .navbar-link,html.theme--catppuccin-latte .content kbd.hero .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .hero.is-dark a.navbar-item:hover,html.theme--catppuccin-latte .content kbd.hero a.navbar-item:hover,html.theme--catppuccin-latte .hero.is-dark a.navbar-item.is-active,html.theme--catppuccin-latte .content kbd.hero a.navbar-item.is-active,html.theme--catppuccin-latte .hero.is-dark .navbar-link:hover,html.theme--catppuccin-latte .content kbd.hero .navbar-link:hover,html.theme--catppuccin-latte .hero.is-dark .navbar-link.is-active,html.theme--catppuccin-latte .content kbd.hero .navbar-link.is-active{background-color:#bdc2cf;color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .hero.is-dark .tabs a,html.theme--catppuccin-latte .content kbd.hero .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--catppuccin-latte .hero.is-dark .tabs a:hover,html.theme--catppuccin-latte .content kbd.hero .tabs a:hover{opacity:1}html.theme--catppuccin-latte .hero.is-dark .tabs li.is-active a,html.theme--catppuccin-latte .content kbd.hero .tabs li.is-active a{color:#ccd0da !important;opacity:1}html.theme--catppuccin-latte .hero.is-dark .tabs.is-boxed a,html.theme--catppuccin-latte .content kbd.hero .tabs.is-boxed a,html.theme--catppuccin-latte .hero.is-dark .tabs.is-toggle a,html.theme--catppuccin-latte .content kbd.hero .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--catppuccin-latte .hero.is-dark .tabs.is-boxed a:hover,html.theme--catppuccin-latte .content kbd.hero .tabs.is-boxed a:hover,html.theme--catppuccin-latte .hero.is-dark .tabs.is-toggle a:hover,html.theme--catppuccin-latte .content kbd.hero .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-latte .hero.is-dark .tabs.is-boxed li.is-active a,html.theme--catppuccin-latte .content kbd.hero .tabs.is-boxed li.is-active a,html.theme--catppuccin-latte .hero.is-dark .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-latte .hero.is-dark .tabs.is-toggle li.is-active a,html.theme--catppuccin-latte .content kbd.hero .tabs.is-toggle li.is-active a,html.theme--catppuccin-latte .hero.is-dark .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#ccd0da}html.theme--catppuccin-latte .hero.is-dark.is-bold,html.theme--catppuccin-latte .content kbd.hero.is-bold{background-image:linear-gradient(141deg, #a7b8cc 0%, #ccd0da 71%, #d9dbe6 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-latte .hero.is-dark.is-bold .navbar-menu,html.theme--catppuccin-latte .content kbd.hero.is-bold .navbar-menu{background-image:linear-gradient(141deg, #a7b8cc 0%, #ccd0da 71%, #d9dbe6 100%)}}html.theme--catppuccin-latte .hero.is-primary,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink{background-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-latte .hero.is-primary strong,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink strong{color:inherit}html.theme--catppuccin-latte .hero.is-primary .title,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink .title{color:#fff}html.theme--catppuccin-latte .hero.is-primary .subtitle,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-latte .hero.is-primary .subtitle a:not(.button),html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink .subtitle a:not(.button),html.theme--catppuccin-latte .hero.is-primary .subtitle strong,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .hero.is-primary .navbar-menu,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink .navbar-menu{background-color:#1e66f5}}html.theme--catppuccin-latte .hero.is-primary .navbar-item,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink .navbar-item,html.theme--catppuccin-latte .hero.is-primary .navbar-link,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-latte .hero.is-primary a.navbar-item:hover,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink a.navbar-item:hover,html.theme--catppuccin-latte .hero.is-primary a.navbar-item.is-active,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink a.navbar-item.is-active,html.theme--catppuccin-latte .hero.is-primary .navbar-link:hover,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink .navbar-link:hover,html.theme--catppuccin-latte .hero.is-primary .navbar-link.is-active,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink .navbar-link.is-active{background-color:#0b57ef;color:#fff}html.theme--catppuccin-latte .hero.is-primary .tabs a,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-latte .hero.is-primary .tabs a:hover,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink .tabs a:hover{opacity:1}html.theme--catppuccin-latte .hero.is-primary .tabs li.is-active a,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink .tabs li.is-active a{color:#1e66f5 !important;opacity:1}html.theme--catppuccin-latte .hero.is-primary .tabs.is-boxed a,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a,html.theme--catppuccin-latte .hero.is-primary .tabs.is-toggle a,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a{color:#fff}html.theme--catppuccin-latte .hero.is-primary .tabs.is-boxed a:hover,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a:hover,html.theme--catppuccin-latte .hero.is-primary .tabs.is-toggle a:hover,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-latte .hero.is-primary .tabs.is-boxed li.is-active a,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed li.is-active a,html.theme--catppuccin-latte .hero.is-primary .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-latte .hero.is-primary .tabs.is-toggle li.is-active a,html.theme--catppuccin-latte .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle li.is-active a,html.theme--catppuccin-latte .hero.is-primary .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#1e66f5}html.theme--catppuccin-latte .hero.is-primary.is-bold,html.theme--catppuccin-latte .docstring>section>a.hero.is-bold.docs-sourcelink{background-image:linear-gradient(141deg, #0070e0 0%, #1e66f5 71%, #3153fb 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-latte .hero.is-primary.is-bold .navbar-menu,html.theme--catppuccin-latte .docstring>section>a.hero.is-bold.docs-sourcelink .navbar-menu{background-image:linear-gradient(141deg, #0070e0 0%, #1e66f5 71%, #3153fb 100%)}}html.theme--catppuccin-latte .hero.is-link{background-color:#1e66f5;color:#fff}html.theme--catppuccin-latte .hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-latte .hero.is-link strong{color:inherit}html.theme--catppuccin-latte .hero.is-link .title{color:#fff}html.theme--catppuccin-latte .hero.is-link .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-latte .hero.is-link .subtitle a:not(.button),html.theme--catppuccin-latte .hero.is-link .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .hero.is-link .navbar-menu{background-color:#1e66f5}}html.theme--catppuccin-latte .hero.is-link .navbar-item,html.theme--catppuccin-latte .hero.is-link .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-latte .hero.is-link a.navbar-item:hover,html.theme--catppuccin-latte .hero.is-link a.navbar-item.is-active,html.theme--catppuccin-latte .hero.is-link .navbar-link:hover,html.theme--catppuccin-latte .hero.is-link .navbar-link.is-active{background-color:#0b57ef;color:#fff}html.theme--catppuccin-latte .hero.is-link .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-latte .hero.is-link .tabs a:hover{opacity:1}html.theme--catppuccin-latte .hero.is-link .tabs li.is-active a{color:#1e66f5 !important;opacity:1}html.theme--catppuccin-latte .hero.is-link .tabs.is-boxed a,html.theme--catppuccin-latte .hero.is-link .tabs.is-toggle a{color:#fff}html.theme--catppuccin-latte .hero.is-link .tabs.is-boxed a:hover,html.theme--catppuccin-latte .hero.is-link .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-latte .hero.is-link .tabs.is-boxed li.is-active a,html.theme--catppuccin-latte .hero.is-link .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-latte .hero.is-link .tabs.is-toggle li.is-active a,html.theme--catppuccin-latte .hero.is-link .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#1e66f5}html.theme--catppuccin-latte .hero.is-link.is-bold{background-image:linear-gradient(141deg, #0070e0 0%, #1e66f5 71%, #3153fb 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-latte .hero.is-link.is-bold .navbar-menu{background-image:linear-gradient(141deg, #0070e0 0%, #1e66f5 71%, #3153fb 100%)}}html.theme--catppuccin-latte .hero.is-info{background-color:#179299;color:#fff}html.theme--catppuccin-latte .hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-latte .hero.is-info strong{color:inherit}html.theme--catppuccin-latte .hero.is-info .title{color:#fff}html.theme--catppuccin-latte .hero.is-info .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-latte .hero.is-info .subtitle a:not(.button),html.theme--catppuccin-latte .hero.is-info .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .hero.is-info .navbar-menu{background-color:#179299}}html.theme--catppuccin-latte .hero.is-info .navbar-item,html.theme--catppuccin-latte .hero.is-info .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-latte .hero.is-info a.navbar-item:hover,html.theme--catppuccin-latte .hero.is-info a.navbar-item.is-active,html.theme--catppuccin-latte .hero.is-info .navbar-link:hover,html.theme--catppuccin-latte .hero.is-info .navbar-link.is-active{background-color:#147d83;color:#fff}html.theme--catppuccin-latte .hero.is-info .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-latte .hero.is-info .tabs a:hover{opacity:1}html.theme--catppuccin-latte .hero.is-info .tabs li.is-active a{color:#179299 !important;opacity:1}html.theme--catppuccin-latte .hero.is-info .tabs.is-boxed a,html.theme--catppuccin-latte .hero.is-info .tabs.is-toggle a{color:#fff}html.theme--catppuccin-latte .hero.is-info .tabs.is-boxed a:hover,html.theme--catppuccin-latte .hero.is-info .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-latte .hero.is-info .tabs.is-boxed li.is-active a,html.theme--catppuccin-latte .hero.is-info .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-latte .hero.is-info .tabs.is-toggle li.is-active a,html.theme--catppuccin-latte .hero.is-info .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#179299}html.theme--catppuccin-latte .hero.is-info.is-bold{background-image:linear-gradient(141deg, #0a7367 0%, #179299 71%, #1591b4 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-latte .hero.is-info.is-bold .navbar-menu{background-image:linear-gradient(141deg, #0a7367 0%, #179299 71%, #1591b4 100%)}}html.theme--catppuccin-latte .hero.is-success{background-color:#40a02b;color:#fff}html.theme--catppuccin-latte .hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-latte .hero.is-success strong{color:inherit}html.theme--catppuccin-latte .hero.is-success .title{color:#fff}html.theme--catppuccin-latte .hero.is-success .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-latte .hero.is-success .subtitle a:not(.button),html.theme--catppuccin-latte .hero.is-success .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .hero.is-success .navbar-menu{background-color:#40a02b}}html.theme--catppuccin-latte .hero.is-success .navbar-item,html.theme--catppuccin-latte .hero.is-success .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-latte .hero.is-success a.navbar-item:hover,html.theme--catppuccin-latte .hero.is-success a.navbar-item.is-active,html.theme--catppuccin-latte .hero.is-success .navbar-link:hover,html.theme--catppuccin-latte .hero.is-success .navbar-link.is-active{background-color:#388c26;color:#fff}html.theme--catppuccin-latte .hero.is-success .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-latte .hero.is-success .tabs a:hover{opacity:1}html.theme--catppuccin-latte .hero.is-success .tabs li.is-active a{color:#40a02b !important;opacity:1}html.theme--catppuccin-latte .hero.is-success .tabs.is-boxed a,html.theme--catppuccin-latte .hero.is-success .tabs.is-toggle a{color:#fff}html.theme--catppuccin-latte .hero.is-success .tabs.is-boxed a:hover,html.theme--catppuccin-latte .hero.is-success .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-latte .hero.is-success .tabs.is-boxed li.is-active a,html.theme--catppuccin-latte .hero.is-success .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-latte .hero.is-success .tabs.is-toggle li.is-active a,html.theme--catppuccin-latte .hero.is-success .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#40a02b}html.theme--catppuccin-latte .hero.is-success.is-bold{background-image:linear-gradient(141deg, #3c7f19 0%, #40a02b 71%, #2dba2b 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-latte .hero.is-success.is-bold .navbar-menu{background-image:linear-gradient(141deg, #3c7f19 0%, #40a02b 71%, #2dba2b 100%)}}html.theme--catppuccin-latte .hero.is-warning{background-color:#df8e1d;color:#fff}html.theme--catppuccin-latte .hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-latte .hero.is-warning strong{color:inherit}html.theme--catppuccin-latte .hero.is-warning .title{color:#fff}html.theme--catppuccin-latte .hero.is-warning .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-latte .hero.is-warning .subtitle a:not(.button),html.theme--catppuccin-latte .hero.is-warning .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .hero.is-warning .navbar-menu{background-color:#df8e1d}}html.theme--catppuccin-latte .hero.is-warning .navbar-item,html.theme--catppuccin-latte .hero.is-warning .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-latte .hero.is-warning a.navbar-item:hover,html.theme--catppuccin-latte .hero.is-warning a.navbar-item.is-active,html.theme--catppuccin-latte .hero.is-warning .navbar-link:hover,html.theme--catppuccin-latte .hero.is-warning .navbar-link.is-active{background-color:#c8801a;color:#fff}html.theme--catppuccin-latte .hero.is-warning .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-latte .hero.is-warning .tabs a:hover{opacity:1}html.theme--catppuccin-latte .hero.is-warning .tabs li.is-active a{color:#df8e1d !important;opacity:1}html.theme--catppuccin-latte .hero.is-warning .tabs.is-boxed a,html.theme--catppuccin-latte .hero.is-warning .tabs.is-toggle a{color:#fff}html.theme--catppuccin-latte .hero.is-warning .tabs.is-boxed a:hover,html.theme--catppuccin-latte .hero.is-warning .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-latte .hero.is-warning .tabs.is-boxed li.is-active a,html.theme--catppuccin-latte .hero.is-warning .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-latte .hero.is-warning .tabs.is-toggle li.is-active a,html.theme--catppuccin-latte .hero.is-warning .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#df8e1d}html.theme--catppuccin-latte .hero.is-warning.is-bold{background-image:linear-gradient(141deg, #bc560d 0%, #df8e1d 71%, #eaba2b 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-latte .hero.is-warning.is-bold .navbar-menu{background-image:linear-gradient(141deg, #bc560d 0%, #df8e1d 71%, #eaba2b 100%)}}html.theme--catppuccin-latte .hero.is-danger{background-color:#d20f39;color:#fff}html.theme--catppuccin-latte .hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-latte .hero.is-danger strong{color:inherit}html.theme--catppuccin-latte .hero.is-danger .title{color:#fff}html.theme--catppuccin-latte .hero.is-danger .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-latte .hero.is-danger .subtitle a:not(.button),html.theme--catppuccin-latte .hero.is-danger .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .hero.is-danger .navbar-menu{background-color:#d20f39}}html.theme--catppuccin-latte .hero.is-danger .navbar-item,html.theme--catppuccin-latte .hero.is-danger .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-latte .hero.is-danger a.navbar-item:hover,html.theme--catppuccin-latte .hero.is-danger a.navbar-item.is-active,html.theme--catppuccin-latte .hero.is-danger .navbar-link:hover,html.theme--catppuccin-latte .hero.is-danger .navbar-link.is-active{background-color:#ba0d33;color:#fff}html.theme--catppuccin-latte .hero.is-danger .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-latte .hero.is-danger .tabs a:hover{opacity:1}html.theme--catppuccin-latte .hero.is-danger .tabs li.is-active a{color:#d20f39 !important;opacity:1}html.theme--catppuccin-latte .hero.is-danger .tabs.is-boxed a,html.theme--catppuccin-latte .hero.is-danger .tabs.is-toggle a{color:#fff}html.theme--catppuccin-latte .hero.is-danger .tabs.is-boxed a:hover,html.theme--catppuccin-latte .hero.is-danger .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-latte .hero.is-danger .tabs.is-boxed li.is-active a,html.theme--catppuccin-latte .hero.is-danger .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-latte .hero.is-danger .tabs.is-toggle li.is-active a,html.theme--catppuccin-latte .hero.is-danger .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#d20f39}html.theme--catppuccin-latte .hero.is-danger.is-bold{background-image:linear-gradient(141deg, #ab0343 0%, #d20f39 71%, #f00a16 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-latte .hero.is-danger.is-bold .navbar-menu{background-image:linear-gradient(141deg, #ab0343 0%, #d20f39 71%, #f00a16 100%)}}html.theme--catppuccin-latte .hero.is-small .hero-body,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.hero .hero-body{padding:1.5rem}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .hero.is-medium .hero-body{padding:9rem 4.5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .hero.is-large .hero-body{padding:18rem 6rem}}html.theme--catppuccin-latte .hero.is-halfheight .hero-body,html.theme--catppuccin-latte .hero.is-fullheight .hero-body,html.theme--catppuccin-latte .hero.is-fullheight-with-navbar .hero-body{align-items:center;display:flex}html.theme--catppuccin-latte .hero.is-halfheight .hero-body>.container,html.theme--catppuccin-latte .hero.is-fullheight .hero-body>.container,html.theme--catppuccin-latte .hero.is-fullheight-with-navbar .hero-body>.container{flex-grow:1;flex-shrink:1}html.theme--catppuccin-latte .hero.is-halfheight{min-height:50vh}html.theme--catppuccin-latte .hero.is-fullheight{min-height:100vh}html.theme--catppuccin-latte .hero-video{overflow:hidden}html.theme--catppuccin-latte .hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;transform:translate3d(-50%, -50%, 0)}html.theme--catppuccin-latte .hero-video.is-transparent{opacity:0.3}@media screen and (max-width: 768px){html.theme--catppuccin-latte .hero-video{display:none}}html.theme--catppuccin-latte .hero-buttons{margin-top:1.5rem}@media screen and (max-width: 768px){html.theme--catppuccin-latte .hero-buttons .button{display:flex}html.theme--catppuccin-latte .hero-buttons .button:not(:last-child){margin-bottom:0.75rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .hero-buttons{display:flex;justify-content:center}html.theme--catppuccin-latte .hero-buttons .button:not(:last-child){margin-right:1.5rem}}html.theme--catppuccin-latte .hero-head,html.theme--catppuccin-latte .hero-foot{flex-grow:0;flex-shrink:0}html.theme--catppuccin-latte .hero-body{flex-grow:1;flex-shrink:0;padding:3rem 1.5rem}@media screen and (min-width: 769px),print{html.theme--catppuccin-latte .hero-body{padding:3rem 3rem}}html.theme--catppuccin-latte .section{padding:3rem 1.5rem}@media screen and (min-width: 1056px){html.theme--catppuccin-latte .section{padding:3rem 3rem}html.theme--catppuccin-latte .section.is-medium{padding:9rem 4.5rem}html.theme--catppuccin-latte .section.is-large{padding:18rem 6rem}}html.theme--catppuccin-latte .footer{background-color:#e6e9ef;padding:3rem 1.5rem 6rem}html.theme--catppuccin-latte h1 .docs-heading-anchor,html.theme--catppuccin-latte h1 .docs-heading-anchor:hover,html.theme--catppuccin-latte h1 .docs-heading-anchor:visited,html.theme--catppuccin-latte h2 .docs-heading-anchor,html.theme--catppuccin-latte h2 .docs-heading-anchor:hover,html.theme--catppuccin-latte h2 .docs-heading-anchor:visited,html.theme--catppuccin-latte h3 .docs-heading-anchor,html.theme--catppuccin-latte h3 .docs-heading-anchor:hover,html.theme--catppuccin-latte h3 .docs-heading-anchor:visited,html.theme--catppuccin-latte h4 .docs-heading-anchor,html.theme--catppuccin-latte h4 .docs-heading-anchor:hover,html.theme--catppuccin-latte h4 .docs-heading-anchor:visited,html.theme--catppuccin-latte h5 .docs-heading-anchor,html.theme--catppuccin-latte h5 .docs-heading-anchor:hover,html.theme--catppuccin-latte h5 .docs-heading-anchor:visited,html.theme--catppuccin-latte h6 .docs-heading-anchor,html.theme--catppuccin-latte h6 .docs-heading-anchor:hover,html.theme--catppuccin-latte h6 .docs-heading-anchor:visited{color:#4c4f69}html.theme--catppuccin-latte h1 .docs-heading-anchor-permalink,html.theme--catppuccin-latte h2 .docs-heading-anchor-permalink,html.theme--catppuccin-latte h3 .docs-heading-anchor-permalink,html.theme--catppuccin-latte h4 .docs-heading-anchor-permalink,html.theme--catppuccin-latte h5 .docs-heading-anchor-permalink,html.theme--catppuccin-latte h6 .docs-heading-anchor-permalink{visibility:hidden;vertical-align:middle;margin-left:0.5em;font-size:0.7rem}html.theme--catppuccin-latte h1 .docs-heading-anchor-permalink::before,html.theme--catppuccin-latte h2 .docs-heading-anchor-permalink::before,html.theme--catppuccin-latte h3 .docs-heading-anchor-permalink::before,html.theme--catppuccin-latte h4 .docs-heading-anchor-permalink::before,html.theme--catppuccin-latte h5 .docs-heading-anchor-permalink::before,html.theme--catppuccin-latte h6 .docs-heading-anchor-permalink::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f0c1"}html.theme--catppuccin-latte h1:hover .docs-heading-anchor-permalink,html.theme--catppuccin-latte h2:hover .docs-heading-anchor-permalink,html.theme--catppuccin-latte h3:hover .docs-heading-anchor-permalink,html.theme--catppuccin-latte h4:hover .docs-heading-anchor-permalink,html.theme--catppuccin-latte h5:hover .docs-heading-anchor-permalink,html.theme--catppuccin-latte h6:hover .docs-heading-anchor-permalink{visibility:visible}html.theme--catppuccin-latte .docs-dark-only{display:none !important}html.theme--catppuccin-latte pre{position:relative;overflow:hidden}html.theme--catppuccin-latte pre code,html.theme--catppuccin-latte pre code.hljs{padding:0 .75rem !important;overflow:auto;display:block}html.theme--catppuccin-latte pre code:first-of-type,html.theme--catppuccin-latte pre code.hljs:first-of-type{padding-top:0.5rem !important}html.theme--catppuccin-latte pre code:last-of-type,html.theme--catppuccin-latte pre code.hljs:last-of-type{padding-bottom:0.5rem !important}html.theme--catppuccin-latte pre .copy-button{opacity:0.2;transition:opacity 0.2s;position:absolute;right:0em;top:0em;padding:0.5em;width:2.5em;height:2.5em;background:transparent;border:none;font-family:"Font Awesome 6 Free";color:#4c4f69;cursor:pointer;text-align:center}html.theme--catppuccin-latte pre .copy-button:focus,html.theme--catppuccin-latte pre .copy-button:hover{opacity:1;background:rgba(76,79,105,0.1);color:#1e66f5}html.theme--catppuccin-latte pre .copy-button.success{color:#40a02b;opacity:1}html.theme--catppuccin-latte pre .copy-button.error{color:#d20f39;opacity:1}html.theme--catppuccin-latte pre:hover .copy-button{opacity:1}html.theme--catppuccin-latte .admonition{background-color:#e6e9ef;border-style:solid;border-width:2px;border-color:#5c5f77;border-radius:4px;font-size:1rem}html.theme--catppuccin-latte .admonition strong{color:currentColor}html.theme--catppuccin-latte .admonition.is-small,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input.admonition{font-size:.75rem}html.theme--catppuccin-latte .admonition.is-medium{font-size:1.25rem}html.theme--catppuccin-latte .admonition.is-large{font-size:1.5rem}html.theme--catppuccin-latte .admonition.is-default{background-color:#e6e9ef;border-color:#5c5f77}html.theme--catppuccin-latte .admonition.is-default>.admonition-header{background-color:rgba(0,0,0,0);color:#5c5f77}html.theme--catppuccin-latte .admonition.is-default>.admonition-body{color:#4c4f69}html.theme--catppuccin-latte .admonition.is-info{background-color:#e6e9ef;border-color:#179299}html.theme--catppuccin-latte .admonition.is-info>.admonition-header{background-color:rgba(0,0,0,0);color:#179299}html.theme--catppuccin-latte .admonition.is-info>.admonition-body{color:#4c4f69}html.theme--catppuccin-latte .admonition.is-success{background-color:#e6e9ef;border-color:#40a02b}html.theme--catppuccin-latte .admonition.is-success>.admonition-header{background-color:rgba(0,0,0,0);color:#40a02b}html.theme--catppuccin-latte .admonition.is-success>.admonition-body{color:#4c4f69}html.theme--catppuccin-latte .admonition.is-warning{background-color:#e6e9ef;border-color:#df8e1d}html.theme--catppuccin-latte .admonition.is-warning>.admonition-header{background-color:rgba(0,0,0,0);color:#df8e1d}html.theme--catppuccin-latte .admonition.is-warning>.admonition-body{color:#4c4f69}html.theme--catppuccin-latte .admonition.is-danger{background-color:#e6e9ef;border-color:#d20f39}html.theme--catppuccin-latte .admonition.is-danger>.admonition-header{background-color:rgba(0,0,0,0);color:#d20f39}html.theme--catppuccin-latte .admonition.is-danger>.admonition-body{color:#4c4f69}html.theme--catppuccin-latte .admonition.is-compat{background-color:#e6e9ef;border-color:#04a5e5}html.theme--catppuccin-latte .admonition.is-compat>.admonition-header{background-color:rgba(0,0,0,0);color:#04a5e5}html.theme--catppuccin-latte .admonition.is-compat>.admonition-body{color:#4c4f69}html.theme--catppuccin-latte .admonition.is-todo{background-color:#e6e9ef;border-color:#8839ef}html.theme--catppuccin-latte .admonition.is-todo>.admonition-header{background-color:rgba(0,0,0,0);color:#8839ef}html.theme--catppuccin-latte .admonition.is-todo>.admonition-body{color:#4c4f69}html.theme--catppuccin-latte .admonition-header{color:#5c5f77;background-color:rgba(0,0,0,0);align-items:center;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.5rem .75rem;position:relative}html.theme--catppuccin-latte .admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;margin-right:.75rem;content:"\f06a"}html.theme--catppuccin-latte details.admonition.is-details>.admonition-header{list-style:none}html.theme--catppuccin-latte details.admonition.is-details>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f055"}html.theme--catppuccin-latte details.admonition.is-details[open]>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f056"}html.theme--catppuccin-latte .admonition-body{color:#4c4f69;padding:0.5rem .75rem}html.theme--catppuccin-latte .admonition-body pre{background-color:#e6e9ef}html.theme--catppuccin-latte .admonition-body code{background-color:#e6e9ef}html.theme--catppuccin-latte .docstring{margin-bottom:1em;background-color:rgba(0,0,0,0);border:2px solid #acb0be;border-radius:4px;box-shadow:none;max-width:100%}html.theme--catppuccin-latte .docstring>header{cursor:pointer;display:flex;flex-grow:1;align-items:stretch;padding:0.5rem .75rem;background-color:#e6e9ef;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);box-shadow:none;border-bottom:1px solid #acb0be;overflow:auto}html.theme--catppuccin-latte .docstring>header code{background-color:transparent}html.theme--catppuccin-latte .docstring>header .docstring-article-toggle-button{min-width:1.1rem;padding:0.2rem 0.2rem 0.2rem 0}html.theme--catppuccin-latte .docstring>header .docstring-binding{margin-right:0.3em}html.theme--catppuccin-latte .docstring>header .docstring-category{margin-left:0.3em}html.theme--catppuccin-latte .docstring>section{position:relative;padding:.75rem .75rem;border-bottom:1px solid #acb0be}html.theme--catppuccin-latte .docstring>section:last-child{border-bottom:none}html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink{transition:opacity 0.3s;opacity:0;position:absolute;right:.375rem;bottom:.375rem}html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink:focus{opacity:1 !important}html.theme--catppuccin-latte .docstring:hover>section>a.docs-sourcelink{opacity:0.2}html.theme--catppuccin-latte .docstring:focus-within>section>a.docs-sourcelink{opacity:0.2}html.theme--catppuccin-latte .docstring>section:hover a.docs-sourcelink{opacity:1}html.theme--catppuccin-latte .documenter-example-output{background-color:#eff1f5}html.theme--catppuccin-latte .outdated-warning-overlay{position:fixed;top:0;left:0;right:0;box-shadow:0 0 10px rgba(0,0,0,0.3);z-index:999;background-color:#e6e9ef;color:#4c4f69;border-bottom:3px solid rgba(0,0,0,0);padding:10px 35px;text-align:center;font-size:15px}html.theme--catppuccin-latte .outdated-warning-overlay .outdated-warning-closer{position:absolute;top:calc(50% - 10px);right:18px;cursor:pointer;width:12px}html.theme--catppuccin-latte .outdated-warning-overlay a{color:#1e66f5}html.theme--catppuccin-latte .outdated-warning-overlay a:hover{color:#04a5e5}html.theme--catppuccin-latte .content pre{border:2px solid #acb0be;border-radius:4px}html.theme--catppuccin-latte .content code{font-weight:inherit}html.theme--catppuccin-latte .content a code{color:#1e66f5}html.theme--catppuccin-latte .content a:hover code{color:#04a5e5}html.theme--catppuccin-latte .content h1 code,html.theme--catppuccin-latte .content h2 code,html.theme--catppuccin-latte .content h3 code,html.theme--catppuccin-latte .content h4 code,html.theme--catppuccin-latte .content h5 code,html.theme--catppuccin-latte .content h6 code{color:#4c4f69}html.theme--catppuccin-latte .content table{display:block;width:initial;max-width:100%;overflow-x:auto}html.theme--catppuccin-latte .content blockquote>ul:first-child,html.theme--catppuccin-latte .content blockquote>ol:first-child,html.theme--catppuccin-latte .content .admonition-body>ul:first-child,html.theme--catppuccin-latte .content .admonition-body>ol:first-child{margin-top:0}html.theme--catppuccin-latte pre,html.theme--catppuccin-latte code{font-variant-ligatures:no-contextual}html.theme--catppuccin-latte .breadcrumb a.is-disabled{cursor:default;pointer-events:none}html.theme--catppuccin-latte .breadcrumb a.is-disabled,html.theme--catppuccin-latte .breadcrumb a.is-disabled:hover{color:#41445a}html.theme--catppuccin-latte .hljs{background:initial !important}html.theme--catppuccin-latte .katex .katex-mathml{top:0;right:0}html.theme--catppuccin-latte .katex-display,html.theme--catppuccin-latte mjx-container,html.theme--catppuccin-latte .MathJax_Display{margin:0.5em 0 !important}html.theme--catppuccin-latte html{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto}html.theme--catppuccin-latte li.no-marker{list-style:none}html.theme--catppuccin-latte #documenter .docs-main>article{overflow-wrap:break-word}html.theme--catppuccin-latte #documenter .docs-main>article .math-container{overflow-x:auto;overflow-y:hidden}@media screen and (min-width: 1056px){html.theme--catppuccin-latte #documenter .docs-main{max-width:52rem;margin-left:20rem;padding-right:1rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-latte #documenter .docs-main{width:100%}html.theme--catppuccin-latte #documenter .docs-main>article{max-width:52rem;margin-left:auto;margin-right:auto;margin-bottom:1rem;padding:0 1rem}html.theme--catppuccin-latte #documenter .docs-main>header,html.theme--catppuccin-latte #documenter .docs-main>nav{max-width:100%;width:100%;margin:0}}html.theme--catppuccin-latte #documenter .docs-main header.docs-navbar{background-color:#eff1f5;border-bottom:1px solid #acb0be;z-index:2;min-height:4rem;margin-bottom:1rem;display:flex}html.theme--catppuccin-latte #documenter .docs-main header.docs-navbar .breadcrumb{flex-grow:1;overflow-x:hidden}html.theme--catppuccin-latte #documenter .docs-main header.docs-navbar .docs-sidebar-button{display:block;font-size:1.5rem;padding-bottom:0.1rem;margin-right:1rem}html.theme--catppuccin-latte #documenter .docs-main header.docs-navbar .docs-right{display:flex;white-space:nowrap;gap:1rem;align-items:center}html.theme--catppuccin-latte #documenter .docs-main header.docs-navbar .docs-right .docs-icon,html.theme--catppuccin-latte #documenter .docs-main header.docs-navbar .docs-right .docs-label{display:inline-block}html.theme--catppuccin-latte #documenter .docs-main header.docs-navbar .docs-right .docs-label{padding:0;margin-left:0.3em}@media screen and (max-width: 1055px){html.theme--catppuccin-latte #documenter .docs-main header.docs-navbar .docs-right .docs-navbar-link{margin-left:0.4rem;margin-right:0.4rem}}html.theme--catppuccin-latte #documenter .docs-main header.docs-navbar>*{margin:auto 0}@media screen and (max-width: 1055px){html.theme--catppuccin-latte #documenter .docs-main header.docs-navbar{position:sticky;top:0;padding:0 1rem;transition-property:top, box-shadow;-webkit-transition-property:top, box-shadow;transition-duration:0.3s;-webkit-transition-duration:0.3s}html.theme--catppuccin-latte #documenter .docs-main header.docs-navbar.headroom--not-top{box-shadow:.2rem 0rem .4rem #171717;transition-duration:0.7s;-webkit-transition-duration:0.7s}html.theme--catppuccin-latte #documenter .docs-main header.docs-navbar.headroom--unpinned.headroom--not-top.headroom--not-bottom{top:-4.5rem;transition-duration:0.7s;-webkit-transition-duration:0.7s}}html.theme--catppuccin-latte #documenter .docs-main section.footnotes{border-top:1px solid #acb0be}html.theme--catppuccin-latte #documenter .docs-main section.footnotes li .tag:first-child,html.theme--catppuccin-latte #documenter .docs-main section.footnotes li .docstring>section>a.docs-sourcelink:first-child,html.theme--catppuccin-latte #documenter .docs-main section.footnotes li .content kbd:first-child,html.theme--catppuccin-latte .content #documenter .docs-main section.footnotes li kbd:first-child{margin-right:1em;margin-bottom:0.4em}html.theme--catppuccin-latte #documenter .docs-main .docs-footer{display:flex;flex-wrap:wrap;margin-left:0;margin-right:0;border-top:1px solid #acb0be;padding-top:1rem;padding-bottom:1rem}@media screen and (max-width: 1055px){html.theme--catppuccin-latte #documenter .docs-main .docs-footer{padding-left:1rem;padding-right:1rem}}html.theme--catppuccin-latte #documenter .docs-main .docs-footer .docs-footer-nextpage,html.theme--catppuccin-latte #documenter .docs-main .docs-footer .docs-footer-prevpage{flex-grow:1}html.theme--catppuccin-latte #documenter .docs-main .docs-footer .docs-footer-nextpage{text-align:right}html.theme--catppuccin-latte #documenter .docs-main .docs-footer .flexbox-break{flex-basis:100%;height:0}html.theme--catppuccin-latte #documenter .docs-main .docs-footer .footer-message{font-size:0.8em;margin:0.5em auto 0 auto;text-align:center}html.theme--catppuccin-latte #documenter .docs-sidebar{display:flex;flex-direction:column;color:#4c4f69;background-color:#e6e9ef;border-right:1px solid #acb0be;padding:0;flex:0 0 18rem;z-index:5;font-size:1rem;position:fixed;left:-18rem;width:18rem;height:100%;transition:left 0.3s}html.theme--catppuccin-latte #documenter .docs-sidebar.visible{left:0;box-shadow:.4rem 0rem .8rem #171717}@media screen and (min-width: 1056px){html.theme--catppuccin-latte #documenter .docs-sidebar.visible{box-shadow:none}}@media screen and (min-width: 1056px){html.theme--catppuccin-latte #documenter .docs-sidebar{left:0;top:0}}html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo{margin-top:1rem;padding:0 1rem}html.theme--catppuccin-latte #documenter .docs-sidebar .docs-logo>img{max-height:6rem;margin:auto}html.theme--catppuccin-latte #documenter .docs-sidebar .docs-package-name{flex-shrink:0;font-size:1.5rem;font-weight:700;text-align:center;white-space:nowrap;overflow:hidden;padding:0.5rem 0}html.theme--catppuccin-latte #documenter .docs-sidebar .docs-package-name .docs-autofit{max-width:16.2rem}html.theme--catppuccin-latte #documenter .docs-sidebar .docs-package-name a,html.theme--catppuccin-latte #documenter .docs-sidebar .docs-package-name a:hover{color:#4c4f69}html.theme--catppuccin-latte #documenter .docs-sidebar .docs-version-selector{border-top:1px solid #acb0be;display:none;padding:0.5rem}html.theme--catppuccin-latte #documenter .docs-sidebar .docs-version-selector.visible{display:flex}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu{flex-grow:1;user-select:none;border-top:1px solid #acb0be;padding-bottom:1.5rem}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu>li>.tocitem{font-weight:bold}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu>li li{font-size:.95rem;margin-left:1em;border-left:1px solid #acb0be}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu input.collapse-toggle{display:none}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu ul.collapsed{display:none}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu input:checked~ul.collapsed{display:block}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu label.tocitem{display:flex}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-label{flex-grow:2}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-size:.75rem;margin-left:1rem;margin-top:auto;margin-bottom:auto}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f054"}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu input:checked~label.tocitem .docs-chevron::before{content:"\f078"}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu .tocitem{display:block;padding:0.5rem 0.5rem}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu .tocitem,html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu .tocitem:hover{color:#4c4f69;background:#e6e9ef}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu a.tocitem:hover,html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu label.tocitem:hover{color:#4c4f69;background-color:#f2f4f7}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu li.is-active{border-top:1px solid #acb0be;border-bottom:1px solid #acb0be;background-color:#dce0e8}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem,html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem:hover{background-color:#dce0e8;color:#4c4f69}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu li.is-active ul.internal .tocitem:hover{background-color:#f2f4f7;color:#4c4f69}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu>li.is-active:first-child{border-top:none}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu ul.internal{margin:0 0.5rem 0.5rem;border-top:1px solid #acb0be}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu ul.internal li{font-size:.85rem;border-left:none;margin-left:0;margin-top:0.5rem}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem{width:100%;padding:0}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem::before{content:"⚬";margin-right:0.4em}html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search{margin:auto;margin-top:0.5rem;margin-bottom:0.5rem}html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input{width:14.4rem}html.theme--catppuccin-latte #documenter .docs-sidebar #documenter-search-query{color:#868c98;width:14.4rem;box-shadow:inset 0 1px 2px rgba(10,10,10,0.1)}@media screen and (min-width: 1056px){html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar{width:.3rem;background:none}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#fff}html.theme--catppuccin-latte #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb:hover{background:#fff}}@media screen and (max-width: 1055px){html.theme--catppuccin-latte #documenter .docs-sidebar{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--catppuccin-latte #documenter .docs-sidebar::-webkit-scrollbar{width:.3rem;background:none}html.theme--catppuccin-latte #documenter .docs-sidebar::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#fff}html.theme--catppuccin-latte #documenter .docs-sidebar::-webkit-scrollbar-thumb:hover{background:#fff}}html.theme--catppuccin-latte kbd.search-modal-key-hints{border-radius:0.25rem;border:1px solid rgba(245,245,245,0.6);box-shadow:0 2px 0 1px rgba(245,245,245,0.6);cursor:default;font-size:0.9rem;line-height:1.5;min-width:0.75rem;text-align:center;padding:0.1rem 0.3rem;position:relative;top:-1px}html.theme--catppuccin-latte .search-min-width-50{min-width:50%}html.theme--catppuccin-latte .search-min-height-100{min-height:100%}html.theme--catppuccin-latte .search-modal-card-body{max-height:calc(100vh - 15rem)}html.theme--catppuccin-latte .search-result-link{border-radius:0.7em;transition:all 300ms}html.theme--catppuccin-latte .search-result-link:hover,html.theme--catppuccin-latte .search-result-link:focus{background-color:rgba(0,128,128,0.1)}html.theme--catppuccin-latte .search-result-link .property-search-result-badge,html.theme--catppuccin-latte .search-result-link .search-filter{transition:all 300ms}html.theme--catppuccin-latte .property-search-result-badge,html.theme--catppuccin-latte .search-filter{padding:0.15em 0.5em;font-size:0.8em;font-style:italic;text-transform:none !important;line-height:1.5;color:#f5f5f5;background-color:rgba(51,65,85,0.501961);border-radius:0.6rem}html.theme--catppuccin-latte .search-result-link:hover .property-search-result-badge,html.theme--catppuccin-latte .search-result-link:hover .search-filter,html.theme--catppuccin-latte .search-result-link:focus .property-search-result-badge,html.theme--catppuccin-latte .search-result-link:focus .search-filter{color:#333;background-color:#f1f5f9}html.theme--catppuccin-latte .search-filter{color:#333;background-color:#f5f5f5;transition:all 300ms}html.theme--catppuccin-latte .search-filter:hover,html.theme--catppuccin-latte .search-filter:focus{color:#333}html.theme--catppuccin-latte .search-filter-selected{color:#ccd0da;background-color:#7287fd}html.theme--catppuccin-latte .search-filter-selected:hover,html.theme--catppuccin-latte .search-filter-selected:focus{color:#ccd0da}html.theme--catppuccin-latte .search-result-highlight{background-color:#ffdd57;color:black}html.theme--catppuccin-latte .search-divider{border-bottom:1px solid #acb0be}html.theme--catppuccin-latte .search-result-title{width:85%;color:#f5f5f5}html.theme--catppuccin-latte .search-result-code-title{font-size:0.875rem;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}html.theme--catppuccin-latte #search-modal .modal-card-body::-webkit-scrollbar,html.theme--catppuccin-latte #search-modal .filter-tabs::-webkit-scrollbar{height:10px;width:10px;background-color:transparent}html.theme--catppuccin-latte #search-modal .modal-card-body::-webkit-scrollbar-thumb,html.theme--catppuccin-latte #search-modal .filter-tabs::-webkit-scrollbar-thumb{background-color:gray;border-radius:1rem}html.theme--catppuccin-latte #search-modal .modal-card-body::-webkit-scrollbar-track,html.theme--catppuccin-latte #search-modal .filter-tabs::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,0.6);background-color:transparent}html.theme--catppuccin-latte .w-100{width:100%}html.theme--catppuccin-latte .gap-2{gap:0.5rem}html.theme--catppuccin-latte .gap-4{gap:1rem}html.theme--catppuccin-latte .gap-8{gap:2rem}html.theme--catppuccin-latte{background-color:#eff1f5;font-size:16px;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--catppuccin-latte a{transition:all 200ms ease}html.theme--catppuccin-latte .label{color:#4c4f69}html.theme--catppuccin-latte .button,html.theme--catppuccin-latte .control.has-icons-left .icon,html.theme--catppuccin-latte .control.has-icons-right .icon,html.theme--catppuccin-latte .input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-latte .pagination-ellipsis,html.theme--catppuccin-latte .pagination-link,html.theme--catppuccin-latte .pagination-next,html.theme--catppuccin-latte .pagination-previous,html.theme--catppuccin-latte .select,html.theme--catppuccin-latte .select select,html.theme--catppuccin-latte .textarea{height:2.5em;color:#4c4f69}html.theme--catppuccin-latte .input,html.theme--catppuccin-latte #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-latte .textarea{transition:all 200ms ease;box-shadow:none;border-width:1px;padding-left:1em;padding-right:1em;color:#4c4f69}html.theme--catppuccin-latte .select:after,html.theme--catppuccin-latte .select select{border-width:1px}html.theme--catppuccin-latte .menu-list a{transition:all 300ms ease}html.theme--catppuccin-latte .modal-card-foot,html.theme--catppuccin-latte .modal-card-head{border-color:#acb0be}html.theme--catppuccin-latte .navbar{border-radius:.4em}html.theme--catppuccin-latte .navbar.is-transparent{background:none}html.theme--catppuccin-latte .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--catppuccin-latte .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#1e66f5}@media screen and (max-width: 1055px){html.theme--catppuccin-latte .navbar .navbar-menu{background-color:#1e66f5;border-radius:0 0 .4em .4em}}html.theme--catppuccin-latte .docstring>section>a.docs-sourcelink:not(body){color:#ccd0da}html.theme--catppuccin-latte .tag.is-link:not(body),html.theme--catppuccin-latte .docstring>section>a.is-link.docs-sourcelink:not(body),html.theme--catppuccin-latte .content kbd.is-link:not(body){color:#ccd0da}html.theme--catppuccin-latte .ansi span.sgr1{font-weight:bolder}html.theme--catppuccin-latte .ansi span.sgr2{font-weight:lighter}html.theme--catppuccin-latte .ansi span.sgr3{font-style:italic}html.theme--catppuccin-latte .ansi span.sgr4{text-decoration:underline}html.theme--catppuccin-latte .ansi span.sgr7{color:#eff1f5;background-color:#4c4f69}html.theme--catppuccin-latte .ansi span.sgr8{color:transparent}html.theme--catppuccin-latte .ansi span.sgr8 span{color:transparent}html.theme--catppuccin-latte .ansi span.sgr9{text-decoration:line-through}html.theme--catppuccin-latte .ansi span.sgr30{color:#5c5f77}html.theme--catppuccin-latte .ansi span.sgr31{color:#d20f39}html.theme--catppuccin-latte .ansi span.sgr32{color:#40a02b}html.theme--catppuccin-latte .ansi span.sgr33{color:#df8e1d}html.theme--catppuccin-latte .ansi span.sgr34{color:#1e66f5}html.theme--catppuccin-latte .ansi span.sgr35{color:#ea76cb}html.theme--catppuccin-latte .ansi span.sgr36{color:#179299}html.theme--catppuccin-latte .ansi span.sgr37{color:#acb0be}html.theme--catppuccin-latte .ansi span.sgr40{background-color:#5c5f77}html.theme--catppuccin-latte .ansi span.sgr41{background-color:#d20f39}html.theme--catppuccin-latte .ansi span.sgr42{background-color:#40a02b}html.theme--catppuccin-latte .ansi span.sgr43{background-color:#df8e1d}html.theme--catppuccin-latte .ansi span.sgr44{background-color:#1e66f5}html.theme--catppuccin-latte .ansi span.sgr45{background-color:#ea76cb}html.theme--catppuccin-latte .ansi span.sgr46{background-color:#179299}html.theme--catppuccin-latte .ansi span.sgr47{background-color:#acb0be}html.theme--catppuccin-latte .ansi span.sgr90{color:#6c6f85}html.theme--catppuccin-latte .ansi span.sgr91{color:#d20f39}html.theme--catppuccin-latte .ansi span.sgr92{color:#40a02b}html.theme--catppuccin-latte .ansi span.sgr93{color:#df8e1d}html.theme--catppuccin-latte .ansi span.sgr94{color:#1e66f5}html.theme--catppuccin-latte .ansi span.sgr95{color:#ea76cb}html.theme--catppuccin-latte .ansi span.sgr96{color:#179299}html.theme--catppuccin-latte .ansi span.sgr97{color:#bcc0cc}html.theme--catppuccin-latte .ansi span.sgr100{background-color:#6c6f85}html.theme--catppuccin-latte .ansi span.sgr101{background-color:#d20f39}html.theme--catppuccin-latte .ansi span.sgr102{background-color:#40a02b}html.theme--catppuccin-latte .ansi span.sgr103{background-color:#df8e1d}html.theme--catppuccin-latte .ansi span.sgr104{background-color:#1e66f5}html.theme--catppuccin-latte .ansi span.sgr105{background-color:#ea76cb}html.theme--catppuccin-latte .ansi span.sgr106{background-color:#179299}html.theme--catppuccin-latte .ansi span.sgr107{background-color:#bcc0cc}html.theme--catppuccin-latte code.language-julia-repl>span.hljs-meta{color:#40a02b;font-weight:bolder}html.theme--catppuccin-latte code .hljs{color:#4c4f69;background:#eff1f5}html.theme--catppuccin-latte code .hljs-keyword{color:#8839ef}html.theme--catppuccin-latte code .hljs-built_in{color:#d20f39}html.theme--catppuccin-latte code .hljs-type{color:#df8e1d}html.theme--catppuccin-latte code .hljs-literal{color:#fe640b}html.theme--catppuccin-latte code .hljs-number{color:#fe640b}html.theme--catppuccin-latte code .hljs-operator{color:#179299}html.theme--catppuccin-latte code .hljs-punctuation{color:#5c5f77}html.theme--catppuccin-latte code .hljs-property{color:#179299}html.theme--catppuccin-latte code .hljs-regexp{color:#ea76cb}html.theme--catppuccin-latte code .hljs-string{color:#40a02b}html.theme--catppuccin-latte code .hljs-char.escape_{color:#40a02b}html.theme--catppuccin-latte code .hljs-subst{color:#6c6f85}html.theme--catppuccin-latte code .hljs-symbol{color:#dd7878}html.theme--catppuccin-latte code .hljs-variable{color:#8839ef}html.theme--catppuccin-latte code .hljs-variable.language_{color:#8839ef}html.theme--catppuccin-latte code .hljs-variable.constant_{color:#fe640b}html.theme--catppuccin-latte code .hljs-title{color:#1e66f5}html.theme--catppuccin-latte code .hljs-title.class_{color:#df8e1d}html.theme--catppuccin-latte code .hljs-title.function_{color:#1e66f5}html.theme--catppuccin-latte code .hljs-params{color:#4c4f69}html.theme--catppuccin-latte code .hljs-comment{color:#acb0be}html.theme--catppuccin-latte code .hljs-doctag{color:#d20f39}html.theme--catppuccin-latte code .hljs-meta{color:#fe640b}html.theme--catppuccin-latte code .hljs-section{color:#1e66f5}html.theme--catppuccin-latte code .hljs-tag{color:#6c6f85}html.theme--catppuccin-latte code .hljs-name{color:#8839ef}html.theme--catppuccin-latte code .hljs-attr{color:#1e66f5}html.theme--catppuccin-latte code .hljs-attribute{color:#40a02b}html.theme--catppuccin-latte code .hljs-bullet{color:#179299}html.theme--catppuccin-latte code .hljs-code{color:#40a02b}html.theme--catppuccin-latte code .hljs-emphasis{color:#d20f39;font-style:italic}html.theme--catppuccin-latte code .hljs-strong{color:#d20f39;font-weight:bold}html.theme--catppuccin-latte code .hljs-formula{color:#179299}html.theme--catppuccin-latte code .hljs-link{color:#209fb5;font-style:italic}html.theme--catppuccin-latte code .hljs-quote{color:#40a02b;font-style:italic}html.theme--catppuccin-latte code .hljs-selector-tag{color:#df8e1d}html.theme--catppuccin-latte code .hljs-selector-id{color:#1e66f5}html.theme--catppuccin-latte code .hljs-selector-class{color:#179299}html.theme--catppuccin-latte code .hljs-selector-attr{color:#8839ef}html.theme--catppuccin-latte code .hljs-selector-pseudo{color:#179299}html.theme--catppuccin-latte code .hljs-template-tag{color:#dd7878}html.theme--catppuccin-latte code .hljs-template-variable{color:#dd7878}html.theme--catppuccin-latte code .hljs-addition{color:#40a02b;background:rgba(166,227,161,0.15)}html.theme--catppuccin-latte code .hljs-deletion{color:#d20f39;background:rgba(243,139,168,0.15)}html.theme--catppuccin-latte .search-result-link{border-radius:0.7em;transition:all 300ms}html.theme--catppuccin-latte .search-result-link:hover,html.theme--catppuccin-latte .search-result-link:focus{background-color:#ccd0da}html.theme--catppuccin-latte .search-result-link .property-search-result-badge,html.theme--catppuccin-latte .search-result-link .search-filter{transition:all 300ms}html.theme--catppuccin-latte .search-result-link:hover .property-search-result-badge,html.theme--catppuccin-latte .search-result-link:hover .search-filter,html.theme--catppuccin-latte .search-result-link:focus .property-search-result-badge,html.theme--catppuccin-latte .search-result-link:focus .search-filter{color:#ccd0da !important;background-color:#7287fd !important}html.theme--catppuccin-latte .search-result-title{color:#4c4f69}html.theme--catppuccin-latte .search-result-highlight{background-color:#d20f39;color:#e6e9ef}html.theme--catppuccin-latte .search-divider{border-bottom:1px solid #5e6d6f50}html.theme--catppuccin-latte .w-100{width:100%}html.theme--catppuccin-latte .gap-2{gap:0.5rem}html.theme--catppuccin-latte .gap-4{gap:1rem} diff --git a/v0.2.0/assets/themes/catppuccin-macchiato.css b/v0.2.0/assets/themes/catppuccin-macchiato.css new file mode 100644 index 000000000..a9cf9c573 --- /dev/null +++ b/v0.2.0/assets/themes/catppuccin-macchiato.css @@ -0,0 +1 @@ +html.theme--catppuccin-macchiato .pagination-previous,html.theme--catppuccin-macchiato .pagination-next,html.theme--catppuccin-macchiato .pagination-link,html.theme--catppuccin-macchiato .pagination-ellipsis,html.theme--catppuccin-macchiato .file-cta,html.theme--catppuccin-macchiato .file-name,html.theme--catppuccin-macchiato .select select,html.theme--catppuccin-macchiato .textarea,html.theme--catppuccin-macchiato .input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-macchiato .button{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;border-radius:.4em;box-shadow:none;display:inline-flex;font-size:1rem;height:2.5em;justify-content:flex-start;line-height:1.5;padding-bottom:calc(0.5em - 1px);padding-left:calc(0.75em - 1px);padding-right:calc(0.75em - 1px);padding-top:calc(0.5em - 1px);position:relative;vertical-align:top}html.theme--catppuccin-macchiato .pagination-previous:focus,html.theme--catppuccin-macchiato .pagination-next:focus,html.theme--catppuccin-macchiato .pagination-link:focus,html.theme--catppuccin-macchiato .pagination-ellipsis:focus,html.theme--catppuccin-macchiato .file-cta:focus,html.theme--catppuccin-macchiato .file-name:focus,html.theme--catppuccin-macchiato .select select:focus,html.theme--catppuccin-macchiato .textarea:focus,html.theme--catppuccin-macchiato .input:focus,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input:focus,html.theme--catppuccin-macchiato .button:focus,html.theme--catppuccin-macchiato .is-focused.pagination-previous,html.theme--catppuccin-macchiato .is-focused.pagination-next,html.theme--catppuccin-macchiato .is-focused.pagination-link,html.theme--catppuccin-macchiato .is-focused.pagination-ellipsis,html.theme--catppuccin-macchiato .is-focused.file-cta,html.theme--catppuccin-macchiato .is-focused.file-name,html.theme--catppuccin-macchiato .select select.is-focused,html.theme--catppuccin-macchiato .is-focused.textarea,html.theme--catppuccin-macchiato .is-focused.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-macchiato .is-focused.button,html.theme--catppuccin-macchiato .pagination-previous:active,html.theme--catppuccin-macchiato .pagination-next:active,html.theme--catppuccin-macchiato .pagination-link:active,html.theme--catppuccin-macchiato .pagination-ellipsis:active,html.theme--catppuccin-macchiato .file-cta:active,html.theme--catppuccin-macchiato .file-name:active,html.theme--catppuccin-macchiato .select select:active,html.theme--catppuccin-macchiato .textarea:active,html.theme--catppuccin-macchiato .input:active,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input:active,html.theme--catppuccin-macchiato .button:active,html.theme--catppuccin-macchiato .is-active.pagination-previous,html.theme--catppuccin-macchiato .is-active.pagination-next,html.theme--catppuccin-macchiato .is-active.pagination-link,html.theme--catppuccin-macchiato .is-active.pagination-ellipsis,html.theme--catppuccin-macchiato .is-active.file-cta,html.theme--catppuccin-macchiato .is-active.file-name,html.theme--catppuccin-macchiato .select select.is-active,html.theme--catppuccin-macchiato .is-active.textarea,html.theme--catppuccin-macchiato .is-active.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--catppuccin-macchiato .is-active.button{outline:none}html.theme--catppuccin-macchiato .pagination-previous[disabled],html.theme--catppuccin-macchiato .pagination-next[disabled],html.theme--catppuccin-macchiato .pagination-link[disabled],html.theme--catppuccin-macchiato .pagination-ellipsis[disabled],html.theme--catppuccin-macchiato .file-cta[disabled],html.theme--catppuccin-macchiato .file-name[disabled],html.theme--catppuccin-macchiato .select select[disabled],html.theme--catppuccin-macchiato .textarea[disabled],html.theme--catppuccin-macchiato .input[disabled],html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input[disabled],html.theme--catppuccin-macchiato .button[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .pagination-previous,html.theme--catppuccin-macchiato fieldset[disabled] .pagination-previous,fieldset[disabled] html.theme--catppuccin-macchiato .pagination-next,html.theme--catppuccin-macchiato fieldset[disabled] .pagination-next,fieldset[disabled] html.theme--catppuccin-macchiato .pagination-link,html.theme--catppuccin-macchiato fieldset[disabled] .pagination-link,fieldset[disabled] html.theme--catppuccin-macchiato .pagination-ellipsis,html.theme--catppuccin-macchiato fieldset[disabled] .pagination-ellipsis,fieldset[disabled] html.theme--catppuccin-macchiato .file-cta,html.theme--catppuccin-macchiato fieldset[disabled] .file-cta,fieldset[disabled] html.theme--catppuccin-macchiato .file-name,html.theme--catppuccin-macchiato fieldset[disabled] .file-name,fieldset[disabled] html.theme--catppuccin-macchiato .select select,fieldset[disabled] html.theme--catppuccin-macchiato .textarea,fieldset[disabled] html.theme--catppuccin-macchiato .input,fieldset[disabled] html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-macchiato fieldset[disabled] .select select,html.theme--catppuccin-macchiato .select fieldset[disabled] select,html.theme--catppuccin-macchiato fieldset[disabled] .textarea,html.theme--catppuccin-macchiato fieldset[disabled] .input,html.theme--catppuccin-macchiato fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-macchiato #documenter .docs-sidebar fieldset[disabled] form.docs-search>input,fieldset[disabled] html.theme--catppuccin-macchiato .button,html.theme--catppuccin-macchiato fieldset[disabled] .button{cursor:not-allowed}html.theme--catppuccin-macchiato .tabs,html.theme--catppuccin-macchiato .pagination-previous,html.theme--catppuccin-macchiato .pagination-next,html.theme--catppuccin-macchiato .pagination-link,html.theme--catppuccin-macchiato .pagination-ellipsis,html.theme--catppuccin-macchiato .breadcrumb,html.theme--catppuccin-macchiato .file,html.theme--catppuccin-macchiato .button,.is-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}html.theme--catppuccin-macchiato .navbar-link:not(.is-arrowless)::after,html.theme--catppuccin-macchiato .select:not(.is-multiple):not(.is-loading)::after{border:3px solid rgba(0,0,0,0);border-radius:2px;border-right:0;border-top:0;content:" ";display:block;height:0.625em;margin-top:-0.4375em;pointer-events:none;position:absolute;top:50%;transform:rotate(-45deg);transform-origin:center;width:0.625em}html.theme--catppuccin-macchiato .admonition:not(:last-child),html.theme--catppuccin-macchiato .tabs:not(:last-child),html.theme--catppuccin-macchiato .pagination:not(:last-child),html.theme--catppuccin-macchiato .message:not(:last-child),html.theme--catppuccin-macchiato .level:not(:last-child),html.theme--catppuccin-macchiato .breadcrumb:not(:last-child),html.theme--catppuccin-macchiato .block:not(:last-child),html.theme--catppuccin-macchiato .title:not(:last-child),html.theme--catppuccin-macchiato .subtitle:not(:last-child),html.theme--catppuccin-macchiato .table-container:not(:last-child),html.theme--catppuccin-macchiato .table:not(:last-child),html.theme--catppuccin-macchiato .progress:not(:last-child),html.theme--catppuccin-macchiato .notification:not(:last-child),html.theme--catppuccin-macchiato .content:not(:last-child),html.theme--catppuccin-macchiato .box:not(:last-child){margin-bottom:1.5rem}html.theme--catppuccin-macchiato .modal-close,html.theme--catppuccin-macchiato .delete{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,0.2);border:none;border-radius:9999px;cursor:pointer;pointer-events:auto;display:inline-block;flex-grow:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:none;position:relative;vertical-align:top;width:20px}html.theme--catppuccin-macchiato .modal-close::before,html.theme--catppuccin-macchiato .delete::before,html.theme--catppuccin-macchiato .modal-close::after,html.theme--catppuccin-macchiato .delete::after{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--catppuccin-macchiato .modal-close::before,html.theme--catppuccin-macchiato .delete::before{height:2px;width:50%}html.theme--catppuccin-macchiato .modal-close::after,html.theme--catppuccin-macchiato .delete::after{height:50%;width:2px}html.theme--catppuccin-macchiato .modal-close:hover,html.theme--catppuccin-macchiato .delete:hover,html.theme--catppuccin-macchiato .modal-close:focus,html.theme--catppuccin-macchiato .delete:focus{background-color:rgba(10,10,10,0.3)}html.theme--catppuccin-macchiato .modal-close:active,html.theme--catppuccin-macchiato .delete:active{background-color:rgba(10,10,10,0.4)}html.theme--catppuccin-macchiato .is-small.modal-close,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.modal-close,html.theme--catppuccin-macchiato .is-small.delete,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.delete{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}html.theme--catppuccin-macchiato .is-medium.modal-close,html.theme--catppuccin-macchiato .is-medium.delete{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}html.theme--catppuccin-macchiato .is-large.modal-close,html.theme--catppuccin-macchiato .is-large.delete{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}html.theme--catppuccin-macchiato .control.is-loading::after,html.theme--catppuccin-macchiato .select.is-loading::after,html.theme--catppuccin-macchiato .loader,html.theme--catppuccin-macchiato .button.is-loading::after{animation:spinAround 500ms infinite linear;border:2px solid #8087a2;border-radius:9999px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em}html.theme--catppuccin-macchiato .hero-video,html.theme--catppuccin-macchiato .modal-background,html.theme--catppuccin-macchiato .modal,html.theme--catppuccin-macchiato .image.is-square img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--catppuccin-macchiato .image.is-square .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--catppuccin-macchiato .image.is-1by1 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--catppuccin-macchiato .image.is-1by1 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--catppuccin-macchiato .image.is-5by4 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--catppuccin-macchiato .image.is-5by4 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--catppuccin-macchiato .image.is-4by3 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--catppuccin-macchiato .image.is-4by3 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--catppuccin-macchiato .image.is-3by2 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--catppuccin-macchiato .image.is-3by2 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--catppuccin-macchiato .image.is-5by3 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--catppuccin-macchiato .image.is-5by3 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--catppuccin-macchiato .image.is-16by9 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--catppuccin-macchiato .image.is-16by9 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--catppuccin-macchiato .image.is-2by1 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--catppuccin-macchiato .image.is-2by1 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--catppuccin-macchiato .image.is-3by1 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--catppuccin-macchiato .image.is-3by1 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--catppuccin-macchiato .image.is-4by5 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--catppuccin-macchiato .image.is-4by5 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--catppuccin-macchiato .image.is-3by4 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--catppuccin-macchiato .image.is-3by4 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--catppuccin-macchiato .image.is-2by3 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--catppuccin-macchiato .image.is-2by3 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--catppuccin-macchiato .image.is-3by5 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--catppuccin-macchiato .image.is-3by5 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--catppuccin-macchiato .image.is-9by16 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--catppuccin-macchiato .image.is-9by16 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--catppuccin-macchiato .image.is-1by2 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--catppuccin-macchiato .image.is-1by2 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--catppuccin-macchiato .image.is-1by3 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--catppuccin-macchiato .image.is-1by3 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio,.is-overlay{bottom:0;left:0;position:absolute;right:0;top:0}html.theme--catppuccin-macchiato .navbar-burger{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0}/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:inherit}.has-text-white{color:#fff !important}a.has-text-white:hover,a.has-text-white:focus{color:#e6e6e6 !important}.has-background-white{background-color:#fff !important}.has-text-black{color:#0a0a0a !important}a.has-text-black:hover,a.has-text-black:focus{color:#000 !important}.has-background-black{background-color:#0a0a0a !important}.has-text-light{color:#f5f5f5 !important}a.has-text-light:hover,a.has-text-light:focus{color:#dbdbdb !important}.has-background-light{background-color:#f5f5f5 !important}.has-text-dark{color:#363a4f !important}a.has-text-dark:hover,a.has-text-dark:focus{color:#212431 !important}.has-background-dark{background-color:#363a4f !important}.has-text-primary{color:#8aadf4 !important}a.has-text-primary:hover,a.has-text-primary:focus{color:#5b8cf0 !important}.has-background-primary{background-color:#8aadf4 !important}.has-text-primary-light{color:#ecf2fd !important}a.has-text-primary-light:hover,a.has-text-primary-light:focus{color:#bed1f9 !important}.has-background-primary-light{background-color:#ecf2fd !important}.has-text-primary-dark{color:#0e3b95 !important}a.has-text-primary-dark:hover,a.has-text-primary-dark:focus{color:#124dc4 !important}.has-background-primary-dark{background-color:#0e3b95 !important}.has-text-link{color:#8aadf4 !important}a.has-text-link:hover,a.has-text-link:focus{color:#5b8cf0 !important}.has-background-link{background-color:#8aadf4 !important}.has-text-link-light{color:#ecf2fd !important}a.has-text-link-light:hover,a.has-text-link-light:focus{color:#bed1f9 !important}.has-background-link-light{background-color:#ecf2fd !important}.has-text-link-dark{color:#0e3b95 !important}a.has-text-link-dark:hover,a.has-text-link-dark:focus{color:#124dc4 !important}.has-background-link-dark{background-color:#0e3b95 !important}.has-text-info{color:#8bd5ca !important}a.has-text-info:hover,a.has-text-info:focus{color:#66c7b9 !important}.has-background-info{background-color:#8bd5ca !important}.has-text-info-light{color:#f0faf8 !important}a.has-text-info-light:hover,a.has-text-info-light:focus{color:#cbece7 !important}.has-background-info-light{background-color:#f0faf8 !important}.has-text-info-dark{color:#276d62 !important}a.has-text-info-dark:hover,a.has-text-info-dark:focus{color:#359284 !important}.has-background-info-dark{background-color:#276d62 !important}.has-text-success{color:#a6da95 !important}a.has-text-success:hover,a.has-text-success:focus{color:#86cd6f !important}.has-background-success{background-color:#a6da95 !important}.has-text-success-light{color:#f2faf0 !important}a.has-text-success-light:hover,a.has-text-success-light:focus{color:#d3edca !important}.has-background-success-light{background-color:#f2faf0 !important}.has-text-success-dark{color:#386e26 !important}a.has-text-success-dark:hover,a.has-text-success-dark:focus{color:#4b9333 !important}.has-background-success-dark{background-color:#386e26 !important}.has-text-warning{color:#eed49f !important}a.has-text-warning:hover,a.has-text-warning:focus{color:#e6c174 !important}.has-background-warning{background-color:#eed49f !important}.has-text-warning-light{color:#fcf7ee !important}a.has-text-warning-light:hover,a.has-text-warning-light:focus{color:#f4e4c2 !important}.has-background-warning-light{background-color:#fcf7ee !important}.has-text-warning-dark{color:#7e5c16 !important}a.has-text-warning-dark:hover,a.has-text-warning-dark:focus{color:#a97b1e !important}.has-background-warning-dark{background-color:#7e5c16 !important}.has-text-danger{color:#ed8796 !important}a.has-text-danger:hover,a.has-text-danger:focus{color:#e65b6f !important}.has-background-danger{background-color:#ed8796 !important}.has-text-danger-light{color:#fcedef !important}a.has-text-danger-light:hover,a.has-text-danger-light:focus{color:#f6c1c9 !important}.has-background-danger-light{background-color:#fcedef !important}.has-text-danger-dark{color:#971729 !important}a.has-text-danger-dark:hover,a.has-text-danger-dark:focus{color:#c31d36 !important}.has-background-danger-dark{background-color:#971729 !important}.has-text-black-bis{color:#121212 !important}.has-background-black-bis{background-color:#121212 !important}.has-text-black-ter{color:#242424 !important}.has-background-black-ter{background-color:#242424 !important}.has-text-grey-darker{color:#363a4f !important}.has-background-grey-darker{background-color:#363a4f !important}.has-text-grey-dark{color:#494d64 !important}.has-background-grey-dark{background-color:#494d64 !important}.has-text-grey{color:#5b6078 !important}.has-background-grey{background-color:#5b6078 !important}.has-text-grey-light{color:#6e738d !important}.has-background-grey-light{background-color:#6e738d !important}.has-text-grey-lighter{color:#8087a2 !important}.has-background-grey-lighter{background-color:#8087a2 !important}.has-text-white-ter{color:#f5f5f5 !important}.has-background-white-ter{background-color:#f5f5f5 !important}.has-text-white-bis{color:#fafafa !important}.has-background-white-bis{background-color:#fafafa !important}.is-flex-direction-row{flex-direction:row !important}.is-flex-direction-row-reverse{flex-direction:row-reverse !important}.is-flex-direction-column{flex-direction:column !important}.is-flex-direction-column-reverse{flex-direction:column-reverse !important}.is-flex-wrap-nowrap{flex-wrap:nowrap !important}.is-flex-wrap-wrap{flex-wrap:wrap !important}.is-flex-wrap-wrap-reverse{flex-wrap:wrap-reverse !important}.is-justify-content-flex-start{justify-content:flex-start !important}.is-justify-content-flex-end{justify-content:flex-end !important}.is-justify-content-center{justify-content:center !important}.is-justify-content-space-between{justify-content:space-between !important}.is-justify-content-space-around{justify-content:space-around !important}.is-justify-content-space-evenly{justify-content:space-evenly !important}.is-justify-content-start{justify-content:start !important}.is-justify-content-end{justify-content:end !important}.is-justify-content-left{justify-content:left !important}.is-justify-content-right{justify-content:right !important}.is-align-content-flex-start{align-content:flex-start !important}.is-align-content-flex-end{align-content:flex-end !important}.is-align-content-center{align-content:center !important}.is-align-content-space-between{align-content:space-between !important}.is-align-content-space-around{align-content:space-around !important}.is-align-content-space-evenly{align-content:space-evenly !important}.is-align-content-stretch{align-content:stretch !important}.is-align-content-start{align-content:start !important}.is-align-content-end{align-content:end !important}.is-align-content-baseline{align-content:baseline !important}.is-align-items-stretch{align-items:stretch !important}.is-align-items-flex-start{align-items:flex-start !important}.is-align-items-flex-end{align-items:flex-end !important}.is-align-items-center{align-items:center !important}.is-align-items-baseline{align-items:baseline !important}.is-align-items-start{align-items:start !important}.is-align-items-end{align-items:end !important}.is-align-items-self-start{align-items:self-start !important}.is-align-items-self-end{align-items:self-end !important}.is-align-self-auto{align-self:auto !important}.is-align-self-flex-start{align-self:flex-start !important}.is-align-self-flex-end{align-self:flex-end !important}.is-align-self-center{align-self:center !important}.is-align-self-baseline{align-self:baseline !important}.is-align-self-stretch{align-self:stretch !important}.is-flex-grow-0{flex-grow:0 !important}.is-flex-grow-1{flex-grow:1 !important}.is-flex-grow-2{flex-grow:2 !important}.is-flex-grow-3{flex-grow:3 !important}.is-flex-grow-4{flex-grow:4 !important}.is-flex-grow-5{flex-grow:5 !important}.is-flex-shrink-0{flex-shrink:0 !important}.is-flex-shrink-1{flex-shrink:1 !important}.is-flex-shrink-2{flex-shrink:2 !important}.is-flex-shrink-3{flex-shrink:3 !important}.is-flex-shrink-4{flex-shrink:4 !important}.is-flex-shrink-5{flex-shrink:5 !important}.is-clearfix::after{clear:both;content:" ";display:table}.is-pulled-left{float:left !important}.is-pulled-right{float:right !important}.is-radiusless{border-radius:0 !important}.is-shadowless{box-shadow:none !important}.is-clickable{cursor:pointer !important;pointer-events:all !important}.is-clipped{overflow:hidden !important}.is-relative{position:relative !important}.is-marginless{margin:0 !important}.is-paddingless{padding:0 !important}.m-0{margin:0 !important}.mt-0{margin-top:0 !important}.mr-0{margin-right:0 !important}.mb-0{margin-bottom:0 !important}.ml-0{margin-left:0 !important}.mx-0{margin-left:0 !important;margin-right:0 !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.m-1{margin:.25rem !important}.mt-1{margin-top:.25rem !important}.mr-1{margin-right:.25rem !important}.mb-1{margin-bottom:.25rem !important}.ml-1{margin-left:.25rem !important}.mx-1{margin-left:.25rem !important;margin-right:.25rem !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.m-2{margin:.5rem !important}.mt-2{margin-top:.5rem !important}.mr-2{margin-right:.5rem !important}.mb-2{margin-bottom:.5rem !important}.ml-2{margin-left:.5rem !important}.mx-2{margin-left:.5rem !important;margin-right:.5rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.m-3{margin:.75rem !important}.mt-3{margin-top:.75rem !important}.mr-3{margin-right:.75rem !important}.mb-3{margin-bottom:.75rem !important}.ml-3{margin-left:.75rem !important}.mx-3{margin-left:.75rem !important;margin-right:.75rem !important}.my-3{margin-top:.75rem !important;margin-bottom:.75rem !important}.m-4{margin:1rem !important}.mt-4{margin-top:1rem !important}.mr-4{margin-right:1rem !important}.mb-4{margin-bottom:1rem !important}.ml-4{margin-left:1rem !important}.mx-4{margin-left:1rem !important;margin-right:1rem !important}.my-4{margin-top:1rem !important;margin-bottom:1rem !important}.m-5{margin:1.5rem !important}.mt-5{margin-top:1.5rem !important}.mr-5{margin-right:1.5rem !important}.mb-5{margin-bottom:1.5rem !important}.ml-5{margin-left:1.5rem !important}.mx-5{margin-left:1.5rem !important;margin-right:1.5rem !important}.my-5{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.m-6{margin:3rem !important}.mt-6{margin-top:3rem !important}.mr-6{margin-right:3rem !important}.mb-6{margin-bottom:3rem !important}.ml-6{margin-left:3rem !important}.mx-6{margin-left:3rem !important;margin-right:3rem !important}.my-6{margin-top:3rem !important;margin-bottom:3rem !important}.m-auto{margin:auto !important}.mt-auto{margin-top:auto !important}.mr-auto{margin-right:auto !important}.mb-auto{margin-bottom:auto !important}.ml-auto{margin-left:auto !important}.mx-auto{margin-left:auto !important;margin-right:auto !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.p-0{padding:0 !important}.pt-0{padding-top:0 !important}.pr-0{padding-right:0 !important}.pb-0{padding-bottom:0 !important}.pl-0{padding-left:0 !important}.px-0{padding-left:0 !important;padding-right:0 !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.p-1{padding:.25rem !important}.pt-1{padding-top:.25rem !important}.pr-1{padding-right:.25rem !important}.pb-1{padding-bottom:.25rem !important}.pl-1{padding-left:.25rem !important}.px-1{padding-left:.25rem !important;padding-right:.25rem !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.p-2{padding:.5rem !important}.pt-2{padding-top:.5rem !important}.pr-2{padding-right:.5rem !important}.pb-2{padding-bottom:.5rem !important}.pl-2{padding-left:.5rem !important}.px-2{padding-left:.5rem !important;padding-right:.5rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.p-3{padding:.75rem !important}.pt-3{padding-top:.75rem !important}.pr-3{padding-right:.75rem !important}.pb-3{padding-bottom:.75rem !important}.pl-3{padding-left:.75rem !important}.px-3{padding-left:.75rem !important;padding-right:.75rem !important}.py-3{padding-top:.75rem !important;padding-bottom:.75rem !important}.p-4{padding:1rem !important}.pt-4{padding-top:1rem !important}.pr-4{padding-right:1rem !important}.pb-4{padding-bottom:1rem !important}.pl-4{padding-left:1rem !important}.px-4{padding-left:1rem !important;padding-right:1rem !important}.py-4{padding-top:1rem !important;padding-bottom:1rem !important}.p-5{padding:1.5rem !important}.pt-5{padding-top:1.5rem !important}.pr-5{padding-right:1.5rem !important}.pb-5{padding-bottom:1.5rem !important}.pl-5{padding-left:1.5rem !important}.px-5{padding-left:1.5rem !important;padding-right:1.5rem !important}.py-5{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.p-6{padding:3rem !important}.pt-6{padding-top:3rem !important}.pr-6{padding-right:3rem !important}.pb-6{padding-bottom:3rem !important}.pl-6{padding-left:3rem !important}.px-6{padding-left:3rem !important;padding-right:3rem !important}.py-6{padding-top:3rem !important;padding-bottom:3rem !important}.p-auto{padding:auto !important}.pt-auto{padding-top:auto !important}.pr-auto{padding-right:auto !important}.pb-auto{padding-bottom:auto !important}.pl-auto{padding-left:auto !important}.px-auto{padding-left:auto !important;padding-right:auto !important}.py-auto{padding-top:auto !important;padding-bottom:auto !important}.is-size-1{font-size:3rem !important}.is-size-2{font-size:2.5rem !important}.is-size-3{font-size:2rem !important}.is-size-4{font-size:1.5rem !important}.is-size-5{font-size:1.25rem !important}.is-size-6{font-size:1rem !important}.is-size-7,html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink{font-size:.75rem !important}@media screen and (max-width: 768px){.is-size-1-mobile{font-size:3rem !important}.is-size-2-mobile{font-size:2.5rem !important}.is-size-3-mobile{font-size:2rem !important}.is-size-4-mobile{font-size:1.5rem !important}.is-size-5-mobile{font-size:1.25rem !important}.is-size-6-mobile{font-size:1rem !important}.is-size-7-mobile{font-size:.75rem !important}}@media screen and (min-width: 769px),print{.is-size-1-tablet{font-size:3rem !important}.is-size-2-tablet{font-size:2.5rem !important}.is-size-3-tablet{font-size:2rem !important}.is-size-4-tablet{font-size:1.5rem !important}.is-size-5-tablet{font-size:1.25rem !important}.is-size-6-tablet{font-size:1rem !important}.is-size-7-tablet{font-size:.75rem !important}}@media screen and (max-width: 1055px){.is-size-1-touch{font-size:3rem !important}.is-size-2-touch{font-size:2.5rem !important}.is-size-3-touch{font-size:2rem !important}.is-size-4-touch{font-size:1.5rem !important}.is-size-5-touch{font-size:1.25rem !important}.is-size-6-touch{font-size:1rem !important}.is-size-7-touch{font-size:.75rem !important}}@media screen and (min-width: 1056px){.is-size-1-desktop{font-size:3rem !important}.is-size-2-desktop{font-size:2.5rem !important}.is-size-3-desktop{font-size:2rem !important}.is-size-4-desktop{font-size:1.5rem !important}.is-size-5-desktop{font-size:1.25rem !important}.is-size-6-desktop{font-size:1rem !important}.is-size-7-desktop{font-size:.75rem !important}}@media screen and (min-width: 1216px){.is-size-1-widescreen{font-size:3rem !important}.is-size-2-widescreen{font-size:2.5rem !important}.is-size-3-widescreen{font-size:2rem !important}.is-size-4-widescreen{font-size:1.5rem !important}.is-size-5-widescreen{font-size:1.25rem !important}.is-size-6-widescreen{font-size:1rem !important}.is-size-7-widescreen{font-size:.75rem !important}}@media screen and (min-width: 1408px){.is-size-1-fullhd{font-size:3rem !important}.is-size-2-fullhd{font-size:2.5rem !important}.is-size-3-fullhd{font-size:2rem !important}.is-size-4-fullhd{font-size:1.5rem !important}.is-size-5-fullhd{font-size:1.25rem !important}.is-size-6-fullhd{font-size:1rem !important}.is-size-7-fullhd{font-size:.75rem !important}}.has-text-centered{text-align:center !important}.has-text-justified{text-align:justify !important}.has-text-left{text-align:left !important}.has-text-right{text-align:right !important}@media screen and (max-width: 768px){.has-text-centered-mobile{text-align:center !important}}@media screen and (min-width: 769px),print{.has-text-centered-tablet{text-align:center !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-centered-tablet-only{text-align:center !important}}@media screen and (max-width: 1055px){.has-text-centered-touch{text-align:center !important}}@media screen and (min-width: 1056px){.has-text-centered-desktop{text-align:center !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-centered-desktop-only{text-align:center !important}}@media screen and (min-width: 1216px){.has-text-centered-widescreen{text-align:center !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-centered-widescreen-only{text-align:center !important}}@media screen and (min-width: 1408px){.has-text-centered-fullhd{text-align:center !important}}@media screen and (max-width: 768px){.has-text-justified-mobile{text-align:justify !important}}@media screen and (min-width: 769px),print{.has-text-justified-tablet{text-align:justify !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-justified-tablet-only{text-align:justify !important}}@media screen and (max-width: 1055px){.has-text-justified-touch{text-align:justify !important}}@media screen and (min-width: 1056px){.has-text-justified-desktop{text-align:justify !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-justified-desktop-only{text-align:justify !important}}@media screen and (min-width: 1216px){.has-text-justified-widescreen{text-align:justify !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-justified-widescreen-only{text-align:justify !important}}@media screen and (min-width: 1408px){.has-text-justified-fullhd{text-align:justify !important}}@media screen and (max-width: 768px){.has-text-left-mobile{text-align:left !important}}@media screen and (min-width: 769px),print{.has-text-left-tablet{text-align:left !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-left-tablet-only{text-align:left !important}}@media screen and (max-width: 1055px){.has-text-left-touch{text-align:left !important}}@media screen and (min-width: 1056px){.has-text-left-desktop{text-align:left !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-left-desktop-only{text-align:left !important}}@media screen and (min-width: 1216px){.has-text-left-widescreen{text-align:left !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-left-widescreen-only{text-align:left !important}}@media screen and (min-width: 1408px){.has-text-left-fullhd{text-align:left !important}}@media screen and (max-width: 768px){.has-text-right-mobile{text-align:right !important}}@media screen and (min-width: 769px),print{.has-text-right-tablet{text-align:right !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-right-tablet-only{text-align:right !important}}@media screen and (max-width: 1055px){.has-text-right-touch{text-align:right !important}}@media screen and (min-width: 1056px){.has-text-right-desktop{text-align:right !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-right-desktop-only{text-align:right !important}}@media screen and (min-width: 1216px){.has-text-right-widescreen{text-align:right !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-right-widescreen-only{text-align:right !important}}@media screen and (min-width: 1408px){.has-text-right-fullhd{text-align:right !important}}.is-capitalized{text-transform:capitalize !important}.is-lowercase{text-transform:lowercase !important}.is-uppercase{text-transform:uppercase !important}.is-italic{font-style:italic !important}.is-underlined{text-decoration:underline !important}.has-text-weight-light{font-weight:300 !important}.has-text-weight-normal{font-weight:400 !important}.has-text-weight-medium{font-weight:500 !important}.has-text-weight-semibold{font-weight:600 !important}.has-text-weight-bold{font-weight:700 !important}.is-family-primary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-secondary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-sans-serif{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-monospace{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-family-code{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-block{display:block !important}@media screen and (max-width: 768px){.is-block-mobile{display:block !important}}@media screen and (min-width: 769px),print{.is-block-tablet{display:block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-block-tablet-only{display:block !important}}@media screen and (max-width: 1055px){.is-block-touch{display:block !important}}@media screen and (min-width: 1056px){.is-block-desktop{display:block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-block-desktop-only{display:block !important}}@media screen and (min-width: 1216px){.is-block-widescreen{display:block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-block-widescreen-only{display:block !important}}@media screen and (min-width: 1408px){.is-block-fullhd{display:block !important}}.is-flex{display:flex !important}@media screen and (max-width: 768px){.is-flex-mobile{display:flex !important}}@media screen and (min-width: 769px),print{.is-flex-tablet{display:flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-flex-tablet-only{display:flex !important}}@media screen and (max-width: 1055px){.is-flex-touch{display:flex !important}}@media screen and (min-width: 1056px){.is-flex-desktop{display:flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-flex-desktop-only{display:flex !important}}@media screen and (min-width: 1216px){.is-flex-widescreen{display:flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-flex-widescreen-only{display:flex !important}}@media screen and (min-width: 1408px){.is-flex-fullhd{display:flex !important}}.is-inline{display:inline !important}@media screen and (max-width: 768px){.is-inline-mobile{display:inline !important}}@media screen and (min-width: 769px),print{.is-inline-tablet{display:inline !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-tablet-only{display:inline !important}}@media screen and (max-width: 1055px){.is-inline-touch{display:inline !important}}@media screen and (min-width: 1056px){.is-inline-desktop{display:inline !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-desktop-only{display:inline !important}}@media screen and (min-width: 1216px){.is-inline-widescreen{display:inline !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-widescreen-only{display:inline !important}}@media screen and (min-width: 1408px){.is-inline-fullhd{display:inline !important}}.is-inline-block{display:inline-block !important}@media screen and (max-width: 768px){.is-inline-block-mobile{display:inline-block !important}}@media screen and (min-width: 769px),print{.is-inline-block-tablet{display:inline-block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-block-tablet-only{display:inline-block !important}}@media screen and (max-width: 1055px){.is-inline-block-touch{display:inline-block !important}}@media screen and (min-width: 1056px){.is-inline-block-desktop{display:inline-block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-block-desktop-only{display:inline-block !important}}@media screen and (min-width: 1216px){.is-inline-block-widescreen{display:inline-block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-block-widescreen-only{display:inline-block !important}}@media screen and (min-width: 1408px){.is-inline-block-fullhd{display:inline-block !important}}.is-inline-flex{display:inline-flex !important}@media screen and (max-width: 768px){.is-inline-flex-mobile{display:inline-flex !important}}@media screen and (min-width: 769px),print{.is-inline-flex-tablet{display:inline-flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-flex-tablet-only{display:inline-flex !important}}@media screen and (max-width: 1055px){.is-inline-flex-touch{display:inline-flex !important}}@media screen and (min-width: 1056px){.is-inline-flex-desktop{display:inline-flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-flex-desktop-only{display:inline-flex !important}}@media screen and (min-width: 1216px){.is-inline-flex-widescreen{display:inline-flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-flex-widescreen-only{display:inline-flex !important}}@media screen and (min-width: 1408px){.is-inline-flex-fullhd{display:inline-flex !important}}.is-hidden{display:none !important}.is-sr-only{border:none !important;clip:rect(0, 0, 0, 0) !important;height:0.01em !important;overflow:hidden !important;padding:0 !important;position:absolute !important;white-space:nowrap !important;width:0.01em !important}@media screen and (max-width: 768px){.is-hidden-mobile{display:none !important}}@media screen and (min-width: 769px),print{.is-hidden-tablet{display:none !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-hidden-tablet-only{display:none !important}}@media screen and (max-width: 1055px){.is-hidden-touch{display:none !important}}@media screen and (min-width: 1056px){.is-hidden-desktop{display:none !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-hidden-desktop-only{display:none !important}}@media screen and (min-width: 1216px){.is-hidden-widescreen{display:none !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-hidden-widescreen-only{display:none !important}}@media screen and (min-width: 1408px){.is-hidden-fullhd{display:none !important}}.is-invisible{visibility:hidden !important}@media screen and (max-width: 768px){.is-invisible-mobile{visibility:hidden !important}}@media screen and (min-width: 769px),print{.is-invisible-tablet{visibility:hidden !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-invisible-tablet-only{visibility:hidden !important}}@media screen and (max-width: 1055px){.is-invisible-touch{visibility:hidden !important}}@media screen and (min-width: 1056px){.is-invisible-desktop{visibility:hidden !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-invisible-desktop-only{visibility:hidden !important}}@media screen and (min-width: 1216px){.is-invisible-widescreen{visibility:hidden !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-invisible-widescreen-only{visibility:hidden !important}}@media screen and (min-width: 1408px){.is-invisible-fullhd{visibility:hidden !important}}html.theme--catppuccin-macchiato html{background-color:#24273a;font-size:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--catppuccin-macchiato article,html.theme--catppuccin-macchiato aside,html.theme--catppuccin-macchiato figure,html.theme--catppuccin-macchiato footer,html.theme--catppuccin-macchiato header,html.theme--catppuccin-macchiato hgroup,html.theme--catppuccin-macchiato section{display:block}html.theme--catppuccin-macchiato body,html.theme--catppuccin-macchiato button,html.theme--catppuccin-macchiato input,html.theme--catppuccin-macchiato optgroup,html.theme--catppuccin-macchiato select,html.theme--catppuccin-macchiato textarea{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif}html.theme--catppuccin-macchiato code,html.theme--catppuccin-macchiato pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}html.theme--catppuccin-macchiato body{color:#cad3f5;font-size:1em;font-weight:400;line-height:1.5}html.theme--catppuccin-macchiato a{color:#8aadf4;cursor:pointer;text-decoration:none}html.theme--catppuccin-macchiato a strong{color:currentColor}html.theme--catppuccin-macchiato a:hover{color:#91d7e3}html.theme--catppuccin-macchiato code{background-color:#1e2030;color:#cad3f5;font-size:.875em;font-weight:normal;padding:.1em}html.theme--catppuccin-macchiato hr{background-color:#1e2030;border:none;display:block;height:2px;margin:1.5rem 0}html.theme--catppuccin-macchiato img{height:auto;max-width:100%}html.theme--catppuccin-macchiato input[type="checkbox"],html.theme--catppuccin-macchiato input[type="radio"]{vertical-align:baseline}html.theme--catppuccin-macchiato small{font-size:.875em}html.theme--catppuccin-macchiato span{font-style:inherit;font-weight:inherit}html.theme--catppuccin-macchiato strong{color:#b5c1f1;font-weight:700}html.theme--catppuccin-macchiato fieldset{border:none}html.theme--catppuccin-macchiato pre{-webkit-overflow-scrolling:touch;background-color:#1e2030;color:#cad3f5;font-size:.875em;overflow-x:auto;padding:1.25rem 1.5rem;white-space:pre;word-wrap:normal}html.theme--catppuccin-macchiato pre code{background-color:transparent;color:currentColor;font-size:1em;padding:0}html.theme--catppuccin-macchiato table td,html.theme--catppuccin-macchiato table th{vertical-align:top}html.theme--catppuccin-macchiato table td:not([align]),html.theme--catppuccin-macchiato table th:not([align]){text-align:inherit}html.theme--catppuccin-macchiato table th{color:#b5c1f1}html.theme--catppuccin-macchiato .box{background-color:#494d64;border-radius:8px;box-shadow:none;color:#cad3f5;display:block;padding:1.25rem}html.theme--catppuccin-macchiato a.box:hover,html.theme--catppuccin-macchiato a.box:focus{box-shadow:0 0.5em 1em -0.125em rgba(10,10,10,0.1),0 0 0 1px #8aadf4}html.theme--catppuccin-macchiato a.box:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2),0 0 0 1px #8aadf4}html.theme--catppuccin-macchiato .button{background-color:#1e2030;border-color:#3b3f5f;border-width:1px;color:#8aadf4;cursor:pointer;justify-content:center;padding-bottom:calc(0.5em - 1px);padding-left:1em;padding-right:1em;padding-top:calc(0.5em - 1px);text-align:center;white-space:nowrap}html.theme--catppuccin-macchiato .button strong{color:inherit}html.theme--catppuccin-macchiato .button .icon,html.theme--catppuccin-macchiato .button .icon.is-small,html.theme--catppuccin-macchiato .button #documenter .docs-sidebar form.docs-search>input.icon,html.theme--catppuccin-macchiato #documenter .docs-sidebar .button form.docs-search>input.icon,html.theme--catppuccin-macchiato .button .icon.is-medium,html.theme--catppuccin-macchiato .button .icon.is-large{height:1.5em;width:1.5em}html.theme--catppuccin-macchiato .button .icon:first-child:not(:last-child){margin-left:calc(-0.5em - 1px);margin-right:.25em}html.theme--catppuccin-macchiato .button .icon:last-child:not(:first-child){margin-left:.25em;margin-right:calc(-0.5em - 1px)}html.theme--catppuccin-macchiato .button .icon:first-child:last-child{margin-left:calc(-0.5em - 1px);margin-right:calc(-0.5em - 1px)}html.theme--catppuccin-macchiato .button:hover,html.theme--catppuccin-macchiato .button.is-hovered{border-color:#6e738d;color:#b5c1f1}html.theme--catppuccin-macchiato .button:focus,html.theme--catppuccin-macchiato .button.is-focused{border-color:#6e738d;color:#739df2}html.theme--catppuccin-macchiato .button:focus:not(:active),html.theme--catppuccin-macchiato .button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(138,173,244,0.25)}html.theme--catppuccin-macchiato .button:active,html.theme--catppuccin-macchiato .button.is-active{border-color:#494d64;color:#b5c1f1}html.theme--catppuccin-macchiato .button.is-text{background-color:transparent;border-color:transparent;color:#cad3f5;text-decoration:underline}html.theme--catppuccin-macchiato .button.is-text:hover,html.theme--catppuccin-macchiato .button.is-text.is-hovered,html.theme--catppuccin-macchiato .button.is-text:focus,html.theme--catppuccin-macchiato .button.is-text.is-focused{background-color:#1e2030;color:#b5c1f1}html.theme--catppuccin-macchiato .button.is-text:active,html.theme--catppuccin-macchiato .button.is-text.is-active{background-color:#141620;color:#b5c1f1}html.theme--catppuccin-macchiato .button.is-text[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-text{background-color:transparent;border-color:transparent;box-shadow:none}html.theme--catppuccin-macchiato .button.is-ghost{background:none;border-color:rgba(0,0,0,0);color:#8aadf4;text-decoration:none}html.theme--catppuccin-macchiato .button.is-ghost:hover,html.theme--catppuccin-macchiato .button.is-ghost.is-hovered{color:#8aadf4;text-decoration:underline}html.theme--catppuccin-macchiato .button.is-white{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-macchiato .button.is-white:hover,html.theme--catppuccin-macchiato .button.is-white.is-hovered{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-macchiato .button.is-white:focus,html.theme--catppuccin-macchiato .button.is-white.is-focused{border-color:transparent;color:#0a0a0a}html.theme--catppuccin-macchiato .button.is-white:focus:not(:active),html.theme--catppuccin-macchiato .button.is-white.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--catppuccin-macchiato .button.is-white:active,html.theme--catppuccin-macchiato .button.is-white.is-active{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-macchiato .button.is-white[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-white{background-color:#fff;border-color:#fff;box-shadow:none}html.theme--catppuccin-macchiato .button.is-white.is-inverted{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-macchiato .button.is-white.is-inverted:hover,html.theme--catppuccin-macchiato .button.is-white.is-inverted.is-hovered{background-color:#000}html.theme--catppuccin-macchiato .button.is-white.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-white.is-inverted{background-color:#0a0a0a;border-color:transparent;box-shadow:none;color:#fff}html.theme--catppuccin-macchiato .button.is-white.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--catppuccin-macchiato .button.is-white.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-macchiato .button.is-white.is-outlined:hover,html.theme--catppuccin-macchiato .button.is-white.is-outlined.is-hovered,html.theme--catppuccin-macchiato .button.is-white.is-outlined:focus,html.theme--catppuccin-macchiato .button.is-white.is-outlined.is-focused{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--catppuccin-macchiato .button.is-white.is-outlined.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-macchiato .button.is-white.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .button.is-white.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .button.is-white.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .button.is-white.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--catppuccin-macchiato .button.is-white.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-white.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-macchiato .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--catppuccin-macchiato .button.is-white.is-inverted.is-outlined:hover,html.theme--catppuccin-macchiato .button.is-white.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-macchiato .button.is-white.is-inverted.is-outlined:focus,html.theme--catppuccin-macchiato .button.is-white.is-inverted.is-outlined.is-focused{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-macchiato .button.is-white.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .button.is-white.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .button.is-white.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-macchiato .button.is-white.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--catppuccin-macchiato .button.is-black{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-black:hover,html.theme--catppuccin-macchiato .button.is-black.is-hovered{background-color:#040404;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-black:focus,html.theme--catppuccin-macchiato .button.is-black.is-focused{border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-black:focus:not(:active),html.theme--catppuccin-macchiato .button.is-black.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--catppuccin-macchiato .button.is-black:active,html.theme--catppuccin-macchiato .button.is-black.is-active{background-color:#000;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-black[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-black{background-color:#0a0a0a;border-color:#0a0a0a;box-shadow:none}html.theme--catppuccin-macchiato .button.is-black.is-inverted{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-macchiato .button.is-black.is-inverted:hover,html.theme--catppuccin-macchiato .button.is-black.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--catppuccin-macchiato .button.is-black.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-black.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#0a0a0a}html.theme--catppuccin-macchiato .button.is-black.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-macchiato .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--catppuccin-macchiato .button.is-black.is-outlined:hover,html.theme--catppuccin-macchiato .button.is-black.is-outlined.is-hovered,html.theme--catppuccin-macchiato .button.is-black.is-outlined:focus,html.theme--catppuccin-macchiato .button.is-black.is-outlined.is-focused{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--catppuccin-macchiato .button.is-black.is-outlined.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--catppuccin-macchiato .button.is-black.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .button.is-black.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .button.is-black.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .button.is-black.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-macchiato .button.is-black.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--catppuccin-macchiato .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-macchiato .button.is-black.is-inverted.is-outlined:hover,html.theme--catppuccin-macchiato .button.is-black.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-macchiato .button.is-black.is-inverted.is-outlined:focus,html.theme--catppuccin-macchiato .button.is-black.is-inverted.is-outlined.is-focused{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-macchiato .button.is-black.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .button.is-black.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .button.is-black.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--catppuccin-macchiato .button.is-black.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-macchiato .button.is-light{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-light:hover,html.theme--catppuccin-macchiato .button.is-light.is-hovered{background-color:#eee;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-light:focus,html.theme--catppuccin-macchiato .button.is-light.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-light:focus:not(:active),html.theme--catppuccin-macchiato .button.is-light.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}html.theme--catppuccin-macchiato .button.is-light:active,html.theme--catppuccin-macchiato .button.is-light.is-active{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-light[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-light{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none}html.theme--catppuccin-macchiato .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);color:#f5f5f5}html.theme--catppuccin-macchiato .button.is-light.is-inverted:hover,html.theme--catppuccin-macchiato .button.is-light.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-light.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#f5f5f5}html.theme--catppuccin-macchiato .button.is-light.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-macchiato .button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;color:#f5f5f5}html.theme--catppuccin-macchiato .button.is-light.is-outlined:hover,html.theme--catppuccin-macchiato .button.is-light.is-outlined.is-hovered,html.theme--catppuccin-macchiato .button.is-light.is-outlined:focus,html.theme--catppuccin-macchiato .button.is-light.is-outlined.is-focused{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-light.is-outlined.is-loading::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}html.theme--catppuccin-macchiato .button.is-light.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .button.is-light.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .button.is-light.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .button.is-light.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-macchiato .button.is-light.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;box-shadow:none;color:#f5f5f5}html.theme--catppuccin-macchiato .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-light.is-inverted.is-outlined:hover,html.theme--catppuccin-macchiato .button.is-light.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-macchiato .button.is-light.is-inverted.is-outlined:focus,html.theme--catppuccin-macchiato .button.is-light.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#f5f5f5}html.theme--catppuccin-macchiato .button.is-light.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .button.is-light.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .button.is-light.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}html.theme--catppuccin-macchiato .button.is-light.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-dark,html.theme--catppuccin-macchiato .content kbd.button{background-color:#363a4f;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-dark:hover,html.theme--catppuccin-macchiato .content kbd.button:hover,html.theme--catppuccin-macchiato .button.is-dark.is-hovered,html.theme--catppuccin-macchiato .content kbd.button.is-hovered{background-color:#313447;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-dark:focus,html.theme--catppuccin-macchiato .content kbd.button:focus,html.theme--catppuccin-macchiato .button.is-dark.is-focused,html.theme--catppuccin-macchiato .content kbd.button.is-focused{border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-dark:focus:not(:active),html.theme--catppuccin-macchiato .content kbd.button:focus:not(:active),html.theme--catppuccin-macchiato .button.is-dark.is-focused:not(:active),html.theme--catppuccin-macchiato .content kbd.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(54,58,79,0.25)}html.theme--catppuccin-macchiato .button.is-dark:active,html.theme--catppuccin-macchiato .content kbd.button:active,html.theme--catppuccin-macchiato .button.is-dark.is-active,html.theme--catppuccin-macchiato .content kbd.button.is-active{background-color:#2c2f40;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-dark[disabled],html.theme--catppuccin-macchiato .content kbd.button[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-dark,fieldset[disabled] html.theme--catppuccin-macchiato .content kbd.button{background-color:#363a4f;border-color:#363a4f;box-shadow:none}html.theme--catppuccin-macchiato .button.is-dark.is-inverted,html.theme--catppuccin-macchiato .content kbd.button.is-inverted{background-color:#fff;color:#363a4f}html.theme--catppuccin-macchiato .button.is-dark.is-inverted:hover,html.theme--catppuccin-macchiato .content kbd.button.is-inverted:hover,html.theme--catppuccin-macchiato .button.is-dark.is-inverted.is-hovered,html.theme--catppuccin-macchiato .content kbd.button.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--catppuccin-macchiato .button.is-dark.is-inverted[disabled],html.theme--catppuccin-macchiato .content kbd.button.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-dark.is-inverted,fieldset[disabled] html.theme--catppuccin-macchiato .content kbd.button.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#363a4f}html.theme--catppuccin-macchiato .button.is-dark.is-loading::after,html.theme--catppuccin-macchiato .content kbd.button.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-macchiato .button.is-dark.is-outlined,html.theme--catppuccin-macchiato .content kbd.button.is-outlined{background-color:transparent;border-color:#363a4f;color:#363a4f}html.theme--catppuccin-macchiato .button.is-dark.is-outlined:hover,html.theme--catppuccin-macchiato .content kbd.button.is-outlined:hover,html.theme--catppuccin-macchiato .button.is-dark.is-outlined.is-hovered,html.theme--catppuccin-macchiato .content kbd.button.is-outlined.is-hovered,html.theme--catppuccin-macchiato .button.is-dark.is-outlined:focus,html.theme--catppuccin-macchiato .content kbd.button.is-outlined:focus,html.theme--catppuccin-macchiato .button.is-dark.is-outlined.is-focused,html.theme--catppuccin-macchiato .content kbd.button.is-outlined.is-focused{background-color:#363a4f;border-color:#363a4f;color:#fff}html.theme--catppuccin-macchiato .button.is-dark.is-outlined.is-loading::after,html.theme--catppuccin-macchiato .content kbd.button.is-outlined.is-loading::after{border-color:transparent transparent #363a4f #363a4f !important}html.theme--catppuccin-macchiato .button.is-dark.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .content kbd.button.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .button.is-dark.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .content kbd.button.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .button.is-dark.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .content kbd.button.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .button.is-dark.is-outlined.is-loading.is-focused::after,html.theme--catppuccin-macchiato .content kbd.button.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-macchiato .button.is-dark.is-outlined[disabled],html.theme--catppuccin-macchiato .content kbd.button.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-dark.is-outlined,fieldset[disabled] html.theme--catppuccin-macchiato .content kbd.button.is-outlined{background-color:transparent;border-color:#363a4f;box-shadow:none;color:#363a4f}html.theme--catppuccin-macchiato .button.is-dark.is-inverted.is-outlined,html.theme--catppuccin-macchiato .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-macchiato .button.is-dark.is-inverted.is-outlined:hover,html.theme--catppuccin-macchiato .content kbd.button.is-inverted.is-outlined:hover,html.theme--catppuccin-macchiato .button.is-dark.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-macchiato .content kbd.button.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-macchiato .button.is-dark.is-inverted.is-outlined:focus,html.theme--catppuccin-macchiato .content kbd.button.is-inverted.is-outlined:focus,html.theme--catppuccin-macchiato .button.is-dark.is-inverted.is-outlined.is-focused,html.theme--catppuccin-macchiato .content kbd.button.is-inverted.is-outlined.is-focused{background-color:#fff;color:#363a4f}html.theme--catppuccin-macchiato .button.is-dark.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .content kbd.button.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .content kbd.button.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .button.is-dark.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .content kbd.button.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--catppuccin-macchiato .content kbd.button.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #363a4f #363a4f !important}html.theme--catppuccin-macchiato .button.is-dark.is-inverted.is-outlined[disabled],html.theme--catppuccin-macchiato .content kbd.button.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-dark.is-inverted.is-outlined,fieldset[disabled] html.theme--catppuccin-macchiato .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-macchiato .button.is-primary,html.theme--catppuccin-macchiato .docstring>section>a.button.docs-sourcelink{background-color:#8aadf4;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-primary:hover,html.theme--catppuccin-macchiato .docstring>section>a.button.docs-sourcelink:hover,html.theme--catppuccin-macchiato .button.is-primary.is-hovered,html.theme--catppuccin-macchiato .docstring>section>a.button.is-hovered.docs-sourcelink{background-color:#7ea5f3;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-primary:focus,html.theme--catppuccin-macchiato .docstring>section>a.button.docs-sourcelink:focus,html.theme--catppuccin-macchiato .button.is-primary.is-focused,html.theme--catppuccin-macchiato .docstring>section>a.button.is-focused.docs-sourcelink{border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-primary:focus:not(:active),html.theme--catppuccin-macchiato .docstring>section>a.button.docs-sourcelink:focus:not(:active),html.theme--catppuccin-macchiato .button.is-primary.is-focused:not(:active),html.theme--catppuccin-macchiato .docstring>section>a.button.is-focused.docs-sourcelink:not(:active){box-shadow:0 0 0 0.125em rgba(138,173,244,0.25)}html.theme--catppuccin-macchiato .button.is-primary:active,html.theme--catppuccin-macchiato .docstring>section>a.button.docs-sourcelink:active,html.theme--catppuccin-macchiato .button.is-primary.is-active,html.theme--catppuccin-macchiato .docstring>section>a.button.is-active.docs-sourcelink{background-color:#739df2;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-primary[disabled],html.theme--catppuccin-macchiato .docstring>section>a.button.docs-sourcelink[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-primary,fieldset[disabled] html.theme--catppuccin-macchiato .docstring>section>a.button.docs-sourcelink{background-color:#8aadf4;border-color:#8aadf4;box-shadow:none}html.theme--catppuccin-macchiato .button.is-primary.is-inverted,html.theme--catppuccin-macchiato .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;color:#8aadf4}html.theme--catppuccin-macchiato .button.is-primary.is-inverted:hover,html.theme--catppuccin-macchiato .docstring>section>a.button.is-inverted.docs-sourcelink:hover,html.theme--catppuccin-macchiato .button.is-primary.is-inverted.is-hovered,html.theme--catppuccin-macchiato .docstring>section>a.button.is-inverted.is-hovered.docs-sourcelink{background-color:#f2f2f2}html.theme--catppuccin-macchiato .button.is-primary.is-inverted[disabled],html.theme--catppuccin-macchiato .docstring>section>a.button.is-inverted.docs-sourcelink[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-primary.is-inverted,fieldset[disabled] html.theme--catppuccin-macchiato .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;border-color:transparent;box-shadow:none;color:#8aadf4}html.theme--catppuccin-macchiato .button.is-primary.is-loading::after,html.theme--catppuccin-macchiato .docstring>section>a.button.is-loading.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-macchiato .button.is-primary.is-outlined,html.theme--catppuccin-macchiato .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#8aadf4;color:#8aadf4}html.theme--catppuccin-macchiato .button.is-primary.is-outlined:hover,html.theme--catppuccin-macchiato .docstring>section>a.button.is-outlined.docs-sourcelink:hover,html.theme--catppuccin-macchiato .button.is-primary.is-outlined.is-hovered,html.theme--catppuccin-macchiato .docstring>section>a.button.is-outlined.is-hovered.docs-sourcelink,html.theme--catppuccin-macchiato .button.is-primary.is-outlined:focus,html.theme--catppuccin-macchiato .docstring>section>a.button.is-outlined.docs-sourcelink:focus,html.theme--catppuccin-macchiato .button.is-primary.is-outlined.is-focused,html.theme--catppuccin-macchiato .docstring>section>a.button.is-outlined.is-focused.docs-sourcelink{background-color:#8aadf4;border-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .button.is-primary.is-outlined.is-loading::after,html.theme--catppuccin-macchiato .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink::after{border-color:transparent transparent #8aadf4 #8aadf4 !important}html.theme--catppuccin-macchiato .button.is-primary.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--catppuccin-macchiato .button.is-primary.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .docstring>section>a.button.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--catppuccin-macchiato .button.is-primary.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--catppuccin-macchiato .button.is-primary.is-outlined.is-loading.is-focused::after,html.theme--catppuccin-macchiato .docstring>section>a.button.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-macchiato .button.is-primary.is-outlined[disabled],html.theme--catppuccin-macchiato .docstring>section>a.button.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-primary.is-outlined,fieldset[disabled] html.theme--catppuccin-macchiato .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#8aadf4;box-shadow:none;color:#8aadf4}html.theme--catppuccin-macchiato .button.is-primary.is-inverted.is-outlined,html.theme--catppuccin-macchiato .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-macchiato .button.is-primary.is-inverted.is-outlined:hover,html.theme--catppuccin-macchiato .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:hover,html.theme--catppuccin-macchiato .button.is-primary.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-macchiato .docstring>section>a.button.is-inverted.is-outlined.is-hovered.docs-sourcelink,html.theme--catppuccin-macchiato .button.is-primary.is-inverted.is-outlined:focus,html.theme--catppuccin-macchiato .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:focus,html.theme--catppuccin-macchiato .button.is-primary.is-inverted.is-outlined.is-focused,html.theme--catppuccin-macchiato .docstring>section>a.button.is-inverted.is-outlined.is-focused.docs-sourcelink{background-color:#fff;color:#8aadf4}html.theme--catppuccin-macchiato .button.is-primary.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--catppuccin-macchiato .button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--catppuccin-macchiato .button.is-primary.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--catppuccin-macchiato .button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--catppuccin-macchiato .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #8aadf4 #8aadf4 !important}html.theme--catppuccin-macchiato .button.is-primary.is-inverted.is-outlined[disabled],html.theme--catppuccin-macchiato .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-primary.is-inverted.is-outlined,fieldset[disabled] html.theme--catppuccin-macchiato .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-macchiato .button.is-primary.is-light,html.theme--catppuccin-macchiato .docstring>section>a.button.is-light.docs-sourcelink{background-color:#ecf2fd;color:#0e3b95}html.theme--catppuccin-macchiato .button.is-primary.is-light:hover,html.theme--catppuccin-macchiato .docstring>section>a.button.is-light.docs-sourcelink:hover,html.theme--catppuccin-macchiato .button.is-primary.is-light.is-hovered,html.theme--catppuccin-macchiato .docstring>section>a.button.is-light.is-hovered.docs-sourcelink{background-color:#e1eafc;border-color:transparent;color:#0e3b95}html.theme--catppuccin-macchiato .button.is-primary.is-light:active,html.theme--catppuccin-macchiato .docstring>section>a.button.is-light.docs-sourcelink:active,html.theme--catppuccin-macchiato .button.is-primary.is-light.is-active,html.theme--catppuccin-macchiato .docstring>section>a.button.is-light.is-active.docs-sourcelink{background-color:#d5e2fb;border-color:transparent;color:#0e3b95}html.theme--catppuccin-macchiato .button.is-link{background-color:#8aadf4;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-link:hover,html.theme--catppuccin-macchiato .button.is-link.is-hovered{background-color:#7ea5f3;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-link:focus,html.theme--catppuccin-macchiato .button.is-link.is-focused{border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-link:focus:not(:active),html.theme--catppuccin-macchiato .button.is-link.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(138,173,244,0.25)}html.theme--catppuccin-macchiato .button.is-link:active,html.theme--catppuccin-macchiato .button.is-link.is-active{background-color:#739df2;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-link[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-link{background-color:#8aadf4;border-color:#8aadf4;box-shadow:none}html.theme--catppuccin-macchiato .button.is-link.is-inverted{background-color:#fff;color:#8aadf4}html.theme--catppuccin-macchiato .button.is-link.is-inverted:hover,html.theme--catppuccin-macchiato .button.is-link.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--catppuccin-macchiato .button.is-link.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-link.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#8aadf4}html.theme--catppuccin-macchiato .button.is-link.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-macchiato .button.is-link.is-outlined{background-color:transparent;border-color:#8aadf4;color:#8aadf4}html.theme--catppuccin-macchiato .button.is-link.is-outlined:hover,html.theme--catppuccin-macchiato .button.is-link.is-outlined.is-hovered,html.theme--catppuccin-macchiato .button.is-link.is-outlined:focus,html.theme--catppuccin-macchiato .button.is-link.is-outlined.is-focused{background-color:#8aadf4;border-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .button.is-link.is-outlined.is-loading::after{border-color:transparent transparent #8aadf4 #8aadf4 !important}html.theme--catppuccin-macchiato .button.is-link.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .button.is-link.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .button.is-link.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .button.is-link.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-macchiato .button.is-link.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-link.is-outlined{background-color:transparent;border-color:#8aadf4;box-shadow:none;color:#8aadf4}html.theme--catppuccin-macchiato .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-macchiato .button.is-link.is-inverted.is-outlined:hover,html.theme--catppuccin-macchiato .button.is-link.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-macchiato .button.is-link.is-inverted.is-outlined:focus,html.theme--catppuccin-macchiato .button.is-link.is-inverted.is-outlined.is-focused{background-color:#fff;color:#8aadf4}html.theme--catppuccin-macchiato .button.is-link.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .button.is-link.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .button.is-link.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #8aadf4 #8aadf4 !important}html.theme--catppuccin-macchiato .button.is-link.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-macchiato .button.is-link.is-light{background-color:#ecf2fd;color:#0e3b95}html.theme--catppuccin-macchiato .button.is-link.is-light:hover,html.theme--catppuccin-macchiato .button.is-link.is-light.is-hovered{background-color:#e1eafc;border-color:transparent;color:#0e3b95}html.theme--catppuccin-macchiato .button.is-link.is-light:active,html.theme--catppuccin-macchiato .button.is-link.is-light.is-active{background-color:#d5e2fb;border-color:transparent;color:#0e3b95}html.theme--catppuccin-macchiato .button.is-info{background-color:#8bd5ca;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-info:hover,html.theme--catppuccin-macchiato .button.is-info.is-hovered{background-color:#82d2c6;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-info:focus,html.theme--catppuccin-macchiato .button.is-info.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-info:focus:not(:active),html.theme--catppuccin-macchiato .button.is-info.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(139,213,202,0.25)}html.theme--catppuccin-macchiato .button.is-info:active,html.theme--catppuccin-macchiato .button.is-info.is-active{background-color:#78cec1;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-info[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-info{background-color:#8bd5ca;border-color:#8bd5ca;box-shadow:none}html.theme--catppuccin-macchiato .button.is-info.is-inverted{background-color:rgba(0,0,0,0.7);color:#8bd5ca}html.theme--catppuccin-macchiato .button.is-info.is-inverted:hover,html.theme--catppuccin-macchiato .button.is-info.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-info.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-info.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#8bd5ca}html.theme--catppuccin-macchiato .button.is-info.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-macchiato .button.is-info.is-outlined{background-color:transparent;border-color:#8bd5ca;color:#8bd5ca}html.theme--catppuccin-macchiato .button.is-info.is-outlined:hover,html.theme--catppuccin-macchiato .button.is-info.is-outlined.is-hovered,html.theme--catppuccin-macchiato .button.is-info.is-outlined:focus,html.theme--catppuccin-macchiato .button.is-info.is-outlined.is-focused{background-color:#8bd5ca;border-color:#8bd5ca;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-info.is-outlined.is-loading::after{border-color:transparent transparent #8bd5ca #8bd5ca !important}html.theme--catppuccin-macchiato .button.is-info.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .button.is-info.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .button.is-info.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .button.is-info.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-macchiato .button.is-info.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-info.is-outlined{background-color:transparent;border-color:#8bd5ca;box-shadow:none;color:#8bd5ca}html.theme--catppuccin-macchiato .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-info.is-inverted.is-outlined:hover,html.theme--catppuccin-macchiato .button.is-info.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-macchiato .button.is-info.is-inverted.is-outlined:focus,html.theme--catppuccin-macchiato .button.is-info.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#8bd5ca}html.theme--catppuccin-macchiato .button.is-info.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .button.is-info.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .button.is-info.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #8bd5ca #8bd5ca !important}html.theme--catppuccin-macchiato .button.is-info.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-info.is-light{background-color:#f0faf8;color:#276d62}html.theme--catppuccin-macchiato .button.is-info.is-light:hover,html.theme--catppuccin-macchiato .button.is-info.is-light.is-hovered{background-color:#e7f6f4;border-color:transparent;color:#276d62}html.theme--catppuccin-macchiato .button.is-info.is-light:active,html.theme--catppuccin-macchiato .button.is-info.is-light.is-active{background-color:#ddf3f0;border-color:transparent;color:#276d62}html.theme--catppuccin-macchiato .button.is-success{background-color:#a6da95;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-success:hover,html.theme--catppuccin-macchiato .button.is-success.is-hovered{background-color:#9ed78c;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-success:focus,html.theme--catppuccin-macchiato .button.is-success.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-success:focus:not(:active),html.theme--catppuccin-macchiato .button.is-success.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(166,218,149,0.25)}html.theme--catppuccin-macchiato .button.is-success:active,html.theme--catppuccin-macchiato .button.is-success.is-active{background-color:#96d382;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-success[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-success{background-color:#a6da95;border-color:#a6da95;box-shadow:none}html.theme--catppuccin-macchiato .button.is-success.is-inverted{background-color:rgba(0,0,0,0.7);color:#a6da95}html.theme--catppuccin-macchiato .button.is-success.is-inverted:hover,html.theme--catppuccin-macchiato .button.is-success.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-success.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-success.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#a6da95}html.theme--catppuccin-macchiato .button.is-success.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-macchiato .button.is-success.is-outlined{background-color:transparent;border-color:#a6da95;color:#a6da95}html.theme--catppuccin-macchiato .button.is-success.is-outlined:hover,html.theme--catppuccin-macchiato .button.is-success.is-outlined.is-hovered,html.theme--catppuccin-macchiato .button.is-success.is-outlined:focus,html.theme--catppuccin-macchiato .button.is-success.is-outlined.is-focused{background-color:#a6da95;border-color:#a6da95;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-success.is-outlined.is-loading::after{border-color:transparent transparent #a6da95 #a6da95 !important}html.theme--catppuccin-macchiato .button.is-success.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .button.is-success.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .button.is-success.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .button.is-success.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-macchiato .button.is-success.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-success.is-outlined{background-color:transparent;border-color:#a6da95;box-shadow:none;color:#a6da95}html.theme--catppuccin-macchiato .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-success.is-inverted.is-outlined:hover,html.theme--catppuccin-macchiato .button.is-success.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-macchiato .button.is-success.is-inverted.is-outlined:focus,html.theme--catppuccin-macchiato .button.is-success.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#a6da95}html.theme--catppuccin-macchiato .button.is-success.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .button.is-success.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .button.is-success.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #a6da95 #a6da95 !important}html.theme--catppuccin-macchiato .button.is-success.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-success.is-light{background-color:#f2faf0;color:#386e26}html.theme--catppuccin-macchiato .button.is-success.is-light:hover,html.theme--catppuccin-macchiato .button.is-success.is-light.is-hovered{background-color:#eaf6e6;border-color:transparent;color:#386e26}html.theme--catppuccin-macchiato .button.is-success.is-light:active,html.theme--catppuccin-macchiato .button.is-success.is-light.is-active{background-color:#e2f3dd;border-color:transparent;color:#386e26}html.theme--catppuccin-macchiato .button.is-warning{background-color:#eed49f;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-warning:hover,html.theme--catppuccin-macchiato .button.is-warning.is-hovered{background-color:#eccf94;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-warning:focus,html.theme--catppuccin-macchiato .button.is-warning.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-warning:focus:not(:active),html.theme--catppuccin-macchiato .button.is-warning.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(238,212,159,0.25)}html.theme--catppuccin-macchiato .button.is-warning:active,html.theme--catppuccin-macchiato .button.is-warning.is-active{background-color:#eaca89;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-warning[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-warning{background-color:#eed49f;border-color:#eed49f;box-shadow:none}html.theme--catppuccin-macchiato .button.is-warning.is-inverted{background-color:rgba(0,0,0,0.7);color:#eed49f}html.theme--catppuccin-macchiato .button.is-warning.is-inverted:hover,html.theme--catppuccin-macchiato .button.is-warning.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-warning.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-warning.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#eed49f}html.theme--catppuccin-macchiato .button.is-warning.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-macchiato .button.is-warning.is-outlined{background-color:transparent;border-color:#eed49f;color:#eed49f}html.theme--catppuccin-macchiato .button.is-warning.is-outlined:hover,html.theme--catppuccin-macchiato .button.is-warning.is-outlined.is-hovered,html.theme--catppuccin-macchiato .button.is-warning.is-outlined:focus,html.theme--catppuccin-macchiato .button.is-warning.is-outlined.is-focused{background-color:#eed49f;border-color:#eed49f;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-warning.is-outlined.is-loading::after{border-color:transparent transparent #eed49f #eed49f !important}html.theme--catppuccin-macchiato .button.is-warning.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .button.is-warning.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .button.is-warning.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .button.is-warning.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-macchiato .button.is-warning.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-warning.is-outlined{background-color:transparent;border-color:#eed49f;box-shadow:none;color:#eed49f}html.theme--catppuccin-macchiato .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-warning.is-inverted.is-outlined:hover,html.theme--catppuccin-macchiato .button.is-warning.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-macchiato .button.is-warning.is-inverted.is-outlined:focus,html.theme--catppuccin-macchiato .button.is-warning.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#eed49f}html.theme--catppuccin-macchiato .button.is-warning.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .button.is-warning.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #eed49f #eed49f !important}html.theme--catppuccin-macchiato .button.is-warning.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .button.is-warning.is-light{background-color:#fcf7ee;color:#7e5c16}html.theme--catppuccin-macchiato .button.is-warning.is-light:hover,html.theme--catppuccin-macchiato .button.is-warning.is-light.is-hovered{background-color:#faf2e3;border-color:transparent;color:#7e5c16}html.theme--catppuccin-macchiato .button.is-warning.is-light:active,html.theme--catppuccin-macchiato .button.is-warning.is-light.is-active{background-color:#f8eed8;border-color:transparent;color:#7e5c16}html.theme--catppuccin-macchiato .button.is-danger{background-color:#ed8796;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-danger:hover,html.theme--catppuccin-macchiato .button.is-danger.is-hovered{background-color:#eb7c8c;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-danger:focus,html.theme--catppuccin-macchiato .button.is-danger.is-focused{border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-danger:focus:not(:active),html.theme--catppuccin-macchiato .button.is-danger.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(237,135,150,0.25)}html.theme--catppuccin-macchiato .button.is-danger:active,html.theme--catppuccin-macchiato .button.is-danger.is-active{background-color:#ea7183;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .button.is-danger[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-danger{background-color:#ed8796;border-color:#ed8796;box-shadow:none}html.theme--catppuccin-macchiato .button.is-danger.is-inverted{background-color:#fff;color:#ed8796}html.theme--catppuccin-macchiato .button.is-danger.is-inverted:hover,html.theme--catppuccin-macchiato .button.is-danger.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--catppuccin-macchiato .button.is-danger.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-danger.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#ed8796}html.theme--catppuccin-macchiato .button.is-danger.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-macchiato .button.is-danger.is-outlined{background-color:transparent;border-color:#ed8796;color:#ed8796}html.theme--catppuccin-macchiato .button.is-danger.is-outlined:hover,html.theme--catppuccin-macchiato .button.is-danger.is-outlined.is-hovered,html.theme--catppuccin-macchiato .button.is-danger.is-outlined:focus,html.theme--catppuccin-macchiato .button.is-danger.is-outlined.is-focused{background-color:#ed8796;border-color:#ed8796;color:#fff}html.theme--catppuccin-macchiato .button.is-danger.is-outlined.is-loading::after{border-color:transparent transparent #ed8796 #ed8796 !important}html.theme--catppuccin-macchiato .button.is-danger.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .button.is-danger.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .button.is-danger.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .button.is-danger.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-macchiato .button.is-danger.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-danger.is-outlined{background-color:transparent;border-color:#ed8796;box-shadow:none;color:#ed8796}html.theme--catppuccin-macchiato .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-macchiato .button.is-danger.is-inverted.is-outlined:hover,html.theme--catppuccin-macchiato .button.is-danger.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-macchiato .button.is-danger.is-inverted.is-outlined:focus,html.theme--catppuccin-macchiato .button.is-danger.is-inverted.is-outlined.is-focused{background-color:#fff;color:#ed8796}html.theme--catppuccin-macchiato .button.is-danger.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-macchiato .button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-macchiato .button.is-danger.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-macchiato .button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #ed8796 #ed8796 !important}html.theme--catppuccin-macchiato .button.is-danger.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-macchiato .button.is-danger.is-light{background-color:#fcedef;color:#971729}html.theme--catppuccin-macchiato .button.is-danger.is-light:hover,html.theme--catppuccin-macchiato .button.is-danger.is-light.is-hovered{background-color:#fbe2e6;border-color:transparent;color:#971729}html.theme--catppuccin-macchiato .button.is-danger.is-light:active,html.theme--catppuccin-macchiato .button.is-danger.is-light.is-active{background-color:#f9d7dc;border-color:transparent;color:#971729}html.theme--catppuccin-macchiato .button.is-small,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.button{font-size:.75rem}html.theme--catppuccin-macchiato .button.is-small:not(.is-rounded),html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.button:not(.is-rounded){border-radius:3px}html.theme--catppuccin-macchiato .button.is-normal{font-size:1rem}html.theme--catppuccin-macchiato .button.is-medium{font-size:1.25rem}html.theme--catppuccin-macchiato .button.is-large{font-size:1.5rem}html.theme--catppuccin-macchiato .button[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .button{background-color:#6e738d;border-color:#5b6078;box-shadow:none;opacity:.5}html.theme--catppuccin-macchiato .button.is-fullwidth{display:flex;width:100%}html.theme--catppuccin-macchiato .button.is-loading{color:transparent !important;pointer-events:none}html.theme--catppuccin-macchiato .button.is-loading::after{position:absolute;left:calc(50% - (1em * 0.5));top:calc(50% - (1em * 0.5));position:absolute !important}html.theme--catppuccin-macchiato .button.is-static{background-color:#1e2030;border-color:#5b6078;color:#8087a2;box-shadow:none;pointer-events:none}html.theme--catppuccin-macchiato .button.is-rounded,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.button{border-radius:9999px;padding-left:calc(1em + 0.25em);padding-right:calc(1em + 0.25em)}html.theme--catppuccin-macchiato .buttons{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--catppuccin-macchiato .buttons .button{margin-bottom:0.5rem}html.theme--catppuccin-macchiato .buttons .button:not(:last-child):not(.is-fullwidth){margin-right:.5rem}html.theme--catppuccin-macchiato .buttons:last-child{margin-bottom:-0.5rem}html.theme--catppuccin-macchiato .buttons:not(:last-child){margin-bottom:1rem}html.theme--catppuccin-macchiato .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large){font-size:.75rem}html.theme--catppuccin-macchiato .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large):not(.is-rounded){border-radius:3px}html.theme--catppuccin-macchiato .buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large){font-size:1.25rem}html.theme--catppuccin-macchiato .buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium){font-size:1.5rem}html.theme--catppuccin-macchiato .buttons.has-addons .button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}html.theme--catppuccin-macchiato .buttons.has-addons .button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}html.theme--catppuccin-macchiato .buttons.has-addons .button:last-child{margin-right:0}html.theme--catppuccin-macchiato .buttons.has-addons .button:hover,html.theme--catppuccin-macchiato .buttons.has-addons .button.is-hovered{z-index:2}html.theme--catppuccin-macchiato .buttons.has-addons .button:focus,html.theme--catppuccin-macchiato .buttons.has-addons .button.is-focused,html.theme--catppuccin-macchiato .buttons.has-addons .button:active,html.theme--catppuccin-macchiato .buttons.has-addons .button.is-active,html.theme--catppuccin-macchiato .buttons.has-addons .button.is-selected{z-index:3}html.theme--catppuccin-macchiato .buttons.has-addons .button:focus:hover,html.theme--catppuccin-macchiato .buttons.has-addons .button.is-focused:hover,html.theme--catppuccin-macchiato .buttons.has-addons .button:active:hover,html.theme--catppuccin-macchiato .buttons.has-addons .button.is-active:hover,html.theme--catppuccin-macchiato .buttons.has-addons .button.is-selected:hover{z-index:4}html.theme--catppuccin-macchiato .buttons.has-addons .button.is-expanded{flex-grow:1;flex-shrink:1}html.theme--catppuccin-macchiato .buttons.is-centered{justify-content:center}html.theme--catppuccin-macchiato .buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}html.theme--catppuccin-macchiato .buttons.is-right{justify-content:flex-end}html.theme--catppuccin-macchiato .buttons.is-right:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .button.is-responsive.is-small,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.5625rem}html.theme--catppuccin-macchiato .button.is-responsive,html.theme--catppuccin-macchiato .button.is-responsive.is-normal{font-size:.65625rem}html.theme--catppuccin-macchiato .button.is-responsive.is-medium{font-size:.75rem}html.theme--catppuccin-macchiato .button.is-responsive.is-large{font-size:1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-macchiato .button.is-responsive.is-small,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.65625rem}html.theme--catppuccin-macchiato .button.is-responsive,html.theme--catppuccin-macchiato .button.is-responsive.is-normal{font-size:.75rem}html.theme--catppuccin-macchiato .button.is-responsive.is-medium{font-size:1rem}html.theme--catppuccin-macchiato .button.is-responsive.is-large{font-size:1.25rem}}html.theme--catppuccin-macchiato .container{flex-grow:1;margin:0 auto;position:relative;width:auto}html.theme--catppuccin-macchiato .container.is-fluid{max-width:none !important;padding-left:32px;padding-right:32px;width:100%}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .container{max-width:992px}}@media screen and (max-width: 1215px){html.theme--catppuccin-macchiato .container.is-widescreen:not(.is-max-desktop){max-width:1152px}}@media screen and (max-width: 1407px){html.theme--catppuccin-macchiato .container.is-fullhd:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}@media screen and (min-width: 1216px){html.theme--catppuccin-macchiato .container:not(.is-max-desktop){max-width:1152px}}@media screen and (min-width: 1408px){html.theme--catppuccin-macchiato .container:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}html.theme--catppuccin-macchiato .content li+li{margin-top:0.25em}html.theme--catppuccin-macchiato .content p:not(:last-child),html.theme--catppuccin-macchiato .content dl:not(:last-child),html.theme--catppuccin-macchiato .content ol:not(:last-child),html.theme--catppuccin-macchiato .content ul:not(:last-child),html.theme--catppuccin-macchiato .content blockquote:not(:last-child),html.theme--catppuccin-macchiato .content pre:not(:last-child),html.theme--catppuccin-macchiato .content table:not(:last-child){margin-bottom:1em}html.theme--catppuccin-macchiato .content h1,html.theme--catppuccin-macchiato .content h2,html.theme--catppuccin-macchiato .content h3,html.theme--catppuccin-macchiato .content h4,html.theme--catppuccin-macchiato .content h5,html.theme--catppuccin-macchiato .content h6{color:#cad3f5;font-weight:600;line-height:1.125}html.theme--catppuccin-macchiato .content h1{font-size:2em;margin-bottom:0.5em}html.theme--catppuccin-macchiato .content h1:not(:first-child){margin-top:1em}html.theme--catppuccin-macchiato .content h2{font-size:1.75em;margin-bottom:0.5714em}html.theme--catppuccin-macchiato .content h2:not(:first-child){margin-top:1.1428em}html.theme--catppuccin-macchiato .content h3{font-size:1.5em;margin-bottom:0.6666em}html.theme--catppuccin-macchiato .content h3:not(:first-child){margin-top:1.3333em}html.theme--catppuccin-macchiato .content h4{font-size:1.25em;margin-bottom:0.8em}html.theme--catppuccin-macchiato .content h5{font-size:1.125em;margin-bottom:0.8888em}html.theme--catppuccin-macchiato .content h6{font-size:1em;margin-bottom:1em}html.theme--catppuccin-macchiato .content blockquote{background-color:#1e2030;border-left:5px solid #5b6078;padding:1.25em 1.5em}html.theme--catppuccin-macchiato .content ol{list-style-position:outside;margin-left:2em;margin-top:1em}html.theme--catppuccin-macchiato .content ol:not([type]){list-style-type:decimal}html.theme--catppuccin-macchiato .content ol.is-lower-alpha:not([type]){list-style-type:lower-alpha}html.theme--catppuccin-macchiato .content ol.is-lower-roman:not([type]){list-style-type:lower-roman}html.theme--catppuccin-macchiato .content ol.is-upper-alpha:not([type]){list-style-type:upper-alpha}html.theme--catppuccin-macchiato .content ol.is-upper-roman:not([type]){list-style-type:upper-roman}html.theme--catppuccin-macchiato .content ul{list-style:disc outside;margin-left:2em;margin-top:1em}html.theme--catppuccin-macchiato .content ul ul{list-style-type:circle;margin-top:0.5em}html.theme--catppuccin-macchiato .content ul ul ul{list-style-type:square}html.theme--catppuccin-macchiato .content dd{margin-left:2em}html.theme--catppuccin-macchiato .content figure{margin-left:2em;margin-right:2em;text-align:center}html.theme--catppuccin-macchiato .content figure:not(:first-child){margin-top:2em}html.theme--catppuccin-macchiato .content figure:not(:last-child){margin-bottom:2em}html.theme--catppuccin-macchiato .content figure img{display:inline-block}html.theme--catppuccin-macchiato .content figure figcaption{font-style:italic}html.theme--catppuccin-macchiato .content pre{-webkit-overflow-scrolling:touch;overflow-x:auto;padding:0;white-space:pre;word-wrap:normal}html.theme--catppuccin-macchiato .content sup,html.theme--catppuccin-macchiato .content sub{font-size:75%}html.theme--catppuccin-macchiato .content table{width:100%}html.theme--catppuccin-macchiato .content table td,html.theme--catppuccin-macchiato .content table th{border:1px solid #5b6078;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--catppuccin-macchiato .content table th{color:#b5c1f1}html.theme--catppuccin-macchiato .content table th:not([align]){text-align:inherit}html.theme--catppuccin-macchiato .content table thead td,html.theme--catppuccin-macchiato .content table thead th{border-width:0 0 2px;color:#b5c1f1}html.theme--catppuccin-macchiato .content table tfoot td,html.theme--catppuccin-macchiato .content table tfoot th{border-width:2px 0 0;color:#b5c1f1}html.theme--catppuccin-macchiato .content table tbody tr:last-child td,html.theme--catppuccin-macchiato .content table tbody tr:last-child th{border-bottom-width:0}html.theme--catppuccin-macchiato .content .tabs li+li{margin-top:0}html.theme--catppuccin-macchiato .content.is-small,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.content{font-size:.75rem}html.theme--catppuccin-macchiato .content.is-normal{font-size:1rem}html.theme--catppuccin-macchiato .content.is-medium{font-size:1.25rem}html.theme--catppuccin-macchiato .content.is-large{font-size:1.5rem}html.theme--catppuccin-macchiato .icon{align-items:center;display:inline-flex;justify-content:center;height:1.5rem;width:1.5rem}html.theme--catppuccin-macchiato .icon.is-small,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.icon{height:1rem;width:1rem}html.theme--catppuccin-macchiato .icon.is-medium{height:2rem;width:2rem}html.theme--catppuccin-macchiato .icon.is-large{height:3rem;width:3rem}html.theme--catppuccin-macchiato .icon-text{align-items:flex-start;color:inherit;display:inline-flex;flex-wrap:wrap;line-height:1.5rem;vertical-align:top}html.theme--catppuccin-macchiato .icon-text .icon{flex-grow:0;flex-shrink:0}html.theme--catppuccin-macchiato .icon-text .icon:not(:last-child){margin-right:.25em}html.theme--catppuccin-macchiato .icon-text .icon:not(:first-child){margin-left:.25em}html.theme--catppuccin-macchiato div.icon-text{display:flex}html.theme--catppuccin-macchiato .image,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img{display:block;position:relative}html.theme--catppuccin-macchiato .image img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img img{display:block;height:auto;width:100%}html.theme--catppuccin-macchiato .image img.is-rounded,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img img.is-rounded{border-radius:9999px}html.theme--catppuccin-macchiato .image.is-fullwidth,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-fullwidth{width:100%}html.theme--catppuccin-macchiato .image.is-square img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--catppuccin-macchiato .image.is-square .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--catppuccin-macchiato .image.is-1by1 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--catppuccin-macchiato .image.is-1by1 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--catppuccin-macchiato .image.is-5by4 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--catppuccin-macchiato .image.is-5by4 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--catppuccin-macchiato .image.is-4by3 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--catppuccin-macchiato .image.is-4by3 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--catppuccin-macchiato .image.is-3by2 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--catppuccin-macchiato .image.is-3by2 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--catppuccin-macchiato .image.is-5by3 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--catppuccin-macchiato .image.is-5by3 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--catppuccin-macchiato .image.is-16by9 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--catppuccin-macchiato .image.is-16by9 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--catppuccin-macchiato .image.is-2by1 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--catppuccin-macchiato .image.is-2by1 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--catppuccin-macchiato .image.is-3by1 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--catppuccin-macchiato .image.is-3by1 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--catppuccin-macchiato .image.is-4by5 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--catppuccin-macchiato .image.is-4by5 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--catppuccin-macchiato .image.is-3by4 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--catppuccin-macchiato .image.is-3by4 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--catppuccin-macchiato .image.is-2by3 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--catppuccin-macchiato .image.is-2by3 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--catppuccin-macchiato .image.is-3by5 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--catppuccin-macchiato .image.is-3by5 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--catppuccin-macchiato .image.is-9by16 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--catppuccin-macchiato .image.is-9by16 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--catppuccin-macchiato .image.is-1by2 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--catppuccin-macchiato .image.is-1by2 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--catppuccin-macchiato .image.is-1by3 img,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--catppuccin-macchiato .image.is-1by3 .has-ratio,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio{height:100%;width:100%}html.theme--catppuccin-macchiato .image.is-square,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-square,html.theme--catppuccin-macchiato .image.is-1by1,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-1by1{padding-top:100%}html.theme--catppuccin-macchiato .image.is-5by4,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-5by4{padding-top:80%}html.theme--catppuccin-macchiato .image.is-4by3,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-4by3{padding-top:75%}html.theme--catppuccin-macchiato .image.is-3by2,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by2{padding-top:66.6666%}html.theme--catppuccin-macchiato .image.is-5by3,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-5by3{padding-top:60%}html.theme--catppuccin-macchiato .image.is-16by9,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-16by9{padding-top:56.25%}html.theme--catppuccin-macchiato .image.is-2by1,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-2by1{padding-top:50%}html.theme--catppuccin-macchiato .image.is-3by1,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by1{padding-top:33.3333%}html.theme--catppuccin-macchiato .image.is-4by5,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-4by5{padding-top:125%}html.theme--catppuccin-macchiato .image.is-3by4,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by4{padding-top:133.3333%}html.theme--catppuccin-macchiato .image.is-2by3,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-2by3{padding-top:150%}html.theme--catppuccin-macchiato .image.is-3by5,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-3by5{padding-top:166.6666%}html.theme--catppuccin-macchiato .image.is-9by16,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-9by16{padding-top:177.7777%}html.theme--catppuccin-macchiato .image.is-1by2,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-1by2{padding-top:200%}html.theme--catppuccin-macchiato .image.is-1by3,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-1by3{padding-top:300%}html.theme--catppuccin-macchiato .image.is-16x16,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-16x16{height:16px;width:16px}html.theme--catppuccin-macchiato .image.is-24x24,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-24x24{height:24px;width:24px}html.theme--catppuccin-macchiato .image.is-32x32,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-32x32{height:32px;width:32px}html.theme--catppuccin-macchiato .image.is-48x48,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-48x48{height:48px;width:48px}html.theme--catppuccin-macchiato .image.is-64x64,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-64x64{height:64px;width:64px}html.theme--catppuccin-macchiato .image.is-96x96,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-96x96{height:96px;width:96px}html.theme--catppuccin-macchiato .image.is-128x128,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img.is-128x128{height:128px;width:128px}html.theme--catppuccin-macchiato .notification{background-color:#1e2030;border-radius:.4em;position:relative;padding:1.25rem 2.5rem 1.25rem 1.5rem}html.theme--catppuccin-macchiato .notification a:not(.button):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--catppuccin-macchiato .notification strong{color:currentColor}html.theme--catppuccin-macchiato .notification code,html.theme--catppuccin-macchiato .notification pre{background:#fff}html.theme--catppuccin-macchiato .notification pre code{background:transparent}html.theme--catppuccin-macchiato .notification>.delete{right:.5rem;position:absolute;top:0.5rem}html.theme--catppuccin-macchiato .notification .title,html.theme--catppuccin-macchiato .notification .subtitle,html.theme--catppuccin-macchiato .notification .content{color:currentColor}html.theme--catppuccin-macchiato .notification.is-white{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-macchiato .notification.is-black{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-macchiato .notification.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .notification.is-dark,html.theme--catppuccin-macchiato .content kbd.notification{background-color:#363a4f;color:#fff}html.theme--catppuccin-macchiato .notification.is-primary,html.theme--catppuccin-macchiato .docstring>section>a.notification.docs-sourcelink{background-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .notification.is-primary.is-light,html.theme--catppuccin-macchiato .docstring>section>a.notification.is-light.docs-sourcelink{background-color:#ecf2fd;color:#0e3b95}html.theme--catppuccin-macchiato .notification.is-link{background-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .notification.is-link.is-light{background-color:#ecf2fd;color:#0e3b95}html.theme--catppuccin-macchiato .notification.is-info{background-color:#8bd5ca;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .notification.is-info.is-light{background-color:#f0faf8;color:#276d62}html.theme--catppuccin-macchiato .notification.is-success{background-color:#a6da95;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .notification.is-success.is-light{background-color:#f2faf0;color:#386e26}html.theme--catppuccin-macchiato .notification.is-warning{background-color:#eed49f;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .notification.is-warning.is-light{background-color:#fcf7ee;color:#7e5c16}html.theme--catppuccin-macchiato .notification.is-danger{background-color:#ed8796;color:#fff}html.theme--catppuccin-macchiato .notification.is-danger.is-light{background-color:#fcedef;color:#971729}html.theme--catppuccin-macchiato .progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:9999px;display:block;height:1rem;overflow:hidden;padding:0;width:100%}html.theme--catppuccin-macchiato .progress::-webkit-progress-bar{background-color:#494d64}html.theme--catppuccin-macchiato .progress::-webkit-progress-value{background-color:#8087a2}html.theme--catppuccin-macchiato .progress::-moz-progress-bar{background-color:#8087a2}html.theme--catppuccin-macchiato .progress::-ms-fill{background-color:#8087a2;border:none}html.theme--catppuccin-macchiato .progress.is-white::-webkit-progress-value{background-color:#fff}html.theme--catppuccin-macchiato .progress.is-white::-moz-progress-bar{background-color:#fff}html.theme--catppuccin-macchiato .progress.is-white::-ms-fill{background-color:#fff}html.theme--catppuccin-macchiato .progress.is-white:indeterminate{background-image:linear-gradient(to right, #fff 30%, #494d64 30%)}html.theme--catppuccin-macchiato .progress.is-black::-webkit-progress-value{background-color:#0a0a0a}html.theme--catppuccin-macchiato .progress.is-black::-moz-progress-bar{background-color:#0a0a0a}html.theme--catppuccin-macchiato .progress.is-black::-ms-fill{background-color:#0a0a0a}html.theme--catppuccin-macchiato .progress.is-black:indeterminate{background-image:linear-gradient(to right, #0a0a0a 30%, #494d64 30%)}html.theme--catppuccin-macchiato .progress.is-light::-webkit-progress-value{background-color:#f5f5f5}html.theme--catppuccin-macchiato .progress.is-light::-moz-progress-bar{background-color:#f5f5f5}html.theme--catppuccin-macchiato .progress.is-light::-ms-fill{background-color:#f5f5f5}html.theme--catppuccin-macchiato .progress.is-light:indeterminate{background-image:linear-gradient(to right, #f5f5f5 30%, #494d64 30%)}html.theme--catppuccin-macchiato .progress.is-dark::-webkit-progress-value,html.theme--catppuccin-macchiato .content kbd.progress::-webkit-progress-value{background-color:#363a4f}html.theme--catppuccin-macchiato .progress.is-dark::-moz-progress-bar,html.theme--catppuccin-macchiato .content kbd.progress::-moz-progress-bar{background-color:#363a4f}html.theme--catppuccin-macchiato .progress.is-dark::-ms-fill,html.theme--catppuccin-macchiato .content kbd.progress::-ms-fill{background-color:#363a4f}html.theme--catppuccin-macchiato .progress.is-dark:indeterminate,html.theme--catppuccin-macchiato .content kbd.progress:indeterminate{background-image:linear-gradient(to right, #363a4f 30%, #494d64 30%)}html.theme--catppuccin-macchiato .progress.is-primary::-webkit-progress-value,html.theme--catppuccin-macchiato .docstring>section>a.progress.docs-sourcelink::-webkit-progress-value{background-color:#8aadf4}html.theme--catppuccin-macchiato .progress.is-primary::-moz-progress-bar,html.theme--catppuccin-macchiato .docstring>section>a.progress.docs-sourcelink::-moz-progress-bar{background-color:#8aadf4}html.theme--catppuccin-macchiato .progress.is-primary::-ms-fill,html.theme--catppuccin-macchiato .docstring>section>a.progress.docs-sourcelink::-ms-fill{background-color:#8aadf4}html.theme--catppuccin-macchiato .progress.is-primary:indeterminate,html.theme--catppuccin-macchiato .docstring>section>a.progress.docs-sourcelink:indeterminate{background-image:linear-gradient(to right, #8aadf4 30%, #494d64 30%)}html.theme--catppuccin-macchiato .progress.is-link::-webkit-progress-value{background-color:#8aadf4}html.theme--catppuccin-macchiato .progress.is-link::-moz-progress-bar{background-color:#8aadf4}html.theme--catppuccin-macchiato .progress.is-link::-ms-fill{background-color:#8aadf4}html.theme--catppuccin-macchiato .progress.is-link:indeterminate{background-image:linear-gradient(to right, #8aadf4 30%, #494d64 30%)}html.theme--catppuccin-macchiato .progress.is-info::-webkit-progress-value{background-color:#8bd5ca}html.theme--catppuccin-macchiato .progress.is-info::-moz-progress-bar{background-color:#8bd5ca}html.theme--catppuccin-macchiato .progress.is-info::-ms-fill{background-color:#8bd5ca}html.theme--catppuccin-macchiato .progress.is-info:indeterminate{background-image:linear-gradient(to right, #8bd5ca 30%, #494d64 30%)}html.theme--catppuccin-macchiato .progress.is-success::-webkit-progress-value{background-color:#a6da95}html.theme--catppuccin-macchiato .progress.is-success::-moz-progress-bar{background-color:#a6da95}html.theme--catppuccin-macchiato .progress.is-success::-ms-fill{background-color:#a6da95}html.theme--catppuccin-macchiato .progress.is-success:indeterminate{background-image:linear-gradient(to right, #a6da95 30%, #494d64 30%)}html.theme--catppuccin-macchiato .progress.is-warning::-webkit-progress-value{background-color:#eed49f}html.theme--catppuccin-macchiato .progress.is-warning::-moz-progress-bar{background-color:#eed49f}html.theme--catppuccin-macchiato .progress.is-warning::-ms-fill{background-color:#eed49f}html.theme--catppuccin-macchiato .progress.is-warning:indeterminate{background-image:linear-gradient(to right, #eed49f 30%, #494d64 30%)}html.theme--catppuccin-macchiato .progress.is-danger::-webkit-progress-value{background-color:#ed8796}html.theme--catppuccin-macchiato .progress.is-danger::-moz-progress-bar{background-color:#ed8796}html.theme--catppuccin-macchiato .progress.is-danger::-ms-fill{background-color:#ed8796}html.theme--catppuccin-macchiato .progress.is-danger:indeterminate{background-image:linear-gradient(to right, #ed8796 30%, #494d64 30%)}html.theme--catppuccin-macchiato .progress:indeterminate{animation-duration:1.5s;animation-iteration-count:infinite;animation-name:moveIndeterminate;animation-timing-function:linear;background-color:#494d64;background-image:linear-gradient(to right, #cad3f5 30%, #494d64 30%);background-position:top left;background-repeat:no-repeat;background-size:150% 150%}html.theme--catppuccin-macchiato .progress:indeterminate::-webkit-progress-bar{background-color:transparent}html.theme--catppuccin-macchiato .progress:indeterminate::-moz-progress-bar{background-color:transparent}html.theme--catppuccin-macchiato .progress:indeterminate::-ms-fill{animation-name:none}html.theme--catppuccin-macchiato .progress.is-small,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.progress{height:.75rem}html.theme--catppuccin-macchiato .progress.is-medium{height:1.25rem}html.theme--catppuccin-macchiato .progress.is-large{height:1.5rem}@keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}html.theme--catppuccin-macchiato .table{background-color:#494d64;color:#cad3f5}html.theme--catppuccin-macchiato .table td,html.theme--catppuccin-macchiato .table th{border:1px solid #5b6078;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--catppuccin-macchiato .table td.is-white,html.theme--catppuccin-macchiato .table th.is-white{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--catppuccin-macchiato .table td.is-black,html.theme--catppuccin-macchiato .table th.is-black{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--catppuccin-macchiato .table td.is-light,html.theme--catppuccin-macchiato .table th.is-light{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .table td.is-dark,html.theme--catppuccin-macchiato .table th.is-dark{background-color:#363a4f;border-color:#363a4f;color:#fff}html.theme--catppuccin-macchiato .table td.is-primary,html.theme--catppuccin-macchiato .table th.is-primary{background-color:#8aadf4;border-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .table td.is-link,html.theme--catppuccin-macchiato .table th.is-link{background-color:#8aadf4;border-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .table td.is-info,html.theme--catppuccin-macchiato .table th.is-info{background-color:#8bd5ca;border-color:#8bd5ca;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .table td.is-success,html.theme--catppuccin-macchiato .table th.is-success{background-color:#a6da95;border-color:#a6da95;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .table td.is-warning,html.theme--catppuccin-macchiato .table th.is-warning{background-color:#eed49f;border-color:#eed49f;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .table td.is-danger,html.theme--catppuccin-macchiato .table th.is-danger{background-color:#ed8796;border-color:#ed8796;color:#fff}html.theme--catppuccin-macchiato .table td.is-narrow,html.theme--catppuccin-macchiato .table th.is-narrow{white-space:nowrap;width:1%}html.theme--catppuccin-macchiato .table td.is-selected,html.theme--catppuccin-macchiato .table th.is-selected{background-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .table td.is-selected a,html.theme--catppuccin-macchiato .table td.is-selected strong,html.theme--catppuccin-macchiato .table th.is-selected a,html.theme--catppuccin-macchiato .table th.is-selected strong{color:currentColor}html.theme--catppuccin-macchiato .table td.is-vcentered,html.theme--catppuccin-macchiato .table th.is-vcentered{vertical-align:middle}html.theme--catppuccin-macchiato .table th{color:#b5c1f1}html.theme--catppuccin-macchiato .table th:not([align]){text-align:left}html.theme--catppuccin-macchiato .table tr.is-selected{background-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .table tr.is-selected a,html.theme--catppuccin-macchiato .table tr.is-selected strong{color:currentColor}html.theme--catppuccin-macchiato .table tr.is-selected td,html.theme--catppuccin-macchiato .table tr.is-selected th{border-color:#fff;color:currentColor}html.theme--catppuccin-macchiato .table thead{background-color:rgba(0,0,0,0)}html.theme--catppuccin-macchiato .table thead td,html.theme--catppuccin-macchiato .table thead th{border-width:0 0 2px;color:#b5c1f1}html.theme--catppuccin-macchiato .table tfoot{background-color:rgba(0,0,0,0)}html.theme--catppuccin-macchiato .table tfoot td,html.theme--catppuccin-macchiato .table tfoot th{border-width:2px 0 0;color:#b5c1f1}html.theme--catppuccin-macchiato .table tbody{background-color:rgba(0,0,0,0)}html.theme--catppuccin-macchiato .table tbody tr:last-child td,html.theme--catppuccin-macchiato .table tbody tr:last-child th{border-bottom-width:0}html.theme--catppuccin-macchiato .table.is-bordered td,html.theme--catppuccin-macchiato .table.is-bordered th{border-width:1px}html.theme--catppuccin-macchiato .table.is-bordered tr:last-child td,html.theme--catppuccin-macchiato .table.is-bordered tr:last-child th{border-bottom-width:1px}html.theme--catppuccin-macchiato .table.is-fullwidth{width:100%}html.theme--catppuccin-macchiato .table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#363a4f}html.theme--catppuccin-macchiato .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover{background-color:#363a4f}html.theme--catppuccin-macchiato .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even){background-color:#3a3e55}html.theme--catppuccin-macchiato .table.is-narrow td,html.theme--catppuccin-macchiato .table.is-narrow th{padding:0.25em 0.5em}html.theme--catppuccin-macchiato .table.is-striped tbody tr:not(.is-selected):nth-child(even){background-color:#363a4f}html.theme--catppuccin-macchiato .table-container{-webkit-overflow-scrolling:touch;overflow:auto;overflow-y:hidden;max-width:100%}html.theme--catppuccin-macchiato .tags{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--catppuccin-macchiato .tags .tag,html.theme--catppuccin-macchiato .tags .content kbd,html.theme--catppuccin-macchiato .content .tags kbd,html.theme--catppuccin-macchiato .tags .docstring>section>a.docs-sourcelink{margin-bottom:0.5rem}html.theme--catppuccin-macchiato .tags .tag:not(:last-child),html.theme--catppuccin-macchiato .tags .content kbd:not(:last-child),html.theme--catppuccin-macchiato .content .tags kbd:not(:last-child),html.theme--catppuccin-macchiato .tags .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:.5rem}html.theme--catppuccin-macchiato .tags:last-child{margin-bottom:-0.5rem}html.theme--catppuccin-macchiato .tags:not(:last-child){margin-bottom:1rem}html.theme--catppuccin-macchiato .tags.are-medium .tag:not(.is-normal):not(.is-large),html.theme--catppuccin-macchiato .tags.are-medium .content kbd:not(.is-normal):not(.is-large),html.theme--catppuccin-macchiato .content .tags.are-medium kbd:not(.is-normal):not(.is-large),html.theme--catppuccin-macchiato .tags.are-medium .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-large){font-size:1rem}html.theme--catppuccin-macchiato .tags.are-large .tag:not(.is-normal):not(.is-medium),html.theme--catppuccin-macchiato .tags.are-large .content kbd:not(.is-normal):not(.is-medium),html.theme--catppuccin-macchiato .content .tags.are-large kbd:not(.is-normal):not(.is-medium),html.theme--catppuccin-macchiato .tags.are-large .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-medium){font-size:1.25rem}html.theme--catppuccin-macchiato .tags.is-centered{justify-content:center}html.theme--catppuccin-macchiato .tags.is-centered .tag,html.theme--catppuccin-macchiato .tags.is-centered .content kbd,html.theme--catppuccin-macchiato .content .tags.is-centered kbd,html.theme--catppuccin-macchiato .tags.is-centered .docstring>section>a.docs-sourcelink{margin-right:0.25rem;margin-left:0.25rem}html.theme--catppuccin-macchiato .tags.is-right{justify-content:flex-end}html.theme--catppuccin-macchiato .tags.is-right .tag:not(:first-child),html.theme--catppuccin-macchiato .tags.is-right .content kbd:not(:first-child),html.theme--catppuccin-macchiato .content .tags.is-right kbd:not(:first-child),html.theme--catppuccin-macchiato .tags.is-right .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0.5rem}html.theme--catppuccin-macchiato .tags.is-right .tag:not(:last-child),html.theme--catppuccin-macchiato .tags.is-right .content kbd:not(:last-child),html.theme--catppuccin-macchiato .content .tags.is-right kbd:not(:last-child),html.theme--catppuccin-macchiato .tags.is-right .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:0}html.theme--catppuccin-macchiato .tags.has-addons .tag,html.theme--catppuccin-macchiato .tags.has-addons .content kbd,html.theme--catppuccin-macchiato .content .tags.has-addons kbd,html.theme--catppuccin-macchiato .tags.has-addons .docstring>section>a.docs-sourcelink{margin-right:0}html.theme--catppuccin-macchiato .tags.has-addons .tag:not(:first-child),html.theme--catppuccin-macchiato .tags.has-addons .content kbd:not(:first-child),html.theme--catppuccin-macchiato .content .tags.has-addons kbd:not(:first-child),html.theme--catppuccin-macchiato .tags.has-addons .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0;border-top-left-radius:0;border-bottom-left-radius:0}html.theme--catppuccin-macchiato .tags.has-addons .tag:not(:last-child),html.theme--catppuccin-macchiato .tags.has-addons .content kbd:not(:last-child),html.theme--catppuccin-macchiato .content .tags.has-addons kbd:not(:last-child),html.theme--catppuccin-macchiato .tags.has-addons .docstring>section>a.docs-sourcelink:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}html.theme--catppuccin-macchiato .tag:not(body),html.theme--catppuccin-macchiato .content kbd:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink:not(body){align-items:center;background-color:#1e2030;border-radius:.4em;color:#cad3f5;display:inline-flex;font-size:.75rem;height:2em;justify-content:center;line-height:1.5;padding-left:0.75em;padding-right:0.75em;white-space:nowrap}html.theme--catppuccin-macchiato .tag:not(body) .delete,html.theme--catppuccin-macchiato .content kbd:not(body) .delete,html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink:not(body) .delete{margin-left:.25rem;margin-right:-.375rem}html.theme--catppuccin-macchiato .tag.is-white:not(body),html.theme--catppuccin-macchiato .content kbd.is-white:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-white:not(body){background-color:#fff;color:#0a0a0a}html.theme--catppuccin-macchiato .tag.is-black:not(body),html.theme--catppuccin-macchiato .content kbd.is-black:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-black:not(body){background-color:#0a0a0a;color:#fff}html.theme--catppuccin-macchiato .tag.is-light:not(body),html.theme--catppuccin-macchiato .content kbd.is-light:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .tag.is-dark:not(body),html.theme--catppuccin-macchiato .content kbd:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-dark:not(body),html.theme--catppuccin-macchiato .content .docstring>section>kbd:not(body){background-color:#363a4f;color:#fff}html.theme--catppuccin-macchiato .tag.is-primary:not(body),html.theme--catppuccin-macchiato .content kbd.is-primary:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink:not(body){background-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .tag.is-primary.is-light:not(body),html.theme--catppuccin-macchiato .content kbd.is-primary.is-light:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#ecf2fd;color:#0e3b95}html.theme--catppuccin-macchiato .tag.is-link:not(body),html.theme--catppuccin-macchiato .content kbd.is-link:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-link:not(body){background-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .tag.is-link.is-light:not(body),html.theme--catppuccin-macchiato .content kbd.is-link.is-light:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-link.is-light:not(body){background-color:#ecf2fd;color:#0e3b95}html.theme--catppuccin-macchiato .tag.is-info:not(body),html.theme--catppuccin-macchiato .content kbd.is-info:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-info:not(body){background-color:#8bd5ca;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .tag.is-info.is-light:not(body),html.theme--catppuccin-macchiato .content kbd.is-info.is-light:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-info.is-light:not(body){background-color:#f0faf8;color:#276d62}html.theme--catppuccin-macchiato .tag.is-success:not(body),html.theme--catppuccin-macchiato .content kbd.is-success:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-success:not(body){background-color:#a6da95;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .tag.is-success.is-light:not(body),html.theme--catppuccin-macchiato .content kbd.is-success.is-light:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-success.is-light:not(body){background-color:#f2faf0;color:#386e26}html.theme--catppuccin-macchiato .tag.is-warning:not(body),html.theme--catppuccin-macchiato .content kbd.is-warning:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-warning:not(body){background-color:#eed49f;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .tag.is-warning.is-light:not(body),html.theme--catppuccin-macchiato .content kbd.is-warning.is-light:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-warning.is-light:not(body){background-color:#fcf7ee;color:#7e5c16}html.theme--catppuccin-macchiato .tag.is-danger:not(body),html.theme--catppuccin-macchiato .content kbd.is-danger:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-danger:not(body){background-color:#ed8796;color:#fff}html.theme--catppuccin-macchiato .tag.is-danger.is-light:not(body),html.theme--catppuccin-macchiato .content kbd.is-danger.is-light:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-danger.is-light:not(body){background-color:#fcedef;color:#971729}html.theme--catppuccin-macchiato .tag.is-normal:not(body),html.theme--catppuccin-macchiato .content kbd.is-normal:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-normal:not(body){font-size:.75rem}html.theme--catppuccin-macchiato .tag.is-medium:not(body),html.theme--catppuccin-macchiato .content kbd.is-medium:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-medium:not(body){font-size:1rem}html.theme--catppuccin-macchiato .tag.is-large:not(body),html.theme--catppuccin-macchiato .content kbd.is-large:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-large:not(body){font-size:1.25rem}html.theme--catppuccin-macchiato .tag:not(body) .icon:first-child:not(:last-child),html.theme--catppuccin-macchiato .content kbd:not(body) .icon:first-child:not(:last-child),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:not(:last-child){margin-left:-.375em;margin-right:.1875em}html.theme--catppuccin-macchiato .tag:not(body) .icon:last-child:not(:first-child),html.theme--catppuccin-macchiato .content kbd:not(body) .icon:last-child:not(:first-child),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink:not(body) .icon:last-child:not(:first-child){margin-left:.1875em;margin-right:-.375em}html.theme--catppuccin-macchiato .tag:not(body) .icon:first-child:last-child,html.theme--catppuccin-macchiato .content kbd:not(body) .icon:first-child:last-child,html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:last-child{margin-left:-.375em;margin-right:-.375em}html.theme--catppuccin-macchiato .tag.is-delete:not(body),html.theme--catppuccin-macchiato .content kbd.is-delete:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-delete:not(body){margin-left:1px;padding:0;position:relative;width:2em}html.theme--catppuccin-macchiato .tag.is-delete:not(body)::before,html.theme--catppuccin-macchiato .content kbd.is-delete:not(body)::before,html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-delete:not(body)::before,html.theme--catppuccin-macchiato .tag.is-delete:not(body)::after,html.theme--catppuccin-macchiato .content kbd.is-delete:not(body)::after,html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{background-color:currentColor;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--catppuccin-macchiato .tag.is-delete:not(body)::before,html.theme--catppuccin-macchiato .content kbd.is-delete:not(body)::before,html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-delete:not(body)::before{height:1px;width:50%}html.theme--catppuccin-macchiato .tag.is-delete:not(body)::after,html.theme--catppuccin-macchiato .content kbd.is-delete:not(body)::after,html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{height:50%;width:1px}html.theme--catppuccin-macchiato .tag.is-delete:not(body):hover,html.theme--catppuccin-macchiato .content kbd.is-delete:not(body):hover,html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-delete:not(body):hover,html.theme--catppuccin-macchiato .tag.is-delete:not(body):focus,html.theme--catppuccin-macchiato .content kbd.is-delete:not(body):focus,html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-delete:not(body):focus{background-color:#141620}html.theme--catppuccin-macchiato .tag.is-delete:not(body):active,html.theme--catppuccin-macchiato .content kbd.is-delete:not(body):active,html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-delete:not(body):active{background-color:#0a0b11}html.theme--catppuccin-macchiato .tag.is-rounded:not(body),html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input:not(body),html.theme--catppuccin-macchiato .content kbd.is-rounded:not(body),html.theme--catppuccin-macchiato #documenter .docs-sidebar .content form.docs-search>input:not(body),html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink.is-rounded:not(body){border-radius:9999px}html.theme--catppuccin-macchiato a.tag:hover,html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink:hover{text-decoration:underline}html.theme--catppuccin-macchiato .title,html.theme--catppuccin-macchiato .subtitle{word-break:break-word}html.theme--catppuccin-macchiato .title em,html.theme--catppuccin-macchiato .title span,html.theme--catppuccin-macchiato .subtitle em,html.theme--catppuccin-macchiato .subtitle span{font-weight:inherit}html.theme--catppuccin-macchiato .title sub,html.theme--catppuccin-macchiato .subtitle sub{font-size:.75em}html.theme--catppuccin-macchiato .title sup,html.theme--catppuccin-macchiato .subtitle sup{font-size:.75em}html.theme--catppuccin-macchiato .title .tag,html.theme--catppuccin-macchiato .title .content kbd,html.theme--catppuccin-macchiato .content .title kbd,html.theme--catppuccin-macchiato .title .docstring>section>a.docs-sourcelink,html.theme--catppuccin-macchiato .subtitle .tag,html.theme--catppuccin-macchiato .subtitle .content kbd,html.theme--catppuccin-macchiato .content .subtitle kbd,html.theme--catppuccin-macchiato .subtitle .docstring>section>a.docs-sourcelink{vertical-align:middle}html.theme--catppuccin-macchiato .title{color:#fff;font-size:2rem;font-weight:500;line-height:1.125}html.theme--catppuccin-macchiato .title strong{color:inherit;font-weight:inherit}html.theme--catppuccin-macchiato .title:not(.is-spaced)+.subtitle{margin-top:-1.25rem}html.theme--catppuccin-macchiato .title.is-1{font-size:3rem}html.theme--catppuccin-macchiato .title.is-2{font-size:2.5rem}html.theme--catppuccin-macchiato .title.is-3{font-size:2rem}html.theme--catppuccin-macchiato .title.is-4{font-size:1.5rem}html.theme--catppuccin-macchiato .title.is-5{font-size:1.25rem}html.theme--catppuccin-macchiato .title.is-6{font-size:1rem}html.theme--catppuccin-macchiato .title.is-7{font-size:.75rem}html.theme--catppuccin-macchiato .subtitle{color:#6e738d;font-size:1.25rem;font-weight:400;line-height:1.25}html.theme--catppuccin-macchiato .subtitle strong{color:#6e738d;font-weight:600}html.theme--catppuccin-macchiato .subtitle:not(.is-spaced)+.title{margin-top:-1.25rem}html.theme--catppuccin-macchiato .subtitle.is-1{font-size:3rem}html.theme--catppuccin-macchiato .subtitle.is-2{font-size:2.5rem}html.theme--catppuccin-macchiato .subtitle.is-3{font-size:2rem}html.theme--catppuccin-macchiato .subtitle.is-4{font-size:1.5rem}html.theme--catppuccin-macchiato .subtitle.is-5{font-size:1.25rem}html.theme--catppuccin-macchiato .subtitle.is-6{font-size:1rem}html.theme--catppuccin-macchiato .subtitle.is-7{font-size:.75rem}html.theme--catppuccin-macchiato .heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}html.theme--catppuccin-macchiato .number{align-items:center;background-color:#1e2030;border-radius:9999px;display:inline-flex;font-size:1.25rem;height:2em;justify-content:center;margin-right:1.5rem;min-width:2.5em;padding:0.25rem 0.5rem;text-align:center;vertical-align:top}html.theme--catppuccin-macchiato .select select,html.theme--catppuccin-macchiato .textarea,html.theme--catppuccin-macchiato .input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input{background-color:#24273a;border-color:#5b6078;border-radius:.4em;color:#8087a2}html.theme--catppuccin-macchiato .select select::-moz-placeholder,html.theme--catppuccin-macchiato .textarea::-moz-placeholder,html.theme--catppuccin-macchiato .input::-moz-placeholder,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:#868c98}html.theme--catppuccin-macchiato .select select::-webkit-input-placeholder,html.theme--catppuccin-macchiato .textarea::-webkit-input-placeholder,html.theme--catppuccin-macchiato .input::-webkit-input-placeholder,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:#868c98}html.theme--catppuccin-macchiato .select select:-moz-placeholder,html.theme--catppuccin-macchiato .textarea:-moz-placeholder,html.theme--catppuccin-macchiato .input:-moz-placeholder,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:#868c98}html.theme--catppuccin-macchiato .select select:-ms-input-placeholder,html.theme--catppuccin-macchiato .textarea:-ms-input-placeholder,html.theme--catppuccin-macchiato .input:-ms-input-placeholder,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:#868c98}html.theme--catppuccin-macchiato .select select:hover,html.theme--catppuccin-macchiato .textarea:hover,html.theme--catppuccin-macchiato .input:hover,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input:hover,html.theme--catppuccin-macchiato .select select.is-hovered,html.theme--catppuccin-macchiato .is-hovered.textarea,html.theme--catppuccin-macchiato .is-hovered.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-hovered{border-color:#6e738d}html.theme--catppuccin-macchiato .select select:focus,html.theme--catppuccin-macchiato .textarea:focus,html.theme--catppuccin-macchiato .input:focus,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input:focus,html.theme--catppuccin-macchiato .select select.is-focused,html.theme--catppuccin-macchiato .is-focused.textarea,html.theme--catppuccin-macchiato .is-focused.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-macchiato .select select:active,html.theme--catppuccin-macchiato .textarea:active,html.theme--catppuccin-macchiato .input:active,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input:active,html.theme--catppuccin-macchiato .select select.is-active,html.theme--catppuccin-macchiato .is-active.textarea,html.theme--catppuccin-macchiato .is-active.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-active{border-color:#8aadf4;box-shadow:0 0 0 0.125em rgba(138,173,244,0.25)}html.theme--catppuccin-macchiato .select select[disabled],html.theme--catppuccin-macchiato .textarea[disabled],html.theme--catppuccin-macchiato .input[disabled],html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .select select,fieldset[disabled] html.theme--catppuccin-macchiato .textarea,fieldset[disabled] html.theme--catppuccin-macchiato .input,fieldset[disabled] html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input{background-color:#6e738d;border-color:#1e2030;box-shadow:none;color:#f5f7fd}html.theme--catppuccin-macchiato .select select[disabled]::-moz-placeholder,html.theme--catppuccin-macchiato .textarea[disabled]::-moz-placeholder,html.theme--catppuccin-macchiato .input[disabled]::-moz-placeholder,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input[disabled]::-moz-placeholder,fieldset[disabled] html.theme--catppuccin-macchiato .select select::-moz-placeholder,fieldset[disabled] html.theme--catppuccin-macchiato .textarea::-moz-placeholder,fieldset[disabled] html.theme--catppuccin-macchiato .input::-moz-placeholder,fieldset[disabled] html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:rgba(245,247,253,0.3)}html.theme--catppuccin-macchiato .select select[disabled]::-webkit-input-placeholder,html.theme--catppuccin-macchiato .textarea[disabled]::-webkit-input-placeholder,html.theme--catppuccin-macchiato .input[disabled]::-webkit-input-placeholder,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input[disabled]::-webkit-input-placeholder,fieldset[disabled] html.theme--catppuccin-macchiato .select select::-webkit-input-placeholder,fieldset[disabled] html.theme--catppuccin-macchiato .textarea::-webkit-input-placeholder,fieldset[disabled] html.theme--catppuccin-macchiato .input::-webkit-input-placeholder,fieldset[disabled] html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:rgba(245,247,253,0.3)}html.theme--catppuccin-macchiato .select select[disabled]:-moz-placeholder,html.theme--catppuccin-macchiato .textarea[disabled]:-moz-placeholder,html.theme--catppuccin-macchiato .input[disabled]:-moz-placeholder,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input[disabled]:-moz-placeholder,fieldset[disabled] html.theme--catppuccin-macchiato .select select:-moz-placeholder,fieldset[disabled] html.theme--catppuccin-macchiato .textarea:-moz-placeholder,fieldset[disabled] html.theme--catppuccin-macchiato .input:-moz-placeholder,fieldset[disabled] html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:rgba(245,247,253,0.3)}html.theme--catppuccin-macchiato .select select[disabled]:-ms-input-placeholder,html.theme--catppuccin-macchiato .textarea[disabled]:-ms-input-placeholder,html.theme--catppuccin-macchiato .input[disabled]:-ms-input-placeholder,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input[disabled]:-ms-input-placeholder,fieldset[disabled] html.theme--catppuccin-macchiato .select select:-ms-input-placeholder,fieldset[disabled] html.theme--catppuccin-macchiato .textarea:-ms-input-placeholder,fieldset[disabled] html.theme--catppuccin-macchiato .input:-ms-input-placeholder,fieldset[disabled] html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:rgba(245,247,253,0.3)}html.theme--catppuccin-macchiato .textarea,html.theme--catppuccin-macchiato .input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input{box-shadow:inset 0 0.0625em 0.125em rgba(10,10,10,0.05);max-width:100%;width:100%}html.theme--catppuccin-macchiato .textarea[readonly],html.theme--catppuccin-macchiato .input[readonly],html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input[readonly]{box-shadow:none}html.theme--catppuccin-macchiato .is-white.textarea,html.theme--catppuccin-macchiato .is-white.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-white{border-color:#fff}html.theme--catppuccin-macchiato .is-white.textarea:focus,html.theme--catppuccin-macchiato .is-white.input:focus,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-white:focus,html.theme--catppuccin-macchiato .is-white.is-focused.textarea,html.theme--catppuccin-macchiato .is-white.is-focused.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-macchiato .is-white.textarea:active,html.theme--catppuccin-macchiato .is-white.input:active,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-white:active,html.theme--catppuccin-macchiato .is-white.is-active.textarea,html.theme--catppuccin-macchiato .is-white.is-active.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--catppuccin-macchiato .is-black.textarea,html.theme--catppuccin-macchiato .is-black.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-black{border-color:#0a0a0a}html.theme--catppuccin-macchiato .is-black.textarea:focus,html.theme--catppuccin-macchiato .is-black.input:focus,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-black:focus,html.theme--catppuccin-macchiato .is-black.is-focused.textarea,html.theme--catppuccin-macchiato .is-black.is-focused.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-macchiato .is-black.textarea:active,html.theme--catppuccin-macchiato .is-black.input:active,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-black:active,html.theme--catppuccin-macchiato .is-black.is-active.textarea,html.theme--catppuccin-macchiato .is-black.is-active.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--catppuccin-macchiato .is-light.textarea,html.theme--catppuccin-macchiato .is-light.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-light{border-color:#f5f5f5}html.theme--catppuccin-macchiato .is-light.textarea:focus,html.theme--catppuccin-macchiato .is-light.input:focus,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-light:focus,html.theme--catppuccin-macchiato .is-light.is-focused.textarea,html.theme--catppuccin-macchiato .is-light.is-focused.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-macchiato .is-light.textarea:active,html.theme--catppuccin-macchiato .is-light.input:active,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-light:active,html.theme--catppuccin-macchiato .is-light.is-active.textarea,html.theme--catppuccin-macchiato .is-light.is-active.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}html.theme--catppuccin-macchiato .is-dark.textarea,html.theme--catppuccin-macchiato .content kbd.textarea,html.theme--catppuccin-macchiato .is-dark.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-dark,html.theme--catppuccin-macchiato .content kbd.input{border-color:#363a4f}html.theme--catppuccin-macchiato .is-dark.textarea:focus,html.theme--catppuccin-macchiato .content kbd.textarea:focus,html.theme--catppuccin-macchiato .is-dark.input:focus,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-dark:focus,html.theme--catppuccin-macchiato .content kbd.input:focus,html.theme--catppuccin-macchiato .is-dark.is-focused.textarea,html.theme--catppuccin-macchiato .content kbd.is-focused.textarea,html.theme--catppuccin-macchiato .is-dark.is-focused.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-macchiato .content kbd.is-focused.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar .content form.docs-search>input.is-focused,html.theme--catppuccin-macchiato .is-dark.textarea:active,html.theme--catppuccin-macchiato .content kbd.textarea:active,html.theme--catppuccin-macchiato .is-dark.input:active,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-dark:active,html.theme--catppuccin-macchiato .content kbd.input:active,html.theme--catppuccin-macchiato .is-dark.is-active.textarea,html.theme--catppuccin-macchiato .content kbd.is-active.textarea,html.theme--catppuccin-macchiato .is-dark.is-active.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--catppuccin-macchiato .content kbd.is-active.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar .content form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(54,58,79,0.25)}html.theme--catppuccin-macchiato .is-primary.textarea,html.theme--catppuccin-macchiato .docstring>section>a.textarea.docs-sourcelink,html.theme--catppuccin-macchiato .is-primary.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-primary,html.theme--catppuccin-macchiato .docstring>section>a.input.docs-sourcelink{border-color:#8aadf4}html.theme--catppuccin-macchiato .is-primary.textarea:focus,html.theme--catppuccin-macchiato .docstring>section>a.textarea.docs-sourcelink:focus,html.theme--catppuccin-macchiato .is-primary.input:focus,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-primary:focus,html.theme--catppuccin-macchiato .docstring>section>a.input.docs-sourcelink:focus,html.theme--catppuccin-macchiato .is-primary.is-focused.textarea,html.theme--catppuccin-macchiato .docstring>section>a.is-focused.textarea.docs-sourcelink,html.theme--catppuccin-macchiato .is-primary.is-focused.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-macchiato .docstring>section>a.is-focused.input.docs-sourcelink,html.theme--catppuccin-macchiato .is-primary.textarea:active,html.theme--catppuccin-macchiato .docstring>section>a.textarea.docs-sourcelink:active,html.theme--catppuccin-macchiato .is-primary.input:active,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-primary:active,html.theme--catppuccin-macchiato .docstring>section>a.input.docs-sourcelink:active,html.theme--catppuccin-macchiato .is-primary.is-active.textarea,html.theme--catppuccin-macchiato .docstring>section>a.is-active.textarea.docs-sourcelink,html.theme--catppuccin-macchiato .is-primary.is-active.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--catppuccin-macchiato .docstring>section>a.is-active.input.docs-sourcelink{box-shadow:0 0 0 0.125em rgba(138,173,244,0.25)}html.theme--catppuccin-macchiato .is-link.textarea,html.theme--catppuccin-macchiato .is-link.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-link{border-color:#8aadf4}html.theme--catppuccin-macchiato .is-link.textarea:focus,html.theme--catppuccin-macchiato .is-link.input:focus,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-link:focus,html.theme--catppuccin-macchiato .is-link.is-focused.textarea,html.theme--catppuccin-macchiato .is-link.is-focused.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-macchiato .is-link.textarea:active,html.theme--catppuccin-macchiato .is-link.input:active,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-link:active,html.theme--catppuccin-macchiato .is-link.is-active.textarea,html.theme--catppuccin-macchiato .is-link.is-active.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(138,173,244,0.25)}html.theme--catppuccin-macchiato .is-info.textarea,html.theme--catppuccin-macchiato .is-info.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-info{border-color:#8bd5ca}html.theme--catppuccin-macchiato .is-info.textarea:focus,html.theme--catppuccin-macchiato .is-info.input:focus,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-info:focus,html.theme--catppuccin-macchiato .is-info.is-focused.textarea,html.theme--catppuccin-macchiato .is-info.is-focused.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-macchiato .is-info.textarea:active,html.theme--catppuccin-macchiato .is-info.input:active,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-info:active,html.theme--catppuccin-macchiato .is-info.is-active.textarea,html.theme--catppuccin-macchiato .is-info.is-active.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(139,213,202,0.25)}html.theme--catppuccin-macchiato .is-success.textarea,html.theme--catppuccin-macchiato .is-success.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-success{border-color:#a6da95}html.theme--catppuccin-macchiato .is-success.textarea:focus,html.theme--catppuccin-macchiato .is-success.input:focus,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-success:focus,html.theme--catppuccin-macchiato .is-success.is-focused.textarea,html.theme--catppuccin-macchiato .is-success.is-focused.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-macchiato .is-success.textarea:active,html.theme--catppuccin-macchiato .is-success.input:active,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-success:active,html.theme--catppuccin-macchiato .is-success.is-active.textarea,html.theme--catppuccin-macchiato .is-success.is-active.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(166,218,149,0.25)}html.theme--catppuccin-macchiato .is-warning.textarea,html.theme--catppuccin-macchiato .is-warning.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-warning{border-color:#eed49f}html.theme--catppuccin-macchiato .is-warning.textarea:focus,html.theme--catppuccin-macchiato .is-warning.input:focus,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-warning:focus,html.theme--catppuccin-macchiato .is-warning.is-focused.textarea,html.theme--catppuccin-macchiato .is-warning.is-focused.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-macchiato .is-warning.textarea:active,html.theme--catppuccin-macchiato .is-warning.input:active,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-warning:active,html.theme--catppuccin-macchiato .is-warning.is-active.textarea,html.theme--catppuccin-macchiato .is-warning.is-active.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(238,212,159,0.25)}html.theme--catppuccin-macchiato .is-danger.textarea,html.theme--catppuccin-macchiato .is-danger.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-danger{border-color:#ed8796}html.theme--catppuccin-macchiato .is-danger.textarea:focus,html.theme--catppuccin-macchiato .is-danger.input:focus,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-danger:focus,html.theme--catppuccin-macchiato .is-danger.is-focused.textarea,html.theme--catppuccin-macchiato .is-danger.is-focused.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-macchiato .is-danger.textarea:active,html.theme--catppuccin-macchiato .is-danger.input:active,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-danger:active,html.theme--catppuccin-macchiato .is-danger.is-active.textarea,html.theme--catppuccin-macchiato .is-danger.is-active.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(237,135,150,0.25)}html.theme--catppuccin-macchiato .is-small.textarea,html.theme--catppuccin-macchiato .is-small.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input{border-radius:3px;font-size:.75rem}html.theme--catppuccin-macchiato .is-medium.textarea,html.theme--catppuccin-macchiato .is-medium.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-medium{font-size:1.25rem}html.theme--catppuccin-macchiato .is-large.textarea,html.theme--catppuccin-macchiato .is-large.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-large{font-size:1.5rem}html.theme--catppuccin-macchiato .is-fullwidth.textarea,html.theme--catppuccin-macchiato .is-fullwidth.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-fullwidth{display:block;width:100%}html.theme--catppuccin-macchiato .is-inline.textarea,html.theme--catppuccin-macchiato .is-inline.input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-inline{display:inline;width:auto}html.theme--catppuccin-macchiato .input.is-rounded,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input{border-radius:9999px;padding-left:calc(calc(0.75em - 1px) + 0.375em);padding-right:calc(calc(0.75em - 1px) + 0.375em)}html.theme--catppuccin-macchiato .input.is-static,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-static{background-color:transparent;border-color:transparent;box-shadow:none;padding-left:0;padding-right:0}html.theme--catppuccin-macchiato .textarea{display:block;max-width:100%;min-width:100%;padding:calc(0.75em - 1px);resize:vertical}html.theme--catppuccin-macchiato .textarea:not([rows]){max-height:40em;min-height:8em}html.theme--catppuccin-macchiato .textarea[rows]{height:initial}html.theme--catppuccin-macchiato .textarea.has-fixed-size{resize:none}html.theme--catppuccin-macchiato .radio,html.theme--catppuccin-macchiato .checkbox{cursor:pointer;display:inline-block;line-height:1.25;position:relative}html.theme--catppuccin-macchiato .radio input,html.theme--catppuccin-macchiato .checkbox input{cursor:pointer}html.theme--catppuccin-macchiato .radio:hover,html.theme--catppuccin-macchiato .checkbox:hover{color:#91d7e3}html.theme--catppuccin-macchiato .radio[disabled],html.theme--catppuccin-macchiato .checkbox[disabled],fieldset[disabled] html.theme--catppuccin-macchiato .radio,fieldset[disabled] html.theme--catppuccin-macchiato .checkbox,html.theme--catppuccin-macchiato .radio input[disabled],html.theme--catppuccin-macchiato .checkbox input[disabled]{color:#f5f7fd;cursor:not-allowed}html.theme--catppuccin-macchiato .radio+.radio{margin-left:.5em}html.theme--catppuccin-macchiato .select{display:inline-block;max-width:100%;position:relative;vertical-align:top}html.theme--catppuccin-macchiato .select:not(.is-multiple){height:2.5em}html.theme--catppuccin-macchiato .select:not(.is-multiple):not(.is-loading)::after{border-color:#8aadf4;right:1.125em;z-index:4}html.theme--catppuccin-macchiato .select.is-rounded select,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.select select{border-radius:9999px;padding-left:1em}html.theme--catppuccin-macchiato .select select{cursor:pointer;display:block;font-size:1em;max-width:100%;outline:none}html.theme--catppuccin-macchiato .select select::-ms-expand{display:none}html.theme--catppuccin-macchiato .select select[disabled]:hover,fieldset[disabled] html.theme--catppuccin-macchiato .select select:hover{border-color:#1e2030}html.theme--catppuccin-macchiato .select select:not([multiple]){padding-right:2.5em}html.theme--catppuccin-macchiato .select select[multiple]{height:auto;padding:0}html.theme--catppuccin-macchiato .select select[multiple] option{padding:0.5em 1em}html.theme--catppuccin-macchiato .select:not(.is-multiple):not(.is-loading):hover::after{border-color:#91d7e3}html.theme--catppuccin-macchiato .select.is-white:not(:hover)::after{border-color:#fff}html.theme--catppuccin-macchiato .select.is-white select{border-color:#fff}html.theme--catppuccin-macchiato .select.is-white select:hover,html.theme--catppuccin-macchiato .select.is-white select.is-hovered{border-color:#f2f2f2}html.theme--catppuccin-macchiato .select.is-white select:focus,html.theme--catppuccin-macchiato .select.is-white select.is-focused,html.theme--catppuccin-macchiato .select.is-white select:active,html.theme--catppuccin-macchiato .select.is-white select.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--catppuccin-macchiato .select.is-black:not(:hover)::after{border-color:#0a0a0a}html.theme--catppuccin-macchiato .select.is-black select{border-color:#0a0a0a}html.theme--catppuccin-macchiato .select.is-black select:hover,html.theme--catppuccin-macchiato .select.is-black select.is-hovered{border-color:#000}html.theme--catppuccin-macchiato .select.is-black select:focus,html.theme--catppuccin-macchiato .select.is-black select.is-focused,html.theme--catppuccin-macchiato .select.is-black select:active,html.theme--catppuccin-macchiato .select.is-black select.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--catppuccin-macchiato .select.is-light:not(:hover)::after{border-color:#f5f5f5}html.theme--catppuccin-macchiato .select.is-light select{border-color:#f5f5f5}html.theme--catppuccin-macchiato .select.is-light select:hover,html.theme--catppuccin-macchiato .select.is-light select.is-hovered{border-color:#e8e8e8}html.theme--catppuccin-macchiato .select.is-light select:focus,html.theme--catppuccin-macchiato .select.is-light select.is-focused,html.theme--catppuccin-macchiato .select.is-light select:active,html.theme--catppuccin-macchiato .select.is-light select.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}html.theme--catppuccin-macchiato .select.is-dark:not(:hover)::after,html.theme--catppuccin-macchiato .content kbd.select:not(:hover)::after{border-color:#363a4f}html.theme--catppuccin-macchiato .select.is-dark select,html.theme--catppuccin-macchiato .content kbd.select select{border-color:#363a4f}html.theme--catppuccin-macchiato .select.is-dark select:hover,html.theme--catppuccin-macchiato .content kbd.select select:hover,html.theme--catppuccin-macchiato .select.is-dark select.is-hovered,html.theme--catppuccin-macchiato .content kbd.select select.is-hovered{border-color:#2c2f40}html.theme--catppuccin-macchiato .select.is-dark select:focus,html.theme--catppuccin-macchiato .content kbd.select select:focus,html.theme--catppuccin-macchiato .select.is-dark select.is-focused,html.theme--catppuccin-macchiato .content kbd.select select.is-focused,html.theme--catppuccin-macchiato .select.is-dark select:active,html.theme--catppuccin-macchiato .content kbd.select select:active,html.theme--catppuccin-macchiato .select.is-dark select.is-active,html.theme--catppuccin-macchiato .content kbd.select select.is-active{box-shadow:0 0 0 0.125em rgba(54,58,79,0.25)}html.theme--catppuccin-macchiato .select.is-primary:not(:hover)::after,html.theme--catppuccin-macchiato .docstring>section>a.select.docs-sourcelink:not(:hover)::after{border-color:#8aadf4}html.theme--catppuccin-macchiato .select.is-primary select,html.theme--catppuccin-macchiato .docstring>section>a.select.docs-sourcelink select{border-color:#8aadf4}html.theme--catppuccin-macchiato .select.is-primary select:hover,html.theme--catppuccin-macchiato .docstring>section>a.select.docs-sourcelink select:hover,html.theme--catppuccin-macchiato .select.is-primary select.is-hovered,html.theme--catppuccin-macchiato .docstring>section>a.select.docs-sourcelink select.is-hovered{border-color:#739df2}html.theme--catppuccin-macchiato .select.is-primary select:focus,html.theme--catppuccin-macchiato .docstring>section>a.select.docs-sourcelink select:focus,html.theme--catppuccin-macchiato .select.is-primary select.is-focused,html.theme--catppuccin-macchiato .docstring>section>a.select.docs-sourcelink select.is-focused,html.theme--catppuccin-macchiato .select.is-primary select:active,html.theme--catppuccin-macchiato .docstring>section>a.select.docs-sourcelink select:active,html.theme--catppuccin-macchiato .select.is-primary select.is-active,html.theme--catppuccin-macchiato .docstring>section>a.select.docs-sourcelink select.is-active{box-shadow:0 0 0 0.125em rgba(138,173,244,0.25)}html.theme--catppuccin-macchiato .select.is-link:not(:hover)::after{border-color:#8aadf4}html.theme--catppuccin-macchiato .select.is-link select{border-color:#8aadf4}html.theme--catppuccin-macchiato .select.is-link select:hover,html.theme--catppuccin-macchiato .select.is-link select.is-hovered{border-color:#739df2}html.theme--catppuccin-macchiato .select.is-link select:focus,html.theme--catppuccin-macchiato .select.is-link select.is-focused,html.theme--catppuccin-macchiato .select.is-link select:active,html.theme--catppuccin-macchiato .select.is-link select.is-active{box-shadow:0 0 0 0.125em rgba(138,173,244,0.25)}html.theme--catppuccin-macchiato .select.is-info:not(:hover)::after{border-color:#8bd5ca}html.theme--catppuccin-macchiato .select.is-info select{border-color:#8bd5ca}html.theme--catppuccin-macchiato .select.is-info select:hover,html.theme--catppuccin-macchiato .select.is-info select.is-hovered{border-color:#78cec1}html.theme--catppuccin-macchiato .select.is-info select:focus,html.theme--catppuccin-macchiato .select.is-info select.is-focused,html.theme--catppuccin-macchiato .select.is-info select:active,html.theme--catppuccin-macchiato .select.is-info select.is-active{box-shadow:0 0 0 0.125em rgba(139,213,202,0.25)}html.theme--catppuccin-macchiato .select.is-success:not(:hover)::after{border-color:#a6da95}html.theme--catppuccin-macchiato .select.is-success select{border-color:#a6da95}html.theme--catppuccin-macchiato .select.is-success select:hover,html.theme--catppuccin-macchiato .select.is-success select.is-hovered{border-color:#96d382}html.theme--catppuccin-macchiato .select.is-success select:focus,html.theme--catppuccin-macchiato .select.is-success select.is-focused,html.theme--catppuccin-macchiato .select.is-success select:active,html.theme--catppuccin-macchiato .select.is-success select.is-active{box-shadow:0 0 0 0.125em rgba(166,218,149,0.25)}html.theme--catppuccin-macchiato .select.is-warning:not(:hover)::after{border-color:#eed49f}html.theme--catppuccin-macchiato .select.is-warning select{border-color:#eed49f}html.theme--catppuccin-macchiato .select.is-warning select:hover,html.theme--catppuccin-macchiato .select.is-warning select.is-hovered{border-color:#eaca89}html.theme--catppuccin-macchiato .select.is-warning select:focus,html.theme--catppuccin-macchiato .select.is-warning select.is-focused,html.theme--catppuccin-macchiato .select.is-warning select:active,html.theme--catppuccin-macchiato .select.is-warning select.is-active{box-shadow:0 0 0 0.125em rgba(238,212,159,0.25)}html.theme--catppuccin-macchiato .select.is-danger:not(:hover)::after{border-color:#ed8796}html.theme--catppuccin-macchiato .select.is-danger select{border-color:#ed8796}html.theme--catppuccin-macchiato .select.is-danger select:hover,html.theme--catppuccin-macchiato .select.is-danger select.is-hovered{border-color:#ea7183}html.theme--catppuccin-macchiato .select.is-danger select:focus,html.theme--catppuccin-macchiato .select.is-danger select.is-focused,html.theme--catppuccin-macchiato .select.is-danger select:active,html.theme--catppuccin-macchiato .select.is-danger select.is-active{box-shadow:0 0 0 0.125em rgba(237,135,150,0.25)}html.theme--catppuccin-macchiato .select.is-small,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.select{border-radius:3px;font-size:.75rem}html.theme--catppuccin-macchiato .select.is-medium{font-size:1.25rem}html.theme--catppuccin-macchiato .select.is-large{font-size:1.5rem}html.theme--catppuccin-macchiato .select.is-disabled::after{border-color:#f5f7fd !important;opacity:0.5}html.theme--catppuccin-macchiato .select.is-fullwidth{width:100%}html.theme--catppuccin-macchiato .select.is-fullwidth select{width:100%}html.theme--catppuccin-macchiato .select.is-loading::after{margin-top:0;position:absolute;right:.625em;top:0.625em;transform:none}html.theme--catppuccin-macchiato .select.is-loading.is-small:after,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}html.theme--catppuccin-macchiato .select.is-loading.is-medium:after{font-size:1.25rem}html.theme--catppuccin-macchiato .select.is-loading.is-large:after{font-size:1.5rem}html.theme--catppuccin-macchiato .file{align-items:stretch;display:flex;justify-content:flex-start;position:relative}html.theme--catppuccin-macchiato .file.is-white .file-cta{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-macchiato .file.is-white:hover .file-cta,html.theme--catppuccin-macchiato .file.is-white.is-hovered .file-cta{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-macchiato .file.is-white:focus .file-cta,html.theme--catppuccin-macchiato .file.is-white.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,255,255,0.25);color:#0a0a0a}html.theme--catppuccin-macchiato .file.is-white:active .file-cta,html.theme--catppuccin-macchiato .file.is-white.is-active .file-cta{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-macchiato .file.is-black .file-cta{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .file.is-black:hover .file-cta,html.theme--catppuccin-macchiato .file.is-black.is-hovered .file-cta{background-color:#040404;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .file.is-black:focus .file-cta,html.theme--catppuccin-macchiato .file.is-black.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(10,10,10,0.25);color:#fff}html.theme--catppuccin-macchiato .file.is-black:active .file-cta,html.theme--catppuccin-macchiato .file.is-black.is-active .file-cta{background-color:#000;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .file.is-light .file-cta{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .file.is-light:hover .file-cta,html.theme--catppuccin-macchiato .file.is-light.is-hovered .file-cta{background-color:#eee;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .file.is-light:focus .file-cta,html.theme--catppuccin-macchiato .file.is-light.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(245,245,245,0.25);color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .file.is-light:active .file-cta,html.theme--catppuccin-macchiato .file.is-light.is-active .file-cta{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .file.is-dark .file-cta,html.theme--catppuccin-macchiato .content kbd.file .file-cta{background-color:#363a4f;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .file.is-dark:hover .file-cta,html.theme--catppuccin-macchiato .content kbd.file:hover .file-cta,html.theme--catppuccin-macchiato .file.is-dark.is-hovered .file-cta,html.theme--catppuccin-macchiato .content kbd.file.is-hovered .file-cta{background-color:#313447;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .file.is-dark:focus .file-cta,html.theme--catppuccin-macchiato .content kbd.file:focus .file-cta,html.theme--catppuccin-macchiato .file.is-dark.is-focused .file-cta,html.theme--catppuccin-macchiato .content kbd.file.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(54,58,79,0.25);color:#fff}html.theme--catppuccin-macchiato .file.is-dark:active .file-cta,html.theme--catppuccin-macchiato .content kbd.file:active .file-cta,html.theme--catppuccin-macchiato .file.is-dark.is-active .file-cta,html.theme--catppuccin-macchiato .content kbd.file.is-active .file-cta{background-color:#2c2f40;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .file.is-primary .file-cta,html.theme--catppuccin-macchiato .docstring>section>a.file.docs-sourcelink .file-cta{background-color:#8aadf4;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .file.is-primary:hover .file-cta,html.theme--catppuccin-macchiato .docstring>section>a.file.docs-sourcelink:hover .file-cta,html.theme--catppuccin-macchiato .file.is-primary.is-hovered .file-cta,html.theme--catppuccin-macchiato .docstring>section>a.file.is-hovered.docs-sourcelink .file-cta{background-color:#7ea5f3;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .file.is-primary:focus .file-cta,html.theme--catppuccin-macchiato .docstring>section>a.file.docs-sourcelink:focus .file-cta,html.theme--catppuccin-macchiato .file.is-primary.is-focused .file-cta,html.theme--catppuccin-macchiato .docstring>section>a.file.is-focused.docs-sourcelink .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(138,173,244,0.25);color:#fff}html.theme--catppuccin-macchiato .file.is-primary:active .file-cta,html.theme--catppuccin-macchiato .docstring>section>a.file.docs-sourcelink:active .file-cta,html.theme--catppuccin-macchiato .file.is-primary.is-active .file-cta,html.theme--catppuccin-macchiato .docstring>section>a.file.is-active.docs-sourcelink .file-cta{background-color:#739df2;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .file.is-link .file-cta{background-color:#8aadf4;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .file.is-link:hover .file-cta,html.theme--catppuccin-macchiato .file.is-link.is-hovered .file-cta{background-color:#7ea5f3;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .file.is-link:focus .file-cta,html.theme--catppuccin-macchiato .file.is-link.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(138,173,244,0.25);color:#fff}html.theme--catppuccin-macchiato .file.is-link:active .file-cta,html.theme--catppuccin-macchiato .file.is-link.is-active .file-cta{background-color:#739df2;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .file.is-info .file-cta{background-color:#8bd5ca;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .file.is-info:hover .file-cta,html.theme--catppuccin-macchiato .file.is-info.is-hovered .file-cta{background-color:#82d2c6;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .file.is-info:focus .file-cta,html.theme--catppuccin-macchiato .file.is-info.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(139,213,202,0.25);color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .file.is-info:active .file-cta,html.theme--catppuccin-macchiato .file.is-info.is-active .file-cta{background-color:#78cec1;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .file.is-success .file-cta{background-color:#a6da95;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .file.is-success:hover .file-cta,html.theme--catppuccin-macchiato .file.is-success.is-hovered .file-cta{background-color:#9ed78c;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .file.is-success:focus .file-cta,html.theme--catppuccin-macchiato .file.is-success.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(166,218,149,0.25);color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .file.is-success:active .file-cta,html.theme--catppuccin-macchiato .file.is-success.is-active .file-cta{background-color:#96d382;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .file.is-warning .file-cta{background-color:#eed49f;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .file.is-warning:hover .file-cta,html.theme--catppuccin-macchiato .file.is-warning.is-hovered .file-cta{background-color:#eccf94;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .file.is-warning:focus .file-cta,html.theme--catppuccin-macchiato .file.is-warning.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(238,212,159,0.25);color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .file.is-warning:active .file-cta,html.theme--catppuccin-macchiato .file.is-warning.is-active .file-cta{background-color:#eaca89;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .file.is-danger .file-cta{background-color:#ed8796;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .file.is-danger:hover .file-cta,html.theme--catppuccin-macchiato .file.is-danger.is-hovered .file-cta{background-color:#eb7c8c;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .file.is-danger:focus .file-cta,html.theme--catppuccin-macchiato .file.is-danger.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(237,135,150,0.25);color:#fff}html.theme--catppuccin-macchiato .file.is-danger:active .file-cta,html.theme--catppuccin-macchiato .file.is-danger.is-active .file-cta{background-color:#ea7183;border-color:transparent;color:#fff}html.theme--catppuccin-macchiato .file.is-small,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.file{font-size:.75rem}html.theme--catppuccin-macchiato .file.is-normal{font-size:1rem}html.theme--catppuccin-macchiato .file.is-medium{font-size:1.25rem}html.theme--catppuccin-macchiato .file.is-medium .file-icon .fa{font-size:21px}html.theme--catppuccin-macchiato .file.is-large{font-size:1.5rem}html.theme--catppuccin-macchiato .file.is-large .file-icon .fa{font-size:28px}html.theme--catppuccin-macchiato .file.has-name .file-cta{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--catppuccin-macchiato .file.has-name .file-name{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--catppuccin-macchiato .file.has-name.is-empty .file-cta{border-radius:.4em}html.theme--catppuccin-macchiato .file.has-name.is-empty .file-name{display:none}html.theme--catppuccin-macchiato .file.is-boxed .file-label{flex-direction:column}html.theme--catppuccin-macchiato .file.is-boxed .file-cta{flex-direction:column;height:auto;padding:1em 3em}html.theme--catppuccin-macchiato .file.is-boxed .file-name{border-width:0 1px 1px}html.theme--catppuccin-macchiato .file.is-boxed .file-icon{height:1.5em;width:1.5em}html.theme--catppuccin-macchiato .file.is-boxed .file-icon .fa{font-size:21px}html.theme--catppuccin-macchiato .file.is-boxed.is-small .file-icon .fa,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-boxed .file-icon .fa{font-size:14px}html.theme--catppuccin-macchiato .file.is-boxed.is-medium .file-icon .fa{font-size:28px}html.theme--catppuccin-macchiato .file.is-boxed.is-large .file-icon .fa{font-size:35px}html.theme--catppuccin-macchiato .file.is-boxed.has-name .file-cta{border-radius:.4em .4em 0 0}html.theme--catppuccin-macchiato .file.is-boxed.has-name .file-name{border-radius:0 0 .4em .4em;border-width:0 1px 1px}html.theme--catppuccin-macchiato .file.is-centered{justify-content:center}html.theme--catppuccin-macchiato .file.is-fullwidth .file-label{width:100%}html.theme--catppuccin-macchiato .file.is-fullwidth .file-name{flex-grow:1;max-width:none}html.theme--catppuccin-macchiato .file.is-right{justify-content:flex-end}html.theme--catppuccin-macchiato .file.is-right .file-cta{border-radius:0 .4em .4em 0}html.theme--catppuccin-macchiato .file.is-right .file-name{border-radius:.4em 0 0 .4em;border-width:1px 0 1px 1px;order:-1}html.theme--catppuccin-macchiato .file-label{align-items:stretch;display:flex;cursor:pointer;justify-content:flex-start;overflow:hidden;position:relative}html.theme--catppuccin-macchiato .file-label:hover .file-cta{background-color:#313447;color:#b5c1f1}html.theme--catppuccin-macchiato .file-label:hover .file-name{border-color:#565a71}html.theme--catppuccin-macchiato .file-label:active .file-cta{background-color:#2c2f40;color:#b5c1f1}html.theme--catppuccin-macchiato .file-label:active .file-name{border-color:#505469}html.theme--catppuccin-macchiato .file-input{height:100%;left:0;opacity:0;outline:none;position:absolute;top:0;width:100%}html.theme--catppuccin-macchiato .file-cta,html.theme--catppuccin-macchiato .file-name{border-color:#5b6078;border-radius:.4em;font-size:1em;padding-left:1em;padding-right:1em;white-space:nowrap}html.theme--catppuccin-macchiato .file-cta{background-color:#363a4f;color:#cad3f5}html.theme--catppuccin-macchiato .file-name{border-color:#5b6078;border-style:solid;border-width:1px 1px 1px 0;display:block;max-width:16em;overflow:hidden;text-align:inherit;text-overflow:ellipsis}html.theme--catppuccin-macchiato .file-icon{align-items:center;display:flex;height:1em;justify-content:center;margin-right:.5em;width:1em}html.theme--catppuccin-macchiato .file-icon .fa{font-size:14px}html.theme--catppuccin-macchiato .label{color:#b5c1f1;display:block;font-size:1rem;font-weight:700}html.theme--catppuccin-macchiato .label:not(:last-child){margin-bottom:0.5em}html.theme--catppuccin-macchiato .label.is-small,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.label{font-size:.75rem}html.theme--catppuccin-macchiato .label.is-medium{font-size:1.25rem}html.theme--catppuccin-macchiato .label.is-large{font-size:1.5rem}html.theme--catppuccin-macchiato .help{display:block;font-size:.75rem;margin-top:0.25rem}html.theme--catppuccin-macchiato .help.is-white{color:#fff}html.theme--catppuccin-macchiato .help.is-black{color:#0a0a0a}html.theme--catppuccin-macchiato .help.is-light{color:#f5f5f5}html.theme--catppuccin-macchiato .help.is-dark,html.theme--catppuccin-macchiato .content kbd.help{color:#363a4f}html.theme--catppuccin-macchiato .help.is-primary,html.theme--catppuccin-macchiato .docstring>section>a.help.docs-sourcelink{color:#8aadf4}html.theme--catppuccin-macchiato .help.is-link{color:#8aadf4}html.theme--catppuccin-macchiato .help.is-info{color:#8bd5ca}html.theme--catppuccin-macchiato .help.is-success{color:#a6da95}html.theme--catppuccin-macchiato .help.is-warning{color:#eed49f}html.theme--catppuccin-macchiato .help.is-danger{color:#ed8796}html.theme--catppuccin-macchiato .field:not(:last-child){margin-bottom:0.75rem}html.theme--catppuccin-macchiato .field.has-addons{display:flex;justify-content:flex-start}html.theme--catppuccin-macchiato .field.has-addons .control:not(:last-child){margin-right:-1px}html.theme--catppuccin-macchiato .field.has-addons .control:not(:first-child):not(:last-child) .button,html.theme--catppuccin-macchiato .field.has-addons .control:not(:first-child):not(:last-child) .input,html.theme--catppuccin-macchiato .field.has-addons .control:not(:first-child):not(:last-child) #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-macchiato #documenter .docs-sidebar .field.has-addons .control:not(:first-child):not(:last-child) form.docs-search>input,html.theme--catppuccin-macchiato .field.has-addons .control:not(:first-child):not(:last-child) .select select{border-radius:0}html.theme--catppuccin-macchiato .field.has-addons .control:first-child:not(:only-child) .button,html.theme--catppuccin-macchiato .field.has-addons .control:first-child:not(:only-child) .input,html.theme--catppuccin-macchiato .field.has-addons .control:first-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-macchiato #documenter .docs-sidebar .field.has-addons .control:first-child:not(:only-child) form.docs-search>input,html.theme--catppuccin-macchiato .field.has-addons .control:first-child:not(:only-child) .select select{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--catppuccin-macchiato .field.has-addons .control:last-child:not(:only-child) .button,html.theme--catppuccin-macchiato .field.has-addons .control:last-child:not(:only-child) .input,html.theme--catppuccin-macchiato .field.has-addons .control:last-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-macchiato #documenter .docs-sidebar .field.has-addons .control:last-child:not(:only-child) form.docs-search>input,html.theme--catppuccin-macchiato .field.has-addons .control:last-child:not(:only-child) .select select{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--catppuccin-macchiato .field.has-addons .control .button:not([disabled]):hover,html.theme--catppuccin-macchiato .field.has-addons .control .button.is-hovered:not([disabled]),html.theme--catppuccin-macchiato .field.has-addons .control .input:not([disabled]):hover,html.theme--catppuccin-macchiato .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):hover,html.theme--catppuccin-macchiato #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):hover,html.theme--catppuccin-macchiato .field.has-addons .control .input.is-hovered:not([disabled]),html.theme--catppuccin-macchiato .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-hovered:not([disabled]),html.theme--catppuccin-macchiato #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-hovered:not([disabled]),html.theme--catppuccin-macchiato .field.has-addons .control .select select:not([disabled]):hover,html.theme--catppuccin-macchiato .field.has-addons .control .select select.is-hovered:not([disabled]){z-index:2}html.theme--catppuccin-macchiato .field.has-addons .control .button:not([disabled]):focus,html.theme--catppuccin-macchiato .field.has-addons .control .button.is-focused:not([disabled]),html.theme--catppuccin-macchiato .field.has-addons .control .button:not([disabled]):active,html.theme--catppuccin-macchiato .field.has-addons .control .button.is-active:not([disabled]),html.theme--catppuccin-macchiato .field.has-addons .control .input:not([disabled]):focus,html.theme--catppuccin-macchiato .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus,html.theme--catppuccin-macchiato #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus,html.theme--catppuccin-macchiato .field.has-addons .control .input.is-focused:not([disabled]),html.theme--catppuccin-macchiato .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]),html.theme--catppuccin-macchiato #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]),html.theme--catppuccin-macchiato .field.has-addons .control .input:not([disabled]):active,html.theme--catppuccin-macchiato .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active,html.theme--catppuccin-macchiato #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active,html.theme--catppuccin-macchiato .field.has-addons .control .input.is-active:not([disabled]),html.theme--catppuccin-macchiato .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]),html.theme--catppuccin-macchiato #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]),html.theme--catppuccin-macchiato .field.has-addons .control .select select:not([disabled]):focus,html.theme--catppuccin-macchiato .field.has-addons .control .select select.is-focused:not([disabled]),html.theme--catppuccin-macchiato .field.has-addons .control .select select:not([disabled]):active,html.theme--catppuccin-macchiato .field.has-addons .control .select select.is-active:not([disabled]){z-index:3}html.theme--catppuccin-macchiato .field.has-addons .control .button:not([disabled]):focus:hover,html.theme--catppuccin-macchiato .field.has-addons .control .button.is-focused:not([disabled]):hover,html.theme--catppuccin-macchiato .field.has-addons .control .button:not([disabled]):active:hover,html.theme--catppuccin-macchiato .field.has-addons .control .button.is-active:not([disabled]):hover,html.theme--catppuccin-macchiato .field.has-addons .control .input:not([disabled]):focus:hover,html.theme--catppuccin-macchiato .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus:hover,html.theme--catppuccin-macchiato #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus:hover,html.theme--catppuccin-macchiato .field.has-addons .control .input.is-focused:not([disabled]):hover,html.theme--catppuccin-macchiato .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]):hover,html.theme--catppuccin-macchiato #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]):hover,html.theme--catppuccin-macchiato .field.has-addons .control .input:not([disabled]):active:hover,html.theme--catppuccin-macchiato .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active:hover,html.theme--catppuccin-macchiato #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active:hover,html.theme--catppuccin-macchiato .field.has-addons .control .input.is-active:not([disabled]):hover,html.theme--catppuccin-macchiato .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]):hover,html.theme--catppuccin-macchiato #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]):hover,html.theme--catppuccin-macchiato .field.has-addons .control .select select:not([disabled]):focus:hover,html.theme--catppuccin-macchiato .field.has-addons .control .select select.is-focused:not([disabled]):hover,html.theme--catppuccin-macchiato .field.has-addons .control .select select:not([disabled]):active:hover,html.theme--catppuccin-macchiato .field.has-addons .control .select select.is-active:not([disabled]):hover{z-index:4}html.theme--catppuccin-macchiato .field.has-addons .control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--catppuccin-macchiato .field.has-addons.has-addons-centered{justify-content:center}html.theme--catppuccin-macchiato .field.has-addons.has-addons-right{justify-content:flex-end}html.theme--catppuccin-macchiato .field.has-addons.has-addons-fullwidth .control{flex-grow:1;flex-shrink:0}html.theme--catppuccin-macchiato .field.is-grouped{display:flex;justify-content:flex-start}html.theme--catppuccin-macchiato .field.is-grouped>.control{flex-shrink:0}html.theme--catppuccin-macchiato .field.is-grouped>.control:not(:last-child){margin-bottom:0;margin-right:.75rem}html.theme--catppuccin-macchiato .field.is-grouped>.control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--catppuccin-macchiato .field.is-grouped.is-grouped-centered{justify-content:center}html.theme--catppuccin-macchiato .field.is-grouped.is-grouped-right{justify-content:flex-end}html.theme--catppuccin-macchiato .field.is-grouped.is-grouped-multiline{flex-wrap:wrap}html.theme--catppuccin-macchiato .field.is-grouped.is-grouped-multiline>.control:last-child,html.theme--catppuccin-macchiato .field.is-grouped.is-grouped-multiline>.control:not(:last-child){margin-bottom:0.75rem}html.theme--catppuccin-macchiato .field.is-grouped.is-grouped-multiline:last-child{margin-bottom:-0.75rem}html.theme--catppuccin-macchiato .field.is-grouped.is-grouped-multiline:not(:last-child){margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .field.is-horizontal{display:flex}}html.theme--catppuccin-macchiato .field-label .label{font-size:inherit}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .field-label{margin-bottom:0.5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .field-label{flex-basis:0;flex-grow:1;flex-shrink:0;margin-right:1.5rem;text-align:right}html.theme--catppuccin-macchiato .field-label.is-small,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.field-label{font-size:.75rem;padding-top:0.375em}html.theme--catppuccin-macchiato .field-label.is-normal{padding-top:0.375em}html.theme--catppuccin-macchiato .field-label.is-medium{font-size:1.25rem;padding-top:0.375em}html.theme--catppuccin-macchiato .field-label.is-large{font-size:1.5rem;padding-top:0.375em}}html.theme--catppuccin-macchiato .field-body .field .field{margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .field-body{display:flex;flex-basis:0;flex-grow:5;flex-shrink:1}html.theme--catppuccin-macchiato .field-body .field{margin-bottom:0}html.theme--catppuccin-macchiato .field-body>.field{flex-shrink:1}html.theme--catppuccin-macchiato .field-body>.field:not(.is-narrow){flex-grow:1}html.theme--catppuccin-macchiato .field-body>.field:not(:last-child){margin-right:.75rem}}html.theme--catppuccin-macchiato .control{box-sizing:border-box;clear:both;font-size:1rem;position:relative;text-align:inherit}html.theme--catppuccin-macchiato .control.has-icons-left .input:focus~.icon,html.theme--catppuccin-macchiato .control.has-icons-left #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--catppuccin-macchiato #documenter .docs-sidebar .control.has-icons-left form.docs-search>input:focus~.icon,html.theme--catppuccin-macchiato .control.has-icons-left .select:focus~.icon,html.theme--catppuccin-macchiato .control.has-icons-right .input:focus~.icon,html.theme--catppuccin-macchiato .control.has-icons-right #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--catppuccin-macchiato #documenter .docs-sidebar .control.has-icons-right form.docs-search>input:focus~.icon,html.theme--catppuccin-macchiato .control.has-icons-right .select:focus~.icon{color:#363a4f}html.theme--catppuccin-macchiato .control.has-icons-left .input.is-small~.icon,html.theme--catppuccin-macchiato .control.has-icons-left #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--catppuccin-macchiato #documenter .docs-sidebar .control.has-icons-left form.docs-search>input~.icon,html.theme--catppuccin-macchiato .control.has-icons-left .select.is-small~.icon,html.theme--catppuccin-macchiato .control.has-icons-right .input.is-small~.icon,html.theme--catppuccin-macchiato .control.has-icons-right #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--catppuccin-macchiato #documenter .docs-sidebar .control.has-icons-right form.docs-search>input~.icon,html.theme--catppuccin-macchiato .control.has-icons-right .select.is-small~.icon{font-size:.75rem}html.theme--catppuccin-macchiato .control.has-icons-left .input.is-medium~.icon,html.theme--catppuccin-macchiato .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--catppuccin-macchiato #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-medium~.icon,html.theme--catppuccin-macchiato .control.has-icons-left .select.is-medium~.icon,html.theme--catppuccin-macchiato .control.has-icons-right .input.is-medium~.icon,html.theme--catppuccin-macchiato .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--catppuccin-macchiato #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-medium~.icon,html.theme--catppuccin-macchiato .control.has-icons-right .select.is-medium~.icon{font-size:1.25rem}html.theme--catppuccin-macchiato .control.has-icons-left .input.is-large~.icon,html.theme--catppuccin-macchiato .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--catppuccin-macchiato #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-large~.icon,html.theme--catppuccin-macchiato .control.has-icons-left .select.is-large~.icon,html.theme--catppuccin-macchiato .control.has-icons-right .input.is-large~.icon,html.theme--catppuccin-macchiato .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--catppuccin-macchiato #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-large~.icon,html.theme--catppuccin-macchiato .control.has-icons-right .select.is-large~.icon{font-size:1.5rem}html.theme--catppuccin-macchiato .control.has-icons-left .icon,html.theme--catppuccin-macchiato .control.has-icons-right .icon{color:#5b6078;height:2.5em;pointer-events:none;position:absolute;top:0;width:2.5em;z-index:4}html.theme--catppuccin-macchiato .control.has-icons-left .input,html.theme--catppuccin-macchiato .control.has-icons-left #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-macchiato #documenter .docs-sidebar .control.has-icons-left form.docs-search>input,html.theme--catppuccin-macchiato .control.has-icons-left .select select{padding-left:2.5em}html.theme--catppuccin-macchiato .control.has-icons-left .icon.is-left{left:0}html.theme--catppuccin-macchiato .control.has-icons-right .input,html.theme--catppuccin-macchiato .control.has-icons-right #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-macchiato #documenter .docs-sidebar .control.has-icons-right form.docs-search>input,html.theme--catppuccin-macchiato .control.has-icons-right .select select{padding-right:2.5em}html.theme--catppuccin-macchiato .control.has-icons-right .icon.is-right{right:0}html.theme--catppuccin-macchiato .control.is-loading::after{position:absolute !important;right:.625em;top:0.625em;z-index:4}html.theme--catppuccin-macchiato .control.is-loading.is-small:after,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}html.theme--catppuccin-macchiato .control.is-loading.is-medium:after{font-size:1.25rem}html.theme--catppuccin-macchiato .control.is-loading.is-large:after{font-size:1.5rem}html.theme--catppuccin-macchiato .breadcrumb{font-size:1rem;white-space:nowrap}html.theme--catppuccin-macchiato .breadcrumb a{align-items:center;color:#8aadf4;display:flex;justify-content:center;padding:0 .75em}html.theme--catppuccin-macchiato .breadcrumb a:hover{color:#91d7e3}html.theme--catppuccin-macchiato .breadcrumb li{align-items:center;display:flex}html.theme--catppuccin-macchiato .breadcrumb li:first-child a{padding-left:0}html.theme--catppuccin-macchiato .breadcrumb li.is-active a{color:#b5c1f1;cursor:default;pointer-events:none}html.theme--catppuccin-macchiato .breadcrumb li+li::before{color:#6e738d;content:"\0002f"}html.theme--catppuccin-macchiato .breadcrumb ul,html.theme--catppuccin-macchiato .breadcrumb ol{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--catppuccin-macchiato .breadcrumb .icon:first-child{margin-right:.5em}html.theme--catppuccin-macchiato .breadcrumb .icon:last-child{margin-left:.5em}html.theme--catppuccin-macchiato .breadcrumb.is-centered ol,html.theme--catppuccin-macchiato .breadcrumb.is-centered ul{justify-content:center}html.theme--catppuccin-macchiato .breadcrumb.is-right ol,html.theme--catppuccin-macchiato .breadcrumb.is-right ul{justify-content:flex-end}html.theme--catppuccin-macchiato .breadcrumb.is-small,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.breadcrumb{font-size:.75rem}html.theme--catppuccin-macchiato .breadcrumb.is-medium{font-size:1.25rem}html.theme--catppuccin-macchiato .breadcrumb.is-large{font-size:1.5rem}html.theme--catppuccin-macchiato .breadcrumb.has-arrow-separator li+li::before{content:"\02192"}html.theme--catppuccin-macchiato .breadcrumb.has-bullet-separator li+li::before{content:"\02022"}html.theme--catppuccin-macchiato .breadcrumb.has-dot-separator li+li::before{content:"\000b7"}html.theme--catppuccin-macchiato .breadcrumb.has-succeeds-separator li+li::before{content:"\0227B"}html.theme--catppuccin-macchiato .card{background-color:#fff;border-radius:.25rem;box-shadow:#171717;color:#cad3f5;max-width:100%;position:relative}html.theme--catppuccin-macchiato .card-footer:first-child,html.theme--catppuccin-macchiato .card-content:first-child,html.theme--catppuccin-macchiato .card-header:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}html.theme--catppuccin-macchiato .card-footer:last-child,html.theme--catppuccin-macchiato .card-content:last-child,html.theme--catppuccin-macchiato .card-header:last-child{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}html.theme--catppuccin-macchiato .card-header{background-color:rgba(0,0,0,0);align-items:stretch;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);display:flex}html.theme--catppuccin-macchiato .card-header-title{align-items:center;color:#b5c1f1;display:flex;flex-grow:1;font-weight:700;padding:0.75rem 1rem}html.theme--catppuccin-macchiato .card-header-title.is-centered{justify-content:center}html.theme--catppuccin-macchiato .card-header-icon{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0;align-items:center;cursor:pointer;display:flex;justify-content:center;padding:0.75rem 1rem}html.theme--catppuccin-macchiato .card-image{display:block;position:relative}html.theme--catppuccin-macchiato .card-image:first-child img{border-top-left-radius:.25rem;border-top-right-radius:.25rem}html.theme--catppuccin-macchiato .card-image:last-child img{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}html.theme--catppuccin-macchiato .card-content{background-color:rgba(0,0,0,0);padding:1.5rem}html.theme--catppuccin-macchiato .card-footer{background-color:rgba(0,0,0,0);border-top:1px solid #ededed;align-items:stretch;display:flex}html.theme--catppuccin-macchiato .card-footer-item{align-items:center;display:flex;flex-basis:0;flex-grow:1;flex-shrink:0;justify-content:center;padding:.75rem}html.theme--catppuccin-macchiato .card-footer-item:not(:last-child){border-right:1px solid #ededed}html.theme--catppuccin-macchiato .card .media:not(:last-child){margin-bottom:1.5rem}html.theme--catppuccin-macchiato .dropdown{display:inline-flex;position:relative;vertical-align:top}html.theme--catppuccin-macchiato .dropdown.is-active .dropdown-menu,html.theme--catppuccin-macchiato .dropdown.is-hoverable:hover .dropdown-menu{display:block}html.theme--catppuccin-macchiato .dropdown.is-right .dropdown-menu{left:auto;right:0}html.theme--catppuccin-macchiato .dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:initial;top:auto}html.theme--catppuccin-macchiato .dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:20}html.theme--catppuccin-macchiato .dropdown-content{background-color:#1e2030;border-radius:.4em;box-shadow:#171717;padding-bottom:.5rem;padding-top:.5rem}html.theme--catppuccin-macchiato .dropdown-item{color:#cad3f5;display:block;font-size:0.875rem;line-height:1.5;padding:0.375rem 1rem;position:relative}html.theme--catppuccin-macchiato a.dropdown-item,html.theme--catppuccin-macchiato button.dropdown-item{padding-right:3rem;text-align:inherit;white-space:nowrap;width:100%}html.theme--catppuccin-macchiato a.dropdown-item:hover,html.theme--catppuccin-macchiato button.dropdown-item:hover{background-color:#1e2030;color:#0a0a0a}html.theme--catppuccin-macchiato a.dropdown-item.is-active,html.theme--catppuccin-macchiato button.dropdown-item.is-active{background-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .dropdown-divider{background-color:#ededed;border:none;display:block;height:1px;margin:0.5rem 0}html.theme--catppuccin-macchiato .level{align-items:center;justify-content:space-between}html.theme--catppuccin-macchiato .level code{border-radius:.4em}html.theme--catppuccin-macchiato .level img{display:inline-block;vertical-align:top}html.theme--catppuccin-macchiato .level.is-mobile{display:flex}html.theme--catppuccin-macchiato .level.is-mobile .level-left,html.theme--catppuccin-macchiato .level.is-mobile .level-right{display:flex}html.theme--catppuccin-macchiato .level.is-mobile .level-left+.level-right{margin-top:0}html.theme--catppuccin-macchiato .level.is-mobile .level-item:not(:last-child){margin-bottom:0;margin-right:.75rem}html.theme--catppuccin-macchiato .level.is-mobile .level-item:not(.is-narrow){flex-grow:1}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .level{display:flex}html.theme--catppuccin-macchiato .level>.level-item:not(.is-narrow){flex-grow:1}}html.theme--catppuccin-macchiato .level-item{align-items:center;display:flex;flex-basis:auto;flex-grow:0;flex-shrink:0;justify-content:center}html.theme--catppuccin-macchiato .level-item .title,html.theme--catppuccin-macchiato .level-item .subtitle{margin-bottom:0}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .level-item:not(:last-child){margin-bottom:.75rem}}html.theme--catppuccin-macchiato .level-left,html.theme--catppuccin-macchiato .level-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--catppuccin-macchiato .level-left .level-item.is-flexible,html.theme--catppuccin-macchiato .level-right .level-item.is-flexible{flex-grow:1}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .level-left .level-item:not(:last-child),html.theme--catppuccin-macchiato .level-right .level-item:not(:last-child){margin-right:.75rem}}html.theme--catppuccin-macchiato .level-left{align-items:center;justify-content:flex-start}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .level-left+.level-right{margin-top:1.5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .level-left{display:flex}}html.theme--catppuccin-macchiato .level-right{align-items:center;justify-content:flex-end}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .level-right{display:flex}}html.theme--catppuccin-macchiato .media{align-items:flex-start;display:flex;text-align:inherit}html.theme--catppuccin-macchiato .media .content:not(:last-child){margin-bottom:.75rem}html.theme--catppuccin-macchiato .media .media{border-top:1px solid rgba(91,96,120,0.5);display:flex;padding-top:.75rem}html.theme--catppuccin-macchiato .media .media .content:not(:last-child),html.theme--catppuccin-macchiato .media .media .control:not(:last-child){margin-bottom:.5rem}html.theme--catppuccin-macchiato .media .media .media{padding-top:.5rem}html.theme--catppuccin-macchiato .media .media .media+.media{margin-top:.5rem}html.theme--catppuccin-macchiato .media+.media{border-top:1px solid rgba(91,96,120,0.5);margin-top:1rem;padding-top:1rem}html.theme--catppuccin-macchiato .media.is-large+.media{margin-top:1.5rem;padding-top:1.5rem}html.theme--catppuccin-macchiato .media-left,html.theme--catppuccin-macchiato .media-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--catppuccin-macchiato .media-left{margin-right:1rem}html.theme--catppuccin-macchiato .media-right{margin-left:1rem}html.theme--catppuccin-macchiato .media-content{flex-basis:auto;flex-grow:1;flex-shrink:1;text-align:inherit}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .media-content{overflow-x:auto}}html.theme--catppuccin-macchiato .menu{font-size:1rem}html.theme--catppuccin-macchiato .menu.is-small,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.menu{font-size:.75rem}html.theme--catppuccin-macchiato .menu.is-medium{font-size:1.25rem}html.theme--catppuccin-macchiato .menu.is-large{font-size:1.5rem}html.theme--catppuccin-macchiato .menu-list{line-height:1.25}html.theme--catppuccin-macchiato .menu-list a{border-radius:3px;color:#cad3f5;display:block;padding:0.5em 0.75em}html.theme--catppuccin-macchiato .menu-list a:hover{background-color:#1e2030;color:#b5c1f1}html.theme--catppuccin-macchiato .menu-list a.is-active{background-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .menu-list li ul{border-left:1px solid #5b6078;margin:.75em;padding-left:.75em}html.theme--catppuccin-macchiato .menu-label{color:#f5f7fd;font-size:.75em;letter-spacing:.1em;text-transform:uppercase}html.theme--catppuccin-macchiato .menu-label:not(:first-child){margin-top:1em}html.theme--catppuccin-macchiato .menu-label:not(:last-child){margin-bottom:1em}html.theme--catppuccin-macchiato .message{background-color:#1e2030;border-radius:.4em;font-size:1rem}html.theme--catppuccin-macchiato .message strong{color:currentColor}html.theme--catppuccin-macchiato .message a:not(.button):not(.tag):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--catppuccin-macchiato .message.is-small,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.message{font-size:.75rem}html.theme--catppuccin-macchiato .message.is-medium{font-size:1.25rem}html.theme--catppuccin-macchiato .message.is-large{font-size:1.5rem}html.theme--catppuccin-macchiato .message.is-white{background-color:#fff}html.theme--catppuccin-macchiato .message.is-white .message-header{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-macchiato .message.is-white .message-body{border-color:#fff}html.theme--catppuccin-macchiato .message.is-black{background-color:#fafafa}html.theme--catppuccin-macchiato .message.is-black .message-header{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-macchiato .message.is-black .message-body{border-color:#0a0a0a}html.theme--catppuccin-macchiato .message.is-light{background-color:#fafafa}html.theme--catppuccin-macchiato .message.is-light .message-header{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .message.is-light .message-body{border-color:#f5f5f5}html.theme--catppuccin-macchiato .message.is-dark,html.theme--catppuccin-macchiato .content kbd.message{background-color:#f9f9fb}html.theme--catppuccin-macchiato .message.is-dark .message-header,html.theme--catppuccin-macchiato .content kbd.message .message-header{background-color:#363a4f;color:#fff}html.theme--catppuccin-macchiato .message.is-dark .message-body,html.theme--catppuccin-macchiato .content kbd.message .message-body{border-color:#363a4f}html.theme--catppuccin-macchiato .message.is-primary,html.theme--catppuccin-macchiato .docstring>section>a.message.docs-sourcelink{background-color:#ecf2fd}html.theme--catppuccin-macchiato .message.is-primary .message-header,html.theme--catppuccin-macchiato .docstring>section>a.message.docs-sourcelink .message-header{background-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .message.is-primary .message-body,html.theme--catppuccin-macchiato .docstring>section>a.message.docs-sourcelink .message-body{border-color:#8aadf4;color:#0e3b95}html.theme--catppuccin-macchiato .message.is-link{background-color:#ecf2fd}html.theme--catppuccin-macchiato .message.is-link .message-header{background-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .message.is-link .message-body{border-color:#8aadf4;color:#0e3b95}html.theme--catppuccin-macchiato .message.is-info{background-color:#f0faf8}html.theme--catppuccin-macchiato .message.is-info .message-header{background-color:#8bd5ca;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .message.is-info .message-body{border-color:#8bd5ca;color:#276d62}html.theme--catppuccin-macchiato .message.is-success{background-color:#f2faf0}html.theme--catppuccin-macchiato .message.is-success .message-header{background-color:#a6da95;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .message.is-success .message-body{border-color:#a6da95;color:#386e26}html.theme--catppuccin-macchiato .message.is-warning{background-color:#fcf7ee}html.theme--catppuccin-macchiato .message.is-warning .message-header{background-color:#eed49f;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .message.is-warning .message-body{border-color:#eed49f;color:#7e5c16}html.theme--catppuccin-macchiato .message.is-danger{background-color:#fcedef}html.theme--catppuccin-macchiato .message.is-danger .message-header{background-color:#ed8796;color:#fff}html.theme--catppuccin-macchiato .message.is-danger .message-body{border-color:#ed8796;color:#971729}html.theme--catppuccin-macchiato .message-header{align-items:center;background-color:#cad3f5;border-radius:.4em .4em 0 0;color:rgba(0,0,0,0.7);display:flex;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.75em 1em;position:relative}html.theme--catppuccin-macchiato .message-header .delete{flex-grow:0;flex-shrink:0;margin-left:.75em}html.theme--catppuccin-macchiato .message-header+.message-body{border-width:0;border-top-left-radius:0;border-top-right-radius:0}html.theme--catppuccin-macchiato .message-body{border-color:#5b6078;border-radius:.4em;border-style:solid;border-width:0 0 0 4px;color:#cad3f5;padding:1.25em 1.5em}html.theme--catppuccin-macchiato .message-body code,html.theme--catppuccin-macchiato .message-body pre{background-color:#fff}html.theme--catppuccin-macchiato .message-body pre code{background-color:rgba(0,0,0,0)}html.theme--catppuccin-macchiato .modal{align-items:center;display:none;flex-direction:column;justify-content:center;overflow:hidden;position:fixed;z-index:40}html.theme--catppuccin-macchiato .modal.is-active{display:flex}html.theme--catppuccin-macchiato .modal-background{background-color:rgba(10,10,10,0.86)}html.theme--catppuccin-macchiato .modal-content,html.theme--catppuccin-macchiato .modal-card{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width: 769px){html.theme--catppuccin-macchiato .modal-content,html.theme--catppuccin-macchiato .modal-card{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}html.theme--catppuccin-macchiato .modal-close{background:none;height:40px;position:fixed;right:20px;top:20px;width:40px}html.theme--catppuccin-macchiato .modal-card{display:flex;flex-direction:column;max-height:calc(100vh - 40px);overflow:hidden;-ms-overflow-y:visible}html.theme--catppuccin-macchiato .modal-card-head,html.theme--catppuccin-macchiato .modal-card-foot{align-items:center;background-color:#1e2030;display:flex;flex-shrink:0;justify-content:flex-start;padding:20px;position:relative}html.theme--catppuccin-macchiato .modal-card-head{border-bottom:1px solid #5b6078;border-top-left-radius:8px;border-top-right-radius:8px}html.theme--catppuccin-macchiato .modal-card-title{color:#cad3f5;flex-grow:1;flex-shrink:0;font-size:1.5rem;line-height:1}html.theme--catppuccin-macchiato .modal-card-foot{border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid #5b6078}html.theme--catppuccin-macchiato .modal-card-foot .button:not(:last-child){margin-right:.5em}html.theme--catppuccin-macchiato .modal-card-body{-webkit-overflow-scrolling:touch;background-color:#24273a;flex-grow:1;flex-shrink:1;overflow:auto;padding:20px}html.theme--catppuccin-macchiato .navbar{background-color:#8aadf4;min-height:4rem;position:relative;z-index:30}html.theme--catppuccin-macchiato .navbar.is-white{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-macchiato .navbar.is-white .navbar-brand>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-white .navbar-brand .navbar-link{color:#0a0a0a}html.theme--catppuccin-macchiato .navbar.is-white .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-white .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-white .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-white .navbar-brand .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-white .navbar-brand .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-white .navbar-brand .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--catppuccin-macchiato .navbar.is-white .navbar-brand .navbar-link::after{border-color:#0a0a0a}html.theme--catppuccin-macchiato .navbar.is-white .navbar-burger{color:#0a0a0a}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .navbar.is-white .navbar-start>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-white .navbar-start .navbar-link,html.theme--catppuccin-macchiato .navbar.is-white .navbar-end>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-white .navbar-end .navbar-link{color:#0a0a0a}html.theme--catppuccin-macchiato .navbar.is-white .navbar-start>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-white .navbar-start>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-white .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-white .navbar-start .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-white .navbar-start .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-white .navbar-start .navbar-link.is-active,html.theme--catppuccin-macchiato .navbar.is-white .navbar-end>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-white .navbar-end>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-white .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-white .navbar-end .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-white .navbar-end .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-white .navbar-end .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--catppuccin-macchiato .navbar.is-white .navbar-start .navbar-link::after,html.theme--catppuccin-macchiato .navbar.is-white .navbar-end .navbar-link::after{border-color:#0a0a0a}html.theme--catppuccin-macchiato .navbar.is-white .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-macchiato .navbar.is-white .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-macchiato .navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link{background-color:#f2f2f2;color:#0a0a0a}html.theme--catppuccin-macchiato .navbar.is-white .navbar-dropdown a.navbar-item.is-active{background-color:#fff;color:#0a0a0a}}html.theme--catppuccin-macchiato .navbar.is-black{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-macchiato .navbar.is-black .navbar-brand>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-black .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-macchiato .navbar.is-black .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-black .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-black .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-black .navbar-brand .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-black .navbar-brand .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-black .navbar-brand .navbar-link.is-active{background-color:#000;color:#fff}html.theme--catppuccin-macchiato .navbar.is-black .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-macchiato .navbar.is-black .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .navbar.is-black .navbar-start>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-black .navbar-start .navbar-link,html.theme--catppuccin-macchiato .navbar.is-black .navbar-end>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-black .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-macchiato .navbar.is-black .navbar-start>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-black .navbar-start>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-black .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-black .navbar-start .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-black .navbar-start .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-black .navbar-start .navbar-link.is-active,html.theme--catppuccin-macchiato .navbar.is-black .navbar-end>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-black .navbar-end>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-black .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-black .navbar-end .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-black .navbar-end .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-black .navbar-end .navbar-link.is-active{background-color:#000;color:#fff}html.theme--catppuccin-macchiato .navbar.is-black .navbar-start .navbar-link::after,html.theme--catppuccin-macchiato .navbar.is-black .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-macchiato .navbar.is-black .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-macchiato .navbar.is-black .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-macchiato .navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link{background-color:#000;color:#fff}html.theme--catppuccin-macchiato .navbar.is-black .navbar-dropdown a.navbar-item.is-active{background-color:#0a0a0a;color:#fff}}html.theme--catppuccin-macchiato .navbar.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-light .navbar-brand>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-light .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-light .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-light .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-light .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-light .navbar-brand .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-light .navbar-brand .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-light .navbar-brand .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-light .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-light .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .navbar.is-light .navbar-start>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-light .navbar-start .navbar-link,html.theme--catppuccin-macchiato .navbar.is-light .navbar-end>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-light .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-light .navbar-start>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-light .navbar-start>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-light .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-light .navbar-start .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-light .navbar-start .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-light .navbar-start .navbar-link.is-active,html.theme--catppuccin-macchiato .navbar.is-light .navbar-end>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-light .navbar-end>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-light .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-light .navbar-end .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-light .navbar-end .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-light .navbar-end .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-light .navbar-start .navbar-link::after,html.theme--catppuccin-macchiato .navbar.is-light .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-light .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-macchiato .navbar.is-light .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-macchiato .navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-light .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}}html.theme--catppuccin-macchiato .navbar.is-dark,html.theme--catppuccin-macchiato .content kbd.navbar{background-color:#363a4f;color:#fff}html.theme--catppuccin-macchiato .navbar.is-dark .navbar-brand>.navbar-item,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-brand>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-brand .navbar-link,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-macchiato .navbar.is-dark .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-brand .navbar-link:focus,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-brand .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-brand .navbar-link:hover,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-brand .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-brand .navbar-link.is-active,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-brand .navbar-link.is-active{background-color:#2c2f40;color:#fff}html.theme--catppuccin-macchiato .navbar.is-dark .navbar-brand .navbar-link::after,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-macchiato .navbar.is-dark .navbar-burger,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .navbar.is-dark .navbar-start>.navbar-item,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-start>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-start .navbar-link,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-start .navbar-link,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-end>.navbar-item,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-end>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-end .navbar-link,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-macchiato .navbar.is-dark .navbar-start>a.navbar-item:focus,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-start>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-start>a.navbar-item:hover,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-start>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-start .navbar-link:focus,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-start .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-start .navbar-link:hover,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-start .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-start .navbar-link.is-active,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-start .navbar-link.is-active,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-end>a.navbar-item:focus,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-end>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-end>a.navbar-item:hover,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-end>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-end .navbar-link:focus,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-end .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-end .navbar-link:hover,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-end .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-end .navbar-link.is-active,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-end .navbar-link.is-active{background-color:#2c2f40;color:#fff}html.theme--catppuccin-macchiato .navbar.is-dark .navbar-start .navbar-link::after,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-start .navbar-link::after,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-end .navbar-link::after,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-macchiato .navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-macchiato .navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-item.has-dropdown.is-active .navbar-link{background-color:#2c2f40;color:#fff}html.theme--catppuccin-macchiato .navbar.is-dark .navbar-dropdown a.navbar-item.is-active,html.theme--catppuccin-macchiato .content kbd.navbar .navbar-dropdown a.navbar-item.is-active{background-color:#363a4f;color:#fff}}html.theme--catppuccin-macchiato .navbar.is-primary,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink{background-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .navbar.is-primary .navbar-brand>.navbar-item,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-brand>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-brand .navbar-link,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-macchiato .navbar.is-primary .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-brand .navbar-link:focus,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-brand .navbar-link:hover,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-brand .navbar-link.is-active,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link.is-active{background-color:#739df2;color:#fff}html.theme--catppuccin-macchiato .navbar.is-primary .navbar-brand .navbar-link::after,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-macchiato .navbar.is-primary .navbar-burger,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .navbar.is-primary .navbar-start>.navbar-item,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-start>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-start .navbar-link,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-end>.navbar-item,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-end>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-end .navbar-link,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-macchiato .navbar.is-primary .navbar-start>a.navbar-item:focus,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-start>a.navbar-item:hover,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-start .navbar-link:focus,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-start .navbar-link:hover,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-start .navbar-link.is-active,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link.is-active,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-end>a.navbar-item:focus,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-end>a.navbar-item:hover,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-end .navbar-link:focus,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-end .navbar-link:hover,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-end .navbar-link.is-active,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link.is-active{background-color:#739df2;color:#fff}html.theme--catppuccin-macchiato .navbar.is-primary .navbar-start .navbar-link::after,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link::after,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-end .navbar-link::after,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-macchiato .navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-macchiato .navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown.is-active .navbar-link{background-color:#739df2;color:#fff}html.theme--catppuccin-macchiato .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#8aadf4;color:#fff}}html.theme--catppuccin-macchiato .navbar.is-link{background-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .navbar.is-link .navbar-brand>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-link .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-macchiato .navbar.is-link .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-link .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-link .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-link .navbar-brand .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-link .navbar-brand .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-link .navbar-brand .navbar-link.is-active{background-color:#739df2;color:#fff}html.theme--catppuccin-macchiato .navbar.is-link .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-macchiato .navbar.is-link .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .navbar.is-link .navbar-start>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-link .navbar-start .navbar-link,html.theme--catppuccin-macchiato .navbar.is-link .navbar-end>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-link .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-macchiato .navbar.is-link .navbar-start>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-link .navbar-start>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-link .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-link .navbar-start .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-link .navbar-start .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-link .navbar-start .navbar-link.is-active,html.theme--catppuccin-macchiato .navbar.is-link .navbar-end>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-link .navbar-end>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-link .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-link .navbar-end .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-link .navbar-end .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-link .navbar-end .navbar-link.is-active{background-color:#739df2;color:#fff}html.theme--catppuccin-macchiato .navbar.is-link .navbar-start .navbar-link::after,html.theme--catppuccin-macchiato .navbar.is-link .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-macchiato .navbar.is-link .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-macchiato .navbar.is-link .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-macchiato .navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link{background-color:#739df2;color:#fff}html.theme--catppuccin-macchiato .navbar.is-link .navbar-dropdown a.navbar-item.is-active{background-color:#8aadf4;color:#fff}}html.theme--catppuccin-macchiato .navbar.is-info{background-color:#8bd5ca;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-info .navbar-brand>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-info .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-info .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-info .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-info .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-info .navbar-brand .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-info .navbar-brand .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-info .navbar-brand .navbar-link.is-active{background-color:#78cec1;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-info .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-info .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .navbar.is-info .navbar-start>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-info .navbar-start .navbar-link,html.theme--catppuccin-macchiato .navbar.is-info .navbar-end>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-info .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-info .navbar-start>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-info .navbar-start>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-info .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-info .navbar-start .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-info .navbar-start .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-info .navbar-start .navbar-link.is-active,html.theme--catppuccin-macchiato .navbar.is-info .navbar-end>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-info .navbar-end>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-info .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-info .navbar-end .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-info .navbar-end .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-info .navbar-end .navbar-link.is-active{background-color:#78cec1;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-info .navbar-start .navbar-link::after,html.theme--catppuccin-macchiato .navbar.is-info .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-info .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-macchiato .navbar.is-info .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-macchiato .navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link{background-color:#78cec1;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-info .navbar-dropdown a.navbar-item.is-active{background-color:#8bd5ca;color:rgba(0,0,0,0.7)}}html.theme--catppuccin-macchiato .navbar.is-success{background-color:#a6da95;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-success .navbar-brand>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-success .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-success .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-success .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-success .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-success .navbar-brand .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-success .navbar-brand .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-success .navbar-brand .navbar-link.is-active{background-color:#96d382;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-success .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-success .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .navbar.is-success .navbar-start>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-success .navbar-start .navbar-link,html.theme--catppuccin-macchiato .navbar.is-success .navbar-end>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-success .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-success .navbar-start>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-success .navbar-start>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-success .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-success .navbar-start .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-success .navbar-start .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-success .navbar-start .navbar-link.is-active,html.theme--catppuccin-macchiato .navbar.is-success .navbar-end>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-success .navbar-end>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-success .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-success .navbar-end .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-success .navbar-end .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-success .navbar-end .navbar-link.is-active{background-color:#96d382;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-success .navbar-start .navbar-link::after,html.theme--catppuccin-macchiato .navbar.is-success .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-success .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-macchiato .navbar.is-success .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-macchiato .navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link{background-color:#96d382;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-success .navbar-dropdown a.navbar-item.is-active{background-color:#a6da95;color:rgba(0,0,0,0.7)}}html.theme--catppuccin-macchiato .navbar.is-warning{background-color:#eed49f;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-warning .navbar-brand>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-warning .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-brand .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-brand .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-brand .navbar-link.is-active{background-color:#eaca89;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-warning .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-warning .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .navbar.is-warning .navbar-start>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-start .navbar-link,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-end>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-warning .navbar-start>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-start>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-start .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-start .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-start .navbar-link.is-active,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-end>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-end>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-end .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-end .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-end .navbar-link.is-active{background-color:#eaca89;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-warning .navbar-start .navbar-link::after,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-macchiato .navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link{background-color:#eaca89;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .navbar.is-warning .navbar-dropdown a.navbar-item.is-active{background-color:#eed49f;color:rgba(0,0,0,0.7)}}html.theme--catppuccin-macchiato .navbar.is-danger{background-color:#ed8796;color:#fff}html.theme--catppuccin-macchiato .navbar.is-danger .navbar-brand>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-macchiato .navbar.is-danger .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-brand .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-brand .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-brand .navbar-link.is-active{background-color:#ea7183;color:#fff}html.theme--catppuccin-macchiato .navbar.is-danger .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-macchiato .navbar.is-danger .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .navbar.is-danger .navbar-start>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-start .navbar-link,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-end>.navbar-item,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-macchiato .navbar.is-danger .navbar-start>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-start>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-start .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-start .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-start .navbar-link.is-active,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-end>a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-end>a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-end .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-end .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-end .navbar-link.is-active{background-color:#ea7183;color:#fff}html.theme--catppuccin-macchiato .navbar.is-danger .navbar-start .navbar-link::after,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-macchiato .navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-macchiato .navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link{background-color:#ea7183;color:#fff}html.theme--catppuccin-macchiato .navbar.is-danger .navbar-dropdown a.navbar-item.is-active{background-color:#ed8796;color:#fff}}html.theme--catppuccin-macchiato .navbar>.container{align-items:stretch;display:flex;min-height:4rem;width:100%}html.theme--catppuccin-macchiato .navbar.has-shadow{box-shadow:0 2px 0 0 #1e2030}html.theme--catppuccin-macchiato .navbar.is-fixed-bottom,html.theme--catppuccin-macchiato .navbar.is-fixed-top{left:0;position:fixed;right:0;z-index:30}html.theme--catppuccin-macchiato .navbar.is-fixed-bottom{bottom:0}html.theme--catppuccin-macchiato .navbar.is-fixed-bottom.has-shadow{box-shadow:0 -2px 0 0 #1e2030}html.theme--catppuccin-macchiato .navbar.is-fixed-top{top:0}html.theme--catppuccin-macchiato html.has-navbar-fixed-top,html.theme--catppuccin-macchiato body.has-navbar-fixed-top{padding-top:4rem}html.theme--catppuccin-macchiato html.has-navbar-fixed-bottom,html.theme--catppuccin-macchiato body.has-navbar-fixed-bottom{padding-bottom:4rem}html.theme--catppuccin-macchiato .navbar-brand,html.theme--catppuccin-macchiato .navbar-tabs{align-items:stretch;display:flex;flex-shrink:0;min-height:4rem}html.theme--catppuccin-macchiato .navbar-brand a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar-brand a.navbar-item:hover{background-color:transparent}html.theme--catppuccin-macchiato .navbar-tabs{-webkit-overflow-scrolling:touch;max-width:100vw;overflow-x:auto;overflow-y:hidden}html.theme--catppuccin-macchiato .navbar-burger{color:#cad3f5;-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;cursor:pointer;display:block;height:4rem;position:relative;width:4rem;margin-left:auto}html.theme--catppuccin-macchiato .navbar-burger span{background-color:currentColor;display:block;height:1px;left:calc(50% - 8px);position:absolute;transform-origin:center;transition-duration:86ms;transition-property:background-color, opacity, transform;transition-timing-function:ease-out;width:16px}html.theme--catppuccin-macchiato .navbar-burger span:nth-child(1){top:calc(50% - 6px)}html.theme--catppuccin-macchiato .navbar-burger span:nth-child(2){top:calc(50% - 1px)}html.theme--catppuccin-macchiato .navbar-burger span:nth-child(3){top:calc(50% + 4px)}html.theme--catppuccin-macchiato .navbar-burger:hover{background-color:rgba(0,0,0,0.05)}html.theme--catppuccin-macchiato .navbar-burger.is-active span:nth-child(1){transform:translateY(5px) rotate(45deg)}html.theme--catppuccin-macchiato .navbar-burger.is-active span:nth-child(2){opacity:0}html.theme--catppuccin-macchiato .navbar-burger.is-active span:nth-child(3){transform:translateY(-5px) rotate(-45deg)}html.theme--catppuccin-macchiato .navbar-menu{display:none}html.theme--catppuccin-macchiato .navbar-item,html.theme--catppuccin-macchiato .navbar-link{color:#cad3f5;display:block;line-height:1.5;padding:0.5rem 0.75rem;position:relative}html.theme--catppuccin-macchiato .navbar-item .icon:only-child,html.theme--catppuccin-macchiato .navbar-link .icon:only-child{margin-left:-0.25rem;margin-right:-0.25rem}html.theme--catppuccin-macchiato a.navbar-item,html.theme--catppuccin-macchiato .navbar-link{cursor:pointer}html.theme--catppuccin-macchiato a.navbar-item:focus,html.theme--catppuccin-macchiato a.navbar-item:focus-within,html.theme--catppuccin-macchiato a.navbar-item:hover,html.theme--catppuccin-macchiato a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar-link:focus,html.theme--catppuccin-macchiato .navbar-link:focus-within,html.theme--catppuccin-macchiato .navbar-link:hover,html.theme--catppuccin-macchiato .navbar-link.is-active{background-color:rgba(0,0,0,0);color:#8aadf4}html.theme--catppuccin-macchiato .navbar-item{flex-grow:0;flex-shrink:0}html.theme--catppuccin-macchiato .navbar-item img{max-height:1.75rem}html.theme--catppuccin-macchiato .navbar-item.has-dropdown{padding:0}html.theme--catppuccin-macchiato .navbar-item.is-expanded{flex-grow:1;flex-shrink:1}html.theme--catppuccin-macchiato .navbar-item.is-tab{border-bottom:1px solid transparent;min-height:4rem;padding-bottom:calc(0.5rem - 1px)}html.theme--catppuccin-macchiato .navbar-item.is-tab:focus,html.theme--catppuccin-macchiato .navbar-item.is-tab:hover{background-color:rgba(0,0,0,0);border-bottom-color:#8aadf4}html.theme--catppuccin-macchiato .navbar-item.is-tab.is-active{background-color:rgba(0,0,0,0);border-bottom-color:#8aadf4;border-bottom-style:solid;border-bottom-width:3px;color:#8aadf4;padding-bottom:calc(0.5rem - 3px)}html.theme--catppuccin-macchiato .navbar-content{flex-grow:1;flex-shrink:1}html.theme--catppuccin-macchiato .navbar-link:not(.is-arrowless){padding-right:2.5em}html.theme--catppuccin-macchiato .navbar-link:not(.is-arrowless)::after{border-color:#fff;margin-top:-0.375em;right:1.125em}html.theme--catppuccin-macchiato .navbar-dropdown{font-size:0.875rem;padding-bottom:0.5rem;padding-top:0.5rem}html.theme--catppuccin-macchiato .navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}html.theme--catppuccin-macchiato .navbar-divider{background-color:rgba(0,0,0,0.2);border:none;display:none;height:2px;margin:0.5rem 0}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .navbar>.container{display:block}html.theme--catppuccin-macchiato .navbar-brand .navbar-item,html.theme--catppuccin-macchiato .navbar-tabs .navbar-item{align-items:center;display:flex}html.theme--catppuccin-macchiato .navbar-link::after{display:none}html.theme--catppuccin-macchiato .navbar-menu{background-color:#8aadf4;box-shadow:0 8px 16px rgba(10,10,10,0.1);padding:0.5rem 0}html.theme--catppuccin-macchiato .navbar-menu.is-active{display:block}html.theme--catppuccin-macchiato .navbar.is-fixed-bottom-touch,html.theme--catppuccin-macchiato .navbar.is-fixed-top-touch{left:0;position:fixed;right:0;z-index:30}html.theme--catppuccin-macchiato .navbar.is-fixed-bottom-touch{bottom:0}html.theme--catppuccin-macchiato .navbar.is-fixed-bottom-touch.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--catppuccin-macchiato .navbar.is-fixed-top-touch{top:0}html.theme--catppuccin-macchiato .navbar.is-fixed-top .navbar-menu,html.theme--catppuccin-macchiato .navbar.is-fixed-top-touch .navbar-menu{-webkit-overflow-scrolling:touch;max-height:calc(100vh - 4rem);overflow:auto}html.theme--catppuccin-macchiato html.has-navbar-fixed-top-touch,html.theme--catppuccin-macchiato body.has-navbar-fixed-top-touch{padding-top:4rem}html.theme--catppuccin-macchiato html.has-navbar-fixed-bottom-touch,html.theme--catppuccin-macchiato body.has-navbar-fixed-bottom-touch{padding-bottom:4rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .navbar,html.theme--catppuccin-macchiato .navbar-menu,html.theme--catppuccin-macchiato .navbar-start,html.theme--catppuccin-macchiato .navbar-end{align-items:stretch;display:flex}html.theme--catppuccin-macchiato .navbar{min-height:4rem}html.theme--catppuccin-macchiato .navbar.is-spaced{padding:1rem 2rem}html.theme--catppuccin-macchiato .navbar.is-spaced .navbar-start,html.theme--catppuccin-macchiato .navbar.is-spaced .navbar-end{align-items:center}html.theme--catppuccin-macchiato .navbar.is-spaced a.navbar-item,html.theme--catppuccin-macchiato .navbar.is-spaced .navbar-link{border-radius:.4em}html.theme--catppuccin-macchiato .navbar.is-transparent a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-transparent a.navbar-item:hover,html.theme--catppuccin-macchiato .navbar.is-transparent a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar.is-transparent .navbar-link:focus,html.theme--catppuccin-macchiato .navbar.is-transparent .navbar-link:hover,html.theme--catppuccin-macchiato .navbar.is-transparent .navbar-link.is-active{background-color:transparent !important}html.theme--catppuccin-macchiato .navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link,html.theme--catppuccin-macchiato .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link,html.theme--catppuccin-macchiato .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link,html.theme--catppuccin-macchiato .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link{background-color:transparent !important}html.theme--catppuccin-macchiato .navbar.is-transparent .navbar-dropdown a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar.is-transparent .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#8087a2}html.theme--catppuccin-macchiato .navbar.is-transparent .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#8aadf4}html.theme--catppuccin-macchiato .navbar-burger{display:none}html.theme--catppuccin-macchiato .navbar-item,html.theme--catppuccin-macchiato .navbar-link{align-items:center;display:flex}html.theme--catppuccin-macchiato .navbar-item.has-dropdown{align-items:stretch}html.theme--catppuccin-macchiato .navbar-item.has-dropdown-up .navbar-link::after{transform:rotate(135deg) translate(0.25em, -0.25em)}html.theme--catppuccin-macchiato .navbar-item.has-dropdown-up .navbar-dropdown{border-bottom:1px solid rgba(0,0,0,0.2);border-radius:8px 8px 0 0;border-top:none;bottom:100%;box-shadow:0 -8px 8px rgba(10,10,10,0.1);top:auto}html.theme--catppuccin-macchiato .navbar-item.is-active .navbar-dropdown,html.theme--catppuccin-macchiato .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--catppuccin-macchiato .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--catppuccin-macchiato .navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar.is-spaced html.theme--catppuccin-macchiato .navbar-item.is-active .navbar-dropdown,html.theme--catppuccin-macchiato .navbar-item.is-active .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--catppuccin-macchiato .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--catppuccin-macchiato .navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--catppuccin-macchiato .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--catppuccin-macchiato .navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--catppuccin-macchiato .navbar-item.is-hoverable:hover .navbar-dropdown,html.theme--catppuccin-macchiato .navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed{opacity:1;pointer-events:auto;transform:translateY(0)}html.theme--catppuccin-macchiato .navbar-menu{flex-grow:1;flex-shrink:0}html.theme--catppuccin-macchiato .navbar-start{justify-content:flex-start;margin-right:auto}html.theme--catppuccin-macchiato .navbar-end{justify-content:flex-end;margin-left:auto}html.theme--catppuccin-macchiato .navbar-dropdown{background-color:#8aadf4;border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid rgba(0,0,0,0.2);box-shadow:0 8px 8px rgba(10,10,10,0.1);display:none;font-size:0.875rem;left:0;min-width:100%;position:absolute;top:100%;z-index:20}html.theme--catppuccin-macchiato .navbar-dropdown .navbar-item{padding:0.375rem 1rem;white-space:nowrap}html.theme--catppuccin-macchiato .navbar-dropdown a.navbar-item{padding-right:3rem}html.theme--catppuccin-macchiato .navbar-dropdown a.navbar-item:focus,html.theme--catppuccin-macchiato .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#8087a2}html.theme--catppuccin-macchiato .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#8aadf4}.navbar.is-spaced html.theme--catppuccin-macchiato .navbar-dropdown,html.theme--catppuccin-macchiato .navbar-dropdown.is-boxed{border-radius:8px;border-top:none;box-shadow:0 8px 8px rgba(10,10,10,0.1), 0 0 0 1px rgba(10,10,10,0.1);display:block;opacity:0;pointer-events:none;top:calc(100% + (-4px));transform:translateY(-5px);transition-duration:86ms;transition-property:opacity, transform}html.theme--catppuccin-macchiato .navbar-dropdown.is-right{left:auto;right:0}html.theme--catppuccin-macchiato .navbar-divider{display:block}html.theme--catppuccin-macchiato .navbar>.container .navbar-brand,html.theme--catppuccin-macchiato .container>.navbar .navbar-brand{margin-left:-.75rem}html.theme--catppuccin-macchiato .navbar>.container .navbar-menu,html.theme--catppuccin-macchiato .container>.navbar .navbar-menu{margin-right:-.75rem}html.theme--catppuccin-macchiato .navbar.is-fixed-bottom-desktop,html.theme--catppuccin-macchiato .navbar.is-fixed-top-desktop{left:0;position:fixed;right:0;z-index:30}html.theme--catppuccin-macchiato .navbar.is-fixed-bottom-desktop{bottom:0}html.theme--catppuccin-macchiato .navbar.is-fixed-bottom-desktop.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--catppuccin-macchiato .navbar.is-fixed-top-desktop{top:0}html.theme--catppuccin-macchiato html.has-navbar-fixed-top-desktop,html.theme--catppuccin-macchiato body.has-navbar-fixed-top-desktop{padding-top:4rem}html.theme--catppuccin-macchiato html.has-navbar-fixed-bottom-desktop,html.theme--catppuccin-macchiato body.has-navbar-fixed-bottom-desktop{padding-bottom:4rem}html.theme--catppuccin-macchiato html.has-spaced-navbar-fixed-top,html.theme--catppuccin-macchiato body.has-spaced-navbar-fixed-top{padding-top:6rem}html.theme--catppuccin-macchiato html.has-spaced-navbar-fixed-bottom,html.theme--catppuccin-macchiato body.has-spaced-navbar-fixed-bottom{padding-bottom:6rem}html.theme--catppuccin-macchiato a.navbar-item.is-active,html.theme--catppuccin-macchiato .navbar-link.is-active{color:#8aadf4}html.theme--catppuccin-macchiato a.navbar-item.is-active:not(:focus):not(:hover),html.theme--catppuccin-macchiato .navbar-link.is-active:not(:focus):not(:hover){background-color:rgba(0,0,0,0)}html.theme--catppuccin-macchiato .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-macchiato .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-macchiato .navbar-item.has-dropdown.is-active .navbar-link{background-color:rgba(0,0,0,0)}}html.theme--catppuccin-macchiato .hero.is-fullheight-with-navbar{min-height:calc(100vh - 4rem)}html.theme--catppuccin-macchiato .pagination{font-size:1rem;margin:-.25rem}html.theme--catppuccin-macchiato .pagination.is-small,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.pagination{font-size:.75rem}html.theme--catppuccin-macchiato .pagination.is-medium{font-size:1.25rem}html.theme--catppuccin-macchiato .pagination.is-large{font-size:1.5rem}html.theme--catppuccin-macchiato .pagination.is-rounded .pagination-previous,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.pagination .pagination-previous,html.theme--catppuccin-macchiato .pagination.is-rounded .pagination-next,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.pagination .pagination-next{padding-left:1em;padding-right:1em;border-radius:9999px}html.theme--catppuccin-macchiato .pagination.is-rounded .pagination-link,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.pagination .pagination-link{border-radius:9999px}html.theme--catppuccin-macchiato .pagination,html.theme--catppuccin-macchiato .pagination-list{align-items:center;display:flex;justify-content:center;text-align:center}html.theme--catppuccin-macchiato .pagination-previous,html.theme--catppuccin-macchiato .pagination-next,html.theme--catppuccin-macchiato .pagination-link,html.theme--catppuccin-macchiato .pagination-ellipsis{font-size:1em;justify-content:center;margin:.25rem;padding-left:.5em;padding-right:.5em;text-align:center}html.theme--catppuccin-macchiato .pagination-previous,html.theme--catppuccin-macchiato .pagination-next,html.theme--catppuccin-macchiato .pagination-link{border-color:#5b6078;color:#8aadf4;min-width:2.5em}html.theme--catppuccin-macchiato .pagination-previous:hover,html.theme--catppuccin-macchiato .pagination-next:hover,html.theme--catppuccin-macchiato .pagination-link:hover{border-color:#6e738d;color:#91d7e3}html.theme--catppuccin-macchiato .pagination-previous:focus,html.theme--catppuccin-macchiato .pagination-next:focus,html.theme--catppuccin-macchiato .pagination-link:focus{border-color:#6e738d}html.theme--catppuccin-macchiato .pagination-previous:active,html.theme--catppuccin-macchiato .pagination-next:active,html.theme--catppuccin-macchiato .pagination-link:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2)}html.theme--catppuccin-macchiato .pagination-previous[disabled],html.theme--catppuccin-macchiato .pagination-previous.is-disabled,html.theme--catppuccin-macchiato .pagination-next[disabled],html.theme--catppuccin-macchiato .pagination-next.is-disabled,html.theme--catppuccin-macchiato .pagination-link[disabled],html.theme--catppuccin-macchiato .pagination-link.is-disabled{background-color:#5b6078;border-color:#5b6078;box-shadow:none;color:#f5f7fd;opacity:0.5}html.theme--catppuccin-macchiato .pagination-previous,html.theme--catppuccin-macchiato .pagination-next{padding-left:.75em;padding-right:.75em;white-space:nowrap}html.theme--catppuccin-macchiato .pagination-link.is-current{background-color:#8aadf4;border-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .pagination-ellipsis{color:#6e738d;pointer-events:none}html.theme--catppuccin-macchiato .pagination-list{flex-wrap:wrap}html.theme--catppuccin-macchiato .pagination-list li{list-style:none}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .pagination{flex-wrap:wrap}html.theme--catppuccin-macchiato .pagination-previous,html.theme--catppuccin-macchiato .pagination-next{flex-grow:1;flex-shrink:1}html.theme--catppuccin-macchiato .pagination-list li{flex-grow:1;flex-shrink:1}}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .pagination-list{flex-grow:1;flex-shrink:1;justify-content:flex-start;order:1}html.theme--catppuccin-macchiato .pagination-previous,html.theme--catppuccin-macchiato .pagination-next,html.theme--catppuccin-macchiato .pagination-link,html.theme--catppuccin-macchiato .pagination-ellipsis{margin-bottom:0;margin-top:0}html.theme--catppuccin-macchiato .pagination-previous{order:2}html.theme--catppuccin-macchiato .pagination-next{order:3}html.theme--catppuccin-macchiato .pagination{justify-content:space-between;margin-bottom:0;margin-top:0}html.theme--catppuccin-macchiato .pagination.is-centered .pagination-previous{order:1}html.theme--catppuccin-macchiato .pagination.is-centered .pagination-list{justify-content:center;order:2}html.theme--catppuccin-macchiato .pagination.is-centered .pagination-next{order:3}html.theme--catppuccin-macchiato .pagination.is-right .pagination-previous{order:1}html.theme--catppuccin-macchiato .pagination.is-right .pagination-next{order:2}html.theme--catppuccin-macchiato .pagination.is-right .pagination-list{justify-content:flex-end;order:3}}html.theme--catppuccin-macchiato .panel{border-radius:8px;box-shadow:#171717;font-size:1rem}html.theme--catppuccin-macchiato .panel:not(:last-child){margin-bottom:1.5rem}html.theme--catppuccin-macchiato .panel.is-white .panel-heading{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-macchiato .panel.is-white .panel-tabs a.is-active{border-bottom-color:#fff}html.theme--catppuccin-macchiato .panel.is-white .panel-block.is-active .panel-icon{color:#fff}html.theme--catppuccin-macchiato .panel.is-black .panel-heading{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-macchiato .panel.is-black .panel-tabs a.is-active{border-bottom-color:#0a0a0a}html.theme--catppuccin-macchiato .panel.is-black .panel-block.is-active .panel-icon{color:#0a0a0a}html.theme--catppuccin-macchiato .panel.is-light .panel-heading{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .panel.is-light .panel-tabs a.is-active{border-bottom-color:#f5f5f5}html.theme--catppuccin-macchiato .panel.is-light .panel-block.is-active .panel-icon{color:#f5f5f5}html.theme--catppuccin-macchiato .panel.is-dark .panel-heading,html.theme--catppuccin-macchiato .content kbd.panel .panel-heading{background-color:#363a4f;color:#fff}html.theme--catppuccin-macchiato .panel.is-dark .panel-tabs a.is-active,html.theme--catppuccin-macchiato .content kbd.panel .panel-tabs a.is-active{border-bottom-color:#363a4f}html.theme--catppuccin-macchiato .panel.is-dark .panel-block.is-active .panel-icon,html.theme--catppuccin-macchiato .content kbd.panel .panel-block.is-active .panel-icon{color:#363a4f}html.theme--catppuccin-macchiato .panel.is-primary .panel-heading,html.theme--catppuccin-macchiato .docstring>section>a.panel.docs-sourcelink .panel-heading{background-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .panel.is-primary .panel-tabs a.is-active,html.theme--catppuccin-macchiato .docstring>section>a.panel.docs-sourcelink .panel-tabs a.is-active{border-bottom-color:#8aadf4}html.theme--catppuccin-macchiato .panel.is-primary .panel-block.is-active .panel-icon,html.theme--catppuccin-macchiato .docstring>section>a.panel.docs-sourcelink .panel-block.is-active .panel-icon{color:#8aadf4}html.theme--catppuccin-macchiato .panel.is-link .panel-heading{background-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .panel.is-link .panel-tabs a.is-active{border-bottom-color:#8aadf4}html.theme--catppuccin-macchiato .panel.is-link .panel-block.is-active .panel-icon{color:#8aadf4}html.theme--catppuccin-macchiato .panel.is-info .panel-heading{background-color:#8bd5ca;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .panel.is-info .panel-tabs a.is-active{border-bottom-color:#8bd5ca}html.theme--catppuccin-macchiato .panel.is-info .panel-block.is-active .panel-icon{color:#8bd5ca}html.theme--catppuccin-macchiato .panel.is-success .panel-heading{background-color:#a6da95;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .panel.is-success .panel-tabs a.is-active{border-bottom-color:#a6da95}html.theme--catppuccin-macchiato .panel.is-success .panel-block.is-active .panel-icon{color:#a6da95}html.theme--catppuccin-macchiato .panel.is-warning .panel-heading{background-color:#eed49f;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .panel.is-warning .panel-tabs a.is-active{border-bottom-color:#eed49f}html.theme--catppuccin-macchiato .panel.is-warning .panel-block.is-active .panel-icon{color:#eed49f}html.theme--catppuccin-macchiato .panel.is-danger .panel-heading{background-color:#ed8796;color:#fff}html.theme--catppuccin-macchiato .panel.is-danger .panel-tabs a.is-active{border-bottom-color:#ed8796}html.theme--catppuccin-macchiato .panel.is-danger .panel-block.is-active .panel-icon{color:#ed8796}html.theme--catppuccin-macchiato .panel-tabs:not(:last-child),html.theme--catppuccin-macchiato .panel-block:not(:last-child){border-bottom:1px solid #ededed}html.theme--catppuccin-macchiato .panel-heading{background-color:#494d64;border-radius:8px 8px 0 0;color:#b5c1f1;font-size:1.25em;font-weight:700;line-height:1.25;padding:0.75em 1em}html.theme--catppuccin-macchiato .panel-tabs{align-items:flex-end;display:flex;font-size:.875em;justify-content:center}html.theme--catppuccin-macchiato .panel-tabs a{border-bottom:1px solid #5b6078;margin-bottom:-1px;padding:0.5em}html.theme--catppuccin-macchiato .panel-tabs a.is-active{border-bottom-color:#494d64;color:#739df2}html.theme--catppuccin-macchiato .panel-list a{color:#cad3f5}html.theme--catppuccin-macchiato .panel-list a:hover{color:#8aadf4}html.theme--catppuccin-macchiato .panel-block{align-items:center;color:#b5c1f1;display:flex;justify-content:flex-start;padding:0.5em 0.75em}html.theme--catppuccin-macchiato .panel-block input[type="checkbox"]{margin-right:.75em}html.theme--catppuccin-macchiato .panel-block>.control{flex-grow:1;flex-shrink:1;width:100%}html.theme--catppuccin-macchiato .panel-block.is-wrapped{flex-wrap:wrap}html.theme--catppuccin-macchiato .panel-block.is-active{border-left-color:#8aadf4;color:#739df2}html.theme--catppuccin-macchiato .panel-block.is-active .panel-icon{color:#8aadf4}html.theme--catppuccin-macchiato .panel-block:last-child{border-bottom-left-radius:8px;border-bottom-right-radius:8px}html.theme--catppuccin-macchiato a.panel-block,html.theme--catppuccin-macchiato label.panel-block{cursor:pointer}html.theme--catppuccin-macchiato a.panel-block:hover,html.theme--catppuccin-macchiato label.panel-block:hover{background-color:#1e2030}html.theme--catppuccin-macchiato .panel-icon{display:inline-block;font-size:14px;height:1em;line-height:1em;text-align:center;vertical-align:top;width:1em;color:#f5f7fd;margin-right:.75em}html.theme--catppuccin-macchiato .panel-icon .fa{font-size:inherit;line-height:inherit}html.theme--catppuccin-macchiato .tabs{-webkit-overflow-scrolling:touch;align-items:stretch;display:flex;font-size:1rem;justify-content:space-between;overflow:hidden;overflow-x:auto;white-space:nowrap}html.theme--catppuccin-macchiato .tabs a{align-items:center;border-bottom-color:#5b6078;border-bottom-style:solid;border-bottom-width:1px;color:#cad3f5;display:flex;justify-content:center;margin-bottom:-1px;padding:0.5em 1em;vertical-align:top}html.theme--catppuccin-macchiato .tabs a:hover{border-bottom-color:#b5c1f1;color:#b5c1f1}html.theme--catppuccin-macchiato .tabs li{display:block}html.theme--catppuccin-macchiato .tabs li.is-active a{border-bottom-color:#8aadf4;color:#8aadf4}html.theme--catppuccin-macchiato .tabs ul{align-items:center;border-bottom-color:#5b6078;border-bottom-style:solid;border-bottom-width:1px;display:flex;flex-grow:1;flex-shrink:0;justify-content:flex-start}html.theme--catppuccin-macchiato .tabs ul.is-left{padding-right:0.75em}html.theme--catppuccin-macchiato .tabs ul.is-center{flex:none;justify-content:center;padding-left:0.75em;padding-right:0.75em}html.theme--catppuccin-macchiato .tabs ul.is-right{justify-content:flex-end;padding-left:0.75em}html.theme--catppuccin-macchiato .tabs .icon:first-child{margin-right:.5em}html.theme--catppuccin-macchiato .tabs .icon:last-child{margin-left:.5em}html.theme--catppuccin-macchiato .tabs.is-centered ul{justify-content:center}html.theme--catppuccin-macchiato .tabs.is-right ul{justify-content:flex-end}html.theme--catppuccin-macchiato .tabs.is-boxed a{border:1px solid transparent;border-radius:.4em .4em 0 0}html.theme--catppuccin-macchiato .tabs.is-boxed a:hover{background-color:#1e2030;border-bottom-color:#5b6078}html.theme--catppuccin-macchiato .tabs.is-boxed li.is-active a{background-color:#fff;border-color:#5b6078;border-bottom-color:rgba(0,0,0,0) !important}html.theme--catppuccin-macchiato .tabs.is-fullwidth li{flex-grow:1;flex-shrink:0}html.theme--catppuccin-macchiato .tabs.is-toggle a{border-color:#5b6078;border-style:solid;border-width:1px;margin-bottom:0;position:relative}html.theme--catppuccin-macchiato .tabs.is-toggle a:hover{background-color:#1e2030;border-color:#6e738d;z-index:2}html.theme--catppuccin-macchiato .tabs.is-toggle li+li{margin-left:-1px}html.theme--catppuccin-macchiato .tabs.is-toggle li:first-child a{border-top-left-radius:.4em;border-bottom-left-radius:.4em}html.theme--catppuccin-macchiato .tabs.is-toggle li:last-child a{border-top-right-radius:.4em;border-bottom-right-radius:.4em}html.theme--catppuccin-macchiato .tabs.is-toggle li.is-active a{background-color:#8aadf4;border-color:#8aadf4;color:#fff;z-index:1}html.theme--catppuccin-macchiato .tabs.is-toggle ul{border-bottom:none}html.theme--catppuccin-macchiato .tabs.is-toggle.is-toggle-rounded li:first-child a{border-bottom-left-radius:9999px;border-top-left-radius:9999px;padding-left:1.25em}html.theme--catppuccin-macchiato .tabs.is-toggle.is-toggle-rounded li:last-child a{border-bottom-right-radius:9999px;border-top-right-radius:9999px;padding-right:1.25em}html.theme--catppuccin-macchiato .tabs.is-small,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.tabs{font-size:.75rem}html.theme--catppuccin-macchiato .tabs.is-medium{font-size:1.25rem}html.theme--catppuccin-macchiato .tabs.is-large{font-size:1.5rem}html.theme--catppuccin-macchiato .column{display:block;flex-basis:0;flex-grow:1;flex-shrink:1;padding:.75rem}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-narrow{flex:none;width:unset}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-full{flex:none;width:100%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-three-quarters{flex:none;width:75%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-two-thirds{flex:none;width:66.6666%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-half{flex:none;width:50%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-one-third{flex:none;width:33.3333%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-one-quarter{flex:none;width:25%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-one-fifth{flex:none;width:20%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-two-fifths{flex:none;width:40%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-three-fifths{flex:none;width:60%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-four-fifths{flex:none;width:80%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-three-quarters{margin-left:75%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-two-thirds{margin-left:66.6666%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-half{margin-left:50%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-one-third{margin-left:33.3333%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-one-quarter{margin-left:25%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-one-fifth{margin-left:20%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-two-fifths{margin-left:40%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-three-fifths{margin-left:60%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-four-fifths{margin-left:80%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-0{flex:none;width:0%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-0{margin-left:0%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-1{flex:none;width:8.33333337%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-1{margin-left:8.33333337%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-2{flex:none;width:16.66666674%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-2{margin-left:16.66666674%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-3{flex:none;width:25%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-3{margin-left:25%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-4{flex:none;width:33.33333337%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-4{margin-left:33.33333337%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-5{flex:none;width:41.66666674%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-5{margin-left:41.66666674%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-6{flex:none;width:50%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-6{margin-left:50%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-7{flex:none;width:58.33333337%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-7{margin-left:58.33333337%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-8{flex:none;width:66.66666674%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-8{margin-left:66.66666674%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-9{flex:none;width:75%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-9{margin-left:75%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-10{flex:none;width:83.33333337%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-10{margin-left:83.33333337%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-11{flex:none;width:91.66666674%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-11{margin-left:91.66666674%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-12{flex:none;width:100%}.columns.is-mobile>html.theme--catppuccin-macchiato .column.is-offset-12{margin-left:100%}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .column.is-narrow-mobile{flex:none;width:unset}html.theme--catppuccin-macchiato .column.is-full-mobile{flex:none;width:100%}html.theme--catppuccin-macchiato .column.is-three-quarters-mobile{flex:none;width:75%}html.theme--catppuccin-macchiato .column.is-two-thirds-mobile{flex:none;width:66.6666%}html.theme--catppuccin-macchiato .column.is-half-mobile{flex:none;width:50%}html.theme--catppuccin-macchiato .column.is-one-third-mobile{flex:none;width:33.3333%}html.theme--catppuccin-macchiato .column.is-one-quarter-mobile{flex:none;width:25%}html.theme--catppuccin-macchiato .column.is-one-fifth-mobile{flex:none;width:20%}html.theme--catppuccin-macchiato .column.is-two-fifths-mobile{flex:none;width:40%}html.theme--catppuccin-macchiato .column.is-three-fifths-mobile{flex:none;width:60%}html.theme--catppuccin-macchiato .column.is-four-fifths-mobile{flex:none;width:80%}html.theme--catppuccin-macchiato .column.is-offset-three-quarters-mobile{margin-left:75%}html.theme--catppuccin-macchiato .column.is-offset-two-thirds-mobile{margin-left:66.6666%}html.theme--catppuccin-macchiato .column.is-offset-half-mobile{margin-left:50%}html.theme--catppuccin-macchiato .column.is-offset-one-third-mobile{margin-left:33.3333%}html.theme--catppuccin-macchiato .column.is-offset-one-quarter-mobile{margin-left:25%}html.theme--catppuccin-macchiato .column.is-offset-one-fifth-mobile{margin-left:20%}html.theme--catppuccin-macchiato .column.is-offset-two-fifths-mobile{margin-left:40%}html.theme--catppuccin-macchiato .column.is-offset-three-fifths-mobile{margin-left:60%}html.theme--catppuccin-macchiato .column.is-offset-four-fifths-mobile{margin-left:80%}html.theme--catppuccin-macchiato .column.is-0-mobile{flex:none;width:0%}html.theme--catppuccin-macchiato .column.is-offset-0-mobile{margin-left:0%}html.theme--catppuccin-macchiato .column.is-1-mobile{flex:none;width:8.33333337%}html.theme--catppuccin-macchiato .column.is-offset-1-mobile{margin-left:8.33333337%}html.theme--catppuccin-macchiato .column.is-2-mobile{flex:none;width:16.66666674%}html.theme--catppuccin-macchiato .column.is-offset-2-mobile{margin-left:16.66666674%}html.theme--catppuccin-macchiato .column.is-3-mobile{flex:none;width:25%}html.theme--catppuccin-macchiato .column.is-offset-3-mobile{margin-left:25%}html.theme--catppuccin-macchiato .column.is-4-mobile{flex:none;width:33.33333337%}html.theme--catppuccin-macchiato .column.is-offset-4-mobile{margin-left:33.33333337%}html.theme--catppuccin-macchiato .column.is-5-mobile{flex:none;width:41.66666674%}html.theme--catppuccin-macchiato .column.is-offset-5-mobile{margin-left:41.66666674%}html.theme--catppuccin-macchiato .column.is-6-mobile{flex:none;width:50%}html.theme--catppuccin-macchiato .column.is-offset-6-mobile{margin-left:50%}html.theme--catppuccin-macchiato .column.is-7-mobile{flex:none;width:58.33333337%}html.theme--catppuccin-macchiato .column.is-offset-7-mobile{margin-left:58.33333337%}html.theme--catppuccin-macchiato .column.is-8-mobile{flex:none;width:66.66666674%}html.theme--catppuccin-macchiato .column.is-offset-8-mobile{margin-left:66.66666674%}html.theme--catppuccin-macchiato .column.is-9-mobile{flex:none;width:75%}html.theme--catppuccin-macchiato .column.is-offset-9-mobile{margin-left:75%}html.theme--catppuccin-macchiato .column.is-10-mobile{flex:none;width:83.33333337%}html.theme--catppuccin-macchiato .column.is-offset-10-mobile{margin-left:83.33333337%}html.theme--catppuccin-macchiato .column.is-11-mobile{flex:none;width:91.66666674%}html.theme--catppuccin-macchiato .column.is-offset-11-mobile{margin-left:91.66666674%}html.theme--catppuccin-macchiato .column.is-12-mobile{flex:none;width:100%}html.theme--catppuccin-macchiato .column.is-offset-12-mobile{margin-left:100%}}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .column.is-narrow,html.theme--catppuccin-macchiato .column.is-narrow-tablet{flex:none;width:unset}html.theme--catppuccin-macchiato .column.is-full,html.theme--catppuccin-macchiato .column.is-full-tablet{flex:none;width:100%}html.theme--catppuccin-macchiato .column.is-three-quarters,html.theme--catppuccin-macchiato .column.is-three-quarters-tablet{flex:none;width:75%}html.theme--catppuccin-macchiato .column.is-two-thirds,html.theme--catppuccin-macchiato .column.is-two-thirds-tablet{flex:none;width:66.6666%}html.theme--catppuccin-macchiato .column.is-half,html.theme--catppuccin-macchiato .column.is-half-tablet{flex:none;width:50%}html.theme--catppuccin-macchiato .column.is-one-third,html.theme--catppuccin-macchiato .column.is-one-third-tablet{flex:none;width:33.3333%}html.theme--catppuccin-macchiato .column.is-one-quarter,html.theme--catppuccin-macchiato .column.is-one-quarter-tablet{flex:none;width:25%}html.theme--catppuccin-macchiato .column.is-one-fifth,html.theme--catppuccin-macchiato .column.is-one-fifth-tablet{flex:none;width:20%}html.theme--catppuccin-macchiato .column.is-two-fifths,html.theme--catppuccin-macchiato .column.is-two-fifths-tablet{flex:none;width:40%}html.theme--catppuccin-macchiato .column.is-three-fifths,html.theme--catppuccin-macchiato .column.is-three-fifths-tablet{flex:none;width:60%}html.theme--catppuccin-macchiato .column.is-four-fifths,html.theme--catppuccin-macchiato .column.is-four-fifths-tablet{flex:none;width:80%}html.theme--catppuccin-macchiato .column.is-offset-three-quarters,html.theme--catppuccin-macchiato .column.is-offset-three-quarters-tablet{margin-left:75%}html.theme--catppuccin-macchiato .column.is-offset-two-thirds,html.theme--catppuccin-macchiato .column.is-offset-two-thirds-tablet{margin-left:66.6666%}html.theme--catppuccin-macchiato .column.is-offset-half,html.theme--catppuccin-macchiato .column.is-offset-half-tablet{margin-left:50%}html.theme--catppuccin-macchiato .column.is-offset-one-third,html.theme--catppuccin-macchiato .column.is-offset-one-third-tablet{margin-left:33.3333%}html.theme--catppuccin-macchiato .column.is-offset-one-quarter,html.theme--catppuccin-macchiato .column.is-offset-one-quarter-tablet{margin-left:25%}html.theme--catppuccin-macchiato .column.is-offset-one-fifth,html.theme--catppuccin-macchiato .column.is-offset-one-fifth-tablet{margin-left:20%}html.theme--catppuccin-macchiato .column.is-offset-two-fifths,html.theme--catppuccin-macchiato .column.is-offset-two-fifths-tablet{margin-left:40%}html.theme--catppuccin-macchiato .column.is-offset-three-fifths,html.theme--catppuccin-macchiato .column.is-offset-three-fifths-tablet{margin-left:60%}html.theme--catppuccin-macchiato .column.is-offset-four-fifths,html.theme--catppuccin-macchiato .column.is-offset-four-fifths-tablet{margin-left:80%}html.theme--catppuccin-macchiato .column.is-0,html.theme--catppuccin-macchiato .column.is-0-tablet{flex:none;width:0%}html.theme--catppuccin-macchiato .column.is-offset-0,html.theme--catppuccin-macchiato .column.is-offset-0-tablet{margin-left:0%}html.theme--catppuccin-macchiato .column.is-1,html.theme--catppuccin-macchiato .column.is-1-tablet{flex:none;width:8.33333337%}html.theme--catppuccin-macchiato .column.is-offset-1,html.theme--catppuccin-macchiato .column.is-offset-1-tablet{margin-left:8.33333337%}html.theme--catppuccin-macchiato .column.is-2,html.theme--catppuccin-macchiato .column.is-2-tablet{flex:none;width:16.66666674%}html.theme--catppuccin-macchiato .column.is-offset-2,html.theme--catppuccin-macchiato .column.is-offset-2-tablet{margin-left:16.66666674%}html.theme--catppuccin-macchiato .column.is-3,html.theme--catppuccin-macchiato .column.is-3-tablet{flex:none;width:25%}html.theme--catppuccin-macchiato .column.is-offset-3,html.theme--catppuccin-macchiato .column.is-offset-3-tablet{margin-left:25%}html.theme--catppuccin-macchiato .column.is-4,html.theme--catppuccin-macchiato .column.is-4-tablet{flex:none;width:33.33333337%}html.theme--catppuccin-macchiato .column.is-offset-4,html.theme--catppuccin-macchiato .column.is-offset-4-tablet{margin-left:33.33333337%}html.theme--catppuccin-macchiato .column.is-5,html.theme--catppuccin-macchiato .column.is-5-tablet{flex:none;width:41.66666674%}html.theme--catppuccin-macchiato .column.is-offset-5,html.theme--catppuccin-macchiato .column.is-offset-5-tablet{margin-left:41.66666674%}html.theme--catppuccin-macchiato .column.is-6,html.theme--catppuccin-macchiato .column.is-6-tablet{flex:none;width:50%}html.theme--catppuccin-macchiato .column.is-offset-6,html.theme--catppuccin-macchiato .column.is-offset-6-tablet{margin-left:50%}html.theme--catppuccin-macchiato .column.is-7,html.theme--catppuccin-macchiato .column.is-7-tablet{flex:none;width:58.33333337%}html.theme--catppuccin-macchiato .column.is-offset-7,html.theme--catppuccin-macchiato .column.is-offset-7-tablet{margin-left:58.33333337%}html.theme--catppuccin-macchiato .column.is-8,html.theme--catppuccin-macchiato .column.is-8-tablet{flex:none;width:66.66666674%}html.theme--catppuccin-macchiato .column.is-offset-8,html.theme--catppuccin-macchiato .column.is-offset-8-tablet{margin-left:66.66666674%}html.theme--catppuccin-macchiato .column.is-9,html.theme--catppuccin-macchiato .column.is-9-tablet{flex:none;width:75%}html.theme--catppuccin-macchiato .column.is-offset-9,html.theme--catppuccin-macchiato .column.is-offset-9-tablet{margin-left:75%}html.theme--catppuccin-macchiato .column.is-10,html.theme--catppuccin-macchiato .column.is-10-tablet{flex:none;width:83.33333337%}html.theme--catppuccin-macchiato .column.is-offset-10,html.theme--catppuccin-macchiato .column.is-offset-10-tablet{margin-left:83.33333337%}html.theme--catppuccin-macchiato .column.is-11,html.theme--catppuccin-macchiato .column.is-11-tablet{flex:none;width:91.66666674%}html.theme--catppuccin-macchiato .column.is-offset-11,html.theme--catppuccin-macchiato .column.is-offset-11-tablet{margin-left:91.66666674%}html.theme--catppuccin-macchiato .column.is-12,html.theme--catppuccin-macchiato .column.is-12-tablet{flex:none;width:100%}html.theme--catppuccin-macchiato .column.is-offset-12,html.theme--catppuccin-macchiato .column.is-offset-12-tablet{margin-left:100%}}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .column.is-narrow-touch{flex:none;width:unset}html.theme--catppuccin-macchiato .column.is-full-touch{flex:none;width:100%}html.theme--catppuccin-macchiato .column.is-three-quarters-touch{flex:none;width:75%}html.theme--catppuccin-macchiato .column.is-two-thirds-touch{flex:none;width:66.6666%}html.theme--catppuccin-macchiato .column.is-half-touch{flex:none;width:50%}html.theme--catppuccin-macchiato .column.is-one-third-touch{flex:none;width:33.3333%}html.theme--catppuccin-macchiato .column.is-one-quarter-touch{flex:none;width:25%}html.theme--catppuccin-macchiato .column.is-one-fifth-touch{flex:none;width:20%}html.theme--catppuccin-macchiato .column.is-two-fifths-touch{flex:none;width:40%}html.theme--catppuccin-macchiato .column.is-three-fifths-touch{flex:none;width:60%}html.theme--catppuccin-macchiato .column.is-four-fifths-touch{flex:none;width:80%}html.theme--catppuccin-macchiato .column.is-offset-three-quarters-touch{margin-left:75%}html.theme--catppuccin-macchiato .column.is-offset-two-thirds-touch{margin-left:66.6666%}html.theme--catppuccin-macchiato .column.is-offset-half-touch{margin-left:50%}html.theme--catppuccin-macchiato .column.is-offset-one-third-touch{margin-left:33.3333%}html.theme--catppuccin-macchiato .column.is-offset-one-quarter-touch{margin-left:25%}html.theme--catppuccin-macchiato .column.is-offset-one-fifth-touch{margin-left:20%}html.theme--catppuccin-macchiato .column.is-offset-two-fifths-touch{margin-left:40%}html.theme--catppuccin-macchiato .column.is-offset-three-fifths-touch{margin-left:60%}html.theme--catppuccin-macchiato .column.is-offset-four-fifths-touch{margin-left:80%}html.theme--catppuccin-macchiato .column.is-0-touch{flex:none;width:0%}html.theme--catppuccin-macchiato .column.is-offset-0-touch{margin-left:0%}html.theme--catppuccin-macchiato .column.is-1-touch{flex:none;width:8.33333337%}html.theme--catppuccin-macchiato .column.is-offset-1-touch{margin-left:8.33333337%}html.theme--catppuccin-macchiato .column.is-2-touch{flex:none;width:16.66666674%}html.theme--catppuccin-macchiato .column.is-offset-2-touch{margin-left:16.66666674%}html.theme--catppuccin-macchiato .column.is-3-touch{flex:none;width:25%}html.theme--catppuccin-macchiato .column.is-offset-3-touch{margin-left:25%}html.theme--catppuccin-macchiato .column.is-4-touch{flex:none;width:33.33333337%}html.theme--catppuccin-macchiato .column.is-offset-4-touch{margin-left:33.33333337%}html.theme--catppuccin-macchiato .column.is-5-touch{flex:none;width:41.66666674%}html.theme--catppuccin-macchiato .column.is-offset-5-touch{margin-left:41.66666674%}html.theme--catppuccin-macchiato .column.is-6-touch{flex:none;width:50%}html.theme--catppuccin-macchiato .column.is-offset-6-touch{margin-left:50%}html.theme--catppuccin-macchiato .column.is-7-touch{flex:none;width:58.33333337%}html.theme--catppuccin-macchiato .column.is-offset-7-touch{margin-left:58.33333337%}html.theme--catppuccin-macchiato .column.is-8-touch{flex:none;width:66.66666674%}html.theme--catppuccin-macchiato .column.is-offset-8-touch{margin-left:66.66666674%}html.theme--catppuccin-macchiato .column.is-9-touch{flex:none;width:75%}html.theme--catppuccin-macchiato .column.is-offset-9-touch{margin-left:75%}html.theme--catppuccin-macchiato .column.is-10-touch{flex:none;width:83.33333337%}html.theme--catppuccin-macchiato .column.is-offset-10-touch{margin-left:83.33333337%}html.theme--catppuccin-macchiato .column.is-11-touch{flex:none;width:91.66666674%}html.theme--catppuccin-macchiato .column.is-offset-11-touch{margin-left:91.66666674%}html.theme--catppuccin-macchiato .column.is-12-touch{flex:none;width:100%}html.theme--catppuccin-macchiato .column.is-offset-12-touch{margin-left:100%}}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .column.is-narrow-desktop{flex:none;width:unset}html.theme--catppuccin-macchiato .column.is-full-desktop{flex:none;width:100%}html.theme--catppuccin-macchiato .column.is-three-quarters-desktop{flex:none;width:75%}html.theme--catppuccin-macchiato .column.is-two-thirds-desktop{flex:none;width:66.6666%}html.theme--catppuccin-macchiato .column.is-half-desktop{flex:none;width:50%}html.theme--catppuccin-macchiato .column.is-one-third-desktop{flex:none;width:33.3333%}html.theme--catppuccin-macchiato .column.is-one-quarter-desktop{flex:none;width:25%}html.theme--catppuccin-macchiato .column.is-one-fifth-desktop{flex:none;width:20%}html.theme--catppuccin-macchiato .column.is-two-fifths-desktop{flex:none;width:40%}html.theme--catppuccin-macchiato .column.is-three-fifths-desktop{flex:none;width:60%}html.theme--catppuccin-macchiato .column.is-four-fifths-desktop{flex:none;width:80%}html.theme--catppuccin-macchiato .column.is-offset-three-quarters-desktop{margin-left:75%}html.theme--catppuccin-macchiato .column.is-offset-two-thirds-desktop{margin-left:66.6666%}html.theme--catppuccin-macchiato .column.is-offset-half-desktop{margin-left:50%}html.theme--catppuccin-macchiato .column.is-offset-one-third-desktop{margin-left:33.3333%}html.theme--catppuccin-macchiato .column.is-offset-one-quarter-desktop{margin-left:25%}html.theme--catppuccin-macchiato .column.is-offset-one-fifth-desktop{margin-left:20%}html.theme--catppuccin-macchiato .column.is-offset-two-fifths-desktop{margin-left:40%}html.theme--catppuccin-macchiato .column.is-offset-three-fifths-desktop{margin-left:60%}html.theme--catppuccin-macchiato .column.is-offset-four-fifths-desktop{margin-left:80%}html.theme--catppuccin-macchiato .column.is-0-desktop{flex:none;width:0%}html.theme--catppuccin-macchiato .column.is-offset-0-desktop{margin-left:0%}html.theme--catppuccin-macchiato .column.is-1-desktop{flex:none;width:8.33333337%}html.theme--catppuccin-macchiato .column.is-offset-1-desktop{margin-left:8.33333337%}html.theme--catppuccin-macchiato .column.is-2-desktop{flex:none;width:16.66666674%}html.theme--catppuccin-macchiato .column.is-offset-2-desktop{margin-left:16.66666674%}html.theme--catppuccin-macchiato .column.is-3-desktop{flex:none;width:25%}html.theme--catppuccin-macchiato .column.is-offset-3-desktop{margin-left:25%}html.theme--catppuccin-macchiato .column.is-4-desktop{flex:none;width:33.33333337%}html.theme--catppuccin-macchiato .column.is-offset-4-desktop{margin-left:33.33333337%}html.theme--catppuccin-macchiato .column.is-5-desktop{flex:none;width:41.66666674%}html.theme--catppuccin-macchiato .column.is-offset-5-desktop{margin-left:41.66666674%}html.theme--catppuccin-macchiato .column.is-6-desktop{flex:none;width:50%}html.theme--catppuccin-macchiato .column.is-offset-6-desktop{margin-left:50%}html.theme--catppuccin-macchiato .column.is-7-desktop{flex:none;width:58.33333337%}html.theme--catppuccin-macchiato .column.is-offset-7-desktop{margin-left:58.33333337%}html.theme--catppuccin-macchiato .column.is-8-desktop{flex:none;width:66.66666674%}html.theme--catppuccin-macchiato .column.is-offset-8-desktop{margin-left:66.66666674%}html.theme--catppuccin-macchiato .column.is-9-desktop{flex:none;width:75%}html.theme--catppuccin-macchiato .column.is-offset-9-desktop{margin-left:75%}html.theme--catppuccin-macchiato .column.is-10-desktop{flex:none;width:83.33333337%}html.theme--catppuccin-macchiato .column.is-offset-10-desktop{margin-left:83.33333337%}html.theme--catppuccin-macchiato .column.is-11-desktop{flex:none;width:91.66666674%}html.theme--catppuccin-macchiato .column.is-offset-11-desktop{margin-left:91.66666674%}html.theme--catppuccin-macchiato .column.is-12-desktop{flex:none;width:100%}html.theme--catppuccin-macchiato .column.is-offset-12-desktop{margin-left:100%}}@media screen and (min-width: 1216px){html.theme--catppuccin-macchiato .column.is-narrow-widescreen{flex:none;width:unset}html.theme--catppuccin-macchiato .column.is-full-widescreen{flex:none;width:100%}html.theme--catppuccin-macchiato .column.is-three-quarters-widescreen{flex:none;width:75%}html.theme--catppuccin-macchiato .column.is-two-thirds-widescreen{flex:none;width:66.6666%}html.theme--catppuccin-macchiato .column.is-half-widescreen{flex:none;width:50%}html.theme--catppuccin-macchiato .column.is-one-third-widescreen{flex:none;width:33.3333%}html.theme--catppuccin-macchiato .column.is-one-quarter-widescreen{flex:none;width:25%}html.theme--catppuccin-macchiato .column.is-one-fifth-widescreen{flex:none;width:20%}html.theme--catppuccin-macchiato .column.is-two-fifths-widescreen{flex:none;width:40%}html.theme--catppuccin-macchiato .column.is-three-fifths-widescreen{flex:none;width:60%}html.theme--catppuccin-macchiato .column.is-four-fifths-widescreen{flex:none;width:80%}html.theme--catppuccin-macchiato .column.is-offset-three-quarters-widescreen{margin-left:75%}html.theme--catppuccin-macchiato .column.is-offset-two-thirds-widescreen{margin-left:66.6666%}html.theme--catppuccin-macchiato .column.is-offset-half-widescreen{margin-left:50%}html.theme--catppuccin-macchiato .column.is-offset-one-third-widescreen{margin-left:33.3333%}html.theme--catppuccin-macchiato .column.is-offset-one-quarter-widescreen{margin-left:25%}html.theme--catppuccin-macchiato .column.is-offset-one-fifth-widescreen{margin-left:20%}html.theme--catppuccin-macchiato .column.is-offset-two-fifths-widescreen{margin-left:40%}html.theme--catppuccin-macchiato .column.is-offset-three-fifths-widescreen{margin-left:60%}html.theme--catppuccin-macchiato .column.is-offset-four-fifths-widescreen{margin-left:80%}html.theme--catppuccin-macchiato .column.is-0-widescreen{flex:none;width:0%}html.theme--catppuccin-macchiato .column.is-offset-0-widescreen{margin-left:0%}html.theme--catppuccin-macchiato .column.is-1-widescreen{flex:none;width:8.33333337%}html.theme--catppuccin-macchiato .column.is-offset-1-widescreen{margin-left:8.33333337%}html.theme--catppuccin-macchiato .column.is-2-widescreen{flex:none;width:16.66666674%}html.theme--catppuccin-macchiato .column.is-offset-2-widescreen{margin-left:16.66666674%}html.theme--catppuccin-macchiato .column.is-3-widescreen{flex:none;width:25%}html.theme--catppuccin-macchiato .column.is-offset-3-widescreen{margin-left:25%}html.theme--catppuccin-macchiato .column.is-4-widescreen{flex:none;width:33.33333337%}html.theme--catppuccin-macchiato .column.is-offset-4-widescreen{margin-left:33.33333337%}html.theme--catppuccin-macchiato .column.is-5-widescreen{flex:none;width:41.66666674%}html.theme--catppuccin-macchiato .column.is-offset-5-widescreen{margin-left:41.66666674%}html.theme--catppuccin-macchiato .column.is-6-widescreen{flex:none;width:50%}html.theme--catppuccin-macchiato .column.is-offset-6-widescreen{margin-left:50%}html.theme--catppuccin-macchiato .column.is-7-widescreen{flex:none;width:58.33333337%}html.theme--catppuccin-macchiato .column.is-offset-7-widescreen{margin-left:58.33333337%}html.theme--catppuccin-macchiato .column.is-8-widescreen{flex:none;width:66.66666674%}html.theme--catppuccin-macchiato .column.is-offset-8-widescreen{margin-left:66.66666674%}html.theme--catppuccin-macchiato .column.is-9-widescreen{flex:none;width:75%}html.theme--catppuccin-macchiato .column.is-offset-9-widescreen{margin-left:75%}html.theme--catppuccin-macchiato .column.is-10-widescreen{flex:none;width:83.33333337%}html.theme--catppuccin-macchiato .column.is-offset-10-widescreen{margin-left:83.33333337%}html.theme--catppuccin-macchiato .column.is-11-widescreen{flex:none;width:91.66666674%}html.theme--catppuccin-macchiato .column.is-offset-11-widescreen{margin-left:91.66666674%}html.theme--catppuccin-macchiato .column.is-12-widescreen{flex:none;width:100%}html.theme--catppuccin-macchiato .column.is-offset-12-widescreen{margin-left:100%}}@media screen and (min-width: 1408px){html.theme--catppuccin-macchiato .column.is-narrow-fullhd{flex:none;width:unset}html.theme--catppuccin-macchiato .column.is-full-fullhd{flex:none;width:100%}html.theme--catppuccin-macchiato .column.is-three-quarters-fullhd{flex:none;width:75%}html.theme--catppuccin-macchiato .column.is-two-thirds-fullhd{flex:none;width:66.6666%}html.theme--catppuccin-macchiato .column.is-half-fullhd{flex:none;width:50%}html.theme--catppuccin-macchiato .column.is-one-third-fullhd{flex:none;width:33.3333%}html.theme--catppuccin-macchiato .column.is-one-quarter-fullhd{flex:none;width:25%}html.theme--catppuccin-macchiato .column.is-one-fifth-fullhd{flex:none;width:20%}html.theme--catppuccin-macchiato .column.is-two-fifths-fullhd{flex:none;width:40%}html.theme--catppuccin-macchiato .column.is-three-fifths-fullhd{flex:none;width:60%}html.theme--catppuccin-macchiato .column.is-four-fifths-fullhd{flex:none;width:80%}html.theme--catppuccin-macchiato .column.is-offset-three-quarters-fullhd{margin-left:75%}html.theme--catppuccin-macchiato .column.is-offset-two-thirds-fullhd{margin-left:66.6666%}html.theme--catppuccin-macchiato .column.is-offset-half-fullhd{margin-left:50%}html.theme--catppuccin-macchiato .column.is-offset-one-third-fullhd{margin-left:33.3333%}html.theme--catppuccin-macchiato .column.is-offset-one-quarter-fullhd{margin-left:25%}html.theme--catppuccin-macchiato .column.is-offset-one-fifth-fullhd{margin-left:20%}html.theme--catppuccin-macchiato .column.is-offset-two-fifths-fullhd{margin-left:40%}html.theme--catppuccin-macchiato .column.is-offset-three-fifths-fullhd{margin-left:60%}html.theme--catppuccin-macchiato .column.is-offset-four-fifths-fullhd{margin-left:80%}html.theme--catppuccin-macchiato .column.is-0-fullhd{flex:none;width:0%}html.theme--catppuccin-macchiato .column.is-offset-0-fullhd{margin-left:0%}html.theme--catppuccin-macchiato .column.is-1-fullhd{flex:none;width:8.33333337%}html.theme--catppuccin-macchiato .column.is-offset-1-fullhd{margin-left:8.33333337%}html.theme--catppuccin-macchiato .column.is-2-fullhd{flex:none;width:16.66666674%}html.theme--catppuccin-macchiato .column.is-offset-2-fullhd{margin-left:16.66666674%}html.theme--catppuccin-macchiato .column.is-3-fullhd{flex:none;width:25%}html.theme--catppuccin-macchiato .column.is-offset-3-fullhd{margin-left:25%}html.theme--catppuccin-macchiato .column.is-4-fullhd{flex:none;width:33.33333337%}html.theme--catppuccin-macchiato .column.is-offset-4-fullhd{margin-left:33.33333337%}html.theme--catppuccin-macchiato .column.is-5-fullhd{flex:none;width:41.66666674%}html.theme--catppuccin-macchiato .column.is-offset-5-fullhd{margin-left:41.66666674%}html.theme--catppuccin-macchiato .column.is-6-fullhd{flex:none;width:50%}html.theme--catppuccin-macchiato .column.is-offset-6-fullhd{margin-left:50%}html.theme--catppuccin-macchiato .column.is-7-fullhd{flex:none;width:58.33333337%}html.theme--catppuccin-macchiato .column.is-offset-7-fullhd{margin-left:58.33333337%}html.theme--catppuccin-macchiato .column.is-8-fullhd{flex:none;width:66.66666674%}html.theme--catppuccin-macchiato .column.is-offset-8-fullhd{margin-left:66.66666674%}html.theme--catppuccin-macchiato .column.is-9-fullhd{flex:none;width:75%}html.theme--catppuccin-macchiato .column.is-offset-9-fullhd{margin-left:75%}html.theme--catppuccin-macchiato .column.is-10-fullhd{flex:none;width:83.33333337%}html.theme--catppuccin-macchiato .column.is-offset-10-fullhd{margin-left:83.33333337%}html.theme--catppuccin-macchiato .column.is-11-fullhd{flex:none;width:91.66666674%}html.theme--catppuccin-macchiato .column.is-offset-11-fullhd{margin-left:91.66666674%}html.theme--catppuccin-macchiato .column.is-12-fullhd{flex:none;width:100%}html.theme--catppuccin-macchiato .column.is-offset-12-fullhd{margin-left:100%}}html.theme--catppuccin-macchiato .columns{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--catppuccin-macchiato .columns:last-child{margin-bottom:-.75rem}html.theme--catppuccin-macchiato .columns:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}html.theme--catppuccin-macchiato .columns.is-centered{justify-content:center}html.theme--catppuccin-macchiato .columns.is-gapless{margin-left:0;margin-right:0;margin-top:0}html.theme--catppuccin-macchiato .columns.is-gapless>.column{margin:0;padding:0 !important}html.theme--catppuccin-macchiato .columns.is-gapless:not(:last-child){margin-bottom:1.5rem}html.theme--catppuccin-macchiato .columns.is-gapless:last-child{margin-bottom:0}html.theme--catppuccin-macchiato .columns.is-mobile{display:flex}html.theme--catppuccin-macchiato .columns.is-multiline{flex-wrap:wrap}html.theme--catppuccin-macchiato .columns.is-vcentered{align-items:center}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .columns:not(.is-desktop){display:flex}}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .columns.is-desktop{display:flex}}html.theme--catppuccin-macchiato .columns.is-variable{--columnGap: 0.75rem;margin-left:calc(-1 * var(--columnGap));margin-right:calc(-1 * var(--columnGap))}html.theme--catppuccin-macchiato .columns.is-variable>.column{padding-left:var(--columnGap);padding-right:var(--columnGap)}html.theme--catppuccin-macchiato .columns.is-variable.is-0{--columnGap: 0rem}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .columns.is-variable.is-0-mobile{--columnGap: 0rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .columns.is-variable.is-0-tablet{--columnGap: 0rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-macchiato .columns.is-variable.is-0-tablet-only{--columnGap: 0rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .columns.is-variable.is-0-touch{--columnGap: 0rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .columns.is-variable.is-0-desktop{--columnGap: 0rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-macchiato .columns.is-variable.is-0-desktop-only{--columnGap: 0rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-macchiato .columns.is-variable.is-0-widescreen{--columnGap: 0rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-macchiato .columns.is-variable.is-0-widescreen-only{--columnGap: 0rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-macchiato .columns.is-variable.is-0-fullhd{--columnGap: 0rem}}html.theme--catppuccin-macchiato .columns.is-variable.is-1{--columnGap: .25rem}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .columns.is-variable.is-1-mobile{--columnGap: .25rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .columns.is-variable.is-1-tablet{--columnGap: .25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-macchiato .columns.is-variable.is-1-tablet-only{--columnGap: .25rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .columns.is-variable.is-1-touch{--columnGap: .25rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .columns.is-variable.is-1-desktop{--columnGap: .25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-macchiato .columns.is-variable.is-1-desktop-only{--columnGap: .25rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-macchiato .columns.is-variable.is-1-widescreen{--columnGap: .25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-macchiato .columns.is-variable.is-1-widescreen-only{--columnGap: .25rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-macchiato .columns.is-variable.is-1-fullhd{--columnGap: .25rem}}html.theme--catppuccin-macchiato .columns.is-variable.is-2{--columnGap: .5rem}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .columns.is-variable.is-2-mobile{--columnGap: .5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .columns.is-variable.is-2-tablet{--columnGap: .5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-macchiato .columns.is-variable.is-2-tablet-only{--columnGap: .5rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .columns.is-variable.is-2-touch{--columnGap: .5rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .columns.is-variable.is-2-desktop{--columnGap: .5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-macchiato .columns.is-variable.is-2-desktop-only{--columnGap: .5rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-macchiato .columns.is-variable.is-2-widescreen{--columnGap: .5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-macchiato .columns.is-variable.is-2-widescreen-only{--columnGap: .5rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-macchiato .columns.is-variable.is-2-fullhd{--columnGap: .5rem}}html.theme--catppuccin-macchiato .columns.is-variable.is-3{--columnGap: .75rem}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .columns.is-variable.is-3-mobile{--columnGap: .75rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .columns.is-variable.is-3-tablet{--columnGap: .75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-macchiato .columns.is-variable.is-3-tablet-only{--columnGap: .75rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .columns.is-variable.is-3-touch{--columnGap: .75rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .columns.is-variable.is-3-desktop{--columnGap: .75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-macchiato .columns.is-variable.is-3-desktop-only{--columnGap: .75rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-macchiato .columns.is-variable.is-3-widescreen{--columnGap: .75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-macchiato .columns.is-variable.is-3-widescreen-only{--columnGap: .75rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-macchiato .columns.is-variable.is-3-fullhd{--columnGap: .75rem}}html.theme--catppuccin-macchiato .columns.is-variable.is-4{--columnGap: 1rem}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .columns.is-variable.is-4-mobile{--columnGap: 1rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .columns.is-variable.is-4-tablet{--columnGap: 1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-macchiato .columns.is-variable.is-4-tablet-only{--columnGap: 1rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .columns.is-variable.is-4-touch{--columnGap: 1rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .columns.is-variable.is-4-desktop{--columnGap: 1rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-macchiato .columns.is-variable.is-4-desktop-only{--columnGap: 1rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-macchiato .columns.is-variable.is-4-widescreen{--columnGap: 1rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-macchiato .columns.is-variable.is-4-widescreen-only{--columnGap: 1rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-macchiato .columns.is-variable.is-4-fullhd{--columnGap: 1rem}}html.theme--catppuccin-macchiato .columns.is-variable.is-5{--columnGap: 1.25rem}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .columns.is-variable.is-5-mobile{--columnGap: 1.25rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .columns.is-variable.is-5-tablet{--columnGap: 1.25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-macchiato .columns.is-variable.is-5-tablet-only{--columnGap: 1.25rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .columns.is-variable.is-5-touch{--columnGap: 1.25rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .columns.is-variable.is-5-desktop{--columnGap: 1.25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-macchiato .columns.is-variable.is-5-desktop-only{--columnGap: 1.25rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-macchiato .columns.is-variable.is-5-widescreen{--columnGap: 1.25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-macchiato .columns.is-variable.is-5-widescreen-only{--columnGap: 1.25rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-macchiato .columns.is-variable.is-5-fullhd{--columnGap: 1.25rem}}html.theme--catppuccin-macchiato .columns.is-variable.is-6{--columnGap: 1.5rem}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .columns.is-variable.is-6-mobile{--columnGap: 1.5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .columns.is-variable.is-6-tablet{--columnGap: 1.5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-macchiato .columns.is-variable.is-6-tablet-only{--columnGap: 1.5rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .columns.is-variable.is-6-touch{--columnGap: 1.5rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .columns.is-variable.is-6-desktop{--columnGap: 1.5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-macchiato .columns.is-variable.is-6-desktop-only{--columnGap: 1.5rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-macchiato .columns.is-variable.is-6-widescreen{--columnGap: 1.5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-macchiato .columns.is-variable.is-6-widescreen-only{--columnGap: 1.5rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-macchiato .columns.is-variable.is-6-fullhd{--columnGap: 1.5rem}}html.theme--catppuccin-macchiato .columns.is-variable.is-7{--columnGap: 1.75rem}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .columns.is-variable.is-7-mobile{--columnGap: 1.75rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .columns.is-variable.is-7-tablet{--columnGap: 1.75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-macchiato .columns.is-variable.is-7-tablet-only{--columnGap: 1.75rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .columns.is-variable.is-7-touch{--columnGap: 1.75rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .columns.is-variable.is-7-desktop{--columnGap: 1.75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-macchiato .columns.is-variable.is-7-desktop-only{--columnGap: 1.75rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-macchiato .columns.is-variable.is-7-widescreen{--columnGap: 1.75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-macchiato .columns.is-variable.is-7-widescreen-only{--columnGap: 1.75rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-macchiato .columns.is-variable.is-7-fullhd{--columnGap: 1.75rem}}html.theme--catppuccin-macchiato .columns.is-variable.is-8{--columnGap: 2rem}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .columns.is-variable.is-8-mobile{--columnGap: 2rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .columns.is-variable.is-8-tablet{--columnGap: 2rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-macchiato .columns.is-variable.is-8-tablet-only{--columnGap: 2rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .columns.is-variable.is-8-touch{--columnGap: 2rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .columns.is-variable.is-8-desktop{--columnGap: 2rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-macchiato .columns.is-variable.is-8-desktop-only{--columnGap: 2rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-macchiato .columns.is-variable.is-8-widescreen{--columnGap: 2rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-macchiato .columns.is-variable.is-8-widescreen-only{--columnGap: 2rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-macchiato .columns.is-variable.is-8-fullhd{--columnGap: 2rem}}html.theme--catppuccin-macchiato .tile{align-items:stretch;display:block;flex-basis:0;flex-grow:1;flex-shrink:1;min-height:min-content}html.theme--catppuccin-macchiato .tile.is-ancestor{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--catppuccin-macchiato .tile.is-ancestor:last-child{margin-bottom:-.75rem}html.theme--catppuccin-macchiato .tile.is-ancestor:not(:last-child){margin-bottom:.75rem}html.theme--catppuccin-macchiato .tile.is-child{margin:0 !important}html.theme--catppuccin-macchiato .tile.is-parent{padding:.75rem}html.theme--catppuccin-macchiato .tile.is-vertical{flex-direction:column}html.theme--catppuccin-macchiato .tile.is-vertical>.tile.is-child:not(:last-child){margin-bottom:1.5rem !important}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .tile:not(.is-child){display:flex}html.theme--catppuccin-macchiato .tile.is-1{flex:none;width:8.33333337%}html.theme--catppuccin-macchiato .tile.is-2{flex:none;width:16.66666674%}html.theme--catppuccin-macchiato .tile.is-3{flex:none;width:25%}html.theme--catppuccin-macchiato .tile.is-4{flex:none;width:33.33333337%}html.theme--catppuccin-macchiato .tile.is-5{flex:none;width:41.66666674%}html.theme--catppuccin-macchiato .tile.is-6{flex:none;width:50%}html.theme--catppuccin-macchiato .tile.is-7{flex:none;width:58.33333337%}html.theme--catppuccin-macchiato .tile.is-8{flex:none;width:66.66666674%}html.theme--catppuccin-macchiato .tile.is-9{flex:none;width:75%}html.theme--catppuccin-macchiato .tile.is-10{flex:none;width:83.33333337%}html.theme--catppuccin-macchiato .tile.is-11{flex:none;width:91.66666674%}html.theme--catppuccin-macchiato .tile.is-12{flex:none;width:100%}}html.theme--catppuccin-macchiato .hero{align-items:stretch;display:flex;flex-direction:column;justify-content:space-between}html.theme--catppuccin-macchiato .hero .navbar{background:none}html.theme--catppuccin-macchiato .hero .tabs ul{border-bottom:none}html.theme--catppuccin-macchiato .hero.is-white{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-macchiato .hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-macchiato .hero.is-white strong{color:inherit}html.theme--catppuccin-macchiato .hero.is-white .title{color:#0a0a0a}html.theme--catppuccin-macchiato .hero.is-white .subtitle{color:rgba(10,10,10,0.9)}html.theme--catppuccin-macchiato .hero.is-white .subtitle a:not(.button),html.theme--catppuccin-macchiato .hero.is-white .subtitle strong{color:#0a0a0a}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .hero.is-white .navbar-menu{background-color:#fff}}html.theme--catppuccin-macchiato .hero.is-white .navbar-item,html.theme--catppuccin-macchiato .hero.is-white .navbar-link{color:rgba(10,10,10,0.7)}html.theme--catppuccin-macchiato .hero.is-white a.navbar-item:hover,html.theme--catppuccin-macchiato .hero.is-white a.navbar-item.is-active,html.theme--catppuccin-macchiato .hero.is-white .navbar-link:hover,html.theme--catppuccin-macchiato .hero.is-white .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--catppuccin-macchiato .hero.is-white .tabs a{color:#0a0a0a;opacity:0.9}html.theme--catppuccin-macchiato .hero.is-white .tabs a:hover{opacity:1}html.theme--catppuccin-macchiato .hero.is-white .tabs li.is-active a{color:#fff !important;opacity:1}html.theme--catppuccin-macchiato .hero.is-white .tabs.is-boxed a,html.theme--catppuccin-macchiato .hero.is-white .tabs.is-toggle a{color:#0a0a0a}html.theme--catppuccin-macchiato .hero.is-white .tabs.is-boxed a:hover,html.theme--catppuccin-macchiato .hero.is-white .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-macchiato .hero.is-white .tabs.is-boxed li.is-active a,html.theme--catppuccin-macchiato .hero.is-white .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-macchiato .hero.is-white .tabs.is-toggle li.is-active a,html.theme--catppuccin-macchiato .hero.is-white .tabs.is-toggle li.is-active a:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--catppuccin-macchiato .hero.is-white.is-bold{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .hero.is-white.is-bold .navbar-menu{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}}html.theme--catppuccin-macchiato .hero.is-black{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-macchiato .hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-macchiato .hero.is-black strong{color:inherit}html.theme--catppuccin-macchiato .hero.is-black .title{color:#fff}html.theme--catppuccin-macchiato .hero.is-black .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-macchiato .hero.is-black .subtitle a:not(.button),html.theme--catppuccin-macchiato .hero.is-black .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .hero.is-black .navbar-menu{background-color:#0a0a0a}}html.theme--catppuccin-macchiato .hero.is-black .navbar-item,html.theme--catppuccin-macchiato .hero.is-black .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-macchiato .hero.is-black a.navbar-item:hover,html.theme--catppuccin-macchiato .hero.is-black a.navbar-item.is-active,html.theme--catppuccin-macchiato .hero.is-black .navbar-link:hover,html.theme--catppuccin-macchiato .hero.is-black .navbar-link.is-active{background-color:#000;color:#fff}html.theme--catppuccin-macchiato .hero.is-black .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-macchiato .hero.is-black .tabs a:hover{opacity:1}html.theme--catppuccin-macchiato .hero.is-black .tabs li.is-active a{color:#0a0a0a !important;opacity:1}html.theme--catppuccin-macchiato .hero.is-black .tabs.is-boxed a,html.theme--catppuccin-macchiato .hero.is-black .tabs.is-toggle a{color:#fff}html.theme--catppuccin-macchiato .hero.is-black .tabs.is-boxed a:hover,html.theme--catppuccin-macchiato .hero.is-black .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-macchiato .hero.is-black .tabs.is-boxed li.is-active a,html.theme--catppuccin-macchiato .hero.is-black .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-macchiato .hero.is-black .tabs.is-toggle li.is-active a,html.theme--catppuccin-macchiato .hero.is-black .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--catppuccin-macchiato .hero.is-black.is-bold{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .hero.is-black.is-bold .navbar-menu{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}}html.theme--catppuccin-macchiato .hero.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-macchiato .hero.is-light strong{color:inherit}html.theme--catppuccin-macchiato .hero.is-light .title{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-light .subtitle{color:rgba(0,0,0,0.9)}html.theme--catppuccin-macchiato .hero.is-light .subtitle a:not(.button),html.theme--catppuccin-macchiato .hero.is-light .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .hero.is-light .navbar-menu{background-color:#f5f5f5}}html.theme--catppuccin-macchiato .hero.is-light .navbar-item,html.theme--catppuccin-macchiato .hero.is-light .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-light a.navbar-item:hover,html.theme--catppuccin-macchiato .hero.is-light a.navbar-item.is-active,html.theme--catppuccin-macchiato .hero.is-light .navbar-link:hover,html.theme--catppuccin-macchiato .hero.is-light .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-light .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--catppuccin-macchiato .hero.is-light .tabs a:hover{opacity:1}html.theme--catppuccin-macchiato .hero.is-light .tabs li.is-active a{color:#f5f5f5 !important;opacity:1}html.theme--catppuccin-macchiato .hero.is-light .tabs.is-boxed a,html.theme--catppuccin-macchiato .hero.is-light .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-light .tabs.is-boxed a:hover,html.theme--catppuccin-macchiato .hero.is-light .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-macchiato .hero.is-light .tabs.is-boxed li.is-active a,html.theme--catppuccin-macchiato .hero.is-light .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-macchiato .hero.is-light .tabs.is-toggle li.is-active a,html.theme--catppuccin-macchiato .hero.is-light .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#f5f5f5}html.theme--catppuccin-macchiato .hero.is-light.is-bold{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .hero.is-light.is-bold .navbar-menu{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}}html.theme--catppuccin-macchiato .hero.is-dark,html.theme--catppuccin-macchiato .content kbd.hero{background-color:#363a4f;color:#fff}html.theme--catppuccin-macchiato .hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-macchiato .content kbd.hero a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-macchiato .hero.is-dark strong,html.theme--catppuccin-macchiato .content kbd.hero strong{color:inherit}html.theme--catppuccin-macchiato .hero.is-dark .title,html.theme--catppuccin-macchiato .content kbd.hero .title{color:#fff}html.theme--catppuccin-macchiato .hero.is-dark .subtitle,html.theme--catppuccin-macchiato .content kbd.hero .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-macchiato .hero.is-dark .subtitle a:not(.button),html.theme--catppuccin-macchiato .content kbd.hero .subtitle a:not(.button),html.theme--catppuccin-macchiato .hero.is-dark .subtitle strong,html.theme--catppuccin-macchiato .content kbd.hero .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .hero.is-dark .navbar-menu,html.theme--catppuccin-macchiato .content kbd.hero .navbar-menu{background-color:#363a4f}}html.theme--catppuccin-macchiato .hero.is-dark .navbar-item,html.theme--catppuccin-macchiato .content kbd.hero .navbar-item,html.theme--catppuccin-macchiato .hero.is-dark .navbar-link,html.theme--catppuccin-macchiato .content kbd.hero .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-macchiato .hero.is-dark a.navbar-item:hover,html.theme--catppuccin-macchiato .content kbd.hero a.navbar-item:hover,html.theme--catppuccin-macchiato .hero.is-dark a.navbar-item.is-active,html.theme--catppuccin-macchiato .content kbd.hero a.navbar-item.is-active,html.theme--catppuccin-macchiato .hero.is-dark .navbar-link:hover,html.theme--catppuccin-macchiato .content kbd.hero .navbar-link:hover,html.theme--catppuccin-macchiato .hero.is-dark .navbar-link.is-active,html.theme--catppuccin-macchiato .content kbd.hero .navbar-link.is-active{background-color:#2c2f40;color:#fff}html.theme--catppuccin-macchiato .hero.is-dark .tabs a,html.theme--catppuccin-macchiato .content kbd.hero .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-macchiato .hero.is-dark .tabs a:hover,html.theme--catppuccin-macchiato .content kbd.hero .tabs a:hover{opacity:1}html.theme--catppuccin-macchiato .hero.is-dark .tabs li.is-active a,html.theme--catppuccin-macchiato .content kbd.hero .tabs li.is-active a{color:#363a4f !important;opacity:1}html.theme--catppuccin-macchiato .hero.is-dark .tabs.is-boxed a,html.theme--catppuccin-macchiato .content kbd.hero .tabs.is-boxed a,html.theme--catppuccin-macchiato .hero.is-dark .tabs.is-toggle a,html.theme--catppuccin-macchiato .content kbd.hero .tabs.is-toggle a{color:#fff}html.theme--catppuccin-macchiato .hero.is-dark .tabs.is-boxed a:hover,html.theme--catppuccin-macchiato .content kbd.hero .tabs.is-boxed a:hover,html.theme--catppuccin-macchiato .hero.is-dark .tabs.is-toggle a:hover,html.theme--catppuccin-macchiato .content kbd.hero .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-macchiato .hero.is-dark .tabs.is-boxed li.is-active a,html.theme--catppuccin-macchiato .content kbd.hero .tabs.is-boxed li.is-active a,html.theme--catppuccin-macchiato .hero.is-dark .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-macchiato .hero.is-dark .tabs.is-toggle li.is-active a,html.theme--catppuccin-macchiato .content kbd.hero .tabs.is-toggle li.is-active a,html.theme--catppuccin-macchiato .hero.is-dark .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#363a4f}html.theme--catppuccin-macchiato .hero.is-dark.is-bold,html.theme--catppuccin-macchiato .content kbd.hero.is-bold{background-image:linear-gradient(141deg, #1d2535 0%, #363a4f 71%, #3d3c62 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .hero.is-dark.is-bold .navbar-menu,html.theme--catppuccin-macchiato .content kbd.hero.is-bold .navbar-menu{background-image:linear-gradient(141deg, #1d2535 0%, #363a4f 71%, #3d3c62 100%)}}html.theme--catppuccin-macchiato .hero.is-primary,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink{background-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-macchiato .hero.is-primary strong,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink strong{color:inherit}html.theme--catppuccin-macchiato .hero.is-primary .title,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink .title{color:#fff}html.theme--catppuccin-macchiato .hero.is-primary .subtitle,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-macchiato .hero.is-primary .subtitle a:not(.button),html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink .subtitle a:not(.button),html.theme--catppuccin-macchiato .hero.is-primary .subtitle strong,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .hero.is-primary .navbar-menu,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink .navbar-menu{background-color:#8aadf4}}html.theme--catppuccin-macchiato .hero.is-primary .navbar-item,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink .navbar-item,html.theme--catppuccin-macchiato .hero.is-primary .navbar-link,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-macchiato .hero.is-primary a.navbar-item:hover,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink a.navbar-item:hover,html.theme--catppuccin-macchiato .hero.is-primary a.navbar-item.is-active,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink a.navbar-item.is-active,html.theme--catppuccin-macchiato .hero.is-primary .navbar-link:hover,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink .navbar-link:hover,html.theme--catppuccin-macchiato .hero.is-primary .navbar-link.is-active,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink .navbar-link.is-active{background-color:#739df2;color:#fff}html.theme--catppuccin-macchiato .hero.is-primary .tabs a,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-macchiato .hero.is-primary .tabs a:hover,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink .tabs a:hover{opacity:1}html.theme--catppuccin-macchiato .hero.is-primary .tabs li.is-active a,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink .tabs li.is-active a{color:#8aadf4 !important;opacity:1}html.theme--catppuccin-macchiato .hero.is-primary .tabs.is-boxed a,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a,html.theme--catppuccin-macchiato .hero.is-primary .tabs.is-toggle a,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a{color:#fff}html.theme--catppuccin-macchiato .hero.is-primary .tabs.is-boxed a:hover,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a:hover,html.theme--catppuccin-macchiato .hero.is-primary .tabs.is-toggle a:hover,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-macchiato .hero.is-primary .tabs.is-boxed li.is-active a,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed li.is-active a,html.theme--catppuccin-macchiato .hero.is-primary .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-macchiato .hero.is-primary .tabs.is-toggle li.is-active a,html.theme--catppuccin-macchiato .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle li.is-active a,html.theme--catppuccin-macchiato .hero.is-primary .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#8aadf4}html.theme--catppuccin-macchiato .hero.is-primary.is-bold,html.theme--catppuccin-macchiato .docstring>section>a.hero.is-bold.docs-sourcelink{background-image:linear-gradient(141deg, #52a5f9 0%, #8aadf4 71%, #9fadf9 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .hero.is-primary.is-bold .navbar-menu,html.theme--catppuccin-macchiato .docstring>section>a.hero.is-bold.docs-sourcelink .navbar-menu{background-image:linear-gradient(141deg, #52a5f9 0%, #8aadf4 71%, #9fadf9 100%)}}html.theme--catppuccin-macchiato .hero.is-link{background-color:#8aadf4;color:#fff}html.theme--catppuccin-macchiato .hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-macchiato .hero.is-link strong{color:inherit}html.theme--catppuccin-macchiato .hero.is-link .title{color:#fff}html.theme--catppuccin-macchiato .hero.is-link .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-macchiato .hero.is-link .subtitle a:not(.button),html.theme--catppuccin-macchiato .hero.is-link .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .hero.is-link .navbar-menu{background-color:#8aadf4}}html.theme--catppuccin-macchiato .hero.is-link .navbar-item,html.theme--catppuccin-macchiato .hero.is-link .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-macchiato .hero.is-link a.navbar-item:hover,html.theme--catppuccin-macchiato .hero.is-link a.navbar-item.is-active,html.theme--catppuccin-macchiato .hero.is-link .navbar-link:hover,html.theme--catppuccin-macchiato .hero.is-link .navbar-link.is-active{background-color:#739df2;color:#fff}html.theme--catppuccin-macchiato .hero.is-link .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-macchiato .hero.is-link .tabs a:hover{opacity:1}html.theme--catppuccin-macchiato .hero.is-link .tabs li.is-active a{color:#8aadf4 !important;opacity:1}html.theme--catppuccin-macchiato .hero.is-link .tabs.is-boxed a,html.theme--catppuccin-macchiato .hero.is-link .tabs.is-toggle a{color:#fff}html.theme--catppuccin-macchiato .hero.is-link .tabs.is-boxed a:hover,html.theme--catppuccin-macchiato .hero.is-link .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-macchiato .hero.is-link .tabs.is-boxed li.is-active a,html.theme--catppuccin-macchiato .hero.is-link .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-macchiato .hero.is-link .tabs.is-toggle li.is-active a,html.theme--catppuccin-macchiato .hero.is-link .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#8aadf4}html.theme--catppuccin-macchiato .hero.is-link.is-bold{background-image:linear-gradient(141deg, #52a5f9 0%, #8aadf4 71%, #9fadf9 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .hero.is-link.is-bold .navbar-menu{background-image:linear-gradient(141deg, #52a5f9 0%, #8aadf4 71%, #9fadf9 100%)}}html.theme--catppuccin-macchiato .hero.is-info{background-color:#8bd5ca;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-macchiato .hero.is-info strong{color:inherit}html.theme--catppuccin-macchiato .hero.is-info .title{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-info .subtitle{color:rgba(0,0,0,0.9)}html.theme--catppuccin-macchiato .hero.is-info .subtitle a:not(.button),html.theme--catppuccin-macchiato .hero.is-info .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .hero.is-info .navbar-menu{background-color:#8bd5ca}}html.theme--catppuccin-macchiato .hero.is-info .navbar-item,html.theme--catppuccin-macchiato .hero.is-info .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-info a.navbar-item:hover,html.theme--catppuccin-macchiato .hero.is-info a.navbar-item.is-active,html.theme--catppuccin-macchiato .hero.is-info .navbar-link:hover,html.theme--catppuccin-macchiato .hero.is-info .navbar-link.is-active{background-color:#78cec1;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-info .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--catppuccin-macchiato .hero.is-info .tabs a:hover{opacity:1}html.theme--catppuccin-macchiato .hero.is-info .tabs li.is-active a{color:#8bd5ca !important;opacity:1}html.theme--catppuccin-macchiato .hero.is-info .tabs.is-boxed a,html.theme--catppuccin-macchiato .hero.is-info .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-info .tabs.is-boxed a:hover,html.theme--catppuccin-macchiato .hero.is-info .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-macchiato .hero.is-info .tabs.is-boxed li.is-active a,html.theme--catppuccin-macchiato .hero.is-info .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-macchiato .hero.is-info .tabs.is-toggle li.is-active a,html.theme--catppuccin-macchiato .hero.is-info .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#8bd5ca}html.theme--catppuccin-macchiato .hero.is-info.is-bold{background-image:linear-gradient(141deg, #5bd2ac 0%, #8bd5ca 71%, #9adedf 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .hero.is-info.is-bold .navbar-menu{background-image:linear-gradient(141deg, #5bd2ac 0%, #8bd5ca 71%, #9adedf 100%)}}html.theme--catppuccin-macchiato .hero.is-success{background-color:#a6da95;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-macchiato .hero.is-success strong{color:inherit}html.theme--catppuccin-macchiato .hero.is-success .title{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-success .subtitle{color:rgba(0,0,0,0.9)}html.theme--catppuccin-macchiato .hero.is-success .subtitle a:not(.button),html.theme--catppuccin-macchiato .hero.is-success .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .hero.is-success .navbar-menu{background-color:#a6da95}}html.theme--catppuccin-macchiato .hero.is-success .navbar-item,html.theme--catppuccin-macchiato .hero.is-success .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-success a.navbar-item:hover,html.theme--catppuccin-macchiato .hero.is-success a.navbar-item.is-active,html.theme--catppuccin-macchiato .hero.is-success .navbar-link:hover,html.theme--catppuccin-macchiato .hero.is-success .navbar-link.is-active{background-color:#96d382;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-success .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--catppuccin-macchiato .hero.is-success .tabs a:hover{opacity:1}html.theme--catppuccin-macchiato .hero.is-success .tabs li.is-active a{color:#a6da95 !important;opacity:1}html.theme--catppuccin-macchiato .hero.is-success .tabs.is-boxed a,html.theme--catppuccin-macchiato .hero.is-success .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-success .tabs.is-boxed a:hover,html.theme--catppuccin-macchiato .hero.is-success .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-macchiato .hero.is-success .tabs.is-boxed li.is-active a,html.theme--catppuccin-macchiato .hero.is-success .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-macchiato .hero.is-success .tabs.is-toggle li.is-active a,html.theme--catppuccin-macchiato .hero.is-success .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#a6da95}html.theme--catppuccin-macchiato .hero.is-success.is-bold{background-image:linear-gradient(141deg, #94d765 0%, #a6da95 71%, #aae4a5 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .hero.is-success.is-bold .navbar-menu{background-image:linear-gradient(141deg, #94d765 0%, #a6da95 71%, #aae4a5 100%)}}html.theme--catppuccin-macchiato .hero.is-warning{background-color:#eed49f;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-macchiato .hero.is-warning strong{color:inherit}html.theme--catppuccin-macchiato .hero.is-warning .title{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-warning .subtitle{color:rgba(0,0,0,0.9)}html.theme--catppuccin-macchiato .hero.is-warning .subtitle a:not(.button),html.theme--catppuccin-macchiato .hero.is-warning .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .hero.is-warning .navbar-menu{background-color:#eed49f}}html.theme--catppuccin-macchiato .hero.is-warning .navbar-item,html.theme--catppuccin-macchiato .hero.is-warning .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-warning a.navbar-item:hover,html.theme--catppuccin-macchiato .hero.is-warning a.navbar-item.is-active,html.theme--catppuccin-macchiato .hero.is-warning .navbar-link:hover,html.theme--catppuccin-macchiato .hero.is-warning .navbar-link.is-active{background-color:#eaca89;color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-warning .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--catppuccin-macchiato .hero.is-warning .tabs a:hover{opacity:1}html.theme--catppuccin-macchiato .hero.is-warning .tabs li.is-active a{color:#eed49f !important;opacity:1}html.theme--catppuccin-macchiato .hero.is-warning .tabs.is-boxed a,html.theme--catppuccin-macchiato .hero.is-warning .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--catppuccin-macchiato .hero.is-warning .tabs.is-boxed a:hover,html.theme--catppuccin-macchiato .hero.is-warning .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-macchiato .hero.is-warning .tabs.is-boxed li.is-active a,html.theme--catppuccin-macchiato .hero.is-warning .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-macchiato .hero.is-warning .tabs.is-toggle li.is-active a,html.theme--catppuccin-macchiato .hero.is-warning .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#eed49f}html.theme--catppuccin-macchiato .hero.is-warning.is-bold{background-image:linear-gradient(141deg, #efae6b 0%, #eed49f 71%, #f4e9b2 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .hero.is-warning.is-bold .navbar-menu{background-image:linear-gradient(141deg, #efae6b 0%, #eed49f 71%, #f4e9b2 100%)}}html.theme--catppuccin-macchiato .hero.is-danger{background-color:#ed8796;color:#fff}html.theme--catppuccin-macchiato .hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-macchiato .hero.is-danger strong{color:inherit}html.theme--catppuccin-macchiato .hero.is-danger .title{color:#fff}html.theme--catppuccin-macchiato .hero.is-danger .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-macchiato .hero.is-danger .subtitle a:not(.button),html.theme--catppuccin-macchiato .hero.is-danger .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .hero.is-danger .navbar-menu{background-color:#ed8796}}html.theme--catppuccin-macchiato .hero.is-danger .navbar-item,html.theme--catppuccin-macchiato .hero.is-danger .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-macchiato .hero.is-danger a.navbar-item:hover,html.theme--catppuccin-macchiato .hero.is-danger a.navbar-item.is-active,html.theme--catppuccin-macchiato .hero.is-danger .navbar-link:hover,html.theme--catppuccin-macchiato .hero.is-danger .navbar-link.is-active{background-color:#ea7183;color:#fff}html.theme--catppuccin-macchiato .hero.is-danger .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-macchiato .hero.is-danger .tabs a:hover{opacity:1}html.theme--catppuccin-macchiato .hero.is-danger .tabs li.is-active a{color:#ed8796 !important;opacity:1}html.theme--catppuccin-macchiato .hero.is-danger .tabs.is-boxed a,html.theme--catppuccin-macchiato .hero.is-danger .tabs.is-toggle a{color:#fff}html.theme--catppuccin-macchiato .hero.is-danger .tabs.is-boxed a:hover,html.theme--catppuccin-macchiato .hero.is-danger .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-macchiato .hero.is-danger .tabs.is-boxed li.is-active a,html.theme--catppuccin-macchiato .hero.is-danger .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-macchiato .hero.is-danger .tabs.is-toggle li.is-active a,html.theme--catppuccin-macchiato .hero.is-danger .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#ed8796}html.theme--catppuccin-macchiato .hero.is-danger.is-bold{background-image:linear-gradient(141deg, #f05183 0%, #ed8796 71%, #f39c9a 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .hero.is-danger.is-bold .navbar-menu{background-image:linear-gradient(141deg, #f05183 0%, #ed8796 71%, #f39c9a 100%)}}html.theme--catppuccin-macchiato .hero.is-small .hero-body,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.hero .hero-body{padding:1.5rem}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .hero.is-medium .hero-body{padding:9rem 4.5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .hero.is-large .hero-body{padding:18rem 6rem}}html.theme--catppuccin-macchiato .hero.is-halfheight .hero-body,html.theme--catppuccin-macchiato .hero.is-fullheight .hero-body,html.theme--catppuccin-macchiato .hero.is-fullheight-with-navbar .hero-body{align-items:center;display:flex}html.theme--catppuccin-macchiato .hero.is-halfheight .hero-body>.container,html.theme--catppuccin-macchiato .hero.is-fullheight .hero-body>.container,html.theme--catppuccin-macchiato .hero.is-fullheight-with-navbar .hero-body>.container{flex-grow:1;flex-shrink:1}html.theme--catppuccin-macchiato .hero.is-halfheight{min-height:50vh}html.theme--catppuccin-macchiato .hero.is-fullheight{min-height:100vh}html.theme--catppuccin-macchiato .hero-video{overflow:hidden}html.theme--catppuccin-macchiato .hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;transform:translate3d(-50%, -50%, 0)}html.theme--catppuccin-macchiato .hero-video.is-transparent{opacity:0.3}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .hero-video{display:none}}html.theme--catppuccin-macchiato .hero-buttons{margin-top:1.5rem}@media screen and (max-width: 768px){html.theme--catppuccin-macchiato .hero-buttons .button{display:flex}html.theme--catppuccin-macchiato .hero-buttons .button:not(:last-child){margin-bottom:0.75rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .hero-buttons{display:flex;justify-content:center}html.theme--catppuccin-macchiato .hero-buttons .button:not(:last-child){margin-right:1.5rem}}html.theme--catppuccin-macchiato .hero-head,html.theme--catppuccin-macchiato .hero-foot{flex-grow:0;flex-shrink:0}html.theme--catppuccin-macchiato .hero-body{flex-grow:1;flex-shrink:0;padding:3rem 1.5rem}@media screen and (min-width: 769px),print{html.theme--catppuccin-macchiato .hero-body{padding:3rem 3rem}}html.theme--catppuccin-macchiato .section{padding:3rem 1.5rem}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato .section{padding:3rem 3rem}html.theme--catppuccin-macchiato .section.is-medium{padding:9rem 4.5rem}html.theme--catppuccin-macchiato .section.is-large{padding:18rem 6rem}}html.theme--catppuccin-macchiato .footer{background-color:#1e2030;padding:3rem 1.5rem 6rem}html.theme--catppuccin-macchiato h1 .docs-heading-anchor,html.theme--catppuccin-macchiato h1 .docs-heading-anchor:hover,html.theme--catppuccin-macchiato h1 .docs-heading-anchor:visited,html.theme--catppuccin-macchiato h2 .docs-heading-anchor,html.theme--catppuccin-macchiato h2 .docs-heading-anchor:hover,html.theme--catppuccin-macchiato h2 .docs-heading-anchor:visited,html.theme--catppuccin-macchiato h3 .docs-heading-anchor,html.theme--catppuccin-macchiato h3 .docs-heading-anchor:hover,html.theme--catppuccin-macchiato h3 .docs-heading-anchor:visited,html.theme--catppuccin-macchiato h4 .docs-heading-anchor,html.theme--catppuccin-macchiato h4 .docs-heading-anchor:hover,html.theme--catppuccin-macchiato h4 .docs-heading-anchor:visited,html.theme--catppuccin-macchiato h5 .docs-heading-anchor,html.theme--catppuccin-macchiato h5 .docs-heading-anchor:hover,html.theme--catppuccin-macchiato h5 .docs-heading-anchor:visited,html.theme--catppuccin-macchiato h6 .docs-heading-anchor,html.theme--catppuccin-macchiato h6 .docs-heading-anchor:hover,html.theme--catppuccin-macchiato h6 .docs-heading-anchor:visited{color:#cad3f5}html.theme--catppuccin-macchiato h1 .docs-heading-anchor-permalink,html.theme--catppuccin-macchiato h2 .docs-heading-anchor-permalink,html.theme--catppuccin-macchiato h3 .docs-heading-anchor-permalink,html.theme--catppuccin-macchiato h4 .docs-heading-anchor-permalink,html.theme--catppuccin-macchiato h5 .docs-heading-anchor-permalink,html.theme--catppuccin-macchiato h6 .docs-heading-anchor-permalink{visibility:hidden;vertical-align:middle;margin-left:0.5em;font-size:0.7rem}html.theme--catppuccin-macchiato h1 .docs-heading-anchor-permalink::before,html.theme--catppuccin-macchiato h2 .docs-heading-anchor-permalink::before,html.theme--catppuccin-macchiato h3 .docs-heading-anchor-permalink::before,html.theme--catppuccin-macchiato h4 .docs-heading-anchor-permalink::before,html.theme--catppuccin-macchiato h5 .docs-heading-anchor-permalink::before,html.theme--catppuccin-macchiato h6 .docs-heading-anchor-permalink::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f0c1"}html.theme--catppuccin-macchiato h1:hover .docs-heading-anchor-permalink,html.theme--catppuccin-macchiato h2:hover .docs-heading-anchor-permalink,html.theme--catppuccin-macchiato h3:hover .docs-heading-anchor-permalink,html.theme--catppuccin-macchiato h4:hover .docs-heading-anchor-permalink,html.theme--catppuccin-macchiato h5:hover .docs-heading-anchor-permalink,html.theme--catppuccin-macchiato h6:hover .docs-heading-anchor-permalink{visibility:visible}html.theme--catppuccin-macchiato .docs-light-only{display:none !important}html.theme--catppuccin-macchiato pre{position:relative;overflow:hidden}html.theme--catppuccin-macchiato pre code,html.theme--catppuccin-macchiato pre code.hljs{padding:0 .75rem !important;overflow:auto;display:block}html.theme--catppuccin-macchiato pre code:first-of-type,html.theme--catppuccin-macchiato pre code.hljs:first-of-type{padding-top:0.5rem !important}html.theme--catppuccin-macchiato pre code:last-of-type,html.theme--catppuccin-macchiato pre code.hljs:last-of-type{padding-bottom:0.5rem !important}html.theme--catppuccin-macchiato pre .copy-button{opacity:0.2;transition:opacity 0.2s;position:absolute;right:0em;top:0em;padding:0.5em;width:2.5em;height:2.5em;background:transparent;border:none;font-family:"Font Awesome 6 Free";color:#cad3f5;cursor:pointer;text-align:center}html.theme--catppuccin-macchiato pre .copy-button:focus,html.theme--catppuccin-macchiato pre .copy-button:hover{opacity:1;background:rgba(202,211,245,0.1);color:#8aadf4}html.theme--catppuccin-macchiato pre .copy-button.success{color:#a6da95;opacity:1}html.theme--catppuccin-macchiato pre .copy-button.error{color:#ed8796;opacity:1}html.theme--catppuccin-macchiato pre:hover .copy-button{opacity:1}html.theme--catppuccin-macchiato .admonition{background-color:#1e2030;border-style:solid;border-width:2px;border-color:#b8c0e0;border-radius:4px;font-size:1rem}html.theme--catppuccin-macchiato .admonition strong{color:currentColor}html.theme--catppuccin-macchiato .admonition.is-small,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input.admonition{font-size:.75rem}html.theme--catppuccin-macchiato .admonition.is-medium{font-size:1.25rem}html.theme--catppuccin-macchiato .admonition.is-large{font-size:1.5rem}html.theme--catppuccin-macchiato .admonition.is-default{background-color:#1e2030;border-color:#b8c0e0}html.theme--catppuccin-macchiato .admonition.is-default>.admonition-header{background-color:rgba(0,0,0,0);color:#b8c0e0}html.theme--catppuccin-macchiato .admonition.is-default>.admonition-body{color:#cad3f5}html.theme--catppuccin-macchiato .admonition.is-info{background-color:#1e2030;border-color:#8bd5ca}html.theme--catppuccin-macchiato .admonition.is-info>.admonition-header{background-color:rgba(0,0,0,0);color:#8bd5ca}html.theme--catppuccin-macchiato .admonition.is-info>.admonition-body{color:#cad3f5}html.theme--catppuccin-macchiato .admonition.is-success{background-color:#1e2030;border-color:#a6da95}html.theme--catppuccin-macchiato .admonition.is-success>.admonition-header{background-color:rgba(0,0,0,0);color:#a6da95}html.theme--catppuccin-macchiato .admonition.is-success>.admonition-body{color:#cad3f5}html.theme--catppuccin-macchiato .admonition.is-warning{background-color:#1e2030;border-color:#eed49f}html.theme--catppuccin-macchiato .admonition.is-warning>.admonition-header{background-color:rgba(0,0,0,0);color:#eed49f}html.theme--catppuccin-macchiato .admonition.is-warning>.admonition-body{color:#cad3f5}html.theme--catppuccin-macchiato .admonition.is-danger{background-color:#1e2030;border-color:#ed8796}html.theme--catppuccin-macchiato .admonition.is-danger>.admonition-header{background-color:rgba(0,0,0,0);color:#ed8796}html.theme--catppuccin-macchiato .admonition.is-danger>.admonition-body{color:#cad3f5}html.theme--catppuccin-macchiato .admonition.is-compat{background-color:#1e2030;border-color:#91d7e3}html.theme--catppuccin-macchiato .admonition.is-compat>.admonition-header{background-color:rgba(0,0,0,0);color:#91d7e3}html.theme--catppuccin-macchiato .admonition.is-compat>.admonition-body{color:#cad3f5}html.theme--catppuccin-macchiato .admonition.is-todo{background-color:#1e2030;border-color:#c6a0f6}html.theme--catppuccin-macchiato .admonition.is-todo>.admonition-header{background-color:rgba(0,0,0,0);color:#c6a0f6}html.theme--catppuccin-macchiato .admonition.is-todo>.admonition-body{color:#cad3f5}html.theme--catppuccin-macchiato .admonition-header{color:#b8c0e0;background-color:rgba(0,0,0,0);align-items:center;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.5rem .75rem;position:relative}html.theme--catppuccin-macchiato .admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;margin-right:.75rem;content:"\f06a"}html.theme--catppuccin-macchiato details.admonition.is-details>.admonition-header{list-style:none}html.theme--catppuccin-macchiato details.admonition.is-details>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f055"}html.theme--catppuccin-macchiato details.admonition.is-details[open]>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f056"}html.theme--catppuccin-macchiato .admonition-body{color:#cad3f5;padding:0.5rem .75rem}html.theme--catppuccin-macchiato .admonition-body pre{background-color:#1e2030}html.theme--catppuccin-macchiato .admonition-body code{background-color:#1e2030}html.theme--catppuccin-macchiato .docstring{margin-bottom:1em;background-color:rgba(0,0,0,0);border:2px solid #5b6078;border-radius:4px;box-shadow:none;max-width:100%}html.theme--catppuccin-macchiato .docstring>header{cursor:pointer;display:flex;flex-grow:1;align-items:stretch;padding:0.5rem .75rem;background-color:#1e2030;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);box-shadow:none;border-bottom:1px solid #5b6078;overflow:auto}html.theme--catppuccin-macchiato .docstring>header code{background-color:transparent}html.theme--catppuccin-macchiato .docstring>header .docstring-article-toggle-button{min-width:1.1rem;padding:0.2rem 0.2rem 0.2rem 0}html.theme--catppuccin-macchiato .docstring>header .docstring-binding{margin-right:0.3em}html.theme--catppuccin-macchiato .docstring>header .docstring-category{margin-left:0.3em}html.theme--catppuccin-macchiato .docstring>section{position:relative;padding:.75rem .75rem;border-bottom:1px solid #5b6078}html.theme--catppuccin-macchiato .docstring>section:last-child{border-bottom:none}html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink{transition:opacity 0.3s;opacity:0;position:absolute;right:.375rem;bottom:.375rem}html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink:focus{opacity:1 !important}html.theme--catppuccin-macchiato .docstring:hover>section>a.docs-sourcelink{opacity:0.2}html.theme--catppuccin-macchiato .docstring:focus-within>section>a.docs-sourcelink{opacity:0.2}html.theme--catppuccin-macchiato .docstring>section:hover a.docs-sourcelink{opacity:1}html.theme--catppuccin-macchiato .documenter-example-output{background-color:#24273a}html.theme--catppuccin-macchiato .outdated-warning-overlay{position:fixed;top:0;left:0;right:0;box-shadow:0 0 10px rgba(0,0,0,0.3);z-index:999;background-color:#1e2030;color:#cad3f5;border-bottom:3px solid rgba(0,0,0,0);padding:10px 35px;text-align:center;font-size:15px}html.theme--catppuccin-macchiato .outdated-warning-overlay .outdated-warning-closer{position:absolute;top:calc(50% - 10px);right:18px;cursor:pointer;width:12px}html.theme--catppuccin-macchiato .outdated-warning-overlay a{color:#8aadf4}html.theme--catppuccin-macchiato .outdated-warning-overlay a:hover{color:#91d7e3}html.theme--catppuccin-macchiato .content pre{border:2px solid #5b6078;border-radius:4px}html.theme--catppuccin-macchiato .content code{font-weight:inherit}html.theme--catppuccin-macchiato .content a code{color:#8aadf4}html.theme--catppuccin-macchiato .content a:hover code{color:#91d7e3}html.theme--catppuccin-macchiato .content h1 code,html.theme--catppuccin-macchiato .content h2 code,html.theme--catppuccin-macchiato .content h3 code,html.theme--catppuccin-macchiato .content h4 code,html.theme--catppuccin-macchiato .content h5 code,html.theme--catppuccin-macchiato .content h6 code{color:#cad3f5}html.theme--catppuccin-macchiato .content table{display:block;width:initial;max-width:100%;overflow-x:auto}html.theme--catppuccin-macchiato .content blockquote>ul:first-child,html.theme--catppuccin-macchiato .content blockquote>ol:first-child,html.theme--catppuccin-macchiato .content .admonition-body>ul:first-child,html.theme--catppuccin-macchiato .content .admonition-body>ol:first-child{margin-top:0}html.theme--catppuccin-macchiato pre,html.theme--catppuccin-macchiato code{font-variant-ligatures:no-contextual}html.theme--catppuccin-macchiato .breadcrumb a.is-disabled{cursor:default;pointer-events:none}html.theme--catppuccin-macchiato .breadcrumb a.is-disabled,html.theme--catppuccin-macchiato .breadcrumb a.is-disabled:hover{color:#b5c1f1}html.theme--catppuccin-macchiato .hljs{background:initial !important}html.theme--catppuccin-macchiato .katex .katex-mathml{top:0;right:0}html.theme--catppuccin-macchiato .katex-display,html.theme--catppuccin-macchiato mjx-container,html.theme--catppuccin-macchiato .MathJax_Display{margin:0.5em 0 !important}html.theme--catppuccin-macchiato html{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto}html.theme--catppuccin-macchiato li.no-marker{list-style:none}html.theme--catppuccin-macchiato #documenter .docs-main>article{overflow-wrap:break-word}html.theme--catppuccin-macchiato #documenter .docs-main>article .math-container{overflow-x:auto;overflow-y:hidden}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato #documenter .docs-main{max-width:52rem;margin-left:20rem;padding-right:1rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato #documenter .docs-main{width:100%}html.theme--catppuccin-macchiato #documenter .docs-main>article{max-width:52rem;margin-left:auto;margin-right:auto;margin-bottom:1rem;padding:0 1rem}html.theme--catppuccin-macchiato #documenter .docs-main>header,html.theme--catppuccin-macchiato #documenter .docs-main>nav{max-width:100%;width:100%;margin:0}}html.theme--catppuccin-macchiato #documenter .docs-main header.docs-navbar{background-color:#24273a;border-bottom:1px solid #5b6078;z-index:2;min-height:4rem;margin-bottom:1rem;display:flex}html.theme--catppuccin-macchiato #documenter .docs-main header.docs-navbar .breadcrumb{flex-grow:1;overflow-x:hidden}html.theme--catppuccin-macchiato #documenter .docs-main header.docs-navbar .docs-sidebar-button{display:block;font-size:1.5rem;padding-bottom:0.1rem;margin-right:1rem}html.theme--catppuccin-macchiato #documenter .docs-main header.docs-navbar .docs-right{display:flex;white-space:nowrap;gap:1rem;align-items:center}html.theme--catppuccin-macchiato #documenter .docs-main header.docs-navbar .docs-right .docs-icon,html.theme--catppuccin-macchiato #documenter .docs-main header.docs-navbar .docs-right .docs-label{display:inline-block}html.theme--catppuccin-macchiato #documenter .docs-main header.docs-navbar .docs-right .docs-label{padding:0;margin-left:0.3em}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato #documenter .docs-main header.docs-navbar .docs-right .docs-navbar-link{margin-left:0.4rem;margin-right:0.4rem}}html.theme--catppuccin-macchiato #documenter .docs-main header.docs-navbar>*{margin:auto 0}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato #documenter .docs-main header.docs-navbar{position:sticky;top:0;padding:0 1rem;transition-property:top, box-shadow;-webkit-transition-property:top, box-shadow;transition-duration:0.3s;-webkit-transition-duration:0.3s}html.theme--catppuccin-macchiato #documenter .docs-main header.docs-navbar.headroom--not-top{box-shadow:.2rem 0rem .4rem #171717;transition-duration:0.7s;-webkit-transition-duration:0.7s}html.theme--catppuccin-macchiato #documenter .docs-main header.docs-navbar.headroom--unpinned.headroom--not-top.headroom--not-bottom{top:-4.5rem;transition-duration:0.7s;-webkit-transition-duration:0.7s}}html.theme--catppuccin-macchiato #documenter .docs-main section.footnotes{border-top:1px solid #5b6078}html.theme--catppuccin-macchiato #documenter .docs-main section.footnotes li .tag:first-child,html.theme--catppuccin-macchiato #documenter .docs-main section.footnotes li .docstring>section>a.docs-sourcelink:first-child,html.theme--catppuccin-macchiato #documenter .docs-main section.footnotes li .content kbd:first-child,html.theme--catppuccin-macchiato .content #documenter .docs-main section.footnotes li kbd:first-child{margin-right:1em;margin-bottom:0.4em}html.theme--catppuccin-macchiato #documenter .docs-main .docs-footer{display:flex;flex-wrap:wrap;margin-left:0;margin-right:0;border-top:1px solid #5b6078;padding-top:1rem;padding-bottom:1rem}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato #documenter .docs-main .docs-footer{padding-left:1rem;padding-right:1rem}}html.theme--catppuccin-macchiato #documenter .docs-main .docs-footer .docs-footer-nextpage,html.theme--catppuccin-macchiato #documenter .docs-main .docs-footer .docs-footer-prevpage{flex-grow:1}html.theme--catppuccin-macchiato #documenter .docs-main .docs-footer .docs-footer-nextpage{text-align:right}html.theme--catppuccin-macchiato #documenter .docs-main .docs-footer .flexbox-break{flex-basis:100%;height:0}html.theme--catppuccin-macchiato #documenter .docs-main .docs-footer .footer-message{font-size:0.8em;margin:0.5em auto 0 auto;text-align:center}html.theme--catppuccin-macchiato #documenter .docs-sidebar{display:flex;flex-direction:column;color:#cad3f5;background-color:#1e2030;border-right:1px solid #5b6078;padding:0;flex:0 0 18rem;z-index:5;font-size:1rem;position:fixed;left:-18rem;width:18rem;height:100%;transition:left 0.3s}html.theme--catppuccin-macchiato #documenter .docs-sidebar.visible{left:0;box-shadow:.4rem 0rem .8rem #171717}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato #documenter .docs-sidebar.visible{box-shadow:none}}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato #documenter .docs-sidebar{left:0;top:0}}html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo{margin-top:1rem;padding:0 1rem}html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-logo>img{max-height:6rem;margin:auto}html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-package-name{flex-shrink:0;font-size:1.5rem;font-weight:700;text-align:center;white-space:nowrap;overflow:hidden;padding:0.5rem 0}html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-package-name .docs-autofit{max-width:16.2rem}html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-package-name a,html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-package-name a:hover{color:#cad3f5}html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-version-selector{border-top:1px solid #5b6078;display:none;padding:0.5rem}html.theme--catppuccin-macchiato #documenter .docs-sidebar .docs-version-selector.visible{display:flex}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu{flex-grow:1;user-select:none;border-top:1px solid #5b6078;padding-bottom:1.5rem}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu>li>.tocitem{font-weight:bold}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu>li li{font-size:.95rem;margin-left:1em;border-left:1px solid #5b6078}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu input.collapse-toggle{display:none}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu ul.collapsed{display:none}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu input:checked~ul.collapsed{display:block}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu label.tocitem{display:flex}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-label{flex-grow:2}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-size:.75rem;margin-left:1rem;margin-top:auto;margin-bottom:auto}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f054"}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu input:checked~label.tocitem .docs-chevron::before{content:"\f078"}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu .tocitem{display:block;padding:0.5rem 0.5rem}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu .tocitem,html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu .tocitem:hover{color:#cad3f5;background:#1e2030}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu a.tocitem:hover,html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu label.tocitem:hover{color:#cad3f5;background-color:#26283d}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu li.is-active{border-top:1px solid #5b6078;border-bottom:1px solid #5b6078;background-color:#181926}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem,html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem:hover{background-color:#181926;color:#cad3f5}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu li.is-active ul.internal .tocitem:hover{background-color:#26283d;color:#cad3f5}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu>li.is-active:first-child{border-top:none}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu ul.internal{margin:0 0.5rem 0.5rem;border-top:1px solid #5b6078}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu ul.internal li{font-size:.85rem;border-left:none;margin-left:0;margin-top:0.5rem}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem{width:100%;padding:0}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem::before{content:"⚬";margin-right:0.4em}html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search{margin:auto;margin-top:0.5rem;margin-bottom:0.5rem}html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input{width:14.4rem}html.theme--catppuccin-macchiato #documenter .docs-sidebar #documenter-search-query{color:#868c98;width:14.4rem;box-shadow:inset 0 1px 2px rgba(10,10,10,0.1)}@media screen and (min-width: 1056px){html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar{width:.3rem;background:none}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#2e3149}html.theme--catppuccin-macchiato #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb:hover{background:#3d4162}}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato #documenter .docs-sidebar{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--catppuccin-macchiato #documenter .docs-sidebar::-webkit-scrollbar{width:.3rem;background:none}html.theme--catppuccin-macchiato #documenter .docs-sidebar::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#2e3149}html.theme--catppuccin-macchiato #documenter .docs-sidebar::-webkit-scrollbar-thumb:hover{background:#3d4162}}html.theme--catppuccin-macchiato kbd.search-modal-key-hints{border-radius:0.25rem;border:1px solid rgba(245,245,245,0.6);box-shadow:0 2px 0 1px rgba(245,245,245,0.6);cursor:default;font-size:0.9rem;line-height:1.5;min-width:0.75rem;text-align:center;padding:0.1rem 0.3rem;position:relative;top:-1px}html.theme--catppuccin-macchiato .search-min-width-50{min-width:50%}html.theme--catppuccin-macchiato .search-min-height-100{min-height:100%}html.theme--catppuccin-macchiato .search-modal-card-body{max-height:calc(100vh - 15rem)}html.theme--catppuccin-macchiato .search-result-link{border-radius:0.7em;transition:all 300ms}html.theme--catppuccin-macchiato .search-result-link:hover,html.theme--catppuccin-macchiato .search-result-link:focus{background-color:rgba(0,128,128,0.1)}html.theme--catppuccin-macchiato .search-result-link .property-search-result-badge,html.theme--catppuccin-macchiato .search-result-link .search-filter{transition:all 300ms}html.theme--catppuccin-macchiato .property-search-result-badge,html.theme--catppuccin-macchiato .search-filter{padding:0.15em 0.5em;font-size:0.8em;font-style:italic;text-transform:none !important;line-height:1.5;color:#f5f5f5;background-color:rgba(51,65,85,0.501961);border-radius:0.6rem}html.theme--catppuccin-macchiato .search-result-link:hover .property-search-result-badge,html.theme--catppuccin-macchiato .search-result-link:hover .search-filter,html.theme--catppuccin-macchiato .search-result-link:focus .property-search-result-badge,html.theme--catppuccin-macchiato .search-result-link:focus .search-filter{color:#333;background-color:#f1f5f9}html.theme--catppuccin-macchiato .search-filter{color:#333;background-color:#f5f5f5;transition:all 300ms}html.theme--catppuccin-macchiato .search-filter:hover,html.theme--catppuccin-macchiato .search-filter:focus{color:#333}html.theme--catppuccin-macchiato .search-filter-selected{color:#363a4f;background-color:#b7bdf8}html.theme--catppuccin-macchiato .search-filter-selected:hover,html.theme--catppuccin-macchiato .search-filter-selected:focus{color:#363a4f}html.theme--catppuccin-macchiato .search-result-highlight{background-color:#ffdd57;color:black}html.theme--catppuccin-macchiato .search-divider{border-bottom:1px solid #5b6078}html.theme--catppuccin-macchiato .search-result-title{width:85%;color:#f5f5f5}html.theme--catppuccin-macchiato .search-result-code-title{font-size:0.875rem;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}html.theme--catppuccin-macchiato #search-modal .modal-card-body::-webkit-scrollbar,html.theme--catppuccin-macchiato #search-modal .filter-tabs::-webkit-scrollbar{height:10px;width:10px;background-color:transparent}html.theme--catppuccin-macchiato #search-modal .modal-card-body::-webkit-scrollbar-thumb,html.theme--catppuccin-macchiato #search-modal .filter-tabs::-webkit-scrollbar-thumb{background-color:gray;border-radius:1rem}html.theme--catppuccin-macchiato #search-modal .modal-card-body::-webkit-scrollbar-track,html.theme--catppuccin-macchiato #search-modal .filter-tabs::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,0.6);background-color:transparent}html.theme--catppuccin-macchiato .w-100{width:100%}html.theme--catppuccin-macchiato .gap-2{gap:0.5rem}html.theme--catppuccin-macchiato .gap-4{gap:1rem}html.theme--catppuccin-macchiato .gap-8{gap:2rem}html.theme--catppuccin-macchiato{background-color:#24273a;font-size:16px;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--catppuccin-macchiato a{transition:all 200ms ease}html.theme--catppuccin-macchiato .label{color:#cad3f5}html.theme--catppuccin-macchiato .button,html.theme--catppuccin-macchiato .control.has-icons-left .icon,html.theme--catppuccin-macchiato .control.has-icons-right .icon,html.theme--catppuccin-macchiato .input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-macchiato .pagination-ellipsis,html.theme--catppuccin-macchiato .pagination-link,html.theme--catppuccin-macchiato .pagination-next,html.theme--catppuccin-macchiato .pagination-previous,html.theme--catppuccin-macchiato .select,html.theme--catppuccin-macchiato .select select,html.theme--catppuccin-macchiato .textarea{height:2.5em;color:#cad3f5}html.theme--catppuccin-macchiato .input,html.theme--catppuccin-macchiato #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-macchiato .textarea{transition:all 200ms ease;box-shadow:none;border-width:1px;padding-left:1em;padding-right:1em;color:#cad3f5}html.theme--catppuccin-macchiato .select:after,html.theme--catppuccin-macchiato .select select{border-width:1px}html.theme--catppuccin-macchiato .menu-list a{transition:all 300ms ease}html.theme--catppuccin-macchiato .modal-card-foot,html.theme--catppuccin-macchiato .modal-card-head{border-color:#5b6078}html.theme--catppuccin-macchiato .navbar{border-radius:.4em}html.theme--catppuccin-macchiato .navbar.is-transparent{background:none}html.theme--catppuccin-macchiato .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--catppuccin-macchiato .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#8aadf4}@media screen and (max-width: 1055px){html.theme--catppuccin-macchiato .navbar .navbar-menu{background-color:#8aadf4;border-radius:0 0 .4em .4em}}html.theme--catppuccin-macchiato .docstring>section>a.docs-sourcelink:not(body){color:#363a4f}html.theme--catppuccin-macchiato .tag.is-link:not(body),html.theme--catppuccin-macchiato .docstring>section>a.is-link.docs-sourcelink:not(body),html.theme--catppuccin-macchiato .content kbd.is-link:not(body){color:#363a4f}html.theme--catppuccin-macchiato .ansi span.sgr1{font-weight:bolder}html.theme--catppuccin-macchiato .ansi span.sgr2{font-weight:lighter}html.theme--catppuccin-macchiato .ansi span.sgr3{font-style:italic}html.theme--catppuccin-macchiato .ansi span.sgr4{text-decoration:underline}html.theme--catppuccin-macchiato .ansi span.sgr7{color:#24273a;background-color:#cad3f5}html.theme--catppuccin-macchiato .ansi span.sgr8{color:transparent}html.theme--catppuccin-macchiato .ansi span.sgr8 span{color:transparent}html.theme--catppuccin-macchiato .ansi span.sgr9{text-decoration:line-through}html.theme--catppuccin-macchiato .ansi span.sgr30{color:#494d64}html.theme--catppuccin-macchiato .ansi span.sgr31{color:#ed8796}html.theme--catppuccin-macchiato .ansi span.sgr32{color:#a6da95}html.theme--catppuccin-macchiato .ansi span.sgr33{color:#eed49f}html.theme--catppuccin-macchiato .ansi span.sgr34{color:#8aadf4}html.theme--catppuccin-macchiato .ansi span.sgr35{color:#f5bde6}html.theme--catppuccin-macchiato .ansi span.sgr36{color:#8bd5ca}html.theme--catppuccin-macchiato .ansi span.sgr37{color:#b8c0e0}html.theme--catppuccin-macchiato .ansi span.sgr40{background-color:#494d64}html.theme--catppuccin-macchiato .ansi span.sgr41{background-color:#ed8796}html.theme--catppuccin-macchiato .ansi span.sgr42{background-color:#a6da95}html.theme--catppuccin-macchiato .ansi span.sgr43{background-color:#eed49f}html.theme--catppuccin-macchiato .ansi span.sgr44{background-color:#8aadf4}html.theme--catppuccin-macchiato .ansi span.sgr45{background-color:#f5bde6}html.theme--catppuccin-macchiato .ansi span.sgr46{background-color:#8bd5ca}html.theme--catppuccin-macchiato .ansi span.sgr47{background-color:#b8c0e0}html.theme--catppuccin-macchiato .ansi span.sgr90{color:#5b6078}html.theme--catppuccin-macchiato .ansi span.sgr91{color:#ed8796}html.theme--catppuccin-macchiato .ansi span.sgr92{color:#a6da95}html.theme--catppuccin-macchiato .ansi span.sgr93{color:#eed49f}html.theme--catppuccin-macchiato .ansi span.sgr94{color:#8aadf4}html.theme--catppuccin-macchiato .ansi span.sgr95{color:#f5bde6}html.theme--catppuccin-macchiato .ansi span.sgr96{color:#8bd5ca}html.theme--catppuccin-macchiato .ansi span.sgr97{color:#a5adcb}html.theme--catppuccin-macchiato .ansi span.sgr100{background-color:#5b6078}html.theme--catppuccin-macchiato .ansi span.sgr101{background-color:#ed8796}html.theme--catppuccin-macchiato .ansi span.sgr102{background-color:#a6da95}html.theme--catppuccin-macchiato .ansi span.sgr103{background-color:#eed49f}html.theme--catppuccin-macchiato .ansi span.sgr104{background-color:#8aadf4}html.theme--catppuccin-macchiato .ansi span.sgr105{background-color:#f5bde6}html.theme--catppuccin-macchiato .ansi span.sgr106{background-color:#8bd5ca}html.theme--catppuccin-macchiato .ansi span.sgr107{background-color:#a5adcb}html.theme--catppuccin-macchiato code.language-julia-repl>span.hljs-meta{color:#a6da95;font-weight:bolder}html.theme--catppuccin-macchiato code .hljs{color:#cad3f5;background:#24273a}html.theme--catppuccin-macchiato code .hljs-keyword{color:#c6a0f6}html.theme--catppuccin-macchiato code .hljs-built_in{color:#ed8796}html.theme--catppuccin-macchiato code .hljs-type{color:#eed49f}html.theme--catppuccin-macchiato code .hljs-literal{color:#f5a97f}html.theme--catppuccin-macchiato code .hljs-number{color:#f5a97f}html.theme--catppuccin-macchiato code .hljs-operator{color:#8bd5ca}html.theme--catppuccin-macchiato code .hljs-punctuation{color:#b8c0e0}html.theme--catppuccin-macchiato code .hljs-property{color:#8bd5ca}html.theme--catppuccin-macchiato code .hljs-regexp{color:#f5bde6}html.theme--catppuccin-macchiato code .hljs-string{color:#a6da95}html.theme--catppuccin-macchiato code .hljs-char.escape_{color:#a6da95}html.theme--catppuccin-macchiato code .hljs-subst{color:#a5adcb}html.theme--catppuccin-macchiato code .hljs-symbol{color:#f0c6c6}html.theme--catppuccin-macchiato code .hljs-variable{color:#c6a0f6}html.theme--catppuccin-macchiato code .hljs-variable.language_{color:#c6a0f6}html.theme--catppuccin-macchiato code .hljs-variable.constant_{color:#f5a97f}html.theme--catppuccin-macchiato code .hljs-title{color:#8aadf4}html.theme--catppuccin-macchiato code .hljs-title.class_{color:#eed49f}html.theme--catppuccin-macchiato code .hljs-title.function_{color:#8aadf4}html.theme--catppuccin-macchiato code .hljs-params{color:#cad3f5}html.theme--catppuccin-macchiato code .hljs-comment{color:#5b6078}html.theme--catppuccin-macchiato code .hljs-doctag{color:#ed8796}html.theme--catppuccin-macchiato code .hljs-meta{color:#f5a97f}html.theme--catppuccin-macchiato code .hljs-section{color:#8aadf4}html.theme--catppuccin-macchiato code .hljs-tag{color:#a5adcb}html.theme--catppuccin-macchiato code .hljs-name{color:#c6a0f6}html.theme--catppuccin-macchiato code .hljs-attr{color:#8aadf4}html.theme--catppuccin-macchiato code .hljs-attribute{color:#a6da95}html.theme--catppuccin-macchiato code .hljs-bullet{color:#8bd5ca}html.theme--catppuccin-macchiato code .hljs-code{color:#a6da95}html.theme--catppuccin-macchiato code .hljs-emphasis{color:#ed8796;font-style:italic}html.theme--catppuccin-macchiato code .hljs-strong{color:#ed8796;font-weight:bold}html.theme--catppuccin-macchiato code .hljs-formula{color:#8bd5ca}html.theme--catppuccin-macchiato code .hljs-link{color:#7dc4e4;font-style:italic}html.theme--catppuccin-macchiato code .hljs-quote{color:#a6da95;font-style:italic}html.theme--catppuccin-macchiato code .hljs-selector-tag{color:#eed49f}html.theme--catppuccin-macchiato code .hljs-selector-id{color:#8aadf4}html.theme--catppuccin-macchiato code .hljs-selector-class{color:#8bd5ca}html.theme--catppuccin-macchiato code .hljs-selector-attr{color:#c6a0f6}html.theme--catppuccin-macchiato code .hljs-selector-pseudo{color:#8bd5ca}html.theme--catppuccin-macchiato code .hljs-template-tag{color:#f0c6c6}html.theme--catppuccin-macchiato code .hljs-template-variable{color:#f0c6c6}html.theme--catppuccin-macchiato code .hljs-addition{color:#a6da95;background:rgba(166,227,161,0.15)}html.theme--catppuccin-macchiato code .hljs-deletion{color:#ed8796;background:rgba(243,139,168,0.15)}html.theme--catppuccin-macchiato .search-result-link{border-radius:0.7em;transition:all 300ms}html.theme--catppuccin-macchiato .search-result-link:hover,html.theme--catppuccin-macchiato .search-result-link:focus{background-color:#363a4f}html.theme--catppuccin-macchiato .search-result-link .property-search-result-badge,html.theme--catppuccin-macchiato .search-result-link .search-filter{transition:all 300ms}html.theme--catppuccin-macchiato .search-result-link:hover .property-search-result-badge,html.theme--catppuccin-macchiato .search-result-link:hover .search-filter,html.theme--catppuccin-macchiato .search-result-link:focus .property-search-result-badge,html.theme--catppuccin-macchiato .search-result-link:focus .search-filter{color:#363a4f !important;background-color:#b7bdf8 !important}html.theme--catppuccin-macchiato .search-result-title{color:#cad3f5}html.theme--catppuccin-macchiato .search-result-highlight{background-color:#ed8796;color:#1e2030}html.theme--catppuccin-macchiato .search-divider{border-bottom:1px solid #5e6d6f50}html.theme--catppuccin-macchiato .w-100{width:100%}html.theme--catppuccin-macchiato .gap-2{gap:0.5rem}html.theme--catppuccin-macchiato .gap-4{gap:1rem} diff --git a/v0.2.0/assets/themes/catppuccin-mocha.css b/v0.2.0/assets/themes/catppuccin-mocha.css new file mode 100644 index 000000000..8b8265256 --- /dev/null +++ b/v0.2.0/assets/themes/catppuccin-mocha.css @@ -0,0 +1 @@ +html.theme--catppuccin-mocha .pagination-previous,html.theme--catppuccin-mocha .pagination-next,html.theme--catppuccin-mocha .pagination-link,html.theme--catppuccin-mocha .pagination-ellipsis,html.theme--catppuccin-mocha .file-cta,html.theme--catppuccin-mocha .file-name,html.theme--catppuccin-mocha .select select,html.theme--catppuccin-mocha .textarea,html.theme--catppuccin-mocha .input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-mocha .button{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;border-radius:.4em;box-shadow:none;display:inline-flex;font-size:1rem;height:2.5em;justify-content:flex-start;line-height:1.5;padding-bottom:calc(0.5em - 1px);padding-left:calc(0.75em - 1px);padding-right:calc(0.75em - 1px);padding-top:calc(0.5em - 1px);position:relative;vertical-align:top}html.theme--catppuccin-mocha .pagination-previous:focus,html.theme--catppuccin-mocha .pagination-next:focus,html.theme--catppuccin-mocha .pagination-link:focus,html.theme--catppuccin-mocha .pagination-ellipsis:focus,html.theme--catppuccin-mocha .file-cta:focus,html.theme--catppuccin-mocha .file-name:focus,html.theme--catppuccin-mocha .select select:focus,html.theme--catppuccin-mocha .textarea:focus,html.theme--catppuccin-mocha .input:focus,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input:focus,html.theme--catppuccin-mocha .button:focus,html.theme--catppuccin-mocha .is-focused.pagination-previous,html.theme--catppuccin-mocha .is-focused.pagination-next,html.theme--catppuccin-mocha .is-focused.pagination-link,html.theme--catppuccin-mocha .is-focused.pagination-ellipsis,html.theme--catppuccin-mocha .is-focused.file-cta,html.theme--catppuccin-mocha .is-focused.file-name,html.theme--catppuccin-mocha .select select.is-focused,html.theme--catppuccin-mocha .is-focused.textarea,html.theme--catppuccin-mocha .is-focused.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-mocha .is-focused.button,html.theme--catppuccin-mocha .pagination-previous:active,html.theme--catppuccin-mocha .pagination-next:active,html.theme--catppuccin-mocha .pagination-link:active,html.theme--catppuccin-mocha .pagination-ellipsis:active,html.theme--catppuccin-mocha .file-cta:active,html.theme--catppuccin-mocha .file-name:active,html.theme--catppuccin-mocha .select select:active,html.theme--catppuccin-mocha .textarea:active,html.theme--catppuccin-mocha .input:active,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input:active,html.theme--catppuccin-mocha .button:active,html.theme--catppuccin-mocha .is-active.pagination-previous,html.theme--catppuccin-mocha .is-active.pagination-next,html.theme--catppuccin-mocha .is-active.pagination-link,html.theme--catppuccin-mocha .is-active.pagination-ellipsis,html.theme--catppuccin-mocha .is-active.file-cta,html.theme--catppuccin-mocha .is-active.file-name,html.theme--catppuccin-mocha .select select.is-active,html.theme--catppuccin-mocha .is-active.textarea,html.theme--catppuccin-mocha .is-active.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--catppuccin-mocha .is-active.button{outline:none}html.theme--catppuccin-mocha .pagination-previous[disabled],html.theme--catppuccin-mocha .pagination-next[disabled],html.theme--catppuccin-mocha .pagination-link[disabled],html.theme--catppuccin-mocha .pagination-ellipsis[disabled],html.theme--catppuccin-mocha .file-cta[disabled],html.theme--catppuccin-mocha .file-name[disabled],html.theme--catppuccin-mocha .select select[disabled],html.theme--catppuccin-mocha .textarea[disabled],html.theme--catppuccin-mocha .input[disabled],html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input[disabled],html.theme--catppuccin-mocha .button[disabled],fieldset[disabled] html.theme--catppuccin-mocha .pagination-previous,html.theme--catppuccin-mocha fieldset[disabled] .pagination-previous,fieldset[disabled] html.theme--catppuccin-mocha .pagination-next,html.theme--catppuccin-mocha fieldset[disabled] .pagination-next,fieldset[disabled] html.theme--catppuccin-mocha .pagination-link,html.theme--catppuccin-mocha fieldset[disabled] .pagination-link,fieldset[disabled] html.theme--catppuccin-mocha .pagination-ellipsis,html.theme--catppuccin-mocha fieldset[disabled] .pagination-ellipsis,fieldset[disabled] html.theme--catppuccin-mocha .file-cta,html.theme--catppuccin-mocha fieldset[disabled] .file-cta,fieldset[disabled] html.theme--catppuccin-mocha .file-name,html.theme--catppuccin-mocha fieldset[disabled] .file-name,fieldset[disabled] html.theme--catppuccin-mocha .select select,fieldset[disabled] html.theme--catppuccin-mocha .textarea,fieldset[disabled] html.theme--catppuccin-mocha .input,fieldset[disabled] html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-mocha fieldset[disabled] .select select,html.theme--catppuccin-mocha .select fieldset[disabled] select,html.theme--catppuccin-mocha fieldset[disabled] .textarea,html.theme--catppuccin-mocha fieldset[disabled] .input,html.theme--catppuccin-mocha fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-mocha #documenter .docs-sidebar fieldset[disabled] form.docs-search>input,fieldset[disabled] html.theme--catppuccin-mocha .button,html.theme--catppuccin-mocha fieldset[disabled] .button{cursor:not-allowed}html.theme--catppuccin-mocha .tabs,html.theme--catppuccin-mocha .pagination-previous,html.theme--catppuccin-mocha .pagination-next,html.theme--catppuccin-mocha .pagination-link,html.theme--catppuccin-mocha .pagination-ellipsis,html.theme--catppuccin-mocha .breadcrumb,html.theme--catppuccin-mocha .file,html.theme--catppuccin-mocha .button,.is-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}html.theme--catppuccin-mocha .navbar-link:not(.is-arrowless)::after,html.theme--catppuccin-mocha .select:not(.is-multiple):not(.is-loading)::after{border:3px solid rgba(0,0,0,0);border-radius:2px;border-right:0;border-top:0;content:" ";display:block;height:0.625em;margin-top:-0.4375em;pointer-events:none;position:absolute;top:50%;transform:rotate(-45deg);transform-origin:center;width:0.625em}html.theme--catppuccin-mocha .admonition:not(:last-child),html.theme--catppuccin-mocha .tabs:not(:last-child),html.theme--catppuccin-mocha .pagination:not(:last-child),html.theme--catppuccin-mocha .message:not(:last-child),html.theme--catppuccin-mocha .level:not(:last-child),html.theme--catppuccin-mocha .breadcrumb:not(:last-child),html.theme--catppuccin-mocha .block:not(:last-child),html.theme--catppuccin-mocha .title:not(:last-child),html.theme--catppuccin-mocha .subtitle:not(:last-child),html.theme--catppuccin-mocha .table-container:not(:last-child),html.theme--catppuccin-mocha .table:not(:last-child),html.theme--catppuccin-mocha .progress:not(:last-child),html.theme--catppuccin-mocha .notification:not(:last-child),html.theme--catppuccin-mocha .content:not(:last-child),html.theme--catppuccin-mocha .box:not(:last-child){margin-bottom:1.5rem}html.theme--catppuccin-mocha .modal-close,html.theme--catppuccin-mocha .delete{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,0.2);border:none;border-radius:9999px;cursor:pointer;pointer-events:auto;display:inline-block;flex-grow:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:none;position:relative;vertical-align:top;width:20px}html.theme--catppuccin-mocha .modal-close::before,html.theme--catppuccin-mocha .delete::before,html.theme--catppuccin-mocha .modal-close::after,html.theme--catppuccin-mocha .delete::after{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--catppuccin-mocha .modal-close::before,html.theme--catppuccin-mocha .delete::before{height:2px;width:50%}html.theme--catppuccin-mocha .modal-close::after,html.theme--catppuccin-mocha .delete::after{height:50%;width:2px}html.theme--catppuccin-mocha .modal-close:hover,html.theme--catppuccin-mocha .delete:hover,html.theme--catppuccin-mocha .modal-close:focus,html.theme--catppuccin-mocha .delete:focus{background-color:rgba(10,10,10,0.3)}html.theme--catppuccin-mocha .modal-close:active,html.theme--catppuccin-mocha .delete:active{background-color:rgba(10,10,10,0.4)}html.theme--catppuccin-mocha .is-small.modal-close,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.modal-close,html.theme--catppuccin-mocha .is-small.delete,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.delete{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}html.theme--catppuccin-mocha .is-medium.modal-close,html.theme--catppuccin-mocha .is-medium.delete{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}html.theme--catppuccin-mocha .is-large.modal-close,html.theme--catppuccin-mocha .is-large.delete{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}html.theme--catppuccin-mocha .control.is-loading::after,html.theme--catppuccin-mocha .select.is-loading::after,html.theme--catppuccin-mocha .loader,html.theme--catppuccin-mocha .button.is-loading::after{animation:spinAround 500ms infinite linear;border:2px solid #7f849c;border-radius:9999px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em}html.theme--catppuccin-mocha .hero-video,html.theme--catppuccin-mocha .modal-background,html.theme--catppuccin-mocha .modal,html.theme--catppuccin-mocha .image.is-square img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--catppuccin-mocha .image.is-square .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--catppuccin-mocha .image.is-1by1 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--catppuccin-mocha .image.is-1by1 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--catppuccin-mocha .image.is-5by4 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--catppuccin-mocha .image.is-5by4 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--catppuccin-mocha .image.is-4by3 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--catppuccin-mocha .image.is-4by3 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--catppuccin-mocha .image.is-3by2 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--catppuccin-mocha .image.is-3by2 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--catppuccin-mocha .image.is-5by3 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--catppuccin-mocha .image.is-5by3 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--catppuccin-mocha .image.is-16by9 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--catppuccin-mocha .image.is-16by9 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--catppuccin-mocha .image.is-2by1 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--catppuccin-mocha .image.is-2by1 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--catppuccin-mocha .image.is-3by1 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--catppuccin-mocha .image.is-3by1 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--catppuccin-mocha .image.is-4by5 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--catppuccin-mocha .image.is-4by5 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--catppuccin-mocha .image.is-3by4 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--catppuccin-mocha .image.is-3by4 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--catppuccin-mocha .image.is-2by3 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--catppuccin-mocha .image.is-2by3 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--catppuccin-mocha .image.is-3by5 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--catppuccin-mocha .image.is-3by5 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--catppuccin-mocha .image.is-9by16 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--catppuccin-mocha .image.is-9by16 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--catppuccin-mocha .image.is-1by2 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--catppuccin-mocha .image.is-1by2 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--catppuccin-mocha .image.is-1by3 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--catppuccin-mocha .image.is-1by3 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio,.is-overlay{bottom:0;left:0;position:absolute;right:0;top:0}html.theme--catppuccin-mocha .navbar-burger{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0}/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:inherit}.has-text-white{color:#fff !important}a.has-text-white:hover,a.has-text-white:focus{color:#e6e6e6 !important}.has-background-white{background-color:#fff !important}.has-text-black{color:#0a0a0a !important}a.has-text-black:hover,a.has-text-black:focus{color:#000 !important}.has-background-black{background-color:#0a0a0a !important}.has-text-light{color:#f5f5f5 !important}a.has-text-light:hover,a.has-text-light:focus{color:#dbdbdb !important}.has-background-light{background-color:#f5f5f5 !important}.has-text-dark{color:#313244 !important}a.has-text-dark:hover,a.has-text-dark:focus{color:#1c1c26 !important}.has-background-dark{background-color:#313244 !important}.has-text-primary{color:#89b4fa !important}a.has-text-primary:hover,a.has-text-primary:focus{color:#5895f8 !important}.has-background-primary{background-color:#89b4fa !important}.has-text-primary-light{color:#ebf3fe !important}a.has-text-primary-light:hover,a.has-text-primary-light:focus{color:#bbd3fc !important}.has-background-primary-light{background-color:#ebf3fe !important}.has-text-primary-dark{color:#063c93 !important}a.has-text-primary-dark:hover,a.has-text-primary-dark:focus{color:#0850c4 !important}.has-background-primary-dark{background-color:#063c93 !important}.has-text-link{color:#89b4fa !important}a.has-text-link:hover,a.has-text-link:focus{color:#5895f8 !important}.has-background-link{background-color:#89b4fa !important}.has-text-link-light{color:#ebf3fe !important}a.has-text-link-light:hover,a.has-text-link-light:focus{color:#bbd3fc !important}.has-background-link-light{background-color:#ebf3fe !important}.has-text-link-dark{color:#063c93 !important}a.has-text-link-dark:hover,a.has-text-link-dark:focus{color:#0850c4 !important}.has-background-link-dark{background-color:#063c93 !important}.has-text-info{color:#94e2d5 !important}a.has-text-info:hover,a.has-text-info:focus{color:#6cd7c5 !important}.has-background-info{background-color:#94e2d5 !important}.has-text-info-light{color:#effbf9 !important}a.has-text-info-light:hover,a.has-text-info-light:focus{color:#c7f0e9 !important}.has-background-info-light{background-color:#effbf9 !important}.has-text-info-dark{color:#207466 !important}a.has-text-info-dark:hover,a.has-text-info-dark:focus{color:#2a9c89 !important}.has-background-info-dark{background-color:#207466 !important}.has-text-success{color:#a6e3a1 !important}a.has-text-success:hover,a.has-text-success:focus{color:#81d77a !important}.has-background-success{background-color:#a6e3a1 !important}.has-text-success-light{color:#f0faef !important}a.has-text-success-light:hover,a.has-text-success-light:focus{color:#cbefc8 !important}.has-background-success-light{background-color:#f0faef !important}.has-text-success-dark{color:#287222 !important}a.has-text-success-dark:hover,a.has-text-success-dark:focus{color:#36992e !important}.has-background-success-dark{background-color:#287222 !important}.has-text-warning{color:#f9e2af !important}a.has-text-warning:hover,a.has-text-warning:focus{color:#f5d180 !important}.has-background-warning{background-color:#f9e2af !important}.has-text-warning-light{color:#fef8ec !important}a.has-text-warning-light:hover,a.has-text-warning-light:focus{color:#fae7bd !important}.has-background-warning-light{background-color:#fef8ec !important}.has-text-warning-dark{color:#8a620a !important}a.has-text-warning-dark:hover,a.has-text-warning-dark:focus{color:#b9840e !important}.has-background-warning-dark{background-color:#8a620a !important}.has-text-danger{color:#f38ba8 !important}a.has-text-danger:hover,a.has-text-danger:focus{color:#ee5d85 !important}.has-background-danger{background-color:#f38ba8 !important}.has-text-danger-light{color:#fdedf1 !important}a.has-text-danger-light:hover,a.has-text-danger-light:focus{color:#f8bece !important}.has-background-danger-light{background-color:#fdedf1 !important}.has-text-danger-dark{color:#991036 !important}a.has-text-danger-dark:hover,a.has-text-danger-dark:focus{color:#c71546 !important}.has-background-danger-dark{background-color:#991036 !important}.has-text-black-bis{color:#121212 !important}.has-background-black-bis{background-color:#121212 !important}.has-text-black-ter{color:#242424 !important}.has-background-black-ter{background-color:#242424 !important}.has-text-grey-darker{color:#313244 !important}.has-background-grey-darker{background-color:#313244 !important}.has-text-grey-dark{color:#45475a !important}.has-background-grey-dark{background-color:#45475a !important}.has-text-grey{color:#585b70 !important}.has-background-grey{background-color:#585b70 !important}.has-text-grey-light{color:#6c7086 !important}.has-background-grey-light{background-color:#6c7086 !important}.has-text-grey-lighter{color:#7f849c !important}.has-background-grey-lighter{background-color:#7f849c !important}.has-text-white-ter{color:#f5f5f5 !important}.has-background-white-ter{background-color:#f5f5f5 !important}.has-text-white-bis{color:#fafafa !important}.has-background-white-bis{background-color:#fafafa !important}.is-flex-direction-row{flex-direction:row !important}.is-flex-direction-row-reverse{flex-direction:row-reverse !important}.is-flex-direction-column{flex-direction:column !important}.is-flex-direction-column-reverse{flex-direction:column-reverse !important}.is-flex-wrap-nowrap{flex-wrap:nowrap !important}.is-flex-wrap-wrap{flex-wrap:wrap !important}.is-flex-wrap-wrap-reverse{flex-wrap:wrap-reverse !important}.is-justify-content-flex-start{justify-content:flex-start !important}.is-justify-content-flex-end{justify-content:flex-end !important}.is-justify-content-center{justify-content:center !important}.is-justify-content-space-between{justify-content:space-between !important}.is-justify-content-space-around{justify-content:space-around !important}.is-justify-content-space-evenly{justify-content:space-evenly !important}.is-justify-content-start{justify-content:start !important}.is-justify-content-end{justify-content:end !important}.is-justify-content-left{justify-content:left !important}.is-justify-content-right{justify-content:right !important}.is-align-content-flex-start{align-content:flex-start !important}.is-align-content-flex-end{align-content:flex-end !important}.is-align-content-center{align-content:center !important}.is-align-content-space-between{align-content:space-between !important}.is-align-content-space-around{align-content:space-around !important}.is-align-content-space-evenly{align-content:space-evenly !important}.is-align-content-stretch{align-content:stretch !important}.is-align-content-start{align-content:start !important}.is-align-content-end{align-content:end !important}.is-align-content-baseline{align-content:baseline !important}.is-align-items-stretch{align-items:stretch !important}.is-align-items-flex-start{align-items:flex-start !important}.is-align-items-flex-end{align-items:flex-end !important}.is-align-items-center{align-items:center !important}.is-align-items-baseline{align-items:baseline !important}.is-align-items-start{align-items:start !important}.is-align-items-end{align-items:end !important}.is-align-items-self-start{align-items:self-start !important}.is-align-items-self-end{align-items:self-end !important}.is-align-self-auto{align-self:auto !important}.is-align-self-flex-start{align-self:flex-start !important}.is-align-self-flex-end{align-self:flex-end !important}.is-align-self-center{align-self:center !important}.is-align-self-baseline{align-self:baseline !important}.is-align-self-stretch{align-self:stretch !important}.is-flex-grow-0{flex-grow:0 !important}.is-flex-grow-1{flex-grow:1 !important}.is-flex-grow-2{flex-grow:2 !important}.is-flex-grow-3{flex-grow:3 !important}.is-flex-grow-4{flex-grow:4 !important}.is-flex-grow-5{flex-grow:5 !important}.is-flex-shrink-0{flex-shrink:0 !important}.is-flex-shrink-1{flex-shrink:1 !important}.is-flex-shrink-2{flex-shrink:2 !important}.is-flex-shrink-3{flex-shrink:3 !important}.is-flex-shrink-4{flex-shrink:4 !important}.is-flex-shrink-5{flex-shrink:5 !important}.is-clearfix::after{clear:both;content:" ";display:table}.is-pulled-left{float:left !important}.is-pulled-right{float:right !important}.is-radiusless{border-radius:0 !important}.is-shadowless{box-shadow:none !important}.is-clickable{cursor:pointer !important;pointer-events:all !important}.is-clipped{overflow:hidden !important}.is-relative{position:relative !important}.is-marginless{margin:0 !important}.is-paddingless{padding:0 !important}.m-0{margin:0 !important}.mt-0{margin-top:0 !important}.mr-0{margin-right:0 !important}.mb-0{margin-bottom:0 !important}.ml-0{margin-left:0 !important}.mx-0{margin-left:0 !important;margin-right:0 !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.m-1{margin:.25rem !important}.mt-1{margin-top:.25rem !important}.mr-1{margin-right:.25rem !important}.mb-1{margin-bottom:.25rem !important}.ml-1{margin-left:.25rem !important}.mx-1{margin-left:.25rem !important;margin-right:.25rem !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.m-2{margin:.5rem !important}.mt-2{margin-top:.5rem !important}.mr-2{margin-right:.5rem !important}.mb-2{margin-bottom:.5rem !important}.ml-2{margin-left:.5rem !important}.mx-2{margin-left:.5rem !important;margin-right:.5rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.m-3{margin:.75rem !important}.mt-3{margin-top:.75rem !important}.mr-3{margin-right:.75rem !important}.mb-3{margin-bottom:.75rem !important}.ml-3{margin-left:.75rem !important}.mx-3{margin-left:.75rem !important;margin-right:.75rem !important}.my-3{margin-top:.75rem !important;margin-bottom:.75rem !important}.m-4{margin:1rem !important}.mt-4{margin-top:1rem !important}.mr-4{margin-right:1rem !important}.mb-4{margin-bottom:1rem !important}.ml-4{margin-left:1rem !important}.mx-4{margin-left:1rem !important;margin-right:1rem !important}.my-4{margin-top:1rem !important;margin-bottom:1rem !important}.m-5{margin:1.5rem !important}.mt-5{margin-top:1.5rem !important}.mr-5{margin-right:1.5rem !important}.mb-5{margin-bottom:1.5rem !important}.ml-5{margin-left:1.5rem !important}.mx-5{margin-left:1.5rem !important;margin-right:1.5rem !important}.my-5{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.m-6{margin:3rem !important}.mt-6{margin-top:3rem !important}.mr-6{margin-right:3rem !important}.mb-6{margin-bottom:3rem !important}.ml-6{margin-left:3rem !important}.mx-6{margin-left:3rem !important;margin-right:3rem !important}.my-6{margin-top:3rem !important;margin-bottom:3rem !important}.m-auto{margin:auto !important}.mt-auto{margin-top:auto !important}.mr-auto{margin-right:auto !important}.mb-auto{margin-bottom:auto !important}.ml-auto{margin-left:auto !important}.mx-auto{margin-left:auto !important;margin-right:auto !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.p-0{padding:0 !important}.pt-0{padding-top:0 !important}.pr-0{padding-right:0 !important}.pb-0{padding-bottom:0 !important}.pl-0{padding-left:0 !important}.px-0{padding-left:0 !important;padding-right:0 !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.p-1{padding:.25rem !important}.pt-1{padding-top:.25rem !important}.pr-1{padding-right:.25rem !important}.pb-1{padding-bottom:.25rem !important}.pl-1{padding-left:.25rem !important}.px-1{padding-left:.25rem !important;padding-right:.25rem !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.p-2{padding:.5rem !important}.pt-2{padding-top:.5rem !important}.pr-2{padding-right:.5rem !important}.pb-2{padding-bottom:.5rem !important}.pl-2{padding-left:.5rem !important}.px-2{padding-left:.5rem !important;padding-right:.5rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.p-3{padding:.75rem !important}.pt-3{padding-top:.75rem !important}.pr-3{padding-right:.75rem !important}.pb-3{padding-bottom:.75rem !important}.pl-3{padding-left:.75rem !important}.px-3{padding-left:.75rem !important;padding-right:.75rem !important}.py-3{padding-top:.75rem !important;padding-bottom:.75rem !important}.p-4{padding:1rem !important}.pt-4{padding-top:1rem !important}.pr-4{padding-right:1rem !important}.pb-4{padding-bottom:1rem !important}.pl-4{padding-left:1rem !important}.px-4{padding-left:1rem !important;padding-right:1rem !important}.py-4{padding-top:1rem !important;padding-bottom:1rem !important}.p-5{padding:1.5rem !important}.pt-5{padding-top:1.5rem !important}.pr-5{padding-right:1.5rem !important}.pb-5{padding-bottom:1.5rem !important}.pl-5{padding-left:1.5rem !important}.px-5{padding-left:1.5rem !important;padding-right:1.5rem !important}.py-5{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.p-6{padding:3rem !important}.pt-6{padding-top:3rem !important}.pr-6{padding-right:3rem !important}.pb-6{padding-bottom:3rem !important}.pl-6{padding-left:3rem !important}.px-6{padding-left:3rem !important;padding-right:3rem !important}.py-6{padding-top:3rem !important;padding-bottom:3rem !important}.p-auto{padding:auto !important}.pt-auto{padding-top:auto !important}.pr-auto{padding-right:auto !important}.pb-auto{padding-bottom:auto !important}.pl-auto{padding-left:auto !important}.px-auto{padding-left:auto !important;padding-right:auto !important}.py-auto{padding-top:auto !important;padding-bottom:auto !important}.is-size-1{font-size:3rem !important}.is-size-2{font-size:2.5rem !important}.is-size-3{font-size:2rem !important}.is-size-4{font-size:1.5rem !important}.is-size-5{font-size:1.25rem !important}.is-size-6{font-size:1rem !important}.is-size-7,html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink{font-size:.75rem !important}@media screen and (max-width: 768px){.is-size-1-mobile{font-size:3rem !important}.is-size-2-mobile{font-size:2.5rem !important}.is-size-3-mobile{font-size:2rem !important}.is-size-4-mobile{font-size:1.5rem !important}.is-size-5-mobile{font-size:1.25rem !important}.is-size-6-mobile{font-size:1rem !important}.is-size-7-mobile{font-size:.75rem !important}}@media screen and (min-width: 769px),print{.is-size-1-tablet{font-size:3rem !important}.is-size-2-tablet{font-size:2.5rem !important}.is-size-3-tablet{font-size:2rem !important}.is-size-4-tablet{font-size:1.5rem !important}.is-size-5-tablet{font-size:1.25rem !important}.is-size-6-tablet{font-size:1rem !important}.is-size-7-tablet{font-size:.75rem !important}}@media screen and (max-width: 1055px){.is-size-1-touch{font-size:3rem !important}.is-size-2-touch{font-size:2.5rem !important}.is-size-3-touch{font-size:2rem !important}.is-size-4-touch{font-size:1.5rem !important}.is-size-5-touch{font-size:1.25rem !important}.is-size-6-touch{font-size:1rem !important}.is-size-7-touch{font-size:.75rem !important}}@media screen and (min-width: 1056px){.is-size-1-desktop{font-size:3rem !important}.is-size-2-desktop{font-size:2.5rem !important}.is-size-3-desktop{font-size:2rem !important}.is-size-4-desktop{font-size:1.5rem !important}.is-size-5-desktop{font-size:1.25rem !important}.is-size-6-desktop{font-size:1rem !important}.is-size-7-desktop{font-size:.75rem !important}}@media screen and (min-width: 1216px){.is-size-1-widescreen{font-size:3rem !important}.is-size-2-widescreen{font-size:2.5rem !important}.is-size-3-widescreen{font-size:2rem !important}.is-size-4-widescreen{font-size:1.5rem !important}.is-size-5-widescreen{font-size:1.25rem !important}.is-size-6-widescreen{font-size:1rem !important}.is-size-7-widescreen{font-size:.75rem !important}}@media screen and (min-width: 1408px){.is-size-1-fullhd{font-size:3rem !important}.is-size-2-fullhd{font-size:2.5rem !important}.is-size-3-fullhd{font-size:2rem !important}.is-size-4-fullhd{font-size:1.5rem !important}.is-size-5-fullhd{font-size:1.25rem !important}.is-size-6-fullhd{font-size:1rem !important}.is-size-7-fullhd{font-size:.75rem !important}}.has-text-centered{text-align:center !important}.has-text-justified{text-align:justify !important}.has-text-left{text-align:left !important}.has-text-right{text-align:right !important}@media screen and (max-width: 768px){.has-text-centered-mobile{text-align:center !important}}@media screen and (min-width: 769px),print{.has-text-centered-tablet{text-align:center !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-centered-tablet-only{text-align:center !important}}@media screen and (max-width: 1055px){.has-text-centered-touch{text-align:center !important}}@media screen and (min-width: 1056px){.has-text-centered-desktop{text-align:center !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-centered-desktop-only{text-align:center !important}}@media screen and (min-width: 1216px){.has-text-centered-widescreen{text-align:center !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-centered-widescreen-only{text-align:center !important}}@media screen and (min-width: 1408px){.has-text-centered-fullhd{text-align:center !important}}@media screen and (max-width: 768px){.has-text-justified-mobile{text-align:justify !important}}@media screen and (min-width: 769px),print{.has-text-justified-tablet{text-align:justify !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-justified-tablet-only{text-align:justify !important}}@media screen and (max-width: 1055px){.has-text-justified-touch{text-align:justify !important}}@media screen and (min-width: 1056px){.has-text-justified-desktop{text-align:justify !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-justified-desktop-only{text-align:justify !important}}@media screen and (min-width: 1216px){.has-text-justified-widescreen{text-align:justify !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-justified-widescreen-only{text-align:justify !important}}@media screen and (min-width: 1408px){.has-text-justified-fullhd{text-align:justify !important}}@media screen and (max-width: 768px){.has-text-left-mobile{text-align:left !important}}@media screen and (min-width: 769px),print{.has-text-left-tablet{text-align:left !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-left-tablet-only{text-align:left !important}}@media screen and (max-width: 1055px){.has-text-left-touch{text-align:left !important}}@media screen and (min-width: 1056px){.has-text-left-desktop{text-align:left !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-left-desktop-only{text-align:left !important}}@media screen and (min-width: 1216px){.has-text-left-widescreen{text-align:left !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-left-widescreen-only{text-align:left !important}}@media screen and (min-width: 1408px){.has-text-left-fullhd{text-align:left !important}}@media screen and (max-width: 768px){.has-text-right-mobile{text-align:right !important}}@media screen and (min-width: 769px),print{.has-text-right-tablet{text-align:right !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-right-tablet-only{text-align:right !important}}@media screen and (max-width: 1055px){.has-text-right-touch{text-align:right !important}}@media screen and (min-width: 1056px){.has-text-right-desktop{text-align:right !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-right-desktop-only{text-align:right !important}}@media screen and (min-width: 1216px){.has-text-right-widescreen{text-align:right !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-right-widescreen-only{text-align:right !important}}@media screen and (min-width: 1408px){.has-text-right-fullhd{text-align:right !important}}.is-capitalized{text-transform:capitalize !important}.is-lowercase{text-transform:lowercase !important}.is-uppercase{text-transform:uppercase !important}.is-italic{font-style:italic !important}.is-underlined{text-decoration:underline !important}.has-text-weight-light{font-weight:300 !important}.has-text-weight-normal{font-weight:400 !important}.has-text-weight-medium{font-weight:500 !important}.has-text-weight-semibold{font-weight:600 !important}.has-text-weight-bold{font-weight:700 !important}.is-family-primary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-secondary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-sans-serif{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-monospace{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-family-code{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-block{display:block !important}@media screen and (max-width: 768px){.is-block-mobile{display:block !important}}@media screen and (min-width: 769px),print{.is-block-tablet{display:block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-block-tablet-only{display:block !important}}@media screen and (max-width: 1055px){.is-block-touch{display:block !important}}@media screen and (min-width: 1056px){.is-block-desktop{display:block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-block-desktop-only{display:block !important}}@media screen and (min-width: 1216px){.is-block-widescreen{display:block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-block-widescreen-only{display:block !important}}@media screen and (min-width: 1408px){.is-block-fullhd{display:block !important}}.is-flex{display:flex !important}@media screen and (max-width: 768px){.is-flex-mobile{display:flex !important}}@media screen and (min-width: 769px),print{.is-flex-tablet{display:flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-flex-tablet-only{display:flex !important}}@media screen and (max-width: 1055px){.is-flex-touch{display:flex !important}}@media screen and (min-width: 1056px){.is-flex-desktop{display:flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-flex-desktop-only{display:flex !important}}@media screen and (min-width: 1216px){.is-flex-widescreen{display:flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-flex-widescreen-only{display:flex !important}}@media screen and (min-width: 1408px){.is-flex-fullhd{display:flex !important}}.is-inline{display:inline !important}@media screen and (max-width: 768px){.is-inline-mobile{display:inline !important}}@media screen and (min-width: 769px),print{.is-inline-tablet{display:inline !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-tablet-only{display:inline !important}}@media screen and (max-width: 1055px){.is-inline-touch{display:inline !important}}@media screen and (min-width: 1056px){.is-inline-desktop{display:inline !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-desktop-only{display:inline !important}}@media screen and (min-width: 1216px){.is-inline-widescreen{display:inline !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-widescreen-only{display:inline !important}}@media screen and (min-width: 1408px){.is-inline-fullhd{display:inline !important}}.is-inline-block{display:inline-block !important}@media screen and (max-width: 768px){.is-inline-block-mobile{display:inline-block !important}}@media screen and (min-width: 769px),print{.is-inline-block-tablet{display:inline-block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-block-tablet-only{display:inline-block !important}}@media screen and (max-width: 1055px){.is-inline-block-touch{display:inline-block !important}}@media screen and (min-width: 1056px){.is-inline-block-desktop{display:inline-block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-block-desktop-only{display:inline-block !important}}@media screen and (min-width: 1216px){.is-inline-block-widescreen{display:inline-block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-block-widescreen-only{display:inline-block !important}}@media screen and (min-width: 1408px){.is-inline-block-fullhd{display:inline-block !important}}.is-inline-flex{display:inline-flex !important}@media screen and (max-width: 768px){.is-inline-flex-mobile{display:inline-flex !important}}@media screen and (min-width: 769px),print{.is-inline-flex-tablet{display:inline-flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-flex-tablet-only{display:inline-flex !important}}@media screen and (max-width: 1055px){.is-inline-flex-touch{display:inline-flex !important}}@media screen and (min-width: 1056px){.is-inline-flex-desktop{display:inline-flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-flex-desktop-only{display:inline-flex !important}}@media screen and (min-width: 1216px){.is-inline-flex-widescreen{display:inline-flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-flex-widescreen-only{display:inline-flex !important}}@media screen and (min-width: 1408px){.is-inline-flex-fullhd{display:inline-flex !important}}.is-hidden{display:none !important}.is-sr-only{border:none !important;clip:rect(0, 0, 0, 0) !important;height:0.01em !important;overflow:hidden !important;padding:0 !important;position:absolute !important;white-space:nowrap !important;width:0.01em !important}@media screen and (max-width: 768px){.is-hidden-mobile{display:none !important}}@media screen and (min-width: 769px),print{.is-hidden-tablet{display:none !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-hidden-tablet-only{display:none !important}}@media screen and (max-width: 1055px){.is-hidden-touch{display:none !important}}@media screen and (min-width: 1056px){.is-hidden-desktop{display:none !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-hidden-desktop-only{display:none !important}}@media screen and (min-width: 1216px){.is-hidden-widescreen{display:none !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-hidden-widescreen-only{display:none !important}}@media screen and (min-width: 1408px){.is-hidden-fullhd{display:none !important}}.is-invisible{visibility:hidden !important}@media screen and (max-width: 768px){.is-invisible-mobile{visibility:hidden !important}}@media screen and (min-width: 769px),print{.is-invisible-tablet{visibility:hidden !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-invisible-tablet-only{visibility:hidden !important}}@media screen and (max-width: 1055px){.is-invisible-touch{visibility:hidden !important}}@media screen and (min-width: 1056px){.is-invisible-desktop{visibility:hidden !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-invisible-desktop-only{visibility:hidden !important}}@media screen and (min-width: 1216px){.is-invisible-widescreen{visibility:hidden !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-invisible-widescreen-only{visibility:hidden !important}}@media screen and (min-width: 1408px){.is-invisible-fullhd{visibility:hidden !important}}html.theme--catppuccin-mocha html{background-color:#1e1e2e;font-size:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--catppuccin-mocha article,html.theme--catppuccin-mocha aside,html.theme--catppuccin-mocha figure,html.theme--catppuccin-mocha footer,html.theme--catppuccin-mocha header,html.theme--catppuccin-mocha hgroup,html.theme--catppuccin-mocha section{display:block}html.theme--catppuccin-mocha body,html.theme--catppuccin-mocha button,html.theme--catppuccin-mocha input,html.theme--catppuccin-mocha optgroup,html.theme--catppuccin-mocha select,html.theme--catppuccin-mocha textarea{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif}html.theme--catppuccin-mocha code,html.theme--catppuccin-mocha pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}html.theme--catppuccin-mocha body{color:#cdd6f4;font-size:1em;font-weight:400;line-height:1.5}html.theme--catppuccin-mocha a{color:#89b4fa;cursor:pointer;text-decoration:none}html.theme--catppuccin-mocha a strong{color:currentColor}html.theme--catppuccin-mocha a:hover{color:#89dceb}html.theme--catppuccin-mocha code{background-color:#181825;color:#cdd6f4;font-size:.875em;font-weight:normal;padding:.1em}html.theme--catppuccin-mocha hr{background-color:#181825;border:none;display:block;height:2px;margin:1.5rem 0}html.theme--catppuccin-mocha img{height:auto;max-width:100%}html.theme--catppuccin-mocha input[type="checkbox"],html.theme--catppuccin-mocha input[type="radio"]{vertical-align:baseline}html.theme--catppuccin-mocha small{font-size:.875em}html.theme--catppuccin-mocha span{font-style:inherit;font-weight:inherit}html.theme--catppuccin-mocha strong{color:#b8c5ef;font-weight:700}html.theme--catppuccin-mocha fieldset{border:none}html.theme--catppuccin-mocha pre{-webkit-overflow-scrolling:touch;background-color:#181825;color:#cdd6f4;font-size:.875em;overflow-x:auto;padding:1.25rem 1.5rem;white-space:pre;word-wrap:normal}html.theme--catppuccin-mocha pre code{background-color:transparent;color:currentColor;font-size:1em;padding:0}html.theme--catppuccin-mocha table td,html.theme--catppuccin-mocha table th{vertical-align:top}html.theme--catppuccin-mocha table td:not([align]),html.theme--catppuccin-mocha table th:not([align]){text-align:inherit}html.theme--catppuccin-mocha table th{color:#b8c5ef}html.theme--catppuccin-mocha .box{background-color:#45475a;border-radius:8px;box-shadow:none;color:#cdd6f4;display:block;padding:1.25rem}html.theme--catppuccin-mocha a.box:hover,html.theme--catppuccin-mocha a.box:focus{box-shadow:0 0.5em 1em -0.125em rgba(10,10,10,0.1),0 0 0 1px #89b4fa}html.theme--catppuccin-mocha a.box:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2),0 0 0 1px #89b4fa}html.theme--catppuccin-mocha .button{background-color:#181825;border-color:#363653;border-width:1px;color:#89b4fa;cursor:pointer;justify-content:center;padding-bottom:calc(0.5em - 1px);padding-left:1em;padding-right:1em;padding-top:calc(0.5em - 1px);text-align:center;white-space:nowrap}html.theme--catppuccin-mocha .button strong{color:inherit}html.theme--catppuccin-mocha .button .icon,html.theme--catppuccin-mocha .button .icon.is-small,html.theme--catppuccin-mocha .button #documenter .docs-sidebar form.docs-search>input.icon,html.theme--catppuccin-mocha #documenter .docs-sidebar .button form.docs-search>input.icon,html.theme--catppuccin-mocha .button .icon.is-medium,html.theme--catppuccin-mocha .button .icon.is-large{height:1.5em;width:1.5em}html.theme--catppuccin-mocha .button .icon:first-child:not(:last-child){margin-left:calc(-0.5em - 1px);margin-right:.25em}html.theme--catppuccin-mocha .button .icon:last-child:not(:first-child){margin-left:.25em;margin-right:calc(-0.5em - 1px)}html.theme--catppuccin-mocha .button .icon:first-child:last-child{margin-left:calc(-0.5em - 1px);margin-right:calc(-0.5em - 1px)}html.theme--catppuccin-mocha .button:hover,html.theme--catppuccin-mocha .button.is-hovered{border-color:#6c7086;color:#b8c5ef}html.theme--catppuccin-mocha .button:focus,html.theme--catppuccin-mocha .button.is-focused{border-color:#6c7086;color:#71a4f9}html.theme--catppuccin-mocha .button:focus:not(:active),html.theme--catppuccin-mocha .button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(137,180,250,0.25)}html.theme--catppuccin-mocha .button:active,html.theme--catppuccin-mocha .button.is-active{border-color:#45475a;color:#b8c5ef}html.theme--catppuccin-mocha .button.is-text{background-color:transparent;border-color:transparent;color:#cdd6f4;text-decoration:underline}html.theme--catppuccin-mocha .button.is-text:hover,html.theme--catppuccin-mocha .button.is-text.is-hovered,html.theme--catppuccin-mocha .button.is-text:focus,html.theme--catppuccin-mocha .button.is-text.is-focused{background-color:#181825;color:#b8c5ef}html.theme--catppuccin-mocha .button.is-text:active,html.theme--catppuccin-mocha .button.is-text.is-active{background-color:#0e0e16;color:#b8c5ef}html.theme--catppuccin-mocha .button.is-text[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-text{background-color:transparent;border-color:transparent;box-shadow:none}html.theme--catppuccin-mocha .button.is-ghost{background:none;border-color:rgba(0,0,0,0);color:#89b4fa;text-decoration:none}html.theme--catppuccin-mocha .button.is-ghost:hover,html.theme--catppuccin-mocha .button.is-ghost.is-hovered{color:#89b4fa;text-decoration:underline}html.theme--catppuccin-mocha .button.is-white{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-mocha .button.is-white:hover,html.theme--catppuccin-mocha .button.is-white.is-hovered{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-mocha .button.is-white:focus,html.theme--catppuccin-mocha .button.is-white.is-focused{border-color:transparent;color:#0a0a0a}html.theme--catppuccin-mocha .button.is-white:focus:not(:active),html.theme--catppuccin-mocha .button.is-white.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--catppuccin-mocha .button.is-white:active,html.theme--catppuccin-mocha .button.is-white.is-active{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-mocha .button.is-white[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-white{background-color:#fff;border-color:#fff;box-shadow:none}html.theme--catppuccin-mocha .button.is-white.is-inverted{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-mocha .button.is-white.is-inverted:hover,html.theme--catppuccin-mocha .button.is-white.is-inverted.is-hovered{background-color:#000}html.theme--catppuccin-mocha .button.is-white.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-white.is-inverted{background-color:#0a0a0a;border-color:transparent;box-shadow:none;color:#fff}html.theme--catppuccin-mocha .button.is-white.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--catppuccin-mocha .button.is-white.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-mocha .button.is-white.is-outlined:hover,html.theme--catppuccin-mocha .button.is-white.is-outlined.is-hovered,html.theme--catppuccin-mocha .button.is-white.is-outlined:focus,html.theme--catppuccin-mocha .button.is-white.is-outlined.is-focused{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--catppuccin-mocha .button.is-white.is-outlined.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-mocha .button.is-white.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .button.is-white.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .button.is-white.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .button.is-white.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--catppuccin-mocha .button.is-white.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-white.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-mocha .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--catppuccin-mocha .button.is-white.is-inverted.is-outlined:hover,html.theme--catppuccin-mocha .button.is-white.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-mocha .button.is-white.is-inverted.is-outlined:focus,html.theme--catppuccin-mocha .button.is-white.is-inverted.is-outlined.is-focused{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-mocha .button.is-white.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .button.is-white.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .button.is-white.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-mocha .button.is-white.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--catppuccin-mocha .button.is-black{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-black:hover,html.theme--catppuccin-mocha .button.is-black.is-hovered{background-color:#040404;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-black:focus,html.theme--catppuccin-mocha .button.is-black.is-focused{border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-black:focus:not(:active),html.theme--catppuccin-mocha .button.is-black.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--catppuccin-mocha .button.is-black:active,html.theme--catppuccin-mocha .button.is-black.is-active{background-color:#000;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-black[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-black{background-color:#0a0a0a;border-color:#0a0a0a;box-shadow:none}html.theme--catppuccin-mocha .button.is-black.is-inverted{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-mocha .button.is-black.is-inverted:hover,html.theme--catppuccin-mocha .button.is-black.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--catppuccin-mocha .button.is-black.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-black.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#0a0a0a}html.theme--catppuccin-mocha .button.is-black.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-mocha .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--catppuccin-mocha .button.is-black.is-outlined:hover,html.theme--catppuccin-mocha .button.is-black.is-outlined.is-hovered,html.theme--catppuccin-mocha .button.is-black.is-outlined:focus,html.theme--catppuccin-mocha .button.is-black.is-outlined.is-focused{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--catppuccin-mocha .button.is-black.is-outlined.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--catppuccin-mocha .button.is-black.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .button.is-black.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .button.is-black.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .button.is-black.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-mocha .button.is-black.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--catppuccin-mocha .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-mocha .button.is-black.is-inverted.is-outlined:hover,html.theme--catppuccin-mocha .button.is-black.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-mocha .button.is-black.is-inverted.is-outlined:focus,html.theme--catppuccin-mocha .button.is-black.is-inverted.is-outlined.is-focused{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-mocha .button.is-black.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .button.is-black.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .button.is-black.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--catppuccin-mocha .button.is-black.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-mocha .button.is-light{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-light:hover,html.theme--catppuccin-mocha .button.is-light.is-hovered{background-color:#eee;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-light:focus,html.theme--catppuccin-mocha .button.is-light.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-light:focus:not(:active),html.theme--catppuccin-mocha .button.is-light.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}html.theme--catppuccin-mocha .button.is-light:active,html.theme--catppuccin-mocha .button.is-light.is-active{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-light[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-light{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none}html.theme--catppuccin-mocha .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);color:#f5f5f5}html.theme--catppuccin-mocha .button.is-light.is-inverted:hover,html.theme--catppuccin-mocha .button.is-light.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-light.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#f5f5f5}html.theme--catppuccin-mocha .button.is-light.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-mocha .button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;color:#f5f5f5}html.theme--catppuccin-mocha .button.is-light.is-outlined:hover,html.theme--catppuccin-mocha .button.is-light.is-outlined.is-hovered,html.theme--catppuccin-mocha .button.is-light.is-outlined:focus,html.theme--catppuccin-mocha .button.is-light.is-outlined.is-focused{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-light.is-outlined.is-loading::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}html.theme--catppuccin-mocha .button.is-light.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .button.is-light.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .button.is-light.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .button.is-light.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-mocha .button.is-light.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;box-shadow:none;color:#f5f5f5}html.theme--catppuccin-mocha .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-light.is-inverted.is-outlined:hover,html.theme--catppuccin-mocha .button.is-light.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-mocha .button.is-light.is-inverted.is-outlined:focus,html.theme--catppuccin-mocha .button.is-light.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#f5f5f5}html.theme--catppuccin-mocha .button.is-light.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .button.is-light.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .button.is-light.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}html.theme--catppuccin-mocha .button.is-light.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-dark,html.theme--catppuccin-mocha .content kbd.button{background-color:#313244;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-dark:hover,html.theme--catppuccin-mocha .content kbd.button:hover,html.theme--catppuccin-mocha .button.is-dark.is-hovered,html.theme--catppuccin-mocha .content kbd.button.is-hovered{background-color:#2c2d3d;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-dark:focus,html.theme--catppuccin-mocha .content kbd.button:focus,html.theme--catppuccin-mocha .button.is-dark.is-focused,html.theme--catppuccin-mocha .content kbd.button.is-focused{border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-dark:focus:not(:active),html.theme--catppuccin-mocha .content kbd.button:focus:not(:active),html.theme--catppuccin-mocha .button.is-dark.is-focused:not(:active),html.theme--catppuccin-mocha .content kbd.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(49,50,68,0.25)}html.theme--catppuccin-mocha .button.is-dark:active,html.theme--catppuccin-mocha .content kbd.button:active,html.theme--catppuccin-mocha .button.is-dark.is-active,html.theme--catppuccin-mocha .content kbd.button.is-active{background-color:#262735;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-dark[disabled],html.theme--catppuccin-mocha .content kbd.button[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-dark,fieldset[disabled] html.theme--catppuccin-mocha .content kbd.button{background-color:#313244;border-color:#313244;box-shadow:none}html.theme--catppuccin-mocha .button.is-dark.is-inverted,html.theme--catppuccin-mocha .content kbd.button.is-inverted{background-color:#fff;color:#313244}html.theme--catppuccin-mocha .button.is-dark.is-inverted:hover,html.theme--catppuccin-mocha .content kbd.button.is-inverted:hover,html.theme--catppuccin-mocha .button.is-dark.is-inverted.is-hovered,html.theme--catppuccin-mocha .content kbd.button.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--catppuccin-mocha .button.is-dark.is-inverted[disabled],html.theme--catppuccin-mocha .content kbd.button.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-dark.is-inverted,fieldset[disabled] html.theme--catppuccin-mocha .content kbd.button.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#313244}html.theme--catppuccin-mocha .button.is-dark.is-loading::after,html.theme--catppuccin-mocha .content kbd.button.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-mocha .button.is-dark.is-outlined,html.theme--catppuccin-mocha .content kbd.button.is-outlined{background-color:transparent;border-color:#313244;color:#313244}html.theme--catppuccin-mocha .button.is-dark.is-outlined:hover,html.theme--catppuccin-mocha .content kbd.button.is-outlined:hover,html.theme--catppuccin-mocha .button.is-dark.is-outlined.is-hovered,html.theme--catppuccin-mocha .content kbd.button.is-outlined.is-hovered,html.theme--catppuccin-mocha .button.is-dark.is-outlined:focus,html.theme--catppuccin-mocha .content kbd.button.is-outlined:focus,html.theme--catppuccin-mocha .button.is-dark.is-outlined.is-focused,html.theme--catppuccin-mocha .content kbd.button.is-outlined.is-focused{background-color:#313244;border-color:#313244;color:#fff}html.theme--catppuccin-mocha .button.is-dark.is-outlined.is-loading::after,html.theme--catppuccin-mocha .content kbd.button.is-outlined.is-loading::after{border-color:transparent transparent #313244 #313244 !important}html.theme--catppuccin-mocha .button.is-dark.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .content kbd.button.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .button.is-dark.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .content kbd.button.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .button.is-dark.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .content kbd.button.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .button.is-dark.is-outlined.is-loading.is-focused::after,html.theme--catppuccin-mocha .content kbd.button.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-mocha .button.is-dark.is-outlined[disabled],html.theme--catppuccin-mocha .content kbd.button.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-dark.is-outlined,fieldset[disabled] html.theme--catppuccin-mocha .content kbd.button.is-outlined{background-color:transparent;border-color:#313244;box-shadow:none;color:#313244}html.theme--catppuccin-mocha .button.is-dark.is-inverted.is-outlined,html.theme--catppuccin-mocha .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-mocha .button.is-dark.is-inverted.is-outlined:hover,html.theme--catppuccin-mocha .content kbd.button.is-inverted.is-outlined:hover,html.theme--catppuccin-mocha .button.is-dark.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-mocha .content kbd.button.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-mocha .button.is-dark.is-inverted.is-outlined:focus,html.theme--catppuccin-mocha .content kbd.button.is-inverted.is-outlined:focus,html.theme--catppuccin-mocha .button.is-dark.is-inverted.is-outlined.is-focused,html.theme--catppuccin-mocha .content kbd.button.is-inverted.is-outlined.is-focused{background-color:#fff;color:#313244}html.theme--catppuccin-mocha .button.is-dark.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .content kbd.button.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .content kbd.button.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .button.is-dark.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .content kbd.button.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--catppuccin-mocha .content kbd.button.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #313244 #313244 !important}html.theme--catppuccin-mocha .button.is-dark.is-inverted.is-outlined[disabled],html.theme--catppuccin-mocha .content kbd.button.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-dark.is-inverted.is-outlined,fieldset[disabled] html.theme--catppuccin-mocha .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-mocha .button.is-primary,html.theme--catppuccin-mocha .docstring>section>a.button.docs-sourcelink{background-color:#89b4fa;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-primary:hover,html.theme--catppuccin-mocha .docstring>section>a.button.docs-sourcelink:hover,html.theme--catppuccin-mocha .button.is-primary.is-hovered,html.theme--catppuccin-mocha .docstring>section>a.button.is-hovered.docs-sourcelink{background-color:#7dacf9;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-primary:focus,html.theme--catppuccin-mocha .docstring>section>a.button.docs-sourcelink:focus,html.theme--catppuccin-mocha .button.is-primary.is-focused,html.theme--catppuccin-mocha .docstring>section>a.button.is-focused.docs-sourcelink{border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-primary:focus:not(:active),html.theme--catppuccin-mocha .docstring>section>a.button.docs-sourcelink:focus:not(:active),html.theme--catppuccin-mocha .button.is-primary.is-focused:not(:active),html.theme--catppuccin-mocha .docstring>section>a.button.is-focused.docs-sourcelink:not(:active){box-shadow:0 0 0 0.125em rgba(137,180,250,0.25)}html.theme--catppuccin-mocha .button.is-primary:active,html.theme--catppuccin-mocha .docstring>section>a.button.docs-sourcelink:active,html.theme--catppuccin-mocha .button.is-primary.is-active,html.theme--catppuccin-mocha .docstring>section>a.button.is-active.docs-sourcelink{background-color:#71a4f9;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-primary[disabled],html.theme--catppuccin-mocha .docstring>section>a.button.docs-sourcelink[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-primary,fieldset[disabled] html.theme--catppuccin-mocha .docstring>section>a.button.docs-sourcelink{background-color:#89b4fa;border-color:#89b4fa;box-shadow:none}html.theme--catppuccin-mocha .button.is-primary.is-inverted,html.theme--catppuccin-mocha .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;color:#89b4fa}html.theme--catppuccin-mocha .button.is-primary.is-inverted:hover,html.theme--catppuccin-mocha .docstring>section>a.button.is-inverted.docs-sourcelink:hover,html.theme--catppuccin-mocha .button.is-primary.is-inverted.is-hovered,html.theme--catppuccin-mocha .docstring>section>a.button.is-inverted.is-hovered.docs-sourcelink{background-color:#f2f2f2}html.theme--catppuccin-mocha .button.is-primary.is-inverted[disabled],html.theme--catppuccin-mocha .docstring>section>a.button.is-inverted.docs-sourcelink[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-primary.is-inverted,fieldset[disabled] html.theme--catppuccin-mocha .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;border-color:transparent;box-shadow:none;color:#89b4fa}html.theme--catppuccin-mocha .button.is-primary.is-loading::after,html.theme--catppuccin-mocha .docstring>section>a.button.is-loading.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-mocha .button.is-primary.is-outlined,html.theme--catppuccin-mocha .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#89b4fa;color:#89b4fa}html.theme--catppuccin-mocha .button.is-primary.is-outlined:hover,html.theme--catppuccin-mocha .docstring>section>a.button.is-outlined.docs-sourcelink:hover,html.theme--catppuccin-mocha .button.is-primary.is-outlined.is-hovered,html.theme--catppuccin-mocha .docstring>section>a.button.is-outlined.is-hovered.docs-sourcelink,html.theme--catppuccin-mocha .button.is-primary.is-outlined:focus,html.theme--catppuccin-mocha .docstring>section>a.button.is-outlined.docs-sourcelink:focus,html.theme--catppuccin-mocha .button.is-primary.is-outlined.is-focused,html.theme--catppuccin-mocha .docstring>section>a.button.is-outlined.is-focused.docs-sourcelink{background-color:#89b4fa;border-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .button.is-primary.is-outlined.is-loading::after,html.theme--catppuccin-mocha .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink::after{border-color:transparent transparent #89b4fa #89b4fa !important}html.theme--catppuccin-mocha .button.is-primary.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--catppuccin-mocha .button.is-primary.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .docstring>section>a.button.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--catppuccin-mocha .button.is-primary.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--catppuccin-mocha .button.is-primary.is-outlined.is-loading.is-focused::after,html.theme--catppuccin-mocha .docstring>section>a.button.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-mocha .button.is-primary.is-outlined[disabled],html.theme--catppuccin-mocha .docstring>section>a.button.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-primary.is-outlined,fieldset[disabled] html.theme--catppuccin-mocha .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#89b4fa;box-shadow:none;color:#89b4fa}html.theme--catppuccin-mocha .button.is-primary.is-inverted.is-outlined,html.theme--catppuccin-mocha .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-mocha .button.is-primary.is-inverted.is-outlined:hover,html.theme--catppuccin-mocha .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:hover,html.theme--catppuccin-mocha .button.is-primary.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-mocha .docstring>section>a.button.is-inverted.is-outlined.is-hovered.docs-sourcelink,html.theme--catppuccin-mocha .button.is-primary.is-inverted.is-outlined:focus,html.theme--catppuccin-mocha .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:focus,html.theme--catppuccin-mocha .button.is-primary.is-inverted.is-outlined.is-focused,html.theme--catppuccin-mocha .docstring>section>a.button.is-inverted.is-outlined.is-focused.docs-sourcelink{background-color:#fff;color:#89b4fa}html.theme--catppuccin-mocha .button.is-primary.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--catppuccin-mocha .button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--catppuccin-mocha .button.is-primary.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--catppuccin-mocha .button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--catppuccin-mocha .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #89b4fa #89b4fa !important}html.theme--catppuccin-mocha .button.is-primary.is-inverted.is-outlined[disabled],html.theme--catppuccin-mocha .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-primary.is-inverted.is-outlined,fieldset[disabled] html.theme--catppuccin-mocha .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-mocha .button.is-primary.is-light,html.theme--catppuccin-mocha .docstring>section>a.button.is-light.docs-sourcelink{background-color:#ebf3fe;color:#063c93}html.theme--catppuccin-mocha .button.is-primary.is-light:hover,html.theme--catppuccin-mocha .docstring>section>a.button.is-light.docs-sourcelink:hover,html.theme--catppuccin-mocha .button.is-primary.is-light.is-hovered,html.theme--catppuccin-mocha .docstring>section>a.button.is-light.is-hovered.docs-sourcelink{background-color:#dfebfe;border-color:transparent;color:#063c93}html.theme--catppuccin-mocha .button.is-primary.is-light:active,html.theme--catppuccin-mocha .docstring>section>a.button.is-light.docs-sourcelink:active,html.theme--catppuccin-mocha .button.is-primary.is-light.is-active,html.theme--catppuccin-mocha .docstring>section>a.button.is-light.is-active.docs-sourcelink{background-color:#d3e3fd;border-color:transparent;color:#063c93}html.theme--catppuccin-mocha .button.is-link{background-color:#89b4fa;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-link:hover,html.theme--catppuccin-mocha .button.is-link.is-hovered{background-color:#7dacf9;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-link:focus,html.theme--catppuccin-mocha .button.is-link.is-focused{border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-link:focus:not(:active),html.theme--catppuccin-mocha .button.is-link.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(137,180,250,0.25)}html.theme--catppuccin-mocha .button.is-link:active,html.theme--catppuccin-mocha .button.is-link.is-active{background-color:#71a4f9;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-link[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-link{background-color:#89b4fa;border-color:#89b4fa;box-shadow:none}html.theme--catppuccin-mocha .button.is-link.is-inverted{background-color:#fff;color:#89b4fa}html.theme--catppuccin-mocha .button.is-link.is-inverted:hover,html.theme--catppuccin-mocha .button.is-link.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--catppuccin-mocha .button.is-link.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-link.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#89b4fa}html.theme--catppuccin-mocha .button.is-link.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-mocha .button.is-link.is-outlined{background-color:transparent;border-color:#89b4fa;color:#89b4fa}html.theme--catppuccin-mocha .button.is-link.is-outlined:hover,html.theme--catppuccin-mocha .button.is-link.is-outlined.is-hovered,html.theme--catppuccin-mocha .button.is-link.is-outlined:focus,html.theme--catppuccin-mocha .button.is-link.is-outlined.is-focused{background-color:#89b4fa;border-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .button.is-link.is-outlined.is-loading::after{border-color:transparent transparent #89b4fa #89b4fa !important}html.theme--catppuccin-mocha .button.is-link.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .button.is-link.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .button.is-link.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .button.is-link.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-mocha .button.is-link.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-link.is-outlined{background-color:transparent;border-color:#89b4fa;box-shadow:none;color:#89b4fa}html.theme--catppuccin-mocha .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-mocha .button.is-link.is-inverted.is-outlined:hover,html.theme--catppuccin-mocha .button.is-link.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-mocha .button.is-link.is-inverted.is-outlined:focus,html.theme--catppuccin-mocha .button.is-link.is-inverted.is-outlined.is-focused{background-color:#fff;color:#89b4fa}html.theme--catppuccin-mocha .button.is-link.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .button.is-link.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .button.is-link.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #89b4fa #89b4fa !important}html.theme--catppuccin-mocha .button.is-link.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-mocha .button.is-link.is-light{background-color:#ebf3fe;color:#063c93}html.theme--catppuccin-mocha .button.is-link.is-light:hover,html.theme--catppuccin-mocha .button.is-link.is-light.is-hovered{background-color:#dfebfe;border-color:transparent;color:#063c93}html.theme--catppuccin-mocha .button.is-link.is-light:active,html.theme--catppuccin-mocha .button.is-link.is-light.is-active{background-color:#d3e3fd;border-color:transparent;color:#063c93}html.theme--catppuccin-mocha .button.is-info{background-color:#94e2d5;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-info:hover,html.theme--catppuccin-mocha .button.is-info.is-hovered{background-color:#8adfd1;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-info:focus,html.theme--catppuccin-mocha .button.is-info.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-info:focus:not(:active),html.theme--catppuccin-mocha .button.is-info.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(148,226,213,0.25)}html.theme--catppuccin-mocha .button.is-info:active,html.theme--catppuccin-mocha .button.is-info.is-active{background-color:#80ddcd;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-info[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-info{background-color:#94e2d5;border-color:#94e2d5;box-shadow:none}html.theme--catppuccin-mocha .button.is-info.is-inverted{background-color:rgba(0,0,0,0.7);color:#94e2d5}html.theme--catppuccin-mocha .button.is-info.is-inverted:hover,html.theme--catppuccin-mocha .button.is-info.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-info.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-info.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#94e2d5}html.theme--catppuccin-mocha .button.is-info.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-mocha .button.is-info.is-outlined{background-color:transparent;border-color:#94e2d5;color:#94e2d5}html.theme--catppuccin-mocha .button.is-info.is-outlined:hover,html.theme--catppuccin-mocha .button.is-info.is-outlined.is-hovered,html.theme--catppuccin-mocha .button.is-info.is-outlined:focus,html.theme--catppuccin-mocha .button.is-info.is-outlined.is-focused{background-color:#94e2d5;border-color:#94e2d5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-info.is-outlined.is-loading::after{border-color:transparent transparent #94e2d5 #94e2d5 !important}html.theme--catppuccin-mocha .button.is-info.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .button.is-info.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .button.is-info.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .button.is-info.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-mocha .button.is-info.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-info.is-outlined{background-color:transparent;border-color:#94e2d5;box-shadow:none;color:#94e2d5}html.theme--catppuccin-mocha .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-info.is-inverted.is-outlined:hover,html.theme--catppuccin-mocha .button.is-info.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-mocha .button.is-info.is-inverted.is-outlined:focus,html.theme--catppuccin-mocha .button.is-info.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#94e2d5}html.theme--catppuccin-mocha .button.is-info.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .button.is-info.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .button.is-info.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #94e2d5 #94e2d5 !important}html.theme--catppuccin-mocha .button.is-info.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-info.is-light{background-color:#effbf9;color:#207466}html.theme--catppuccin-mocha .button.is-info.is-light:hover,html.theme--catppuccin-mocha .button.is-info.is-light.is-hovered{background-color:#e5f8f5;border-color:transparent;color:#207466}html.theme--catppuccin-mocha .button.is-info.is-light:active,html.theme--catppuccin-mocha .button.is-info.is-light.is-active{background-color:#dbf5f1;border-color:transparent;color:#207466}html.theme--catppuccin-mocha .button.is-success{background-color:#a6e3a1;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-success:hover,html.theme--catppuccin-mocha .button.is-success.is-hovered{background-color:#9de097;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-success:focus,html.theme--catppuccin-mocha .button.is-success.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-success:focus:not(:active),html.theme--catppuccin-mocha .button.is-success.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(166,227,161,0.25)}html.theme--catppuccin-mocha .button.is-success:active,html.theme--catppuccin-mocha .button.is-success.is-active{background-color:#93dd8d;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-success[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-success{background-color:#a6e3a1;border-color:#a6e3a1;box-shadow:none}html.theme--catppuccin-mocha .button.is-success.is-inverted{background-color:rgba(0,0,0,0.7);color:#a6e3a1}html.theme--catppuccin-mocha .button.is-success.is-inverted:hover,html.theme--catppuccin-mocha .button.is-success.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-success.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-success.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#a6e3a1}html.theme--catppuccin-mocha .button.is-success.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-mocha .button.is-success.is-outlined{background-color:transparent;border-color:#a6e3a1;color:#a6e3a1}html.theme--catppuccin-mocha .button.is-success.is-outlined:hover,html.theme--catppuccin-mocha .button.is-success.is-outlined.is-hovered,html.theme--catppuccin-mocha .button.is-success.is-outlined:focus,html.theme--catppuccin-mocha .button.is-success.is-outlined.is-focused{background-color:#a6e3a1;border-color:#a6e3a1;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-success.is-outlined.is-loading::after{border-color:transparent transparent #a6e3a1 #a6e3a1 !important}html.theme--catppuccin-mocha .button.is-success.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .button.is-success.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .button.is-success.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .button.is-success.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-mocha .button.is-success.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-success.is-outlined{background-color:transparent;border-color:#a6e3a1;box-shadow:none;color:#a6e3a1}html.theme--catppuccin-mocha .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-success.is-inverted.is-outlined:hover,html.theme--catppuccin-mocha .button.is-success.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-mocha .button.is-success.is-inverted.is-outlined:focus,html.theme--catppuccin-mocha .button.is-success.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#a6e3a1}html.theme--catppuccin-mocha .button.is-success.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .button.is-success.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .button.is-success.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #a6e3a1 #a6e3a1 !important}html.theme--catppuccin-mocha .button.is-success.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-success.is-light{background-color:#f0faef;color:#287222}html.theme--catppuccin-mocha .button.is-success.is-light:hover,html.theme--catppuccin-mocha .button.is-success.is-light.is-hovered{background-color:#e7f7e5;border-color:transparent;color:#287222}html.theme--catppuccin-mocha .button.is-success.is-light:active,html.theme--catppuccin-mocha .button.is-success.is-light.is-active{background-color:#def4dc;border-color:transparent;color:#287222}html.theme--catppuccin-mocha .button.is-warning{background-color:#f9e2af;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-warning:hover,html.theme--catppuccin-mocha .button.is-warning.is-hovered{background-color:#f8dea3;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-warning:focus,html.theme--catppuccin-mocha .button.is-warning.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-warning:focus:not(:active),html.theme--catppuccin-mocha .button.is-warning.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(249,226,175,0.25)}html.theme--catppuccin-mocha .button.is-warning:active,html.theme--catppuccin-mocha .button.is-warning.is-active{background-color:#f7d997;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-warning[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-warning{background-color:#f9e2af;border-color:#f9e2af;box-shadow:none}html.theme--catppuccin-mocha .button.is-warning.is-inverted{background-color:rgba(0,0,0,0.7);color:#f9e2af}html.theme--catppuccin-mocha .button.is-warning.is-inverted:hover,html.theme--catppuccin-mocha .button.is-warning.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-warning.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-warning.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#f9e2af}html.theme--catppuccin-mocha .button.is-warning.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-mocha .button.is-warning.is-outlined{background-color:transparent;border-color:#f9e2af;color:#f9e2af}html.theme--catppuccin-mocha .button.is-warning.is-outlined:hover,html.theme--catppuccin-mocha .button.is-warning.is-outlined.is-hovered,html.theme--catppuccin-mocha .button.is-warning.is-outlined:focus,html.theme--catppuccin-mocha .button.is-warning.is-outlined.is-focused{background-color:#f9e2af;border-color:#f9e2af;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-warning.is-outlined.is-loading::after{border-color:transparent transparent #f9e2af #f9e2af !important}html.theme--catppuccin-mocha .button.is-warning.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .button.is-warning.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .button.is-warning.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .button.is-warning.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--catppuccin-mocha .button.is-warning.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-warning.is-outlined{background-color:transparent;border-color:#f9e2af;box-shadow:none;color:#f9e2af}html.theme--catppuccin-mocha .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-warning.is-inverted.is-outlined:hover,html.theme--catppuccin-mocha .button.is-warning.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-mocha .button.is-warning.is-inverted.is-outlined:focus,html.theme--catppuccin-mocha .button.is-warning.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#f9e2af}html.theme--catppuccin-mocha .button.is-warning.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .button.is-warning.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #f9e2af #f9e2af !important}html.theme--catppuccin-mocha .button.is-warning.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .button.is-warning.is-light{background-color:#fef8ec;color:#8a620a}html.theme--catppuccin-mocha .button.is-warning.is-light:hover,html.theme--catppuccin-mocha .button.is-warning.is-light.is-hovered{background-color:#fdf4e0;border-color:transparent;color:#8a620a}html.theme--catppuccin-mocha .button.is-warning.is-light:active,html.theme--catppuccin-mocha .button.is-warning.is-light.is-active{background-color:#fcf0d4;border-color:transparent;color:#8a620a}html.theme--catppuccin-mocha .button.is-danger{background-color:#f38ba8;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-danger:hover,html.theme--catppuccin-mocha .button.is-danger.is-hovered{background-color:#f27f9f;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-danger:focus,html.theme--catppuccin-mocha .button.is-danger.is-focused{border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-danger:focus:not(:active),html.theme--catppuccin-mocha .button.is-danger.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(243,139,168,0.25)}html.theme--catppuccin-mocha .button.is-danger:active,html.theme--catppuccin-mocha .button.is-danger.is-active{background-color:#f17497;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .button.is-danger[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-danger{background-color:#f38ba8;border-color:#f38ba8;box-shadow:none}html.theme--catppuccin-mocha .button.is-danger.is-inverted{background-color:#fff;color:#f38ba8}html.theme--catppuccin-mocha .button.is-danger.is-inverted:hover,html.theme--catppuccin-mocha .button.is-danger.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--catppuccin-mocha .button.is-danger.is-inverted[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-danger.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#f38ba8}html.theme--catppuccin-mocha .button.is-danger.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-mocha .button.is-danger.is-outlined{background-color:transparent;border-color:#f38ba8;color:#f38ba8}html.theme--catppuccin-mocha .button.is-danger.is-outlined:hover,html.theme--catppuccin-mocha .button.is-danger.is-outlined.is-hovered,html.theme--catppuccin-mocha .button.is-danger.is-outlined:focus,html.theme--catppuccin-mocha .button.is-danger.is-outlined.is-focused{background-color:#f38ba8;border-color:#f38ba8;color:#fff}html.theme--catppuccin-mocha .button.is-danger.is-outlined.is-loading::after{border-color:transparent transparent #f38ba8 #f38ba8 !important}html.theme--catppuccin-mocha .button.is-danger.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .button.is-danger.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .button.is-danger.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .button.is-danger.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--catppuccin-mocha .button.is-danger.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-danger.is-outlined{background-color:transparent;border-color:#f38ba8;box-shadow:none;color:#f38ba8}html.theme--catppuccin-mocha .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--catppuccin-mocha .button.is-danger.is-inverted.is-outlined:hover,html.theme--catppuccin-mocha .button.is-danger.is-inverted.is-outlined.is-hovered,html.theme--catppuccin-mocha .button.is-danger.is-inverted.is-outlined:focus,html.theme--catppuccin-mocha .button.is-danger.is-inverted.is-outlined.is-focused{background-color:#fff;color:#f38ba8}html.theme--catppuccin-mocha .button.is-danger.is-inverted.is-outlined.is-loading:hover::after,html.theme--catppuccin-mocha .button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--catppuccin-mocha .button.is-danger.is-inverted.is-outlined.is-loading:focus::after,html.theme--catppuccin-mocha .button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #f38ba8 #f38ba8 !important}html.theme--catppuccin-mocha .button.is-danger.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--catppuccin-mocha .button.is-danger.is-light{background-color:#fdedf1;color:#991036}html.theme--catppuccin-mocha .button.is-danger.is-light:hover,html.theme--catppuccin-mocha .button.is-danger.is-light.is-hovered{background-color:#fce1e8;border-color:transparent;color:#991036}html.theme--catppuccin-mocha .button.is-danger.is-light:active,html.theme--catppuccin-mocha .button.is-danger.is-light.is-active{background-color:#fbd5e0;border-color:transparent;color:#991036}html.theme--catppuccin-mocha .button.is-small,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.button{font-size:.75rem}html.theme--catppuccin-mocha .button.is-small:not(.is-rounded),html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.button:not(.is-rounded){border-radius:3px}html.theme--catppuccin-mocha .button.is-normal{font-size:1rem}html.theme--catppuccin-mocha .button.is-medium{font-size:1.25rem}html.theme--catppuccin-mocha .button.is-large{font-size:1.5rem}html.theme--catppuccin-mocha .button[disabled],fieldset[disabled] html.theme--catppuccin-mocha .button{background-color:#6c7086;border-color:#585b70;box-shadow:none;opacity:.5}html.theme--catppuccin-mocha .button.is-fullwidth{display:flex;width:100%}html.theme--catppuccin-mocha .button.is-loading{color:transparent !important;pointer-events:none}html.theme--catppuccin-mocha .button.is-loading::after{position:absolute;left:calc(50% - (1em * 0.5));top:calc(50% - (1em * 0.5));position:absolute !important}html.theme--catppuccin-mocha .button.is-static{background-color:#181825;border-color:#585b70;color:#7f849c;box-shadow:none;pointer-events:none}html.theme--catppuccin-mocha .button.is-rounded,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.button{border-radius:9999px;padding-left:calc(1em + 0.25em);padding-right:calc(1em + 0.25em)}html.theme--catppuccin-mocha .buttons{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--catppuccin-mocha .buttons .button{margin-bottom:0.5rem}html.theme--catppuccin-mocha .buttons .button:not(:last-child):not(.is-fullwidth){margin-right:.5rem}html.theme--catppuccin-mocha .buttons:last-child{margin-bottom:-0.5rem}html.theme--catppuccin-mocha .buttons:not(:last-child){margin-bottom:1rem}html.theme--catppuccin-mocha .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large){font-size:.75rem}html.theme--catppuccin-mocha .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large):not(.is-rounded){border-radius:3px}html.theme--catppuccin-mocha .buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large){font-size:1.25rem}html.theme--catppuccin-mocha .buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium){font-size:1.5rem}html.theme--catppuccin-mocha .buttons.has-addons .button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}html.theme--catppuccin-mocha .buttons.has-addons .button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}html.theme--catppuccin-mocha .buttons.has-addons .button:last-child{margin-right:0}html.theme--catppuccin-mocha .buttons.has-addons .button:hover,html.theme--catppuccin-mocha .buttons.has-addons .button.is-hovered{z-index:2}html.theme--catppuccin-mocha .buttons.has-addons .button:focus,html.theme--catppuccin-mocha .buttons.has-addons .button.is-focused,html.theme--catppuccin-mocha .buttons.has-addons .button:active,html.theme--catppuccin-mocha .buttons.has-addons .button.is-active,html.theme--catppuccin-mocha .buttons.has-addons .button.is-selected{z-index:3}html.theme--catppuccin-mocha .buttons.has-addons .button:focus:hover,html.theme--catppuccin-mocha .buttons.has-addons .button.is-focused:hover,html.theme--catppuccin-mocha .buttons.has-addons .button:active:hover,html.theme--catppuccin-mocha .buttons.has-addons .button.is-active:hover,html.theme--catppuccin-mocha .buttons.has-addons .button.is-selected:hover{z-index:4}html.theme--catppuccin-mocha .buttons.has-addons .button.is-expanded{flex-grow:1;flex-shrink:1}html.theme--catppuccin-mocha .buttons.is-centered{justify-content:center}html.theme--catppuccin-mocha .buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}html.theme--catppuccin-mocha .buttons.is-right{justify-content:flex-end}html.theme--catppuccin-mocha .buttons.is-right:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .button.is-responsive.is-small,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.5625rem}html.theme--catppuccin-mocha .button.is-responsive,html.theme--catppuccin-mocha .button.is-responsive.is-normal{font-size:.65625rem}html.theme--catppuccin-mocha .button.is-responsive.is-medium{font-size:.75rem}html.theme--catppuccin-mocha .button.is-responsive.is-large{font-size:1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-mocha .button.is-responsive.is-small,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.65625rem}html.theme--catppuccin-mocha .button.is-responsive,html.theme--catppuccin-mocha .button.is-responsive.is-normal{font-size:.75rem}html.theme--catppuccin-mocha .button.is-responsive.is-medium{font-size:1rem}html.theme--catppuccin-mocha .button.is-responsive.is-large{font-size:1.25rem}}html.theme--catppuccin-mocha .container{flex-grow:1;margin:0 auto;position:relative;width:auto}html.theme--catppuccin-mocha .container.is-fluid{max-width:none !important;padding-left:32px;padding-right:32px;width:100%}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .container{max-width:992px}}@media screen and (max-width: 1215px){html.theme--catppuccin-mocha .container.is-widescreen:not(.is-max-desktop){max-width:1152px}}@media screen and (max-width: 1407px){html.theme--catppuccin-mocha .container.is-fullhd:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}@media screen and (min-width: 1216px){html.theme--catppuccin-mocha .container:not(.is-max-desktop){max-width:1152px}}@media screen and (min-width: 1408px){html.theme--catppuccin-mocha .container:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}html.theme--catppuccin-mocha .content li+li{margin-top:0.25em}html.theme--catppuccin-mocha .content p:not(:last-child),html.theme--catppuccin-mocha .content dl:not(:last-child),html.theme--catppuccin-mocha .content ol:not(:last-child),html.theme--catppuccin-mocha .content ul:not(:last-child),html.theme--catppuccin-mocha .content blockquote:not(:last-child),html.theme--catppuccin-mocha .content pre:not(:last-child),html.theme--catppuccin-mocha .content table:not(:last-child){margin-bottom:1em}html.theme--catppuccin-mocha .content h1,html.theme--catppuccin-mocha .content h2,html.theme--catppuccin-mocha .content h3,html.theme--catppuccin-mocha .content h4,html.theme--catppuccin-mocha .content h5,html.theme--catppuccin-mocha .content h6{color:#cdd6f4;font-weight:600;line-height:1.125}html.theme--catppuccin-mocha .content h1{font-size:2em;margin-bottom:0.5em}html.theme--catppuccin-mocha .content h1:not(:first-child){margin-top:1em}html.theme--catppuccin-mocha .content h2{font-size:1.75em;margin-bottom:0.5714em}html.theme--catppuccin-mocha .content h2:not(:first-child){margin-top:1.1428em}html.theme--catppuccin-mocha .content h3{font-size:1.5em;margin-bottom:0.6666em}html.theme--catppuccin-mocha .content h3:not(:first-child){margin-top:1.3333em}html.theme--catppuccin-mocha .content h4{font-size:1.25em;margin-bottom:0.8em}html.theme--catppuccin-mocha .content h5{font-size:1.125em;margin-bottom:0.8888em}html.theme--catppuccin-mocha .content h6{font-size:1em;margin-bottom:1em}html.theme--catppuccin-mocha .content blockquote{background-color:#181825;border-left:5px solid #585b70;padding:1.25em 1.5em}html.theme--catppuccin-mocha .content ol{list-style-position:outside;margin-left:2em;margin-top:1em}html.theme--catppuccin-mocha .content ol:not([type]){list-style-type:decimal}html.theme--catppuccin-mocha .content ol.is-lower-alpha:not([type]){list-style-type:lower-alpha}html.theme--catppuccin-mocha .content ol.is-lower-roman:not([type]){list-style-type:lower-roman}html.theme--catppuccin-mocha .content ol.is-upper-alpha:not([type]){list-style-type:upper-alpha}html.theme--catppuccin-mocha .content ol.is-upper-roman:not([type]){list-style-type:upper-roman}html.theme--catppuccin-mocha .content ul{list-style:disc outside;margin-left:2em;margin-top:1em}html.theme--catppuccin-mocha .content ul ul{list-style-type:circle;margin-top:0.5em}html.theme--catppuccin-mocha .content ul ul ul{list-style-type:square}html.theme--catppuccin-mocha .content dd{margin-left:2em}html.theme--catppuccin-mocha .content figure{margin-left:2em;margin-right:2em;text-align:center}html.theme--catppuccin-mocha .content figure:not(:first-child){margin-top:2em}html.theme--catppuccin-mocha .content figure:not(:last-child){margin-bottom:2em}html.theme--catppuccin-mocha .content figure img{display:inline-block}html.theme--catppuccin-mocha .content figure figcaption{font-style:italic}html.theme--catppuccin-mocha .content pre{-webkit-overflow-scrolling:touch;overflow-x:auto;padding:0;white-space:pre;word-wrap:normal}html.theme--catppuccin-mocha .content sup,html.theme--catppuccin-mocha .content sub{font-size:75%}html.theme--catppuccin-mocha .content table{width:100%}html.theme--catppuccin-mocha .content table td,html.theme--catppuccin-mocha .content table th{border:1px solid #585b70;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--catppuccin-mocha .content table th{color:#b8c5ef}html.theme--catppuccin-mocha .content table th:not([align]){text-align:inherit}html.theme--catppuccin-mocha .content table thead td,html.theme--catppuccin-mocha .content table thead th{border-width:0 0 2px;color:#b8c5ef}html.theme--catppuccin-mocha .content table tfoot td,html.theme--catppuccin-mocha .content table tfoot th{border-width:2px 0 0;color:#b8c5ef}html.theme--catppuccin-mocha .content table tbody tr:last-child td,html.theme--catppuccin-mocha .content table tbody tr:last-child th{border-bottom-width:0}html.theme--catppuccin-mocha .content .tabs li+li{margin-top:0}html.theme--catppuccin-mocha .content.is-small,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.content{font-size:.75rem}html.theme--catppuccin-mocha .content.is-normal{font-size:1rem}html.theme--catppuccin-mocha .content.is-medium{font-size:1.25rem}html.theme--catppuccin-mocha .content.is-large{font-size:1.5rem}html.theme--catppuccin-mocha .icon{align-items:center;display:inline-flex;justify-content:center;height:1.5rem;width:1.5rem}html.theme--catppuccin-mocha .icon.is-small,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.icon{height:1rem;width:1rem}html.theme--catppuccin-mocha .icon.is-medium{height:2rem;width:2rem}html.theme--catppuccin-mocha .icon.is-large{height:3rem;width:3rem}html.theme--catppuccin-mocha .icon-text{align-items:flex-start;color:inherit;display:inline-flex;flex-wrap:wrap;line-height:1.5rem;vertical-align:top}html.theme--catppuccin-mocha .icon-text .icon{flex-grow:0;flex-shrink:0}html.theme--catppuccin-mocha .icon-text .icon:not(:last-child){margin-right:.25em}html.theme--catppuccin-mocha .icon-text .icon:not(:first-child){margin-left:.25em}html.theme--catppuccin-mocha div.icon-text{display:flex}html.theme--catppuccin-mocha .image,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img{display:block;position:relative}html.theme--catppuccin-mocha .image img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img img{display:block;height:auto;width:100%}html.theme--catppuccin-mocha .image img.is-rounded,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img img.is-rounded{border-radius:9999px}html.theme--catppuccin-mocha .image.is-fullwidth,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-fullwidth{width:100%}html.theme--catppuccin-mocha .image.is-square img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--catppuccin-mocha .image.is-square .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--catppuccin-mocha .image.is-1by1 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--catppuccin-mocha .image.is-1by1 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--catppuccin-mocha .image.is-5by4 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--catppuccin-mocha .image.is-5by4 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--catppuccin-mocha .image.is-4by3 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--catppuccin-mocha .image.is-4by3 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--catppuccin-mocha .image.is-3by2 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--catppuccin-mocha .image.is-3by2 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--catppuccin-mocha .image.is-5by3 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--catppuccin-mocha .image.is-5by3 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--catppuccin-mocha .image.is-16by9 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--catppuccin-mocha .image.is-16by9 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--catppuccin-mocha .image.is-2by1 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--catppuccin-mocha .image.is-2by1 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--catppuccin-mocha .image.is-3by1 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--catppuccin-mocha .image.is-3by1 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--catppuccin-mocha .image.is-4by5 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--catppuccin-mocha .image.is-4by5 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--catppuccin-mocha .image.is-3by4 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--catppuccin-mocha .image.is-3by4 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--catppuccin-mocha .image.is-2by3 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--catppuccin-mocha .image.is-2by3 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--catppuccin-mocha .image.is-3by5 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--catppuccin-mocha .image.is-3by5 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--catppuccin-mocha .image.is-9by16 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--catppuccin-mocha .image.is-9by16 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--catppuccin-mocha .image.is-1by2 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--catppuccin-mocha .image.is-1by2 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--catppuccin-mocha .image.is-1by3 img,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--catppuccin-mocha .image.is-1by3 .has-ratio,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio{height:100%;width:100%}html.theme--catppuccin-mocha .image.is-square,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-square,html.theme--catppuccin-mocha .image.is-1by1,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-1by1{padding-top:100%}html.theme--catppuccin-mocha .image.is-5by4,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-5by4{padding-top:80%}html.theme--catppuccin-mocha .image.is-4by3,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-4by3{padding-top:75%}html.theme--catppuccin-mocha .image.is-3by2,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by2{padding-top:66.6666%}html.theme--catppuccin-mocha .image.is-5by3,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-5by3{padding-top:60%}html.theme--catppuccin-mocha .image.is-16by9,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-16by9{padding-top:56.25%}html.theme--catppuccin-mocha .image.is-2by1,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-2by1{padding-top:50%}html.theme--catppuccin-mocha .image.is-3by1,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by1{padding-top:33.3333%}html.theme--catppuccin-mocha .image.is-4by5,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-4by5{padding-top:125%}html.theme--catppuccin-mocha .image.is-3by4,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by4{padding-top:133.3333%}html.theme--catppuccin-mocha .image.is-2by3,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-2by3{padding-top:150%}html.theme--catppuccin-mocha .image.is-3by5,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-3by5{padding-top:166.6666%}html.theme--catppuccin-mocha .image.is-9by16,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-9by16{padding-top:177.7777%}html.theme--catppuccin-mocha .image.is-1by2,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-1by2{padding-top:200%}html.theme--catppuccin-mocha .image.is-1by3,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-1by3{padding-top:300%}html.theme--catppuccin-mocha .image.is-16x16,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-16x16{height:16px;width:16px}html.theme--catppuccin-mocha .image.is-24x24,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-24x24{height:24px;width:24px}html.theme--catppuccin-mocha .image.is-32x32,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-32x32{height:32px;width:32px}html.theme--catppuccin-mocha .image.is-48x48,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-48x48{height:48px;width:48px}html.theme--catppuccin-mocha .image.is-64x64,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-64x64{height:64px;width:64px}html.theme--catppuccin-mocha .image.is-96x96,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-96x96{height:96px;width:96px}html.theme--catppuccin-mocha .image.is-128x128,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img.is-128x128{height:128px;width:128px}html.theme--catppuccin-mocha .notification{background-color:#181825;border-radius:.4em;position:relative;padding:1.25rem 2.5rem 1.25rem 1.5rem}html.theme--catppuccin-mocha .notification a:not(.button):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--catppuccin-mocha .notification strong{color:currentColor}html.theme--catppuccin-mocha .notification code,html.theme--catppuccin-mocha .notification pre{background:#fff}html.theme--catppuccin-mocha .notification pre code{background:transparent}html.theme--catppuccin-mocha .notification>.delete{right:.5rem;position:absolute;top:0.5rem}html.theme--catppuccin-mocha .notification .title,html.theme--catppuccin-mocha .notification .subtitle,html.theme--catppuccin-mocha .notification .content{color:currentColor}html.theme--catppuccin-mocha .notification.is-white{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-mocha .notification.is-black{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-mocha .notification.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .notification.is-dark,html.theme--catppuccin-mocha .content kbd.notification{background-color:#313244;color:#fff}html.theme--catppuccin-mocha .notification.is-primary,html.theme--catppuccin-mocha .docstring>section>a.notification.docs-sourcelink{background-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .notification.is-primary.is-light,html.theme--catppuccin-mocha .docstring>section>a.notification.is-light.docs-sourcelink{background-color:#ebf3fe;color:#063c93}html.theme--catppuccin-mocha .notification.is-link{background-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .notification.is-link.is-light{background-color:#ebf3fe;color:#063c93}html.theme--catppuccin-mocha .notification.is-info{background-color:#94e2d5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .notification.is-info.is-light{background-color:#effbf9;color:#207466}html.theme--catppuccin-mocha .notification.is-success{background-color:#a6e3a1;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .notification.is-success.is-light{background-color:#f0faef;color:#287222}html.theme--catppuccin-mocha .notification.is-warning{background-color:#f9e2af;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .notification.is-warning.is-light{background-color:#fef8ec;color:#8a620a}html.theme--catppuccin-mocha .notification.is-danger{background-color:#f38ba8;color:#fff}html.theme--catppuccin-mocha .notification.is-danger.is-light{background-color:#fdedf1;color:#991036}html.theme--catppuccin-mocha .progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:9999px;display:block;height:1rem;overflow:hidden;padding:0;width:100%}html.theme--catppuccin-mocha .progress::-webkit-progress-bar{background-color:#45475a}html.theme--catppuccin-mocha .progress::-webkit-progress-value{background-color:#7f849c}html.theme--catppuccin-mocha .progress::-moz-progress-bar{background-color:#7f849c}html.theme--catppuccin-mocha .progress::-ms-fill{background-color:#7f849c;border:none}html.theme--catppuccin-mocha .progress.is-white::-webkit-progress-value{background-color:#fff}html.theme--catppuccin-mocha .progress.is-white::-moz-progress-bar{background-color:#fff}html.theme--catppuccin-mocha .progress.is-white::-ms-fill{background-color:#fff}html.theme--catppuccin-mocha .progress.is-white:indeterminate{background-image:linear-gradient(to right, #fff 30%, #45475a 30%)}html.theme--catppuccin-mocha .progress.is-black::-webkit-progress-value{background-color:#0a0a0a}html.theme--catppuccin-mocha .progress.is-black::-moz-progress-bar{background-color:#0a0a0a}html.theme--catppuccin-mocha .progress.is-black::-ms-fill{background-color:#0a0a0a}html.theme--catppuccin-mocha .progress.is-black:indeterminate{background-image:linear-gradient(to right, #0a0a0a 30%, #45475a 30%)}html.theme--catppuccin-mocha .progress.is-light::-webkit-progress-value{background-color:#f5f5f5}html.theme--catppuccin-mocha .progress.is-light::-moz-progress-bar{background-color:#f5f5f5}html.theme--catppuccin-mocha .progress.is-light::-ms-fill{background-color:#f5f5f5}html.theme--catppuccin-mocha .progress.is-light:indeterminate{background-image:linear-gradient(to right, #f5f5f5 30%, #45475a 30%)}html.theme--catppuccin-mocha .progress.is-dark::-webkit-progress-value,html.theme--catppuccin-mocha .content kbd.progress::-webkit-progress-value{background-color:#313244}html.theme--catppuccin-mocha .progress.is-dark::-moz-progress-bar,html.theme--catppuccin-mocha .content kbd.progress::-moz-progress-bar{background-color:#313244}html.theme--catppuccin-mocha .progress.is-dark::-ms-fill,html.theme--catppuccin-mocha .content kbd.progress::-ms-fill{background-color:#313244}html.theme--catppuccin-mocha .progress.is-dark:indeterminate,html.theme--catppuccin-mocha .content kbd.progress:indeterminate{background-image:linear-gradient(to right, #313244 30%, #45475a 30%)}html.theme--catppuccin-mocha .progress.is-primary::-webkit-progress-value,html.theme--catppuccin-mocha .docstring>section>a.progress.docs-sourcelink::-webkit-progress-value{background-color:#89b4fa}html.theme--catppuccin-mocha .progress.is-primary::-moz-progress-bar,html.theme--catppuccin-mocha .docstring>section>a.progress.docs-sourcelink::-moz-progress-bar{background-color:#89b4fa}html.theme--catppuccin-mocha .progress.is-primary::-ms-fill,html.theme--catppuccin-mocha .docstring>section>a.progress.docs-sourcelink::-ms-fill{background-color:#89b4fa}html.theme--catppuccin-mocha .progress.is-primary:indeterminate,html.theme--catppuccin-mocha .docstring>section>a.progress.docs-sourcelink:indeterminate{background-image:linear-gradient(to right, #89b4fa 30%, #45475a 30%)}html.theme--catppuccin-mocha .progress.is-link::-webkit-progress-value{background-color:#89b4fa}html.theme--catppuccin-mocha .progress.is-link::-moz-progress-bar{background-color:#89b4fa}html.theme--catppuccin-mocha .progress.is-link::-ms-fill{background-color:#89b4fa}html.theme--catppuccin-mocha .progress.is-link:indeterminate{background-image:linear-gradient(to right, #89b4fa 30%, #45475a 30%)}html.theme--catppuccin-mocha .progress.is-info::-webkit-progress-value{background-color:#94e2d5}html.theme--catppuccin-mocha .progress.is-info::-moz-progress-bar{background-color:#94e2d5}html.theme--catppuccin-mocha .progress.is-info::-ms-fill{background-color:#94e2d5}html.theme--catppuccin-mocha .progress.is-info:indeterminate{background-image:linear-gradient(to right, #94e2d5 30%, #45475a 30%)}html.theme--catppuccin-mocha .progress.is-success::-webkit-progress-value{background-color:#a6e3a1}html.theme--catppuccin-mocha .progress.is-success::-moz-progress-bar{background-color:#a6e3a1}html.theme--catppuccin-mocha .progress.is-success::-ms-fill{background-color:#a6e3a1}html.theme--catppuccin-mocha .progress.is-success:indeterminate{background-image:linear-gradient(to right, #a6e3a1 30%, #45475a 30%)}html.theme--catppuccin-mocha .progress.is-warning::-webkit-progress-value{background-color:#f9e2af}html.theme--catppuccin-mocha .progress.is-warning::-moz-progress-bar{background-color:#f9e2af}html.theme--catppuccin-mocha .progress.is-warning::-ms-fill{background-color:#f9e2af}html.theme--catppuccin-mocha .progress.is-warning:indeterminate{background-image:linear-gradient(to right, #f9e2af 30%, #45475a 30%)}html.theme--catppuccin-mocha .progress.is-danger::-webkit-progress-value{background-color:#f38ba8}html.theme--catppuccin-mocha .progress.is-danger::-moz-progress-bar{background-color:#f38ba8}html.theme--catppuccin-mocha .progress.is-danger::-ms-fill{background-color:#f38ba8}html.theme--catppuccin-mocha .progress.is-danger:indeterminate{background-image:linear-gradient(to right, #f38ba8 30%, #45475a 30%)}html.theme--catppuccin-mocha .progress:indeterminate{animation-duration:1.5s;animation-iteration-count:infinite;animation-name:moveIndeterminate;animation-timing-function:linear;background-color:#45475a;background-image:linear-gradient(to right, #cdd6f4 30%, #45475a 30%);background-position:top left;background-repeat:no-repeat;background-size:150% 150%}html.theme--catppuccin-mocha .progress:indeterminate::-webkit-progress-bar{background-color:transparent}html.theme--catppuccin-mocha .progress:indeterminate::-moz-progress-bar{background-color:transparent}html.theme--catppuccin-mocha .progress:indeterminate::-ms-fill{animation-name:none}html.theme--catppuccin-mocha .progress.is-small,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.progress{height:.75rem}html.theme--catppuccin-mocha .progress.is-medium{height:1.25rem}html.theme--catppuccin-mocha .progress.is-large{height:1.5rem}@keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}html.theme--catppuccin-mocha .table{background-color:#45475a;color:#cdd6f4}html.theme--catppuccin-mocha .table td,html.theme--catppuccin-mocha .table th{border:1px solid #585b70;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--catppuccin-mocha .table td.is-white,html.theme--catppuccin-mocha .table th.is-white{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--catppuccin-mocha .table td.is-black,html.theme--catppuccin-mocha .table th.is-black{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--catppuccin-mocha .table td.is-light,html.theme--catppuccin-mocha .table th.is-light{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .table td.is-dark,html.theme--catppuccin-mocha .table th.is-dark{background-color:#313244;border-color:#313244;color:#fff}html.theme--catppuccin-mocha .table td.is-primary,html.theme--catppuccin-mocha .table th.is-primary{background-color:#89b4fa;border-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .table td.is-link,html.theme--catppuccin-mocha .table th.is-link{background-color:#89b4fa;border-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .table td.is-info,html.theme--catppuccin-mocha .table th.is-info{background-color:#94e2d5;border-color:#94e2d5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .table td.is-success,html.theme--catppuccin-mocha .table th.is-success{background-color:#a6e3a1;border-color:#a6e3a1;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .table td.is-warning,html.theme--catppuccin-mocha .table th.is-warning{background-color:#f9e2af;border-color:#f9e2af;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .table td.is-danger,html.theme--catppuccin-mocha .table th.is-danger{background-color:#f38ba8;border-color:#f38ba8;color:#fff}html.theme--catppuccin-mocha .table td.is-narrow,html.theme--catppuccin-mocha .table th.is-narrow{white-space:nowrap;width:1%}html.theme--catppuccin-mocha .table td.is-selected,html.theme--catppuccin-mocha .table th.is-selected{background-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .table td.is-selected a,html.theme--catppuccin-mocha .table td.is-selected strong,html.theme--catppuccin-mocha .table th.is-selected a,html.theme--catppuccin-mocha .table th.is-selected strong{color:currentColor}html.theme--catppuccin-mocha .table td.is-vcentered,html.theme--catppuccin-mocha .table th.is-vcentered{vertical-align:middle}html.theme--catppuccin-mocha .table th{color:#b8c5ef}html.theme--catppuccin-mocha .table th:not([align]){text-align:left}html.theme--catppuccin-mocha .table tr.is-selected{background-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .table tr.is-selected a,html.theme--catppuccin-mocha .table tr.is-selected strong{color:currentColor}html.theme--catppuccin-mocha .table tr.is-selected td,html.theme--catppuccin-mocha .table tr.is-selected th{border-color:#fff;color:currentColor}html.theme--catppuccin-mocha .table thead{background-color:rgba(0,0,0,0)}html.theme--catppuccin-mocha .table thead td,html.theme--catppuccin-mocha .table thead th{border-width:0 0 2px;color:#b8c5ef}html.theme--catppuccin-mocha .table tfoot{background-color:rgba(0,0,0,0)}html.theme--catppuccin-mocha .table tfoot td,html.theme--catppuccin-mocha .table tfoot th{border-width:2px 0 0;color:#b8c5ef}html.theme--catppuccin-mocha .table tbody{background-color:rgba(0,0,0,0)}html.theme--catppuccin-mocha .table tbody tr:last-child td,html.theme--catppuccin-mocha .table tbody tr:last-child th{border-bottom-width:0}html.theme--catppuccin-mocha .table.is-bordered td,html.theme--catppuccin-mocha .table.is-bordered th{border-width:1px}html.theme--catppuccin-mocha .table.is-bordered tr:last-child td,html.theme--catppuccin-mocha .table.is-bordered tr:last-child th{border-bottom-width:1px}html.theme--catppuccin-mocha .table.is-fullwidth{width:100%}html.theme--catppuccin-mocha .table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#313244}html.theme--catppuccin-mocha .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover{background-color:#313244}html.theme--catppuccin-mocha .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even){background-color:#35364a}html.theme--catppuccin-mocha .table.is-narrow td,html.theme--catppuccin-mocha .table.is-narrow th{padding:0.25em 0.5em}html.theme--catppuccin-mocha .table.is-striped tbody tr:not(.is-selected):nth-child(even){background-color:#313244}html.theme--catppuccin-mocha .table-container{-webkit-overflow-scrolling:touch;overflow:auto;overflow-y:hidden;max-width:100%}html.theme--catppuccin-mocha .tags{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--catppuccin-mocha .tags .tag,html.theme--catppuccin-mocha .tags .content kbd,html.theme--catppuccin-mocha .content .tags kbd,html.theme--catppuccin-mocha .tags .docstring>section>a.docs-sourcelink{margin-bottom:0.5rem}html.theme--catppuccin-mocha .tags .tag:not(:last-child),html.theme--catppuccin-mocha .tags .content kbd:not(:last-child),html.theme--catppuccin-mocha .content .tags kbd:not(:last-child),html.theme--catppuccin-mocha .tags .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:.5rem}html.theme--catppuccin-mocha .tags:last-child{margin-bottom:-0.5rem}html.theme--catppuccin-mocha .tags:not(:last-child){margin-bottom:1rem}html.theme--catppuccin-mocha .tags.are-medium .tag:not(.is-normal):not(.is-large),html.theme--catppuccin-mocha .tags.are-medium .content kbd:not(.is-normal):not(.is-large),html.theme--catppuccin-mocha .content .tags.are-medium kbd:not(.is-normal):not(.is-large),html.theme--catppuccin-mocha .tags.are-medium .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-large){font-size:1rem}html.theme--catppuccin-mocha .tags.are-large .tag:not(.is-normal):not(.is-medium),html.theme--catppuccin-mocha .tags.are-large .content kbd:not(.is-normal):not(.is-medium),html.theme--catppuccin-mocha .content .tags.are-large kbd:not(.is-normal):not(.is-medium),html.theme--catppuccin-mocha .tags.are-large .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-medium){font-size:1.25rem}html.theme--catppuccin-mocha .tags.is-centered{justify-content:center}html.theme--catppuccin-mocha .tags.is-centered .tag,html.theme--catppuccin-mocha .tags.is-centered .content kbd,html.theme--catppuccin-mocha .content .tags.is-centered kbd,html.theme--catppuccin-mocha .tags.is-centered .docstring>section>a.docs-sourcelink{margin-right:0.25rem;margin-left:0.25rem}html.theme--catppuccin-mocha .tags.is-right{justify-content:flex-end}html.theme--catppuccin-mocha .tags.is-right .tag:not(:first-child),html.theme--catppuccin-mocha .tags.is-right .content kbd:not(:first-child),html.theme--catppuccin-mocha .content .tags.is-right kbd:not(:first-child),html.theme--catppuccin-mocha .tags.is-right .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0.5rem}html.theme--catppuccin-mocha .tags.is-right .tag:not(:last-child),html.theme--catppuccin-mocha .tags.is-right .content kbd:not(:last-child),html.theme--catppuccin-mocha .content .tags.is-right kbd:not(:last-child),html.theme--catppuccin-mocha .tags.is-right .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:0}html.theme--catppuccin-mocha .tags.has-addons .tag,html.theme--catppuccin-mocha .tags.has-addons .content kbd,html.theme--catppuccin-mocha .content .tags.has-addons kbd,html.theme--catppuccin-mocha .tags.has-addons .docstring>section>a.docs-sourcelink{margin-right:0}html.theme--catppuccin-mocha .tags.has-addons .tag:not(:first-child),html.theme--catppuccin-mocha .tags.has-addons .content kbd:not(:first-child),html.theme--catppuccin-mocha .content .tags.has-addons kbd:not(:first-child),html.theme--catppuccin-mocha .tags.has-addons .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0;border-top-left-radius:0;border-bottom-left-radius:0}html.theme--catppuccin-mocha .tags.has-addons .tag:not(:last-child),html.theme--catppuccin-mocha .tags.has-addons .content kbd:not(:last-child),html.theme--catppuccin-mocha .content .tags.has-addons kbd:not(:last-child),html.theme--catppuccin-mocha .tags.has-addons .docstring>section>a.docs-sourcelink:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}html.theme--catppuccin-mocha .tag:not(body),html.theme--catppuccin-mocha .content kbd:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink:not(body){align-items:center;background-color:#181825;border-radius:.4em;color:#cdd6f4;display:inline-flex;font-size:.75rem;height:2em;justify-content:center;line-height:1.5;padding-left:0.75em;padding-right:0.75em;white-space:nowrap}html.theme--catppuccin-mocha .tag:not(body) .delete,html.theme--catppuccin-mocha .content kbd:not(body) .delete,html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink:not(body) .delete{margin-left:.25rem;margin-right:-.375rem}html.theme--catppuccin-mocha .tag.is-white:not(body),html.theme--catppuccin-mocha .content kbd.is-white:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-white:not(body){background-color:#fff;color:#0a0a0a}html.theme--catppuccin-mocha .tag.is-black:not(body),html.theme--catppuccin-mocha .content kbd.is-black:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-black:not(body){background-color:#0a0a0a;color:#fff}html.theme--catppuccin-mocha .tag.is-light:not(body),html.theme--catppuccin-mocha .content kbd.is-light:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .tag.is-dark:not(body),html.theme--catppuccin-mocha .content kbd:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-dark:not(body),html.theme--catppuccin-mocha .content .docstring>section>kbd:not(body){background-color:#313244;color:#fff}html.theme--catppuccin-mocha .tag.is-primary:not(body),html.theme--catppuccin-mocha .content kbd.is-primary:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink:not(body){background-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .tag.is-primary.is-light:not(body),html.theme--catppuccin-mocha .content kbd.is-primary.is-light:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#ebf3fe;color:#063c93}html.theme--catppuccin-mocha .tag.is-link:not(body),html.theme--catppuccin-mocha .content kbd.is-link:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-link:not(body){background-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .tag.is-link.is-light:not(body),html.theme--catppuccin-mocha .content kbd.is-link.is-light:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-link.is-light:not(body){background-color:#ebf3fe;color:#063c93}html.theme--catppuccin-mocha .tag.is-info:not(body),html.theme--catppuccin-mocha .content kbd.is-info:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-info:not(body){background-color:#94e2d5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .tag.is-info.is-light:not(body),html.theme--catppuccin-mocha .content kbd.is-info.is-light:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-info.is-light:not(body){background-color:#effbf9;color:#207466}html.theme--catppuccin-mocha .tag.is-success:not(body),html.theme--catppuccin-mocha .content kbd.is-success:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-success:not(body){background-color:#a6e3a1;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .tag.is-success.is-light:not(body),html.theme--catppuccin-mocha .content kbd.is-success.is-light:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-success.is-light:not(body){background-color:#f0faef;color:#287222}html.theme--catppuccin-mocha .tag.is-warning:not(body),html.theme--catppuccin-mocha .content kbd.is-warning:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-warning:not(body){background-color:#f9e2af;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .tag.is-warning.is-light:not(body),html.theme--catppuccin-mocha .content kbd.is-warning.is-light:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-warning.is-light:not(body){background-color:#fef8ec;color:#8a620a}html.theme--catppuccin-mocha .tag.is-danger:not(body),html.theme--catppuccin-mocha .content kbd.is-danger:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-danger:not(body){background-color:#f38ba8;color:#fff}html.theme--catppuccin-mocha .tag.is-danger.is-light:not(body),html.theme--catppuccin-mocha .content kbd.is-danger.is-light:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-danger.is-light:not(body){background-color:#fdedf1;color:#991036}html.theme--catppuccin-mocha .tag.is-normal:not(body),html.theme--catppuccin-mocha .content kbd.is-normal:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-normal:not(body){font-size:.75rem}html.theme--catppuccin-mocha .tag.is-medium:not(body),html.theme--catppuccin-mocha .content kbd.is-medium:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-medium:not(body){font-size:1rem}html.theme--catppuccin-mocha .tag.is-large:not(body),html.theme--catppuccin-mocha .content kbd.is-large:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-large:not(body){font-size:1.25rem}html.theme--catppuccin-mocha .tag:not(body) .icon:first-child:not(:last-child),html.theme--catppuccin-mocha .content kbd:not(body) .icon:first-child:not(:last-child),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:not(:last-child){margin-left:-.375em;margin-right:.1875em}html.theme--catppuccin-mocha .tag:not(body) .icon:last-child:not(:first-child),html.theme--catppuccin-mocha .content kbd:not(body) .icon:last-child:not(:first-child),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink:not(body) .icon:last-child:not(:first-child){margin-left:.1875em;margin-right:-.375em}html.theme--catppuccin-mocha .tag:not(body) .icon:first-child:last-child,html.theme--catppuccin-mocha .content kbd:not(body) .icon:first-child:last-child,html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:last-child{margin-left:-.375em;margin-right:-.375em}html.theme--catppuccin-mocha .tag.is-delete:not(body),html.theme--catppuccin-mocha .content kbd.is-delete:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-delete:not(body){margin-left:1px;padding:0;position:relative;width:2em}html.theme--catppuccin-mocha .tag.is-delete:not(body)::before,html.theme--catppuccin-mocha .content kbd.is-delete:not(body)::before,html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-delete:not(body)::before,html.theme--catppuccin-mocha .tag.is-delete:not(body)::after,html.theme--catppuccin-mocha .content kbd.is-delete:not(body)::after,html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{background-color:currentColor;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--catppuccin-mocha .tag.is-delete:not(body)::before,html.theme--catppuccin-mocha .content kbd.is-delete:not(body)::before,html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-delete:not(body)::before{height:1px;width:50%}html.theme--catppuccin-mocha .tag.is-delete:not(body)::after,html.theme--catppuccin-mocha .content kbd.is-delete:not(body)::after,html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{height:50%;width:1px}html.theme--catppuccin-mocha .tag.is-delete:not(body):hover,html.theme--catppuccin-mocha .content kbd.is-delete:not(body):hover,html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-delete:not(body):hover,html.theme--catppuccin-mocha .tag.is-delete:not(body):focus,html.theme--catppuccin-mocha .content kbd.is-delete:not(body):focus,html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-delete:not(body):focus{background-color:#0e0e16}html.theme--catppuccin-mocha .tag.is-delete:not(body):active,html.theme--catppuccin-mocha .content kbd.is-delete:not(body):active,html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-delete:not(body):active{background-color:#040406}html.theme--catppuccin-mocha .tag.is-rounded:not(body),html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input:not(body),html.theme--catppuccin-mocha .content kbd.is-rounded:not(body),html.theme--catppuccin-mocha #documenter .docs-sidebar .content form.docs-search>input:not(body),html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink.is-rounded:not(body){border-radius:9999px}html.theme--catppuccin-mocha a.tag:hover,html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink:hover{text-decoration:underline}html.theme--catppuccin-mocha .title,html.theme--catppuccin-mocha .subtitle{word-break:break-word}html.theme--catppuccin-mocha .title em,html.theme--catppuccin-mocha .title span,html.theme--catppuccin-mocha .subtitle em,html.theme--catppuccin-mocha .subtitle span{font-weight:inherit}html.theme--catppuccin-mocha .title sub,html.theme--catppuccin-mocha .subtitle sub{font-size:.75em}html.theme--catppuccin-mocha .title sup,html.theme--catppuccin-mocha .subtitle sup{font-size:.75em}html.theme--catppuccin-mocha .title .tag,html.theme--catppuccin-mocha .title .content kbd,html.theme--catppuccin-mocha .content .title kbd,html.theme--catppuccin-mocha .title .docstring>section>a.docs-sourcelink,html.theme--catppuccin-mocha .subtitle .tag,html.theme--catppuccin-mocha .subtitle .content kbd,html.theme--catppuccin-mocha .content .subtitle kbd,html.theme--catppuccin-mocha .subtitle .docstring>section>a.docs-sourcelink{vertical-align:middle}html.theme--catppuccin-mocha .title{color:#fff;font-size:2rem;font-weight:500;line-height:1.125}html.theme--catppuccin-mocha .title strong{color:inherit;font-weight:inherit}html.theme--catppuccin-mocha .title:not(.is-spaced)+.subtitle{margin-top:-1.25rem}html.theme--catppuccin-mocha .title.is-1{font-size:3rem}html.theme--catppuccin-mocha .title.is-2{font-size:2.5rem}html.theme--catppuccin-mocha .title.is-3{font-size:2rem}html.theme--catppuccin-mocha .title.is-4{font-size:1.5rem}html.theme--catppuccin-mocha .title.is-5{font-size:1.25rem}html.theme--catppuccin-mocha .title.is-6{font-size:1rem}html.theme--catppuccin-mocha .title.is-7{font-size:.75rem}html.theme--catppuccin-mocha .subtitle{color:#6c7086;font-size:1.25rem;font-weight:400;line-height:1.25}html.theme--catppuccin-mocha .subtitle strong{color:#6c7086;font-weight:600}html.theme--catppuccin-mocha .subtitle:not(.is-spaced)+.title{margin-top:-1.25rem}html.theme--catppuccin-mocha .subtitle.is-1{font-size:3rem}html.theme--catppuccin-mocha .subtitle.is-2{font-size:2.5rem}html.theme--catppuccin-mocha .subtitle.is-3{font-size:2rem}html.theme--catppuccin-mocha .subtitle.is-4{font-size:1.5rem}html.theme--catppuccin-mocha .subtitle.is-5{font-size:1.25rem}html.theme--catppuccin-mocha .subtitle.is-6{font-size:1rem}html.theme--catppuccin-mocha .subtitle.is-7{font-size:.75rem}html.theme--catppuccin-mocha .heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}html.theme--catppuccin-mocha .number{align-items:center;background-color:#181825;border-radius:9999px;display:inline-flex;font-size:1.25rem;height:2em;justify-content:center;margin-right:1.5rem;min-width:2.5em;padding:0.25rem 0.5rem;text-align:center;vertical-align:top}html.theme--catppuccin-mocha .select select,html.theme--catppuccin-mocha .textarea,html.theme--catppuccin-mocha .input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input{background-color:#1e1e2e;border-color:#585b70;border-radius:.4em;color:#7f849c}html.theme--catppuccin-mocha .select select::-moz-placeholder,html.theme--catppuccin-mocha .textarea::-moz-placeholder,html.theme--catppuccin-mocha .input::-moz-placeholder,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:#868c98}html.theme--catppuccin-mocha .select select::-webkit-input-placeholder,html.theme--catppuccin-mocha .textarea::-webkit-input-placeholder,html.theme--catppuccin-mocha .input::-webkit-input-placeholder,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:#868c98}html.theme--catppuccin-mocha .select select:-moz-placeholder,html.theme--catppuccin-mocha .textarea:-moz-placeholder,html.theme--catppuccin-mocha .input:-moz-placeholder,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:#868c98}html.theme--catppuccin-mocha .select select:-ms-input-placeholder,html.theme--catppuccin-mocha .textarea:-ms-input-placeholder,html.theme--catppuccin-mocha .input:-ms-input-placeholder,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:#868c98}html.theme--catppuccin-mocha .select select:hover,html.theme--catppuccin-mocha .textarea:hover,html.theme--catppuccin-mocha .input:hover,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input:hover,html.theme--catppuccin-mocha .select select.is-hovered,html.theme--catppuccin-mocha .is-hovered.textarea,html.theme--catppuccin-mocha .is-hovered.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-hovered{border-color:#6c7086}html.theme--catppuccin-mocha .select select:focus,html.theme--catppuccin-mocha .textarea:focus,html.theme--catppuccin-mocha .input:focus,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input:focus,html.theme--catppuccin-mocha .select select.is-focused,html.theme--catppuccin-mocha .is-focused.textarea,html.theme--catppuccin-mocha .is-focused.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-mocha .select select:active,html.theme--catppuccin-mocha .textarea:active,html.theme--catppuccin-mocha .input:active,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input:active,html.theme--catppuccin-mocha .select select.is-active,html.theme--catppuccin-mocha .is-active.textarea,html.theme--catppuccin-mocha .is-active.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-active{border-color:#89b4fa;box-shadow:0 0 0 0.125em rgba(137,180,250,0.25)}html.theme--catppuccin-mocha .select select[disabled],html.theme--catppuccin-mocha .textarea[disabled],html.theme--catppuccin-mocha .input[disabled],html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input[disabled],fieldset[disabled] html.theme--catppuccin-mocha .select select,fieldset[disabled] html.theme--catppuccin-mocha .textarea,fieldset[disabled] html.theme--catppuccin-mocha .input,fieldset[disabled] html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input{background-color:#6c7086;border-color:#181825;box-shadow:none;color:#f7f8fd}html.theme--catppuccin-mocha .select select[disabled]::-moz-placeholder,html.theme--catppuccin-mocha .textarea[disabled]::-moz-placeholder,html.theme--catppuccin-mocha .input[disabled]::-moz-placeholder,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input[disabled]::-moz-placeholder,fieldset[disabled] html.theme--catppuccin-mocha .select select::-moz-placeholder,fieldset[disabled] html.theme--catppuccin-mocha .textarea::-moz-placeholder,fieldset[disabled] html.theme--catppuccin-mocha .input::-moz-placeholder,fieldset[disabled] html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:rgba(247,248,253,0.3)}html.theme--catppuccin-mocha .select select[disabled]::-webkit-input-placeholder,html.theme--catppuccin-mocha .textarea[disabled]::-webkit-input-placeholder,html.theme--catppuccin-mocha .input[disabled]::-webkit-input-placeholder,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input[disabled]::-webkit-input-placeholder,fieldset[disabled] html.theme--catppuccin-mocha .select select::-webkit-input-placeholder,fieldset[disabled] html.theme--catppuccin-mocha .textarea::-webkit-input-placeholder,fieldset[disabled] html.theme--catppuccin-mocha .input::-webkit-input-placeholder,fieldset[disabled] html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:rgba(247,248,253,0.3)}html.theme--catppuccin-mocha .select select[disabled]:-moz-placeholder,html.theme--catppuccin-mocha .textarea[disabled]:-moz-placeholder,html.theme--catppuccin-mocha .input[disabled]:-moz-placeholder,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input[disabled]:-moz-placeholder,fieldset[disabled] html.theme--catppuccin-mocha .select select:-moz-placeholder,fieldset[disabled] html.theme--catppuccin-mocha .textarea:-moz-placeholder,fieldset[disabled] html.theme--catppuccin-mocha .input:-moz-placeholder,fieldset[disabled] html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:rgba(247,248,253,0.3)}html.theme--catppuccin-mocha .select select[disabled]:-ms-input-placeholder,html.theme--catppuccin-mocha .textarea[disabled]:-ms-input-placeholder,html.theme--catppuccin-mocha .input[disabled]:-ms-input-placeholder,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input[disabled]:-ms-input-placeholder,fieldset[disabled] html.theme--catppuccin-mocha .select select:-ms-input-placeholder,fieldset[disabled] html.theme--catppuccin-mocha .textarea:-ms-input-placeholder,fieldset[disabled] html.theme--catppuccin-mocha .input:-ms-input-placeholder,fieldset[disabled] html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:rgba(247,248,253,0.3)}html.theme--catppuccin-mocha .textarea,html.theme--catppuccin-mocha .input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input{box-shadow:inset 0 0.0625em 0.125em rgba(10,10,10,0.05);max-width:100%;width:100%}html.theme--catppuccin-mocha .textarea[readonly],html.theme--catppuccin-mocha .input[readonly],html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input[readonly]{box-shadow:none}html.theme--catppuccin-mocha .is-white.textarea,html.theme--catppuccin-mocha .is-white.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-white{border-color:#fff}html.theme--catppuccin-mocha .is-white.textarea:focus,html.theme--catppuccin-mocha .is-white.input:focus,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-white:focus,html.theme--catppuccin-mocha .is-white.is-focused.textarea,html.theme--catppuccin-mocha .is-white.is-focused.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-mocha .is-white.textarea:active,html.theme--catppuccin-mocha .is-white.input:active,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-white:active,html.theme--catppuccin-mocha .is-white.is-active.textarea,html.theme--catppuccin-mocha .is-white.is-active.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--catppuccin-mocha .is-black.textarea,html.theme--catppuccin-mocha .is-black.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-black{border-color:#0a0a0a}html.theme--catppuccin-mocha .is-black.textarea:focus,html.theme--catppuccin-mocha .is-black.input:focus,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-black:focus,html.theme--catppuccin-mocha .is-black.is-focused.textarea,html.theme--catppuccin-mocha .is-black.is-focused.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-mocha .is-black.textarea:active,html.theme--catppuccin-mocha .is-black.input:active,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-black:active,html.theme--catppuccin-mocha .is-black.is-active.textarea,html.theme--catppuccin-mocha .is-black.is-active.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--catppuccin-mocha .is-light.textarea,html.theme--catppuccin-mocha .is-light.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-light{border-color:#f5f5f5}html.theme--catppuccin-mocha .is-light.textarea:focus,html.theme--catppuccin-mocha .is-light.input:focus,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-light:focus,html.theme--catppuccin-mocha .is-light.is-focused.textarea,html.theme--catppuccin-mocha .is-light.is-focused.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-mocha .is-light.textarea:active,html.theme--catppuccin-mocha .is-light.input:active,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-light:active,html.theme--catppuccin-mocha .is-light.is-active.textarea,html.theme--catppuccin-mocha .is-light.is-active.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}html.theme--catppuccin-mocha .is-dark.textarea,html.theme--catppuccin-mocha .content kbd.textarea,html.theme--catppuccin-mocha .is-dark.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-dark,html.theme--catppuccin-mocha .content kbd.input{border-color:#313244}html.theme--catppuccin-mocha .is-dark.textarea:focus,html.theme--catppuccin-mocha .content kbd.textarea:focus,html.theme--catppuccin-mocha .is-dark.input:focus,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-dark:focus,html.theme--catppuccin-mocha .content kbd.input:focus,html.theme--catppuccin-mocha .is-dark.is-focused.textarea,html.theme--catppuccin-mocha .content kbd.is-focused.textarea,html.theme--catppuccin-mocha .is-dark.is-focused.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-mocha .content kbd.is-focused.input,html.theme--catppuccin-mocha #documenter .docs-sidebar .content form.docs-search>input.is-focused,html.theme--catppuccin-mocha .is-dark.textarea:active,html.theme--catppuccin-mocha .content kbd.textarea:active,html.theme--catppuccin-mocha .is-dark.input:active,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-dark:active,html.theme--catppuccin-mocha .content kbd.input:active,html.theme--catppuccin-mocha .is-dark.is-active.textarea,html.theme--catppuccin-mocha .content kbd.is-active.textarea,html.theme--catppuccin-mocha .is-dark.is-active.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--catppuccin-mocha .content kbd.is-active.input,html.theme--catppuccin-mocha #documenter .docs-sidebar .content form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(49,50,68,0.25)}html.theme--catppuccin-mocha .is-primary.textarea,html.theme--catppuccin-mocha .docstring>section>a.textarea.docs-sourcelink,html.theme--catppuccin-mocha .is-primary.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-primary,html.theme--catppuccin-mocha .docstring>section>a.input.docs-sourcelink{border-color:#89b4fa}html.theme--catppuccin-mocha .is-primary.textarea:focus,html.theme--catppuccin-mocha .docstring>section>a.textarea.docs-sourcelink:focus,html.theme--catppuccin-mocha .is-primary.input:focus,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-primary:focus,html.theme--catppuccin-mocha .docstring>section>a.input.docs-sourcelink:focus,html.theme--catppuccin-mocha .is-primary.is-focused.textarea,html.theme--catppuccin-mocha .docstring>section>a.is-focused.textarea.docs-sourcelink,html.theme--catppuccin-mocha .is-primary.is-focused.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-mocha .docstring>section>a.is-focused.input.docs-sourcelink,html.theme--catppuccin-mocha .is-primary.textarea:active,html.theme--catppuccin-mocha .docstring>section>a.textarea.docs-sourcelink:active,html.theme--catppuccin-mocha .is-primary.input:active,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-primary:active,html.theme--catppuccin-mocha .docstring>section>a.input.docs-sourcelink:active,html.theme--catppuccin-mocha .is-primary.is-active.textarea,html.theme--catppuccin-mocha .docstring>section>a.is-active.textarea.docs-sourcelink,html.theme--catppuccin-mocha .is-primary.is-active.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--catppuccin-mocha .docstring>section>a.is-active.input.docs-sourcelink{box-shadow:0 0 0 0.125em rgba(137,180,250,0.25)}html.theme--catppuccin-mocha .is-link.textarea,html.theme--catppuccin-mocha .is-link.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-link{border-color:#89b4fa}html.theme--catppuccin-mocha .is-link.textarea:focus,html.theme--catppuccin-mocha .is-link.input:focus,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-link:focus,html.theme--catppuccin-mocha .is-link.is-focused.textarea,html.theme--catppuccin-mocha .is-link.is-focused.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-mocha .is-link.textarea:active,html.theme--catppuccin-mocha .is-link.input:active,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-link:active,html.theme--catppuccin-mocha .is-link.is-active.textarea,html.theme--catppuccin-mocha .is-link.is-active.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(137,180,250,0.25)}html.theme--catppuccin-mocha .is-info.textarea,html.theme--catppuccin-mocha .is-info.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-info{border-color:#94e2d5}html.theme--catppuccin-mocha .is-info.textarea:focus,html.theme--catppuccin-mocha .is-info.input:focus,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-info:focus,html.theme--catppuccin-mocha .is-info.is-focused.textarea,html.theme--catppuccin-mocha .is-info.is-focused.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-mocha .is-info.textarea:active,html.theme--catppuccin-mocha .is-info.input:active,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-info:active,html.theme--catppuccin-mocha .is-info.is-active.textarea,html.theme--catppuccin-mocha .is-info.is-active.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(148,226,213,0.25)}html.theme--catppuccin-mocha .is-success.textarea,html.theme--catppuccin-mocha .is-success.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-success{border-color:#a6e3a1}html.theme--catppuccin-mocha .is-success.textarea:focus,html.theme--catppuccin-mocha .is-success.input:focus,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-success:focus,html.theme--catppuccin-mocha .is-success.is-focused.textarea,html.theme--catppuccin-mocha .is-success.is-focused.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-mocha .is-success.textarea:active,html.theme--catppuccin-mocha .is-success.input:active,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-success:active,html.theme--catppuccin-mocha .is-success.is-active.textarea,html.theme--catppuccin-mocha .is-success.is-active.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(166,227,161,0.25)}html.theme--catppuccin-mocha .is-warning.textarea,html.theme--catppuccin-mocha .is-warning.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-warning{border-color:#f9e2af}html.theme--catppuccin-mocha .is-warning.textarea:focus,html.theme--catppuccin-mocha .is-warning.input:focus,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-warning:focus,html.theme--catppuccin-mocha .is-warning.is-focused.textarea,html.theme--catppuccin-mocha .is-warning.is-focused.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-mocha .is-warning.textarea:active,html.theme--catppuccin-mocha .is-warning.input:active,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-warning:active,html.theme--catppuccin-mocha .is-warning.is-active.textarea,html.theme--catppuccin-mocha .is-warning.is-active.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(249,226,175,0.25)}html.theme--catppuccin-mocha .is-danger.textarea,html.theme--catppuccin-mocha .is-danger.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-danger{border-color:#f38ba8}html.theme--catppuccin-mocha .is-danger.textarea:focus,html.theme--catppuccin-mocha .is-danger.input:focus,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-danger:focus,html.theme--catppuccin-mocha .is-danger.is-focused.textarea,html.theme--catppuccin-mocha .is-danger.is-focused.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--catppuccin-mocha .is-danger.textarea:active,html.theme--catppuccin-mocha .is-danger.input:active,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-danger:active,html.theme--catppuccin-mocha .is-danger.is-active.textarea,html.theme--catppuccin-mocha .is-danger.is-active.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(243,139,168,0.25)}html.theme--catppuccin-mocha .is-small.textarea,html.theme--catppuccin-mocha .is-small.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input{border-radius:3px;font-size:.75rem}html.theme--catppuccin-mocha .is-medium.textarea,html.theme--catppuccin-mocha .is-medium.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-medium{font-size:1.25rem}html.theme--catppuccin-mocha .is-large.textarea,html.theme--catppuccin-mocha .is-large.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-large{font-size:1.5rem}html.theme--catppuccin-mocha .is-fullwidth.textarea,html.theme--catppuccin-mocha .is-fullwidth.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-fullwidth{display:block;width:100%}html.theme--catppuccin-mocha .is-inline.textarea,html.theme--catppuccin-mocha .is-inline.input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-inline{display:inline;width:auto}html.theme--catppuccin-mocha .input.is-rounded,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input{border-radius:9999px;padding-left:calc(calc(0.75em - 1px) + 0.375em);padding-right:calc(calc(0.75em - 1px) + 0.375em)}html.theme--catppuccin-mocha .input.is-static,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-static{background-color:transparent;border-color:transparent;box-shadow:none;padding-left:0;padding-right:0}html.theme--catppuccin-mocha .textarea{display:block;max-width:100%;min-width:100%;padding:calc(0.75em - 1px);resize:vertical}html.theme--catppuccin-mocha .textarea:not([rows]){max-height:40em;min-height:8em}html.theme--catppuccin-mocha .textarea[rows]{height:initial}html.theme--catppuccin-mocha .textarea.has-fixed-size{resize:none}html.theme--catppuccin-mocha .radio,html.theme--catppuccin-mocha .checkbox{cursor:pointer;display:inline-block;line-height:1.25;position:relative}html.theme--catppuccin-mocha .radio input,html.theme--catppuccin-mocha .checkbox input{cursor:pointer}html.theme--catppuccin-mocha .radio:hover,html.theme--catppuccin-mocha .checkbox:hover{color:#89dceb}html.theme--catppuccin-mocha .radio[disabled],html.theme--catppuccin-mocha .checkbox[disabled],fieldset[disabled] html.theme--catppuccin-mocha .radio,fieldset[disabled] html.theme--catppuccin-mocha .checkbox,html.theme--catppuccin-mocha .radio input[disabled],html.theme--catppuccin-mocha .checkbox input[disabled]{color:#f7f8fd;cursor:not-allowed}html.theme--catppuccin-mocha .radio+.radio{margin-left:.5em}html.theme--catppuccin-mocha .select{display:inline-block;max-width:100%;position:relative;vertical-align:top}html.theme--catppuccin-mocha .select:not(.is-multiple){height:2.5em}html.theme--catppuccin-mocha .select:not(.is-multiple):not(.is-loading)::after{border-color:#89b4fa;right:1.125em;z-index:4}html.theme--catppuccin-mocha .select.is-rounded select,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.select select{border-radius:9999px;padding-left:1em}html.theme--catppuccin-mocha .select select{cursor:pointer;display:block;font-size:1em;max-width:100%;outline:none}html.theme--catppuccin-mocha .select select::-ms-expand{display:none}html.theme--catppuccin-mocha .select select[disabled]:hover,fieldset[disabled] html.theme--catppuccin-mocha .select select:hover{border-color:#181825}html.theme--catppuccin-mocha .select select:not([multiple]){padding-right:2.5em}html.theme--catppuccin-mocha .select select[multiple]{height:auto;padding:0}html.theme--catppuccin-mocha .select select[multiple] option{padding:0.5em 1em}html.theme--catppuccin-mocha .select:not(.is-multiple):not(.is-loading):hover::after{border-color:#89dceb}html.theme--catppuccin-mocha .select.is-white:not(:hover)::after{border-color:#fff}html.theme--catppuccin-mocha .select.is-white select{border-color:#fff}html.theme--catppuccin-mocha .select.is-white select:hover,html.theme--catppuccin-mocha .select.is-white select.is-hovered{border-color:#f2f2f2}html.theme--catppuccin-mocha .select.is-white select:focus,html.theme--catppuccin-mocha .select.is-white select.is-focused,html.theme--catppuccin-mocha .select.is-white select:active,html.theme--catppuccin-mocha .select.is-white select.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--catppuccin-mocha .select.is-black:not(:hover)::after{border-color:#0a0a0a}html.theme--catppuccin-mocha .select.is-black select{border-color:#0a0a0a}html.theme--catppuccin-mocha .select.is-black select:hover,html.theme--catppuccin-mocha .select.is-black select.is-hovered{border-color:#000}html.theme--catppuccin-mocha .select.is-black select:focus,html.theme--catppuccin-mocha .select.is-black select.is-focused,html.theme--catppuccin-mocha .select.is-black select:active,html.theme--catppuccin-mocha .select.is-black select.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--catppuccin-mocha .select.is-light:not(:hover)::after{border-color:#f5f5f5}html.theme--catppuccin-mocha .select.is-light select{border-color:#f5f5f5}html.theme--catppuccin-mocha .select.is-light select:hover,html.theme--catppuccin-mocha .select.is-light select.is-hovered{border-color:#e8e8e8}html.theme--catppuccin-mocha .select.is-light select:focus,html.theme--catppuccin-mocha .select.is-light select.is-focused,html.theme--catppuccin-mocha .select.is-light select:active,html.theme--catppuccin-mocha .select.is-light select.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}html.theme--catppuccin-mocha .select.is-dark:not(:hover)::after,html.theme--catppuccin-mocha .content kbd.select:not(:hover)::after{border-color:#313244}html.theme--catppuccin-mocha .select.is-dark select,html.theme--catppuccin-mocha .content kbd.select select{border-color:#313244}html.theme--catppuccin-mocha .select.is-dark select:hover,html.theme--catppuccin-mocha .content kbd.select select:hover,html.theme--catppuccin-mocha .select.is-dark select.is-hovered,html.theme--catppuccin-mocha .content kbd.select select.is-hovered{border-color:#262735}html.theme--catppuccin-mocha .select.is-dark select:focus,html.theme--catppuccin-mocha .content kbd.select select:focus,html.theme--catppuccin-mocha .select.is-dark select.is-focused,html.theme--catppuccin-mocha .content kbd.select select.is-focused,html.theme--catppuccin-mocha .select.is-dark select:active,html.theme--catppuccin-mocha .content kbd.select select:active,html.theme--catppuccin-mocha .select.is-dark select.is-active,html.theme--catppuccin-mocha .content kbd.select select.is-active{box-shadow:0 0 0 0.125em rgba(49,50,68,0.25)}html.theme--catppuccin-mocha .select.is-primary:not(:hover)::after,html.theme--catppuccin-mocha .docstring>section>a.select.docs-sourcelink:not(:hover)::after{border-color:#89b4fa}html.theme--catppuccin-mocha .select.is-primary select,html.theme--catppuccin-mocha .docstring>section>a.select.docs-sourcelink select{border-color:#89b4fa}html.theme--catppuccin-mocha .select.is-primary select:hover,html.theme--catppuccin-mocha .docstring>section>a.select.docs-sourcelink select:hover,html.theme--catppuccin-mocha .select.is-primary select.is-hovered,html.theme--catppuccin-mocha .docstring>section>a.select.docs-sourcelink select.is-hovered{border-color:#71a4f9}html.theme--catppuccin-mocha .select.is-primary select:focus,html.theme--catppuccin-mocha .docstring>section>a.select.docs-sourcelink select:focus,html.theme--catppuccin-mocha .select.is-primary select.is-focused,html.theme--catppuccin-mocha .docstring>section>a.select.docs-sourcelink select.is-focused,html.theme--catppuccin-mocha .select.is-primary select:active,html.theme--catppuccin-mocha .docstring>section>a.select.docs-sourcelink select:active,html.theme--catppuccin-mocha .select.is-primary select.is-active,html.theme--catppuccin-mocha .docstring>section>a.select.docs-sourcelink select.is-active{box-shadow:0 0 0 0.125em rgba(137,180,250,0.25)}html.theme--catppuccin-mocha .select.is-link:not(:hover)::after{border-color:#89b4fa}html.theme--catppuccin-mocha .select.is-link select{border-color:#89b4fa}html.theme--catppuccin-mocha .select.is-link select:hover,html.theme--catppuccin-mocha .select.is-link select.is-hovered{border-color:#71a4f9}html.theme--catppuccin-mocha .select.is-link select:focus,html.theme--catppuccin-mocha .select.is-link select.is-focused,html.theme--catppuccin-mocha .select.is-link select:active,html.theme--catppuccin-mocha .select.is-link select.is-active{box-shadow:0 0 0 0.125em rgba(137,180,250,0.25)}html.theme--catppuccin-mocha .select.is-info:not(:hover)::after{border-color:#94e2d5}html.theme--catppuccin-mocha .select.is-info select{border-color:#94e2d5}html.theme--catppuccin-mocha .select.is-info select:hover,html.theme--catppuccin-mocha .select.is-info select.is-hovered{border-color:#80ddcd}html.theme--catppuccin-mocha .select.is-info select:focus,html.theme--catppuccin-mocha .select.is-info select.is-focused,html.theme--catppuccin-mocha .select.is-info select:active,html.theme--catppuccin-mocha .select.is-info select.is-active{box-shadow:0 0 0 0.125em rgba(148,226,213,0.25)}html.theme--catppuccin-mocha .select.is-success:not(:hover)::after{border-color:#a6e3a1}html.theme--catppuccin-mocha .select.is-success select{border-color:#a6e3a1}html.theme--catppuccin-mocha .select.is-success select:hover,html.theme--catppuccin-mocha .select.is-success select.is-hovered{border-color:#93dd8d}html.theme--catppuccin-mocha .select.is-success select:focus,html.theme--catppuccin-mocha .select.is-success select.is-focused,html.theme--catppuccin-mocha .select.is-success select:active,html.theme--catppuccin-mocha .select.is-success select.is-active{box-shadow:0 0 0 0.125em rgba(166,227,161,0.25)}html.theme--catppuccin-mocha .select.is-warning:not(:hover)::after{border-color:#f9e2af}html.theme--catppuccin-mocha .select.is-warning select{border-color:#f9e2af}html.theme--catppuccin-mocha .select.is-warning select:hover,html.theme--catppuccin-mocha .select.is-warning select.is-hovered{border-color:#f7d997}html.theme--catppuccin-mocha .select.is-warning select:focus,html.theme--catppuccin-mocha .select.is-warning select.is-focused,html.theme--catppuccin-mocha .select.is-warning select:active,html.theme--catppuccin-mocha .select.is-warning select.is-active{box-shadow:0 0 0 0.125em rgba(249,226,175,0.25)}html.theme--catppuccin-mocha .select.is-danger:not(:hover)::after{border-color:#f38ba8}html.theme--catppuccin-mocha .select.is-danger select{border-color:#f38ba8}html.theme--catppuccin-mocha .select.is-danger select:hover,html.theme--catppuccin-mocha .select.is-danger select.is-hovered{border-color:#f17497}html.theme--catppuccin-mocha .select.is-danger select:focus,html.theme--catppuccin-mocha .select.is-danger select.is-focused,html.theme--catppuccin-mocha .select.is-danger select:active,html.theme--catppuccin-mocha .select.is-danger select.is-active{box-shadow:0 0 0 0.125em rgba(243,139,168,0.25)}html.theme--catppuccin-mocha .select.is-small,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.select{border-radius:3px;font-size:.75rem}html.theme--catppuccin-mocha .select.is-medium{font-size:1.25rem}html.theme--catppuccin-mocha .select.is-large{font-size:1.5rem}html.theme--catppuccin-mocha .select.is-disabled::after{border-color:#f7f8fd !important;opacity:0.5}html.theme--catppuccin-mocha .select.is-fullwidth{width:100%}html.theme--catppuccin-mocha .select.is-fullwidth select{width:100%}html.theme--catppuccin-mocha .select.is-loading::after{margin-top:0;position:absolute;right:.625em;top:0.625em;transform:none}html.theme--catppuccin-mocha .select.is-loading.is-small:after,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}html.theme--catppuccin-mocha .select.is-loading.is-medium:after{font-size:1.25rem}html.theme--catppuccin-mocha .select.is-loading.is-large:after{font-size:1.5rem}html.theme--catppuccin-mocha .file{align-items:stretch;display:flex;justify-content:flex-start;position:relative}html.theme--catppuccin-mocha .file.is-white .file-cta{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-mocha .file.is-white:hover .file-cta,html.theme--catppuccin-mocha .file.is-white.is-hovered .file-cta{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-mocha .file.is-white:focus .file-cta,html.theme--catppuccin-mocha .file.is-white.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,255,255,0.25);color:#0a0a0a}html.theme--catppuccin-mocha .file.is-white:active .file-cta,html.theme--catppuccin-mocha .file.is-white.is-active .file-cta{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--catppuccin-mocha .file.is-black .file-cta{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .file.is-black:hover .file-cta,html.theme--catppuccin-mocha .file.is-black.is-hovered .file-cta{background-color:#040404;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .file.is-black:focus .file-cta,html.theme--catppuccin-mocha .file.is-black.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(10,10,10,0.25);color:#fff}html.theme--catppuccin-mocha .file.is-black:active .file-cta,html.theme--catppuccin-mocha .file.is-black.is-active .file-cta{background-color:#000;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .file.is-light .file-cta{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .file.is-light:hover .file-cta,html.theme--catppuccin-mocha .file.is-light.is-hovered .file-cta{background-color:#eee;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .file.is-light:focus .file-cta,html.theme--catppuccin-mocha .file.is-light.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(245,245,245,0.25);color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .file.is-light:active .file-cta,html.theme--catppuccin-mocha .file.is-light.is-active .file-cta{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .file.is-dark .file-cta,html.theme--catppuccin-mocha .content kbd.file .file-cta{background-color:#313244;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .file.is-dark:hover .file-cta,html.theme--catppuccin-mocha .content kbd.file:hover .file-cta,html.theme--catppuccin-mocha .file.is-dark.is-hovered .file-cta,html.theme--catppuccin-mocha .content kbd.file.is-hovered .file-cta{background-color:#2c2d3d;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .file.is-dark:focus .file-cta,html.theme--catppuccin-mocha .content kbd.file:focus .file-cta,html.theme--catppuccin-mocha .file.is-dark.is-focused .file-cta,html.theme--catppuccin-mocha .content kbd.file.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(49,50,68,0.25);color:#fff}html.theme--catppuccin-mocha .file.is-dark:active .file-cta,html.theme--catppuccin-mocha .content kbd.file:active .file-cta,html.theme--catppuccin-mocha .file.is-dark.is-active .file-cta,html.theme--catppuccin-mocha .content kbd.file.is-active .file-cta{background-color:#262735;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .file.is-primary .file-cta,html.theme--catppuccin-mocha .docstring>section>a.file.docs-sourcelink .file-cta{background-color:#89b4fa;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .file.is-primary:hover .file-cta,html.theme--catppuccin-mocha .docstring>section>a.file.docs-sourcelink:hover .file-cta,html.theme--catppuccin-mocha .file.is-primary.is-hovered .file-cta,html.theme--catppuccin-mocha .docstring>section>a.file.is-hovered.docs-sourcelink .file-cta{background-color:#7dacf9;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .file.is-primary:focus .file-cta,html.theme--catppuccin-mocha .docstring>section>a.file.docs-sourcelink:focus .file-cta,html.theme--catppuccin-mocha .file.is-primary.is-focused .file-cta,html.theme--catppuccin-mocha .docstring>section>a.file.is-focused.docs-sourcelink .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(137,180,250,0.25);color:#fff}html.theme--catppuccin-mocha .file.is-primary:active .file-cta,html.theme--catppuccin-mocha .docstring>section>a.file.docs-sourcelink:active .file-cta,html.theme--catppuccin-mocha .file.is-primary.is-active .file-cta,html.theme--catppuccin-mocha .docstring>section>a.file.is-active.docs-sourcelink .file-cta{background-color:#71a4f9;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .file.is-link .file-cta{background-color:#89b4fa;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .file.is-link:hover .file-cta,html.theme--catppuccin-mocha .file.is-link.is-hovered .file-cta{background-color:#7dacf9;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .file.is-link:focus .file-cta,html.theme--catppuccin-mocha .file.is-link.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(137,180,250,0.25);color:#fff}html.theme--catppuccin-mocha .file.is-link:active .file-cta,html.theme--catppuccin-mocha .file.is-link.is-active .file-cta{background-color:#71a4f9;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .file.is-info .file-cta{background-color:#94e2d5;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .file.is-info:hover .file-cta,html.theme--catppuccin-mocha .file.is-info.is-hovered .file-cta{background-color:#8adfd1;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .file.is-info:focus .file-cta,html.theme--catppuccin-mocha .file.is-info.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(148,226,213,0.25);color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .file.is-info:active .file-cta,html.theme--catppuccin-mocha .file.is-info.is-active .file-cta{background-color:#80ddcd;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .file.is-success .file-cta{background-color:#a6e3a1;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .file.is-success:hover .file-cta,html.theme--catppuccin-mocha .file.is-success.is-hovered .file-cta{background-color:#9de097;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .file.is-success:focus .file-cta,html.theme--catppuccin-mocha .file.is-success.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(166,227,161,0.25);color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .file.is-success:active .file-cta,html.theme--catppuccin-mocha .file.is-success.is-active .file-cta{background-color:#93dd8d;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .file.is-warning .file-cta{background-color:#f9e2af;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .file.is-warning:hover .file-cta,html.theme--catppuccin-mocha .file.is-warning.is-hovered .file-cta{background-color:#f8dea3;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .file.is-warning:focus .file-cta,html.theme--catppuccin-mocha .file.is-warning.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(249,226,175,0.25);color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .file.is-warning:active .file-cta,html.theme--catppuccin-mocha .file.is-warning.is-active .file-cta{background-color:#f7d997;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .file.is-danger .file-cta{background-color:#f38ba8;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .file.is-danger:hover .file-cta,html.theme--catppuccin-mocha .file.is-danger.is-hovered .file-cta{background-color:#f27f9f;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .file.is-danger:focus .file-cta,html.theme--catppuccin-mocha .file.is-danger.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(243,139,168,0.25);color:#fff}html.theme--catppuccin-mocha .file.is-danger:active .file-cta,html.theme--catppuccin-mocha .file.is-danger.is-active .file-cta{background-color:#f17497;border-color:transparent;color:#fff}html.theme--catppuccin-mocha .file.is-small,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.file{font-size:.75rem}html.theme--catppuccin-mocha .file.is-normal{font-size:1rem}html.theme--catppuccin-mocha .file.is-medium{font-size:1.25rem}html.theme--catppuccin-mocha .file.is-medium .file-icon .fa{font-size:21px}html.theme--catppuccin-mocha .file.is-large{font-size:1.5rem}html.theme--catppuccin-mocha .file.is-large .file-icon .fa{font-size:28px}html.theme--catppuccin-mocha .file.has-name .file-cta{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--catppuccin-mocha .file.has-name .file-name{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--catppuccin-mocha .file.has-name.is-empty .file-cta{border-radius:.4em}html.theme--catppuccin-mocha .file.has-name.is-empty .file-name{display:none}html.theme--catppuccin-mocha .file.is-boxed .file-label{flex-direction:column}html.theme--catppuccin-mocha .file.is-boxed .file-cta{flex-direction:column;height:auto;padding:1em 3em}html.theme--catppuccin-mocha .file.is-boxed .file-name{border-width:0 1px 1px}html.theme--catppuccin-mocha .file.is-boxed .file-icon{height:1.5em;width:1.5em}html.theme--catppuccin-mocha .file.is-boxed .file-icon .fa{font-size:21px}html.theme--catppuccin-mocha .file.is-boxed.is-small .file-icon .fa,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-boxed .file-icon .fa{font-size:14px}html.theme--catppuccin-mocha .file.is-boxed.is-medium .file-icon .fa{font-size:28px}html.theme--catppuccin-mocha .file.is-boxed.is-large .file-icon .fa{font-size:35px}html.theme--catppuccin-mocha .file.is-boxed.has-name .file-cta{border-radius:.4em .4em 0 0}html.theme--catppuccin-mocha .file.is-boxed.has-name .file-name{border-radius:0 0 .4em .4em;border-width:0 1px 1px}html.theme--catppuccin-mocha .file.is-centered{justify-content:center}html.theme--catppuccin-mocha .file.is-fullwidth .file-label{width:100%}html.theme--catppuccin-mocha .file.is-fullwidth .file-name{flex-grow:1;max-width:none}html.theme--catppuccin-mocha .file.is-right{justify-content:flex-end}html.theme--catppuccin-mocha .file.is-right .file-cta{border-radius:0 .4em .4em 0}html.theme--catppuccin-mocha .file.is-right .file-name{border-radius:.4em 0 0 .4em;border-width:1px 0 1px 1px;order:-1}html.theme--catppuccin-mocha .file-label{align-items:stretch;display:flex;cursor:pointer;justify-content:flex-start;overflow:hidden;position:relative}html.theme--catppuccin-mocha .file-label:hover .file-cta{background-color:#2c2d3d;color:#b8c5ef}html.theme--catppuccin-mocha .file-label:hover .file-name{border-color:#525569}html.theme--catppuccin-mocha .file-label:active .file-cta{background-color:#262735;color:#b8c5ef}html.theme--catppuccin-mocha .file-label:active .file-name{border-color:#4d4f62}html.theme--catppuccin-mocha .file-input{height:100%;left:0;opacity:0;outline:none;position:absolute;top:0;width:100%}html.theme--catppuccin-mocha .file-cta,html.theme--catppuccin-mocha .file-name{border-color:#585b70;border-radius:.4em;font-size:1em;padding-left:1em;padding-right:1em;white-space:nowrap}html.theme--catppuccin-mocha .file-cta{background-color:#313244;color:#cdd6f4}html.theme--catppuccin-mocha .file-name{border-color:#585b70;border-style:solid;border-width:1px 1px 1px 0;display:block;max-width:16em;overflow:hidden;text-align:inherit;text-overflow:ellipsis}html.theme--catppuccin-mocha .file-icon{align-items:center;display:flex;height:1em;justify-content:center;margin-right:.5em;width:1em}html.theme--catppuccin-mocha .file-icon .fa{font-size:14px}html.theme--catppuccin-mocha .label{color:#b8c5ef;display:block;font-size:1rem;font-weight:700}html.theme--catppuccin-mocha .label:not(:last-child){margin-bottom:0.5em}html.theme--catppuccin-mocha .label.is-small,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.label{font-size:.75rem}html.theme--catppuccin-mocha .label.is-medium{font-size:1.25rem}html.theme--catppuccin-mocha .label.is-large{font-size:1.5rem}html.theme--catppuccin-mocha .help{display:block;font-size:.75rem;margin-top:0.25rem}html.theme--catppuccin-mocha .help.is-white{color:#fff}html.theme--catppuccin-mocha .help.is-black{color:#0a0a0a}html.theme--catppuccin-mocha .help.is-light{color:#f5f5f5}html.theme--catppuccin-mocha .help.is-dark,html.theme--catppuccin-mocha .content kbd.help{color:#313244}html.theme--catppuccin-mocha .help.is-primary,html.theme--catppuccin-mocha .docstring>section>a.help.docs-sourcelink{color:#89b4fa}html.theme--catppuccin-mocha .help.is-link{color:#89b4fa}html.theme--catppuccin-mocha .help.is-info{color:#94e2d5}html.theme--catppuccin-mocha .help.is-success{color:#a6e3a1}html.theme--catppuccin-mocha .help.is-warning{color:#f9e2af}html.theme--catppuccin-mocha .help.is-danger{color:#f38ba8}html.theme--catppuccin-mocha .field:not(:last-child){margin-bottom:0.75rem}html.theme--catppuccin-mocha .field.has-addons{display:flex;justify-content:flex-start}html.theme--catppuccin-mocha .field.has-addons .control:not(:last-child){margin-right:-1px}html.theme--catppuccin-mocha .field.has-addons .control:not(:first-child):not(:last-child) .button,html.theme--catppuccin-mocha .field.has-addons .control:not(:first-child):not(:last-child) .input,html.theme--catppuccin-mocha .field.has-addons .control:not(:first-child):not(:last-child) #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-mocha #documenter .docs-sidebar .field.has-addons .control:not(:first-child):not(:last-child) form.docs-search>input,html.theme--catppuccin-mocha .field.has-addons .control:not(:first-child):not(:last-child) .select select{border-radius:0}html.theme--catppuccin-mocha .field.has-addons .control:first-child:not(:only-child) .button,html.theme--catppuccin-mocha .field.has-addons .control:first-child:not(:only-child) .input,html.theme--catppuccin-mocha .field.has-addons .control:first-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-mocha #documenter .docs-sidebar .field.has-addons .control:first-child:not(:only-child) form.docs-search>input,html.theme--catppuccin-mocha .field.has-addons .control:first-child:not(:only-child) .select select{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--catppuccin-mocha .field.has-addons .control:last-child:not(:only-child) .button,html.theme--catppuccin-mocha .field.has-addons .control:last-child:not(:only-child) .input,html.theme--catppuccin-mocha .field.has-addons .control:last-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-mocha #documenter .docs-sidebar .field.has-addons .control:last-child:not(:only-child) form.docs-search>input,html.theme--catppuccin-mocha .field.has-addons .control:last-child:not(:only-child) .select select{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--catppuccin-mocha .field.has-addons .control .button:not([disabled]):hover,html.theme--catppuccin-mocha .field.has-addons .control .button.is-hovered:not([disabled]),html.theme--catppuccin-mocha .field.has-addons .control .input:not([disabled]):hover,html.theme--catppuccin-mocha .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):hover,html.theme--catppuccin-mocha #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):hover,html.theme--catppuccin-mocha .field.has-addons .control .input.is-hovered:not([disabled]),html.theme--catppuccin-mocha .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-hovered:not([disabled]),html.theme--catppuccin-mocha #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-hovered:not([disabled]),html.theme--catppuccin-mocha .field.has-addons .control .select select:not([disabled]):hover,html.theme--catppuccin-mocha .field.has-addons .control .select select.is-hovered:not([disabled]){z-index:2}html.theme--catppuccin-mocha .field.has-addons .control .button:not([disabled]):focus,html.theme--catppuccin-mocha .field.has-addons .control .button.is-focused:not([disabled]),html.theme--catppuccin-mocha .field.has-addons .control .button:not([disabled]):active,html.theme--catppuccin-mocha .field.has-addons .control .button.is-active:not([disabled]),html.theme--catppuccin-mocha .field.has-addons .control .input:not([disabled]):focus,html.theme--catppuccin-mocha .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus,html.theme--catppuccin-mocha #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus,html.theme--catppuccin-mocha .field.has-addons .control .input.is-focused:not([disabled]),html.theme--catppuccin-mocha .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]),html.theme--catppuccin-mocha #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]),html.theme--catppuccin-mocha .field.has-addons .control .input:not([disabled]):active,html.theme--catppuccin-mocha .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active,html.theme--catppuccin-mocha #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active,html.theme--catppuccin-mocha .field.has-addons .control .input.is-active:not([disabled]),html.theme--catppuccin-mocha .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]),html.theme--catppuccin-mocha #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]),html.theme--catppuccin-mocha .field.has-addons .control .select select:not([disabled]):focus,html.theme--catppuccin-mocha .field.has-addons .control .select select.is-focused:not([disabled]),html.theme--catppuccin-mocha .field.has-addons .control .select select:not([disabled]):active,html.theme--catppuccin-mocha .field.has-addons .control .select select.is-active:not([disabled]){z-index:3}html.theme--catppuccin-mocha .field.has-addons .control .button:not([disabled]):focus:hover,html.theme--catppuccin-mocha .field.has-addons .control .button.is-focused:not([disabled]):hover,html.theme--catppuccin-mocha .field.has-addons .control .button:not([disabled]):active:hover,html.theme--catppuccin-mocha .field.has-addons .control .button.is-active:not([disabled]):hover,html.theme--catppuccin-mocha .field.has-addons .control .input:not([disabled]):focus:hover,html.theme--catppuccin-mocha .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus:hover,html.theme--catppuccin-mocha #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus:hover,html.theme--catppuccin-mocha .field.has-addons .control .input.is-focused:not([disabled]):hover,html.theme--catppuccin-mocha .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]):hover,html.theme--catppuccin-mocha #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]):hover,html.theme--catppuccin-mocha .field.has-addons .control .input:not([disabled]):active:hover,html.theme--catppuccin-mocha .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active:hover,html.theme--catppuccin-mocha #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active:hover,html.theme--catppuccin-mocha .field.has-addons .control .input.is-active:not([disabled]):hover,html.theme--catppuccin-mocha .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]):hover,html.theme--catppuccin-mocha #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]):hover,html.theme--catppuccin-mocha .field.has-addons .control .select select:not([disabled]):focus:hover,html.theme--catppuccin-mocha .field.has-addons .control .select select.is-focused:not([disabled]):hover,html.theme--catppuccin-mocha .field.has-addons .control .select select:not([disabled]):active:hover,html.theme--catppuccin-mocha .field.has-addons .control .select select.is-active:not([disabled]):hover{z-index:4}html.theme--catppuccin-mocha .field.has-addons .control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--catppuccin-mocha .field.has-addons.has-addons-centered{justify-content:center}html.theme--catppuccin-mocha .field.has-addons.has-addons-right{justify-content:flex-end}html.theme--catppuccin-mocha .field.has-addons.has-addons-fullwidth .control{flex-grow:1;flex-shrink:0}html.theme--catppuccin-mocha .field.is-grouped{display:flex;justify-content:flex-start}html.theme--catppuccin-mocha .field.is-grouped>.control{flex-shrink:0}html.theme--catppuccin-mocha .field.is-grouped>.control:not(:last-child){margin-bottom:0;margin-right:.75rem}html.theme--catppuccin-mocha .field.is-grouped>.control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--catppuccin-mocha .field.is-grouped.is-grouped-centered{justify-content:center}html.theme--catppuccin-mocha .field.is-grouped.is-grouped-right{justify-content:flex-end}html.theme--catppuccin-mocha .field.is-grouped.is-grouped-multiline{flex-wrap:wrap}html.theme--catppuccin-mocha .field.is-grouped.is-grouped-multiline>.control:last-child,html.theme--catppuccin-mocha .field.is-grouped.is-grouped-multiline>.control:not(:last-child){margin-bottom:0.75rem}html.theme--catppuccin-mocha .field.is-grouped.is-grouped-multiline:last-child{margin-bottom:-0.75rem}html.theme--catppuccin-mocha .field.is-grouped.is-grouped-multiline:not(:last-child){margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .field.is-horizontal{display:flex}}html.theme--catppuccin-mocha .field-label .label{font-size:inherit}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .field-label{margin-bottom:0.5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .field-label{flex-basis:0;flex-grow:1;flex-shrink:0;margin-right:1.5rem;text-align:right}html.theme--catppuccin-mocha .field-label.is-small,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.field-label{font-size:.75rem;padding-top:0.375em}html.theme--catppuccin-mocha .field-label.is-normal{padding-top:0.375em}html.theme--catppuccin-mocha .field-label.is-medium{font-size:1.25rem;padding-top:0.375em}html.theme--catppuccin-mocha .field-label.is-large{font-size:1.5rem;padding-top:0.375em}}html.theme--catppuccin-mocha .field-body .field .field{margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .field-body{display:flex;flex-basis:0;flex-grow:5;flex-shrink:1}html.theme--catppuccin-mocha .field-body .field{margin-bottom:0}html.theme--catppuccin-mocha .field-body>.field{flex-shrink:1}html.theme--catppuccin-mocha .field-body>.field:not(.is-narrow){flex-grow:1}html.theme--catppuccin-mocha .field-body>.field:not(:last-child){margin-right:.75rem}}html.theme--catppuccin-mocha .control{box-sizing:border-box;clear:both;font-size:1rem;position:relative;text-align:inherit}html.theme--catppuccin-mocha .control.has-icons-left .input:focus~.icon,html.theme--catppuccin-mocha .control.has-icons-left #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--catppuccin-mocha #documenter .docs-sidebar .control.has-icons-left form.docs-search>input:focus~.icon,html.theme--catppuccin-mocha .control.has-icons-left .select:focus~.icon,html.theme--catppuccin-mocha .control.has-icons-right .input:focus~.icon,html.theme--catppuccin-mocha .control.has-icons-right #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--catppuccin-mocha #documenter .docs-sidebar .control.has-icons-right form.docs-search>input:focus~.icon,html.theme--catppuccin-mocha .control.has-icons-right .select:focus~.icon{color:#313244}html.theme--catppuccin-mocha .control.has-icons-left .input.is-small~.icon,html.theme--catppuccin-mocha .control.has-icons-left #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--catppuccin-mocha #documenter .docs-sidebar .control.has-icons-left form.docs-search>input~.icon,html.theme--catppuccin-mocha .control.has-icons-left .select.is-small~.icon,html.theme--catppuccin-mocha .control.has-icons-right .input.is-small~.icon,html.theme--catppuccin-mocha .control.has-icons-right #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--catppuccin-mocha #documenter .docs-sidebar .control.has-icons-right form.docs-search>input~.icon,html.theme--catppuccin-mocha .control.has-icons-right .select.is-small~.icon{font-size:.75rem}html.theme--catppuccin-mocha .control.has-icons-left .input.is-medium~.icon,html.theme--catppuccin-mocha .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--catppuccin-mocha #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-medium~.icon,html.theme--catppuccin-mocha .control.has-icons-left .select.is-medium~.icon,html.theme--catppuccin-mocha .control.has-icons-right .input.is-medium~.icon,html.theme--catppuccin-mocha .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--catppuccin-mocha #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-medium~.icon,html.theme--catppuccin-mocha .control.has-icons-right .select.is-medium~.icon{font-size:1.25rem}html.theme--catppuccin-mocha .control.has-icons-left .input.is-large~.icon,html.theme--catppuccin-mocha .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--catppuccin-mocha #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-large~.icon,html.theme--catppuccin-mocha .control.has-icons-left .select.is-large~.icon,html.theme--catppuccin-mocha .control.has-icons-right .input.is-large~.icon,html.theme--catppuccin-mocha .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--catppuccin-mocha #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-large~.icon,html.theme--catppuccin-mocha .control.has-icons-right .select.is-large~.icon{font-size:1.5rem}html.theme--catppuccin-mocha .control.has-icons-left .icon,html.theme--catppuccin-mocha .control.has-icons-right .icon{color:#585b70;height:2.5em;pointer-events:none;position:absolute;top:0;width:2.5em;z-index:4}html.theme--catppuccin-mocha .control.has-icons-left .input,html.theme--catppuccin-mocha .control.has-icons-left #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-mocha #documenter .docs-sidebar .control.has-icons-left form.docs-search>input,html.theme--catppuccin-mocha .control.has-icons-left .select select{padding-left:2.5em}html.theme--catppuccin-mocha .control.has-icons-left .icon.is-left{left:0}html.theme--catppuccin-mocha .control.has-icons-right .input,html.theme--catppuccin-mocha .control.has-icons-right #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-mocha #documenter .docs-sidebar .control.has-icons-right form.docs-search>input,html.theme--catppuccin-mocha .control.has-icons-right .select select{padding-right:2.5em}html.theme--catppuccin-mocha .control.has-icons-right .icon.is-right{right:0}html.theme--catppuccin-mocha .control.is-loading::after{position:absolute !important;right:.625em;top:0.625em;z-index:4}html.theme--catppuccin-mocha .control.is-loading.is-small:after,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}html.theme--catppuccin-mocha .control.is-loading.is-medium:after{font-size:1.25rem}html.theme--catppuccin-mocha .control.is-loading.is-large:after{font-size:1.5rem}html.theme--catppuccin-mocha .breadcrumb{font-size:1rem;white-space:nowrap}html.theme--catppuccin-mocha .breadcrumb a{align-items:center;color:#89b4fa;display:flex;justify-content:center;padding:0 .75em}html.theme--catppuccin-mocha .breadcrumb a:hover{color:#89dceb}html.theme--catppuccin-mocha .breadcrumb li{align-items:center;display:flex}html.theme--catppuccin-mocha .breadcrumb li:first-child a{padding-left:0}html.theme--catppuccin-mocha .breadcrumb li.is-active a{color:#b8c5ef;cursor:default;pointer-events:none}html.theme--catppuccin-mocha .breadcrumb li+li::before{color:#6c7086;content:"\0002f"}html.theme--catppuccin-mocha .breadcrumb ul,html.theme--catppuccin-mocha .breadcrumb ol{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--catppuccin-mocha .breadcrumb .icon:first-child{margin-right:.5em}html.theme--catppuccin-mocha .breadcrumb .icon:last-child{margin-left:.5em}html.theme--catppuccin-mocha .breadcrumb.is-centered ol,html.theme--catppuccin-mocha .breadcrumb.is-centered ul{justify-content:center}html.theme--catppuccin-mocha .breadcrumb.is-right ol,html.theme--catppuccin-mocha .breadcrumb.is-right ul{justify-content:flex-end}html.theme--catppuccin-mocha .breadcrumb.is-small,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.breadcrumb{font-size:.75rem}html.theme--catppuccin-mocha .breadcrumb.is-medium{font-size:1.25rem}html.theme--catppuccin-mocha .breadcrumb.is-large{font-size:1.5rem}html.theme--catppuccin-mocha .breadcrumb.has-arrow-separator li+li::before{content:"\02192"}html.theme--catppuccin-mocha .breadcrumb.has-bullet-separator li+li::before{content:"\02022"}html.theme--catppuccin-mocha .breadcrumb.has-dot-separator li+li::before{content:"\000b7"}html.theme--catppuccin-mocha .breadcrumb.has-succeeds-separator li+li::before{content:"\0227B"}html.theme--catppuccin-mocha .card{background-color:#fff;border-radius:.25rem;box-shadow:#171717;color:#cdd6f4;max-width:100%;position:relative}html.theme--catppuccin-mocha .card-footer:first-child,html.theme--catppuccin-mocha .card-content:first-child,html.theme--catppuccin-mocha .card-header:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}html.theme--catppuccin-mocha .card-footer:last-child,html.theme--catppuccin-mocha .card-content:last-child,html.theme--catppuccin-mocha .card-header:last-child{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}html.theme--catppuccin-mocha .card-header{background-color:rgba(0,0,0,0);align-items:stretch;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);display:flex}html.theme--catppuccin-mocha .card-header-title{align-items:center;color:#b8c5ef;display:flex;flex-grow:1;font-weight:700;padding:0.75rem 1rem}html.theme--catppuccin-mocha .card-header-title.is-centered{justify-content:center}html.theme--catppuccin-mocha .card-header-icon{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0;align-items:center;cursor:pointer;display:flex;justify-content:center;padding:0.75rem 1rem}html.theme--catppuccin-mocha .card-image{display:block;position:relative}html.theme--catppuccin-mocha .card-image:first-child img{border-top-left-radius:.25rem;border-top-right-radius:.25rem}html.theme--catppuccin-mocha .card-image:last-child img{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}html.theme--catppuccin-mocha .card-content{background-color:rgba(0,0,0,0);padding:1.5rem}html.theme--catppuccin-mocha .card-footer{background-color:rgba(0,0,0,0);border-top:1px solid #ededed;align-items:stretch;display:flex}html.theme--catppuccin-mocha .card-footer-item{align-items:center;display:flex;flex-basis:0;flex-grow:1;flex-shrink:0;justify-content:center;padding:.75rem}html.theme--catppuccin-mocha .card-footer-item:not(:last-child){border-right:1px solid #ededed}html.theme--catppuccin-mocha .card .media:not(:last-child){margin-bottom:1.5rem}html.theme--catppuccin-mocha .dropdown{display:inline-flex;position:relative;vertical-align:top}html.theme--catppuccin-mocha .dropdown.is-active .dropdown-menu,html.theme--catppuccin-mocha .dropdown.is-hoverable:hover .dropdown-menu{display:block}html.theme--catppuccin-mocha .dropdown.is-right .dropdown-menu{left:auto;right:0}html.theme--catppuccin-mocha .dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:initial;top:auto}html.theme--catppuccin-mocha .dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:20}html.theme--catppuccin-mocha .dropdown-content{background-color:#181825;border-radius:.4em;box-shadow:#171717;padding-bottom:.5rem;padding-top:.5rem}html.theme--catppuccin-mocha .dropdown-item{color:#cdd6f4;display:block;font-size:0.875rem;line-height:1.5;padding:0.375rem 1rem;position:relative}html.theme--catppuccin-mocha a.dropdown-item,html.theme--catppuccin-mocha button.dropdown-item{padding-right:3rem;text-align:inherit;white-space:nowrap;width:100%}html.theme--catppuccin-mocha a.dropdown-item:hover,html.theme--catppuccin-mocha button.dropdown-item:hover{background-color:#181825;color:#0a0a0a}html.theme--catppuccin-mocha a.dropdown-item.is-active,html.theme--catppuccin-mocha button.dropdown-item.is-active{background-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .dropdown-divider{background-color:#ededed;border:none;display:block;height:1px;margin:0.5rem 0}html.theme--catppuccin-mocha .level{align-items:center;justify-content:space-between}html.theme--catppuccin-mocha .level code{border-radius:.4em}html.theme--catppuccin-mocha .level img{display:inline-block;vertical-align:top}html.theme--catppuccin-mocha .level.is-mobile{display:flex}html.theme--catppuccin-mocha .level.is-mobile .level-left,html.theme--catppuccin-mocha .level.is-mobile .level-right{display:flex}html.theme--catppuccin-mocha .level.is-mobile .level-left+.level-right{margin-top:0}html.theme--catppuccin-mocha .level.is-mobile .level-item:not(:last-child){margin-bottom:0;margin-right:.75rem}html.theme--catppuccin-mocha .level.is-mobile .level-item:not(.is-narrow){flex-grow:1}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .level{display:flex}html.theme--catppuccin-mocha .level>.level-item:not(.is-narrow){flex-grow:1}}html.theme--catppuccin-mocha .level-item{align-items:center;display:flex;flex-basis:auto;flex-grow:0;flex-shrink:0;justify-content:center}html.theme--catppuccin-mocha .level-item .title,html.theme--catppuccin-mocha .level-item .subtitle{margin-bottom:0}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .level-item:not(:last-child){margin-bottom:.75rem}}html.theme--catppuccin-mocha .level-left,html.theme--catppuccin-mocha .level-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--catppuccin-mocha .level-left .level-item.is-flexible,html.theme--catppuccin-mocha .level-right .level-item.is-flexible{flex-grow:1}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .level-left .level-item:not(:last-child),html.theme--catppuccin-mocha .level-right .level-item:not(:last-child){margin-right:.75rem}}html.theme--catppuccin-mocha .level-left{align-items:center;justify-content:flex-start}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .level-left+.level-right{margin-top:1.5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .level-left{display:flex}}html.theme--catppuccin-mocha .level-right{align-items:center;justify-content:flex-end}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .level-right{display:flex}}html.theme--catppuccin-mocha .media{align-items:flex-start;display:flex;text-align:inherit}html.theme--catppuccin-mocha .media .content:not(:last-child){margin-bottom:.75rem}html.theme--catppuccin-mocha .media .media{border-top:1px solid rgba(88,91,112,0.5);display:flex;padding-top:.75rem}html.theme--catppuccin-mocha .media .media .content:not(:last-child),html.theme--catppuccin-mocha .media .media .control:not(:last-child){margin-bottom:.5rem}html.theme--catppuccin-mocha .media .media .media{padding-top:.5rem}html.theme--catppuccin-mocha .media .media .media+.media{margin-top:.5rem}html.theme--catppuccin-mocha .media+.media{border-top:1px solid rgba(88,91,112,0.5);margin-top:1rem;padding-top:1rem}html.theme--catppuccin-mocha .media.is-large+.media{margin-top:1.5rem;padding-top:1.5rem}html.theme--catppuccin-mocha .media-left,html.theme--catppuccin-mocha .media-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--catppuccin-mocha .media-left{margin-right:1rem}html.theme--catppuccin-mocha .media-right{margin-left:1rem}html.theme--catppuccin-mocha .media-content{flex-basis:auto;flex-grow:1;flex-shrink:1;text-align:inherit}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .media-content{overflow-x:auto}}html.theme--catppuccin-mocha .menu{font-size:1rem}html.theme--catppuccin-mocha .menu.is-small,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.menu{font-size:.75rem}html.theme--catppuccin-mocha .menu.is-medium{font-size:1.25rem}html.theme--catppuccin-mocha .menu.is-large{font-size:1.5rem}html.theme--catppuccin-mocha .menu-list{line-height:1.25}html.theme--catppuccin-mocha .menu-list a{border-radius:3px;color:#cdd6f4;display:block;padding:0.5em 0.75em}html.theme--catppuccin-mocha .menu-list a:hover{background-color:#181825;color:#b8c5ef}html.theme--catppuccin-mocha .menu-list a.is-active{background-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .menu-list li ul{border-left:1px solid #585b70;margin:.75em;padding-left:.75em}html.theme--catppuccin-mocha .menu-label{color:#f7f8fd;font-size:.75em;letter-spacing:.1em;text-transform:uppercase}html.theme--catppuccin-mocha .menu-label:not(:first-child){margin-top:1em}html.theme--catppuccin-mocha .menu-label:not(:last-child){margin-bottom:1em}html.theme--catppuccin-mocha .message{background-color:#181825;border-radius:.4em;font-size:1rem}html.theme--catppuccin-mocha .message strong{color:currentColor}html.theme--catppuccin-mocha .message a:not(.button):not(.tag):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--catppuccin-mocha .message.is-small,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.message{font-size:.75rem}html.theme--catppuccin-mocha .message.is-medium{font-size:1.25rem}html.theme--catppuccin-mocha .message.is-large{font-size:1.5rem}html.theme--catppuccin-mocha .message.is-white{background-color:#fff}html.theme--catppuccin-mocha .message.is-white .message-header{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-mocha .message.is-white .message-body{border-color:#fff}html.theme--catppuccin-mocha .message.is-black{background-color:#fafafa}html.theme--catppuccin-mocha .message.is-black .message-header{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-mocha .message.is-black .message-body{border-color:#0a0a0a}html.theme--catppuccin-mocha .message.is-light{background-color:#fafafa}html.theme--catppuccin-mocha .message.is-light .message-header{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .message.is-light .message-body{border-color:#f5f5f5}html.theme--catppuccin-mocha .message.is-dark,html.theme--catppuccin-mocha .content kbd.message{background-color:#f9f9fb}html.theme--catppuccin-mocha .message.is-dark .message-header,html.theme--catppuccin-mocha .content kbd.message .message-header{background-color:#313244;color:#fff}html.theme--catppuccin-mocha .message.is-dark .message-body,html.theme--catppuccin-mocha .content kbd.message .message-body{border-color:#313244}html.theme--catppuccin-mocha .message.is-primary,html.theme--catppuccin-mocha .docstring>section>a.message.docs-sourcelink{background-color:#ebf3fe}html.theme--catppuccin-mocha .message.is-primary .message-header,html.theme--catppuccin-mocha .docstring>section>a.message.docs-sourcelink .message-header{background-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .message.is-primary .message-body,html.theme--catppuccin-mocha .docstring>section>a.message.docs-sourcelink .message-body{border-color:#89b4fa;color:#063c93}html.theme--catppuccin-mocha .message.is-link{background-color:#ebf3fe}html.theme--catppuccin-mocha .message.is-link .message-header{background-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .message.is-link .message-body{border-color:#89b4fa;color:#063c93}html.theme--catppuccin-mocha .message.is-info{background-color:#effbf9}html.theme--catppuccin-mocha .message.is-info .message-header{background-color:#94e2d5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .message.is-info .message-body{border-color:#94e2d5;color:#207466}html.theme--catppuccin-mocha .message.is-success{background-color:#f0faef}html.theme--catppuccin-mocha .message.is-success .message-header{background-color:#a6e3a1;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .message.is-success .message-body{border-color:#a6e3a1;color:#287222}html.theme--catppuccin-mocha .message.is-warning{background-color:#fef8ec}html.theme--catppuccin-mocha .message.is-warning .message-header{background-color:#f9e2af;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .message.is-warning .message-body{border-color:#f9e2af;color:#8a620a}html.theme--catppuccin-mocha .message.is-danger{background-color:#fdedf1}html.theme--catppuccin-mocha .message.is-danger .message-header{background-color:#f38ba8;color:#fff}html.theme--catppuccin-mocha .message.is-danger .message-body{border-color:#f38ba8;color:#991036}html.theme--catppuccin-mocha .message-header{align-items:center;background-color:#cdd6f4;border-radius:.4em .4em 0 0;color:rgba(0,0,0,0.7);display:flex;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.75em 1em;position:relative}html.theme--catppuccin-mocha .message-header .delete{flex-grow:0;flex-shrink:0;margin-left:.75em}html.theme--catppuccin-mocha .message-header+.message-body{border-width:0;border-top-left-radius:0;border-top-right-radius:0}html.theme--catppuccin-mocha .message-body{border-color:#585b70;border-radius:.4em;border-style:solid;border-width:0 0 0 4px;color:#cdd6f4;padding:1.25em 1.5em}html.theme--catppuccin-mocha .message-body code,html.theme--catppuccin-mocha .message-body pre{background-color:#fff}html.theme--catppuccin-mocha .message-body pre code{background-color:rgba(0,0,0,0)}html.theme--catppuccin-mocha .modal{align-items:center;display:none;flex-direction:column;justify-content:center;overflow:hidden;position:fixed;z-index:40}html.theme--catppuccin-mocha .modal.is-active{display:flex}html.theme--catppuccin-mocha .modal-background{background-color:rgba(10,10,10,0.86)}html.theme--catppuccin-mocha .modal-content,html.theme--catppuccin-mocha .modal-card{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width: 769px){html.theme--catppuccin-mocha .modal-content,html.theme--catppuccin-mocha .modal-card{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}html.theme--catppuccin-mocha .modal-close{background:none;height:40px;position:fixed;right:20px;top:20px;width:40px}html.theme--catppuccin-mocha .modal-card{display:flex;flex-direction:column;max-height:calc(100vh - 40px);overflow:hidden;-ms-overflow-y:visible}html.theme--catppuccin-mocha .modal-card-head,html.theme--catppuccin-mocha .modal-card-foot{align-items:center;background-color:#181825;display:flex;flex-shrink:0;justify-content:flex-start;padding:20px;position:relative}html.theme--catppuccin-mocha .modal-card-head{border-bottom:1px solid #585b70;border-top-left-radius:8px;border-top-right-radius:8px}html.theme--catppuccin-mocha .modal-card-title{color:#cdd6f4;flex-grow:1;flex-shrink:0;font-size:1.5rem;line-height:1}html.theme--catppuccin-mocha .modal-card-foot{border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid #585b70}html.theme--catppuccin-mocha .modal-card-foot .button:not(:last-child){margin-right:.5em}html.theme--catppuccin-mocha .modal-card-body{-webkit-overflow-scrolling:touch;background-color:#1e1e2e;flex-grow:1;flex-shrink:1;overflow:auto;padding:20px}html.theme--catppuccin-mocha .navbar{background-color:#89b4fa;min-height:4rem;position:relative;z-index:30}html.theme--catppuccin-mocha .navbar.is-white{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-mocha .navbar.is-white .navbar-brand>.navbar-item,html.theme--catppuccin-mocha .navbar.is-white .navbar-brand .navbar-link{color:#0a0a0a}html.theme--catppuccin-mocha .navbar.is-white .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-white .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-white .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-white .navbar-brand .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-white .navbar-brand .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-white .navbar-brand .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--catppuccin-mocha .navbar.is-white .navbar-brand .navbar-link::after{border-color:#0a0a0a}html.theme--catppuccin-mocha .navbar.is-white .navbar-burger{color:#0a0a0a}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .navbar.is-white .navbar-start>.navbar-item,html.theme--catppuccin-mocha .navbar.is-white .navbar-start .navbar-link,html.theme--catppuccin-mocha .navbar.is-white .navbar-end>.navbar-item,html.theme--catppuccin-mocha .navbar.is-white .navbar-end .navbar-link{color:#0a0a0a}html.theme--catppuccin-mocha .navbar.is-white .navbar-start>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-white .navbar-start>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-white .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-white .navbar-start .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-white .navbar-start .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-white .navbar-start .navbar-link.is-active,html.theme--catppuccin-mocha .navbar.is-white .navbar-end>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-white .navbar-end>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-white .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-white .navbar-end .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-white .navbar-end .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-white .navbar-end .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--catppuccin-mocha .navbar.is-white .navbar-start .navbar-link::after,html.theme--catppuccin-mocha .navbar.is-white .navbar-end .navbar-link::after{border-color:#0a0a0a}html.theme--catppuccin-mocha .navbar.is-white .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-mocha .navbar.is-white .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-mocha .navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link{background-color:#f2f2f2;color:#0a0a0a}html.theme--catppuccin-mocha .navbar.is-white .navbar-dropdown a.navbar-item.is-active{background-color:#fff;color:#0a0a0a}}html.theme--catppuccin-mocha .navbar.is-black{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-mocha .navbar.is-black .navbar-brand>.navbar-item,html.theme--catppuccin-mocha .navbar.is-black .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-mocha .navbar.is-black .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-black .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-black .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-black .navbar-brand .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-black .navbar-brand .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-black .navbar-brand .navbar-link.is-active{background-color:#000;color:#fff}html.theme--catppuccin-mocha .navbar.is-black .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-mocha .navbar.is-black .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .navbar.is-black .navbar-start>.navbar-item,html.theme--catppuccin-mocha .navbar.is-black .navbar-start .navbar-link,html.theme--catppuccin-mocha .navbar.is-black .navbar-end>.navbar-item,html.theme--catppuccin-mocha .navbar.is-black .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-mocha .navbar.is-black .navbar-start>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-black .navbar-start>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-black .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-black .navbar-start .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-black .navbar-start .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-black .navbar-start .navbar-link.is-active,html.theme--catppuccin-mocha .navbar.is-black .navbar-end>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-black .navbar-end>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-black .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-black .navbar-end .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-black .navbar-end .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-black .navbar-end .navbar-link.is-active{background-color:#000;color:#fff}html.theme--catppuccin-mocha .navbar.is-black .navbar-start .navbar-link::after,html.theme--catppuccin-mocha .navbar.is-black .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-mocha .navbar.is-black .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-mocha .navbar.is-black .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-mocha .navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link{background-color:#000;color:#fff}html.theme--catppuccin-mocha .navbar.is-black .navbar-dropdown a.navbar-item.is-active{background-color:#0a0a0a;color:#fff}}html.theme--catppuccin-mocha .navbar.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-light .navbar-brand>.navbar-item,html.theme--catppuccin-mocha .navbar.is-light .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-light .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-light .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-light .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-light .navbar-brand .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-light .navbar-brand .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-light .navbar-brand .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-light .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-light .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .navbar.is-light .navbar-start>.navbar-item,html.theme--catppuccin-mocha .navbar.is-light .navbar-start .navbar-link,html.theme--catppuccin-mocha .navbar.is-light .navbar-end>.navbar-item,html.theme--catppuccin-mocha .navbar.is-light .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-light .navbar-start>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-light .navbar-start>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-light .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-light .navbar-start .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-light .navbar-start .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-light .navbar-start .navbar-link.is-active,html.theme--catppuccin-mocha .navbar.is-light .navbar-end>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-light .navbar-end>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-light .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-light .navbar-end .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-light .navbar-end .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-light .navbar-end .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-light .navbar-start .navbar-link::after,html.theme--catppuccin-mocha .navbar.is-light .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-light .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-mocha .navbar.is-light .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-mocha .navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-light .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}}html.theme--catppuccin-mocha .navbar.is-dark,html.theme--catppuccin-mocha .content kbd.navbar{background-color:#313244;color:#fff}html.theme--catppuccin-mocha .navbar.is-dark .navbar-brand>.navbar-item,html.theme--catppuccin-mocha .content kbd.navbar .navbar-brand>.navbar-item,html.theme--catppuccin-mocha .navbar.is-dark .navbar-brand .navbar-link,html.theme--catppuccin-mocha .content kbd.navbar .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-mocha .navbar.is-dark .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-mocha .content kbd.navbar .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-dark .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-mocha .content kbd.navbar .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-dark .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-mocha .content kbd.navbar .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-dark .navbar-brand .navbar-link:focus,html.theme--catppuccin-mocha .content kbd.navbar .navbar-brand .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-dark .navbar-brand .navbar-link:hover,html.theme--catppuccin-mocha .content kbd.navbar .navbar-brand .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-dark .navbar-brand .navbar-link.is-active,html.theme--catppuccin-mocha .content kbd.navbar .navbar-brand .navbar-link.is-active{background-color:#262735;color:#fff}html.theme--catppuccin-mocha .navbar.is-dark .navbar-brand .navbar-link::after,html.theme--catppuccin-mocha .content kbd.navbar .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-mocha .navbar.is-dark .navbar-burger,html.theme--catppuccin-mocha .content kbd.navbar .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .navbar.is-dark .navbar-start>.navbar-item,html.theme--catppuccin-mocha .content kbd.navbar .navbar-start>.navbar-item,html.theme--catppuccin-mocha .navbar.is-dark .navbar-start .navbar-link,html.theme--catppuccin-mocha .content kbd.navbar .navbar-start .navbar-link,html.theme--catppuccin-mocha .navbar.is-dark .navbar-end>.navbar-item,html.theme--catppuccin-mocha .content kbd.navbar .navbar-end>.navbar-item,html.theme--catppuccin-mocha .navbar.is-dark .navbar-end .navbar-link,html.theme--catppuccin-mocha .content kbd.navbar .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-mocha .navbar.is-dark .navbar-start>a.navbar-item:focus,html.theme--catppuccin-mocha .content kbd.navbar .navbar-start>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-dark .navbar-start>a.navbar-item:hover,html.theme--catppuccin-mocha .content kbd.navbar .navbar-start>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-dark .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-mocha .content kbd.navbar .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-dark .navbar-start .navbar-link:focus,html.theme--catppuccin-mocha .content kbd.navbar .navbar-start .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-dark .navbar-start .navbar-link:hover,html.theme--catppuccin-mocha .content kbd.navbar .navbar-start .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-dark .navbar-start .navbar-link.is-active,html.theme--catppuccin-mocha .content kbd.navbar .navbar-start .navbar-link.is-active,html.theme--catppuccin-mocha .navbar.is-dark .navbar-end>a.navbar-item:focus,html.theme--catppuccin-mocha .content kbd.navbar .navbar-end>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-dark .navbar-end>a.navbar-item:hover,html.theme--catppuccin-mocha .content kbd.navbar .navbar-end>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-dark .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-mocha .content kbd.navbar .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-dark .navbar-end .navbar-link:focus,html.theme--catppuccin-mocha .content kbd.navbar .navbar-end .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-dark .navbar-end .navbar-link:hover,html.theme--catppuccin-mocha .content kbd.navbar .navbar-end .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-dark .navbar-end .navbar-link.is-active,html.theme--catppuccin-mocha .content kbd.navbar .navbar-end .navbar-link.is-active{background-color:#262735;color:#fff}html.theme--catppuccin-mocha .navbar.is-dark .navbar-start .navbar-link::after,html.theme--catppuccin-mocha .content kbd.navbar .navbar-start .navbar-link::after,html.theme--catppuccin-mocha .navbar.is-dark .navbar-end .navbar-link::after,html.theme--catppuccin-mocha .content kbd.navbar .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-mocha .navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-mocha .content kbd.navbar .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-mocha .navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-mocha .content kbd.navbar .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-mocha .navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link,html.theme--catppuccin-mocha .content kbd.navbar .navbar-item.has-dropdown.is-active .navbar-link{background-color:#262735;color:#fff}html.theme--catppuccin-mocha .navbar.is-dark .navbar-dropdown a.navbar-item.is-active,html.theme--catppuccin-mocha .content kbd.navbar .navbar-dropdown a.navbar-item.is-active{background-color:#313244;color:#fff}}html.theme--catppuccin-mocha .navbar.is-primary,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink{background-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .navbar.is-primary .navbar-brand>.navbar-item,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-brand>.navbar-item,html.theme--catppuccin-mocha .navbar.is-primary .navbar-brand .navbar-link,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-mocha .navbar.is-primary .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-primary .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-primary .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-primary .navbar-brand .navbar-link:focus,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-primary .navbar-brand .navbar-link:hover,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-primary .navbar-brand .navbar-link.is-active,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link.is-active{background-color:#71a4f9;color:#fff}html.theme--catppuccin-mocha .navbar.is-primary .navbar-brand .navbar-link::after,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-mocha .navbar.is-primary .navbar-burger,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .navbar.is-primary .navbar-start>.navbar-item,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-start>.navbar-item,html.theme--catppuccin-mocha .navbar.is-primary .navbar-start .navbar-link,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link,html.theme--catppuccin-mocha .navbar.is-primary .navbar-end>.navbar-item,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-end>.navbar-item,html.theme--catppuccin-mocha .navbar.is-primary .navbar-end .navbar-link,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-mocha .navbar.is-primary .navbar-start>a.navbar-item:focus,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-primary .navbar-start>a.navbar-item:hover,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-primary .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-primary .navbar-start .navbar-link:focus,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-primary .navbar-start .navbar-link:hover,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-primary .navbar-start .navbar-link.is-active,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link.is-active,html.theme--catppuccin-mocha .navbar.is-primary .navbar-end>a.navbar-item:focus,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-primary .navbar-end>a.navbar-item:hover,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-primary .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-primary .navbar-end .navbar-link:focus,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-primary .navbar-end .navbar-link:hover,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-primary .navbar-end .navbar-link.is-active,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link.is-active{background-color:#71a4f9;color:#fff}html.theme--catppuccin-mocha .navbar.is-primary .navbar-start .navbar-link::after,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link::after,html.theme--catppuccin-mocha .navbar.is-primary .navbar-end .navbar-link::after,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-mocha .navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-mocha .navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-mocha .navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown.is-active .navbar-link{background-color:#71a4f9;color:#fff}html.theme--catppuccin-mocha .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#89b4fa;color:#fff}}html.theme--catppuccin-mocha .navbar.is-link{background-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .navbar.is-link .navbar-brand>.navbar-item,html.theme--catppuccin-mocha .navbar.is-link .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-mocha .navbar.is-link .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-link .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-link .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-link .navbar-brand .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-link .navbar-brand .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-link .navbar-brand .navbar-link.is-active{background-color:#71a4f9;color:#fff}html.theme--catppuccin-mocha .navbar.is-link .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-mocha .navbar.is-link .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .navbar.is-link .navbar-start>.navbar-item,html.theme--catppuccin-mocha .navbar.is-link .navbar-start .navbar-link,html.theme--catppuccin-mocha .navbar.is-link .navbar-end>.navbar-item,html.theme--catppuccin-mocha .navbar.is-link .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-mocha .navbar.is-link .navbar-start>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-link .navbar-start>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-link .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-link .navbar-start .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-link .navbar-start .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-link .navbar-start .navbar-link.is-active,html.theme--catppuccin-mocha .navbar.is-link .navbar-end>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-link .navbar-end>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-link .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-link .navbar-end .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-link .navbar-end .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-link .navbar-end .navbar-link.is-active{background-color:#71a4f9;color:#fff}html.theme--catppuccin-mocha .navbar.is-link .navbar-start .navbar-link::after,html.theme--catppuccin-mocha .navbar.is-link .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-mocha .navbar.is-link .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-mocha .navbar.is-link .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-mocha .navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link{background-color:#71a4f9;color:#fff}html.theme--catppuccin-mocha .navbar.is-link .navbar-dropdown a.navbar-item.is-active{background-color:#89b4fa;color:#fff}}html.theme--catppuccin-mocha .navbar.is-info{background-color:#94e2d5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-info .navbar-brand>.navbar-item,html.theme--catppuccin-mocha .navbar.is-info .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-info .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-info .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-info .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-info .navbar-brand .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-info .navbar-brand .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-info .navbar-brand .navbar-link.is-active{background-color:#80ddcd;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-info .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-info .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .navbar.is-info .navbar-start>.navbar-item,html.theme--catppuccin-mocha .navbar.is-info .navbar-start .navbar-link,html.theme--catppuccin-mocha .navbar.is-info .navbar-end>.navbar-item,html.theme--catppuccin-mocha .navbar.is-info .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-info .navbar-start>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-info .navbar-start>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-info .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-info .navbar-start .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-info .navbar-start .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-info .navbar-start .navbar-link.is-active,html.theme--catppuccin-mocha .navbar.is-info .navbar-end>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-info .navbar-end>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-info .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-info .navbar-end .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-info .navbar-end .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-info .navbar-end .navbar-link.is-active{background-color:#80ddcd;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-info .navbar-start .navbar-link::after,html.theme--catppuccin-mocha .navbar.is-info .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-info .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-mocha .navbar.is-info .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-mocha .navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link{background-color:#80ddcd;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-info .navbar-dropdown a.navbar-item.is-active{background-color:#94e2d5;color:rgba(0,0,0,0.7)}}html.theme--catppuccin-mocha .navbar.is-success{background-color:#a6e3a1;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-success .navbar-brand>.navbar-item,html.theme--catppuccin-mocha .navbar.is-success .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-success .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-success .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-success .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-success .navbar-brand .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-success .navbar-brand .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-success .navbar-brand .navbar-link.is-active{background-color:#93dd8d;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-success .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-success .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .navbar.is-success .navbar-start>.navbar-item,html.theme--catppuccin-mocha .navbar.is-success .navbar-start .navbar-link,html.theme--catppuccin-mocha .navbar.is-success .navbar-end>.navbar-item,html.theme--catppuccin-mocha .navbar.is-success .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-success .navbar-start>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-success .navbar-start>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-success .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-success .navbar-start .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-success .navbar-start .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-success .navbar-start .navbar-link.is-active,html.theme--catppuccin-mocha .navbar.is-success .navbar-end>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-success .navbar-end>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-success .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-success .navbar-end .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-success .navbar-end .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-success .navbar-end .navbar-link.is-active{background-color:#93dd8d;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-success .navbar-start .navbar-link::after,html.theme--catppuccin-mocha .navbar.is-success .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-success .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-mocha .navbar.is-success .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-mocha .navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link{background-color:#93dd8d;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-success .navbar-dropdown a.navbar-item.is-active{background-color:#a6e3a1;color:rgba(0,0,0,0.7)}}html.theme--catppuccin-mocha .navbar.is-warning{background-color:#f9e2af;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-warning .navbar-brand>.navbar-item,html.theme--catppuccin-mocha .navbar.is-warning .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-warning .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-warning .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-warning .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-warning .navbar-brand .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-warning .navbar-brand .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-warning .navbar-brand .navbar-link.is-active{background-color:#f7d997;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-warning .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-warning .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .navbar.is-warning .navbar-start>.navbar-item,html.theme--catppuccin-mocha .navbar.is-warning .navbar-start .navbar-link,html.theme--catppuccin-mocha .navbar.is-warning .navbar-end>.navbar-item,html.theme--catppuccin-mocha .navbar.is-warning .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-warning .navbar-start>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-warning .navbar-start>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-warning .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-warning .navbar-start .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-warning .navbar-start .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-warning .navbar-start .navbar-link.is-active,html.theme--catppuccin-mocha .navbar.is-warning .navbar-end>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-warning .navbar-end>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-warning .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-warning .navbar-end .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-warning .navbar-end .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-warning .navbar-end .navbar-link.is-active{background-color:#f7d997;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-warning .navbar-start .navbar-link::after,html.theme--catppuccin-mocha .navbar.is-warning .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-mocha .navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-mocha .navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link{background-color:#f7d997;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .navbar.is-warning .navbar-dropdown a.navbar-item.is-active{background-color:#f9e2af;color:rgba(0,0,0,0.7)}}html.theme--catppuccin-mocha .navbar.is-danger{background-color:#f38ba8;color:#fff}html.theme--catppuccin-mocha .navbar.is-danger .navbar-brand>.navbar-item,html.theme--catppuccin-mocha .navbar.is-danger .navbar-brand .navbar-link{color:#fff}html.theme--catppuccin-mocha .navbar.is-danger .navbar-brand>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-danger .navbar-brand>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-danger .navbar-brand>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-danger .navbar-brand .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-danger .navbar-brand .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-danger .navbar-brand .navbar-link.is-active{background-color:#f17497;color:#fff}html.theme--catppuccin-mocha .navbar.is-danger .navbar-brand .navbar-link::after{border-color:#fff}html.theme--catppuccin-mocha .navbar.is-danger .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .navbar.is-danger .navbar-start>.navbar-item,html.theme--catppuccin-mocha .navbar.is-danger .navbar-start .navbar-link,html.theme--catppuccin-mocha .navbar.is-danger .navbar-end>.navbar-item,html.theme--catppuccin-mocha .navbar.is-danger .navbar-end .navbar-link{color:#fff}html.theme--catppuccin-mocha .navbar.is-danger .navbar-start>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-danger .navbar-start>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-danger .navbar-start>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-danger .navbar-start .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-danger .navbar-start .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-danger .navbar-start .navbar-link.is-active,html.theme--catppuccin-mocha .navbar.is-danger .navbar-end>a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-danger .navbar-end>a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-danger .navbar-end>a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-danger .navbar-end .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-danger .navbar-end .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-danger .navbar-end .navbar-link.is-active{background-color:#f17497;color:#fff}html.theme--catppuccin-mocha .navbar.is-danger .navbar-start .navbar-link::after,html.theme--catppuccin-mocha .navbar.is-danger .navbar-end .navbar-link::after{border-color:#fff}html.theme--catppuccin-mocha .navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-mocha .navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-mocha .navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link{background-color:#f17497;color:#fff}html.theme--catppuccin-mocha .navbar.is-danger .navbar-dropdown a.navbar-item.is-active{background-color:#f38ba8;color:#fff}}html.theme--catppuccin-mocha .navbar>.container{align-items:stretch;display:flex;min-height:4rem;width:100%}html.theme--catppuccin-mocha .navbar.has-shadow{box-shadow:0 2px 0 0 #181825}html.theme--catppuccin-mocha .navbar.is-fixed-bottom,html.theme--catppuccin-mocha .navbar.is-fixed-top{left:0;position:fixed;right:0;z-index:30}html.theme--catppuccin-mocha .navbar.is-fixed-bottom{bottom:0}html.theme--catppuccin-mocha .navbar.is-fixed-bottom.has-shadow{box-shadow:0 -2px 0 0 #181825}html.theme--catppuccin-mocha .navbar.is-fixed-top{top:0}html.theme--catppuccin-mocha html.has-navbar-fixed-top,html.theme--catppuccin-mocha body.has-navbar-fixed-top{padding-top:4rem}html.theme--catppuccin-mocha html.has-navbar-fixed-bottom,html.theme--catppuccin-mocha body.has-navbar-fixed-bottom{padding-bottom:4rem}html.theme--catppuccin-mocha .navbar-brand,html.theme--catppuccin-mocha .navbar-tabs{align-items:stretch;display:flex;flex-shrink:0;min-height:4rem}html.theme--catppuccin-mocha .navbar-brand a.navbar-item:focus,html.theme--catppuccin-mocha .navbar-brand a.navbar-item:hover{background-color:transparent}html.theme--catppuccin-mocha .navbar-tabs{-webkit-overflow-scrolling:touch;max-width:100vw;overflow-x:auto;overflow-y:hidden}html.theme--catppuccin-mocha .navbar-burger{color:#cdd6f4;-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;cursor:pointer;display:block;height:4rem;position:relative;width:4rem;margin-left:auto}html.theme--catppuccin-mocha .navbar-burger span{background-color:currentColor;display:block;height:1px;left:calc(50% - 8px);position:absolute;transform-origin:center;transition-duration:86ms;transition-property:background-color, opacity, transform;transition-timing-function:ease-out;width:16px}html.theme--catppuccin-mocha .navbar-burger span:nth-child(1){top:calc(50% - 6px)}html.theme--catppuccin-mocha .navbar-burger span:nth-child(2){top:calc(50% - 1px)}html.theme--catppuccin-mocha .navbar-burger span:nth-child(3){top:calc(50% + 4px)}html.theme--catppuccin-mocha .navbar-burger:hover{background-color:rgba(0,0,0,0.05)}html.theme--catppuccin-mocha .navbar-burger.is-active span:nth-child(1){transform:translateY(5px) rotate(45deg)}html.theme--catppuccin-mocha .navbar-burger.is-active span:nth-child(2){opacity:0}html.theme--catppuccin-mocha .navbar-burger.is-active span:nth-child(3){transform:translateY(-5px) rotate(-45deg)}html.theme--catppuccin-mocha .navbar-menu{display:none}html.theme--catppuccin-mocha .navbar-item,html.theme--catppuccin-mocha .navbar-link{color:#cdd6f4;display:block;line-height:1.5;padding:0.5rem 0.75rem;position:relative}html.theme--catppuccin-mocha .navbar-item .icon:only-child,html.theme--catppuccin-mocha .navbar-link .icon:only-child{margin-left:-0.25rem;margin-right:-0.25rem}html.theme--catppuccin-mocha a.navbar-item,html.theme--catppuccin-mocha .navbar-link{cursor:pointer}html.theme--catppuccin-mocha a.navbar-item:focus,html.theme--catppuccin-mocha a.navbar-item:focus-within,html.theme--catppuccin-mocha a.navbar-item:hover,html.theme--catppuccin-mocha a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar-link:focus,html.theme--catppuccin-mocha .navbar-link:focus-within,html.theme--catppuccin-mocha .navbar-link:hover,html.theme--catppuccin-mocha .navbar-link.is-active{background-color:rgba(0,0,0,0);color:#89b4fa}html.theme--catppuccin-mocha .navbar-item{flex-grow:0;flex-shrink:0}html.theme--catppuccin-mocha .navbar-item img{max-height:1.75rem}html.theme--catppuccin-mocha .navbar-item.has-dropdown{padding:0}html.theme--catppuccin-mocha .navbar-item.is-expanded{flex-grow:1;flex-shrink:1}html.theme--catppuccin-mocha .navbar-item.is-tab{border-bottom:1px solid transparent;min-height:4rem;padding-bottom:calc(0.5rem - 1px)}html.theme--catppuccin-mocha .navbar-item.is-tab:focus,html.theme--catppuccin-mocha .navbar-item.is-tab:hover{background-color:rgba(0,0,0,0);border-bottom-color:#89b4fa}html.theme--catppuccin-mocha .navbar-item.is-tab.is-active{background-color:rgba(0,0,0,0);border-bottom-color:#89b4fa;border-bottom-style:solid;border-bottom-width:3px;color:#89b4fa;padding-bottom:calc(0.5rem - 3px)}html.theme--catppuccin-mocha .navbar-content{flex-grow:1;flex-shrink:1}html.theme--catppuccin-mocha .navbar-link:not(.is-arrowless){padding-right:2.5em}html.theme--catppuccin-mocha .navbar-link:not(.is-arrowless)::after{border-color:#fff;margin-top:-0.375em;right:1.125em}html.theme--catppuccin-mocha .navbar-dropdown{font-size:0.875rem;padding-bottom:0.5rem;padding-top:0.5rem}html.theme--catppuccin-mocha .navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}html.theme--catppuccin-mocha .navbar-divider{background-color:rgba(0,0,0,0.2);border:none;display:none;height:2px;margin:0.5rem 0}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .navbar>.container{display:block}html.theme--catppuccin-mocha .navbar-brand .navbar-item,html.theme--catppuccin-mocha .navbar-tabs .navbar-item{align-items:center;display:flex}html.theme--catppuccin-mocha .navbar-link::after{display:none}html.theme--catppuccin-mocha .navbar-menu{background-color:#89b4fa;box-shadow:0 8px 16px rgba(10,10,10,0.1);padding:0.5rem 0}html.theme--catppuccin-mocha .navbar-menu.is-active{display:block}html.theme--catppuccin-mocha .navbar.is-fixed-bottom-touch,html.theme--catppuccin-mocha .navbar.is-fixed-top-touch{left:0;position:fixed;right:0;z-index:30}html.theme--catppuccin-mocha .navbar.is-fixed-bottom-touch{bottom:0}html.theme--catppuccin-mocha .navbar.is-fixed-bottom-touch.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--catppuccin-mocha .navbar.is-fixed-top-touch{top:0}html.theme--catppuccin-mocha .navbar.is-fixed-top .navbar-menu,html.theme--catppuccin-mocha .navbar.is-fixed-top-touch .navbar-menu{-webkit-overflow-scrolling:touch;max-height:calc(100vh - 4rem);overflow:auto}html.theme--catppuccin-mocha html.has-navbar-fixed-top-touch,html.theme--catppuccin-mocha body.has-navbar-fixed-top-touch{padding-top:4rem}html.theme--catppuccin-mocha html.has-navbar-fixed-bottom-touch,html.theme--catppuccin-mocha body.has-navbar-fixed-bottom-touch{padding-bottom:4rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .navbar,html.theme--catppuccin-mocha .navbar-menu,html.theme--catppuccin-mocha .navbar-start,html.theme--catppuccin-mocha .navbar-end{align-items:stretch;display:flex}html.theme--catppuccin-mocha .navbar{min-height:4rem}html.theme--catppuccin-mocha .navbar.is-spaced{padding:1rem 2rem}html.theme--catppuccin-mocha .navbar.is-spaced .navbar-start,html.theme--catppuccin-mocha .navbar.is-spaced .navbar-end{align-items:center}html.theme--catppuccin-mocha .navbar.is-spaced a.navbar-item,html.theme--catppuccin-mocha .navbar.is-spaced .navbar-link{border-radius:.4em}html.theme--catppuccin-mocha .navbar.is-transparent a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-transparent a.navbar-item:hover,html.theme--catppuccin-mocha .navbar.is-transparent a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar.is-transparent .navbar-link:focus,html.theme--catppuccin-mocha .navbar.is-transparent .navbar-link:hover,html.theme--catppuccin-mocha .navbar.is-transparent .navbar-link.is-active{background-color:transparent !important}html.theme--catppuccin-mocha .navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link,html.theme--catppuccin-mocha .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link,html.theme--catppuccin-mocha .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link,html.theme--catppuccin-mocha .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link{background-color:transparent !important}html.theme--catppuccin-mocha .navbar.is-transparent .navbar-dropdown a.navbar-item:focus,html.theme--catppuccin-mocha .navbar.is-transparent .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#7f849c}html.theme--catppuccin-mocha .navbar.is-transparent .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#89b4fa}html.theme--catppuccin-mocha .navbar-burger{display:none}html.theme--catppuccin-mocha .navbar-item,html.theme--catppuccin-mocha .navbar-link{align-items:center;display:flex}html.theme--catppuccin-mocha .navbar-item.has-dropdown{align-items:stretch}html.theme--catppuccin-mocha .navbar-item.has-dropdown-up .navbar-link::after{transform:rotate(135deg) translate(0.25em, -0.25em)}html.theme--catppuccin-mocha .navbar-item.has-dropdown-up .navbar-dropdown{border-bottom:1px solid rgba(0,0,0,0.2);border-radius:8px 8px 0 0;border-top:none;bottom:100%;box-shadow:0 -8px 8px rgba(10,10,10,0.1);top:auto}html.theme--catppuccin-mocha .navbar-item.is-active .navbar-dropdown,html.theme--catppuccin-mocha .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--catppuccin-mocha .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--catppuccin-mocha .navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar.is-spaced html.theme--catppuccin-mocha .navbar-item.is-active .navbar-dropdown,html.theme--catppuccin-mocha .navbar-item.is-active .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--catppuccin-mocha .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--catppuccin-mocha .navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--catppuccin-mocha .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--catppuccin-mocha .navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--catppuccin-mocha .navbar-item.is-hoverable:hover .navbar-dropdown,html.theme--catppuccin-mocha .navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed{opacity:1;pointer-events:auto;transform:translateY(0)}html.theme--catppuccin-mocha .navbar-menu{flex-grow:1;flex-shrink:0}html.theme--catppuccin-mocha .navbar-start{justify-content:flex-start;margin-right:auto}html.theme--catppuccin-mocha .navbar-end{justify-content:flex-end;margin-left:auto}html.theme--catppuccin-mocha .navbar-dropdown{background-color:#89b4fa;border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid rgba(0,0,0,0.2);box-shadow:0 8px 8px rgba(10,10,10,0.1);display:none;font-size:0.875rem;left:0;min-width:100%;position:absolute;top:100%;z-index:20}html.theme--catppuccin-mocha .navbar-dropdown .navbar-item{padding:0.375rem 1rem;white-space:nowrap}html.theme--catppuccin-mocha .navbar-dropdown a.navbar-item{padding-right:3rem}html.theme--catppuccin-mocha .navbar-dropdown a.navbar-item:focus,html.theme--catppuccin-mocha .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#7f849c}html.theme--catppuccin-mocha .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#89b4fa}.navbar.is-spaced html.theme--catppuccin-mocha .navbar-dropdown,html.theme--catppuccin-mocha .navbar-dropdown.is-boxed{border-radius:8px;border-top:none;box-shadow:0 8px 8px rgba(10,10,10,0.1), 0 0 0 1px rgba(10,10,10,0.1);display:block;opacity:0;pointer-events:none;top:calc(100% + (-4px));transform:translateY(-5px);transition-duration:86ms;transition-property:opacity, transform}html.theme--catppuccin-mocha .navbar-dropdown.is-right{left:auto;right:0}html.theme--catppuccin-mocha .navbar-divider{display:block}html.theme--catppuccin-mocha .navbar>.container .navbar-brand,html.theme--catppuccin-mocha .container>.navbar .navbar-brand{margin-left:-.75rem}html.theme--catppuccin-mocha .navbar>.container .navbar-menu,html.theme--catppuccin-mocha .container>.navbar .navbar-menu{margin-right:-.75rem}html.theme--catppuccin-mocha .navbar.is-fixed-bottom-desktop,html.theme--catppuccin-mocha .navbar.is-fixed-top-desktop{left:0;position:fixed;right:0;z-index:30}html.theme--catppuccin-mocha .navbar.is-fixed-bottom-desktop{bottom:0}html.theme--catppuccin-mocha .navbar.is-fixed-bottom-desktop.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--catppuccin-mocha .navbar.is-fixed-top-desktop{top:0}html.theme--catppuccin-mocha html.has-navbar-fixed-top-desktop,html.theme--catppuccin-mocha body.has-navbar-fixed-top-desktop{padding-top:4rem}html.theme--catppuccin-mocha html.has-navbar-fixed-bottom-desktop,html.theme--catppuccin-mocha body.has-navbar-fixed-bottom-desktop{padding-bottom:4rem}html.theme--catppuccin-mocha html.has-spaced-navbar-fixed-top,html.theme--catppuccin-mocha body.has-spaced-navbar-fixed-top{padding-top:6rem}html.theme--catppuccin-mocha html.has-spaced-navbar-fixed-bottom,html.theme--catppuccin-mocha body.has-spaced-navbar-fixed-bottom{padding-bottom:6rem}html.theme--catppuccin-mocha a.navbar-item.is-active,html.theme--catppuccin-mocha .navbar-link.is-active{color:#89b4fa}html.theme--catppuccin-mocha a.navbar-item.is-active:not(:focus):not(:hover),html.theme--catppuccin-mocha .navbar-link.is-active:not(:focus):not(:hover){background-color:rgba(0,0,0,0)}html.theme--catppuccin-mocha .navbar-item.has-dropdown:focus .navbar-link,html.theme--catppuccin-mocha .navbar-item.has-dropdown:hover .navbar-link,html.theme--catppuccin-mocha .navbar-item.has-dropdown.is-active .navbar-link{background-color:rgba(0,0,0,0)}}html.theme--catppuccin-mocha .hero.is-fullheight-with-navbar{min-height:calc(100vh - 4rem)}html.theme--catppuccin-mocha .pagination{font-size:1rem;margin:-.25rem}html.theme--catppuccin-mocha .pagination.is-small,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.pagination{font-size:.75rem}html.theme--catppuccin-mocha .pagination.is-medium{font-size:1.25rem}html.theme--catppuccin-mocha .pagination.is-large{font-size:1.5rem}html.theme--catppuccin-mocha .pagination.is-rounded .pagination-previous,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.pagination .pagination-previous,html.theme--catppuccin-mocha .pagination.is-rounded .pagination-next,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.pagination .pagination-next{padding-left:1em;padding-right:1em;border-radius:9999px}html.theme--catppuccin-mocha .pagination.is-rounded .pagination-link,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.pagination .pagination-link{border-radius:9999px}html.theme--catppuccin-mocha .pagination,html.theme--catppuccin-mocha .pagination-list{align-items:center;display:flex;justify-content:center;text-align:center}html.theme--catppuccin-mocha .pagination-previous,html.theme--catppuccin-mocha .pagination-next,html.theme--catppuccin-mocha .pagination-link,html.theme--catppuccin-mocha .pagination-ellipsis{font-size:1em;justify-content:center;margin:.25rem;padding-left:.5em;padding-right:.5em;text-align:center}html.theme--catppuccin-mocha .pagination-previous,html.theme--catppuccin-mocha .pagination-next,html.theme--catppuccin-mocha .pagination-link{border-color:#585b70;color:#89b4fa;min-width:2.5em}html.theme--catppuccin-mocha .pagination-previous:hover,html.theme--catppuccin-mocha .pagination-next:hover,html.theme--catppuccin-mocha .pagination-link:hover{border-color:#6c7086;color:#89dceb}html.theme--catppuccin-mocha .pagination-previous:focus,html.theme--catppuccin-mocha .pagination-next:focus,html.theme--catppuccin-mocha .pagination-link:focus{border-color:#6c7086}html.theme--catppuccin-mocha .pagination-previous:active,html.theme--catppuccin-mocha .pagination-next:active,html.theme--catppuccin-mocha .pagination-link:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2)}html.theme--catppuccin-mocha .pagination-previous[disabled],html.theme--catppuccin-mocha .pagination-previous.is-disabled,html.theme--catppuccin-mocha .pagination-next[disabled],html.theme--catppuccin-mocha .pagination-next.is-disabled,html.theme--catppuccin-mocha .pagination-link[disabled],html.theme--catppuccin-mocha .pagination-link.is-disabled{background-color:#585b70;border-color:#585b70;box-shadow:none;color:#f7f8fd;opacity:0.5}html.theme--catppuccin-mocha .pagination-previous,html.theme--catppuccin-mocha .pagination-next{padding-left:.75em;padding-right:.75em;white-space:nowrap}html.theme--catppuccin-mocha .pagination-link.is-current{background-color:#89b4fa;border-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .pagination-ellipsis{color:#6c7086;pointer-events:none}html.theme--catppuccin-mocha .pagination-list{flex-wrap:wrap}html.theme--catppuccin-mocha .pagination-list li{list-style:none}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .pagination{flex-wrap:wrap}html.theme--catppuccin-mocha .pagination-previous,html.theme--catppuccin-mocha .pagination-next{flex-grow:1;flex-shrink:1}html.theme--catppuccin-mocha .pagination-list li{flex-grow:1;flex-shrink:1}}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .pagination-list{flex-grow:1;flex-shrink:1;justify-content:flex-start;order:1}html.theme--catppuccin-mocha .pagination-previous,html.theme--catppuccin-mocha .pagination-next,html.theme--catppuccin-mocha .pagination-link,html.theme--catppuccin-mocha .pagination-ellipsis{margin-bottom:0;margin-top:0}html.theme--catppuccin-mocha .pagination-previous{order:2}html.theme--catppuccin-mocha .pagination-next{order:3}html.theme--catppuccin-mocha .pagination{justify-content:space-between;margin-bottom:0;margin-top:0}html.theme--catppuccin-mocha .pagination.is-centered .pagination-previous{order:1}html.theme--catppuccin-mocha .pagination.is-centered .pagination-list{justify-content:center;order:2}html.theme--catppuccin-mocha .pagination.is-centered .pagination-next{order:3}html.theme--catppuccin-mocha .pagination.is-right .pagination-previous{order:1}html.theme--catppuccin-mocha .pagination.is-right .pagination-next{order:2}html.theme--catppuccin-mocha .pagination.is-right .pagination-list{justify-content:flex-end;order:3}}html.theme--catppuccin-mocha .panel{border-radius:8px;box-shadow:#171717;font-size:1rem}html.theme--catppuccin-mocha .panel:not(:last-child){margin-bottom:1.5rem}html.theme--catppuccin-mocha .panel.is-white .panel-heading{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-mocha .panel.is-white .panel-tabs a.is-active{border-bottom-color:#fff}html.theme--catppuccin-mocha .panel.is-white .panel-block.is-active .panel-icon{color:#fff}html.theme--catppuccin-mocha .panel.is-black .panel-heading{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-mocha .panel.is-black .panel-tabs a.is-active{border-bottom-color:#0a0a0a}html.theme--catppuccin-mocha .panel.is-black .panel-block.is-active .panel-icon{color:#0a0a0a}html.theme--catppuccin-mocha .panel.is-light .panel-heading{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .panel.is-light .panel-tabs a.is-active{border-bottom-color:#f5f5f5}html.theme--catppuccin-mocha .panel.is-light .panel-block.is-active .panel-icon{color:#f5f5f5}html.theme--catppuccin-mocha .panel.is-dark .panel-heading,html.theme--catppuccin-mocha .content kbd.panel .panel-heading{background-color:#313244;color:#fff}html.theme--catppuccin-mocha .panel.is-dark .panel-tabs a.is-active,html.theme--catppuccin-mocha .content kbd.panel .panel-tabs a.is-active{border-bottom-color:#313244}html.theme--catppuccin-mocha .panel.is-dark .panel-block.is-active .panel-icon,html.theme--catppuccin-mocha .content kbd.panel .panel-block.is-active .panel-icon{color:#313244}html.theme--catppuccin-mocha .panel.is-primary .panel-heading,html.theme--catppuccin-mocha .docstring>section>a.panel.docs-sourcelink .panel-heading{background-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .panel.is-primary .panel-tabs a.is-active,html.theme--catppuccin-mocha .docstring>section>a.panel.docs-sourcelink .panel-tabs a.is-active{border-bottom-color:#89b4fa}html.theme--catppuccin-mocha .panel.is-primary .panel-block.is-active .panel-icon,html.theme--catppuccin-mocha .docstring>section>a.panel.docs-sourcelink .panel-block.is-active .panel-icon{color:#89b4fa}html.theme--catppuccin-mocha .panel.is-link .panel-heading{background-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .panel.is-link .panel-tabs a.is-active{border-bottom-color:#89b4fa}html.theme--catppuccin-mocha .panel.is-link .panel-block.is-active .panel-icon{color:#89b4fa}html.theme--catppuccin-mocha .panel.is-info .panel-heading{background-color:#94e2d5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .panel.is-info .panel-tabs a.is-active{border-bottom-color:#94e2d5}html.theme--catppuccin-mocha .panel.is-info .panel-block.is-active .panel-icon{color:#94e2d5}html.theme--catppuccin-mocha .panel.is-success .panel-heading{background-color:#a6e3a1;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .panel.is-success .panel-tabs a.is-active{border-bottom-color:#a6e3a1}html.theme--catppuccin-mocha .panel.is-success .panel-block.is-active .panel-icon{color:#a6e3a1}html.theme--catppuccin-mocha .panel.is-warning .panel-heading{background-color:#f9e2af;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .panel.is-warning .panel-tabs a.is-active{border-bottom-color:#f9e2af}html.theme--catppuccin-mocha .panel.is-warning .panel-block.is-active .panel-icon{color:#f9e2af}html.theme--catppuccin-mocha .panel.is-danger .panel-heading{background-color:#f38ba8;color:#fff}html.theme--catppuccin-mocha .panel.is-danger .panel-tabs a.is-active{border-bottom-color:#f38ba8}html.theme--catppuccin-mocha .panel.is-danger .panel-block.is-active .panel-icon{color:#f38ba8}html.theme--catppuccin-mocha .panel-tabs:not(:last-child),html.theme--catppuccin-mocha .panel-block:not(:last-child){border-bottom:1px solid #ededed}html.theme--catppuccin-mocha .panel-heading{background-color:#45475a;border-radius:8px 8px 0 0;color:#b8c5ef;font-size:1.25em;font-weight:700;line-height:1.25;padding:0.75em 1em}html.theme--catppuccin-mocha .panel-tabs{align-items:flex-end;display:flex;font-size:.875em;justify-content:center}html.theme--catppuccin-mocha .panel-tabs a{border-bottom:1px solid #585b70;margin-bottom:-1px;padding:0.5em}html.theme--catppuccin-mocha .panel-tabs a.is-active{border-bottom-color:#45475a;color:#71a4f9}html.theme--catppuccin-mocha .panel-list a{color:#cdd6f4}html.theme--catppuccin-mocha .panel-list a:hover{color:#89b4fa}html.theme--catppuccin-mocha .panel-block{align-items:center;color:#b8c5ef;display:flex;justify-content:flex-start;padding:0.5em 0.75em}html.theme--catppuccin-mocha .panel-block input[type="checkbox"]{margin-right:.75em}html.theme--catppuccin-mocha .panel-block>.control{flex-grow:1;flex-shrink:1;width:100%}html.theme--catppuccin-mocha .panel-block.is-wrapped{flex-wrap:wrap}html.theme--catppuccin-mocha .panel-block.is-active{border-left-color:#89b4fa;color:#71a4f9}html.theme--catppuccin-mocha .panel-block.is-active .panel-icon{color:#89b4fa}html.theme--catppuccin-mocha .panel-block:last-child{border-bottom-left-radius:8px;border-bottom-right-radius:8px}html.theme--catppuccin-mocha a.panel-block,html.theme--catppuccin-mocha label.panel-block{cursor:pointer}html.theme--catppuccin-mocha a.panel-block:hover,html.theme--catppuccin-mocha label.panel-block:hover{background-color:#181825}html.theme--catppuccin-mocha .panel-icon{display:inline-block;font-size:14px;height:1em;line-height:1em;text-align:center;vertical-align:top;width:1em;color:#f7f8fd;margin-right:.75em}html.theme--catppuccin-mocha .panel-icon .fa{font-size:inherit;line-height:inherit}html.theme--catppuccin-mocha .tabs{-webkit-overflow-scrolling:touch;align-items:stretch;display:flex;font-size:1rem;justify-content:space-between;overflow:hidden;overflow-x:auto;white-space:nowrap}html.theme--catppuccin-mocha .tabs a{align-items:center;border-bottom-color:#585b70;border-bottom-style:solid;border-bottom-width:1px;color:#cdd6f4;display:flex;justify-content:center;margin-bottom:-1px;padding:0.5em 1em;vertical-align:top}html.theme--catppuccin-mocha .tabs a:hover{border-bottom-color:#b8c5ef;color:#b8c5ef}html.theme--catppuccin-mocha .tabs li{display:block}html.theme--catppuccin-mocha .tabs li.is-active a{border-bottom-color:#89b4fa;color:#89b4fa}html.theme--catppuccin-mocha .tabs ul{align-items:center;border-bottom-color:#585b70;border-bottom-style:solid;border-bottom-width:1px;display:flex;flex-grow:1;flex-shrink:0;justify-content:flex-start}html.theme--catppuccin-mocha .tabs ul.is-left{padding-right:0.75em}html.theme--catppuccin-mocha .tabs ul.is-center{flex:none;justify-content:center;padding-left:0.75em;padding-right:0.75em}html.theme--catppuccin-mocha .tabs ul.is-right{justify-content:flex-end;padding-left:0.75em}html.theme--catppuccin-mocha .tabs .icon:first-child{margin-right:.5em}html.theme--catppuccin-mocha .tabs .icon:last-child{margin-left:.5em}html.theme--catppuccin-mocha .tabs.is-centered ul{justify-content:center}html.theme--catppuccin-mocha .tabs.is-right ul{justify-content:flex-end}html.theme--catppuccin-mocha .tabs.is-boxed a{border:1px solid transparent;border-radius:.4em .4em 0 0}html.theme--catppuccin-mocha .tabs.is-boxed a:hover{background-color:#181825;border-bottom-color:#585b70}html.theme--catppuccin-mocha .tabs.is-boxed li.is-active a{background-color:#fff;border-color:#585b70;border-bottom-color:rgba(0,0,0,0) !important}html.theme--catppuccin-mocha .tabs.is-fullwidth li{flex-grow:1;flex-shrink:0}html.theme--catppuccin-mocha .tabs.is-toggle a{border-color:#585b70;border-style:solid;border-width:1px;margin-bottom:0;position:relative}html.theme--catppuccin-mocha .tabs.is-toggle a:hover{background-color:#181825;border-color:#6c7086;z-index:2}html.theme--catppuccin-mocha .tabs.is-toggle li+li{margin-left:-1px}html.theme--catppuccin-mocha .tabs.is-toggle li:first-child a{border-top-left-radius:.4em;border-bottom-left-radius:.4em}html.theme--catppuccin-mocha .tabs.is-toggle li:last-child a{border-top-right-radius:.4em;border-bottom-right-radius:.4em}html.theme--catppuccin-mocha .tabs.is-toggle li.is-active a{background-color:#89b4fa;border-color:#89b4fa;color:#fff;z-index:1}html.theme--catppuccin-mocha .tabs.is-toggle ul{border-bottom:none}html.theme--catppuccin-mocha .tabs.is-toggle.is-toggle-rounded li:first-child a{border-bottom-left-radius:9999px;border-top-left-radius:9999px;padding-left:1.25em}html.theme--catppuccin-mocha .tabs.is-toggle.is-toggle-rounded li:last-child a{border-bottom-right-radius:9999px;border-top-right-radius:9999px;padding-right:1.25em}html.theme--catppuccin-mocha .tabs.is-small,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.tabs{font-size:.75rem}html.theme--catppuccin-mocha .tabs.is-medium{font-size:1.25rem}html.theme--catppuccin-mocha .tabs.is-large{font-size:1.5rem}html.theme--catppuccin-mocha .column{display:block;flex-basis:0;flex-grow:1;flex-shrink:1;padding:.75rem}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-narrow{flex:none;width:unset}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-full{flex:none;width:100%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-three-quarters{flex:none;width:75%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-two-thirds{flex:none;width:66.6666%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-half{flex:none;width:50%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-one-third{flex:none;width:33.3333%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-one-quarter{flex:none;width:25%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-one-fifth{flex:none;width:20%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-two-fifths{flex:none;width:40%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-three-fifths{flex:none;width:60%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-four-fifths{flex:none;width:80%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-three-quarters{margin-left:75%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-two-thirds{margin-left:66.6666%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-half{margin-left:50%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-one-third{margin-left:33.3333%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-one-quarter{margin-left:25%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-one-fifth{margin-left:20%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-two-fifths{margin-left:40%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-three-fifths{margin-left:60%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-four-fifths{margin-left:80%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-0{flex:none;width:0%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-0{margin-left:0%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-1{flex:none;width:8.33333337%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-1{margin-left:8.33333337%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-2{flex:none;width:16.66666674%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-2{margin-left:16.66666674%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-3{flex:none;width:25%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-3{margin-left:25%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-4{flex:none;width:33.33333337%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-4{margin-left:33.33333337%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-5{flex:none;width:41.66666674%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-5{margin-left:41.66666674%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-6{flex:none;width:50%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-6{margin-left:50%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-7{flex:none;width:58.33333337%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-7{margin-left:58.33333337%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-8{flex:none;width:66.66666674%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-8{margin-left:66.66666674%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-9{flex:none;width:75%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-9{margin-left:75%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-10{flex:none;width:83.33333337%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-10{margin-left:83.33333337%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-11{flex:none;width:91.66666674%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-11{margin-left:91.66666674%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-12{flex:none;width:100%}.columns.is-mobile>html.theme--catppuccin-mocha .column.is-offset-12{margin-left:100%}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .column.is-narrow-mobile{flex:none;width:unset}html.theme--catppuccin-mocha .column.is-full-mobile{flex:none;width:100%}html.theme--catppuccin-mocha .column.is-three-quarters-mobile{flex:none;width:75%}html.theme--catppuccin-mocha .column.is-two-thirds-mobile{flex:none;width:66.6666%}html.theme--catppuccin-mocha .column.is-half-mobile{flex:none;width:50%}html.theme--catppuccin-mocha .column.is-one-third-mobile{flex:none;width:33.3333%}html.theme--catppuccin-mocha .column.is-one-quarter-mobile{flex:none;width:25%}html.theme--catppuccin-mocha .column.is-one-fifth-mobile{flex:none;width:20%}html.theme--catppuccin-mocha .column.is-two-fifths-mobile{flex:none;width:40%}html.theme--catppuccin-mocha .column.is-three-fifths-mobile{flex:none;width:60%}html.theme--catppuccin-mocha .column.is-four-fifths-mobile{flex:none;width:80%}html.theme--catppuccin-mocha .column.is-offset-three-quarters-mobile{margin-left:75%}html.theme--catppuccin-mocha .column.is-offset-two-thirds-mobile{margin-left:66.6666%}html.theme--catppuccin-mocha .column.is-offset-half-mobile{margin-left:50%}html.theme--catppuccin-mocha .column.is-offset-one-third-mobile{margin-left:33.3333%}html.theme--catppuccin-mocha .column.is-offset-one-quarter-mobile{margin-left:25%}html.theme--catppuccin-mocha .column.is-offset-one-fifth-mobile{margin-left:20%}html.theme--catppuccin-mocha .column.is-offset-two-fifths-mobile{margin-left:40%}html.theme--catppuccin-mocha .column.is-offset-three-fifths-mobile{margin-left:60%}html.theme--catppuccin-mocha .column.is-offset-four-fifths-mobile{margin-left:80%}html.theme--catppuccin-mocha .column.is-0-mobile{flex:none;width:0%}html.theme--catppuccin-mocha .column.is-offset-0-mobile{margin-left:0%}html.theme--catppuccin-mocha .column.is-1-mobile{flex:none;width:8.33333337%}html.theme--catppuccin-mocha .column.is-offset-1-mobile{margin-left:8.33333337%}html.theme--catppuccin-mocha .column.is-2-mobile{flex:none;width:16.66666674%}html.theme--catppuccin-mocha .column.is-offset-2-mobile{margin-left:16.66666674%}html.theme--catppuccin-mocha .column.is-3-mobile{flex:none;width:25%}html.theme--catppuccin-mocha .column.is-offset-3-mobile{margin-left:25%}html.theme--catppuccin-mocha .column.is-4-mobile{flex:none;width:33.33333337%}html.theme--catppuccin-mocha .column.is-offset-4-mobile{margin-left:33.33333337%}html.theme--catppuccin-mocha .column.is-5-mobile{flex:none;width:41.66666674%}html.theme--catppuccin-mocha .column.is-offset-5-mobile{margin-left:41.66666674%}html.theme--catppuccin-mocha .column.is-6-mobile{flex:none;width:50%}html.theme--catppuccin-mocha .column.is-offset-6-mobile{margin-left:50%}html.theme--catppuccin-mocha .column.is-7-mobile{flex:none;width:58.33333337%}html.theme--catppuccin-mocha .column.is-offset-7-mobile{margin-left:58.33333337%}html.theme--catppuccin-mocha .column.is-8-mobile{flex:none;width:66.66666674%}html.theme--catppuccin-mocha .column.is-offset-8-mobile{margin-left:66.66666674%}html.theme--catppuccin-mocha .column.is-9-mobile{flex:none;width:75%}html.theme--catppuccin-mocha .column.is-offset-9-mobile{margin-left:75%}html.theme--catppuccin-mocha .column.is-10-mobile{flex:none;width:83.33333337%}html.theme--catppuccin-mocha .column.is-offset-10-mobile{margin-left:83.33333337%}html.theme--catppuccin-mocha .column.is-11-mobile{flex:none;width:91.66666674%}html.theme--catppuccin-mocha .column.is-offset-11-mobile{margin-left:91.66666674%}html.theme--catppuccin-mocha .column.is-12-mobile{flex:none;width:100%}html.theme--catppuccin-mocha .column.is-offset-12-mobile{margin-left:100%}}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .column.is-narrow,html.theme--catppuccin-mocha .column.is-narrow-tablet{flex:none;width:unset}html.theme--catppuccin-mocha .column.is-full,html.theme--catppuccin-mocha .column.is-full-tablet{flex:none;width:100%}html.theme--catppuccin-mocha .column.is-three-quarters,html.theme--catppuccin-mocha .column.is-three-quarters-tablet{flex:none;width:75%}html.theme--catppuccin-mocha .column.is-two-thirds,html.theme--catppuccin-mocha .column.is-two-thirds-tablet{flex:none;width:66.6666%}html.theme--catppuccin-mocha .column.is-half,html.theme--catppuccin-mocha .column.is-half-tablet{flex:none;width:50%}html.theme--catppuccin-mocha .column.is-one-third,html.theme--catppuccin-mocha .column.is-one-third-tablet{flex:none;width:33.3333%}html.theme--catppuccin-mocha .column.is-one-quarter,html.theme--catppuccin-mocha .column.is-one-quarter-tablet{flex:none;width:25%}html.theme--catppuccin-mocha .column.is-one-fifth,html.theme--catppuccin-mocha .column.is-one-fifth-tablet{flex:none;width:20%}html.theme--catppuccin-mocha .column.is-two-fifths,html.theme--catppuccin-mocha .column.is-two-fifths-tablet{flex:none;width:40%}html.theme--catppuccin-mocha .column.is-three-fifths,html.theme--catppuccin-mocha .column.is-three-fifths-tablet{flex:none;width:60%}html.theme--catppuccin-mocha .column.is-four-fifths,html.theme--catppuccin-mocha .column.is-four-fifths-tablet{flex:none;width:80%}html.theme--catppuccin-mocha .column.is-offset-three-quarters,html.theme--catppuccin-mocha .column.is-offset-three-quarters-tablet{margin-left:75%}html.theme--catppuccin-mocha .column.is-offset-two-thirds,html.theme--catppuccin-mocha .column.is-offset-two-thirds-tablet{margin-left:66.6666%}html.theme--catppuccin-mocha .column.is-offset-half,html.theme--catppuccin-mocha .column.is-offset-half-tablet{margin-left:50%}html.theme--catppuccin-mocha .column.is-offset-one-third,html.theme--catppuccin-mocha .column.is-offset-one-third-tablet{margin-left:33.3333%}html.theme--catppuccin-mocha .column.is-offset-one-quarter,html.theme--catppuccin-mocha .column.is-offset-one-quarter-tablet{margin-left:25%}html.theme--catppuccin-mocha .column.is-offset-one-fifth,html.theme--catppuccin-mocha .column.is-offset-one-fifth-tablet{margin-left:20%}html.theme--catppuccin-mocha .column.is-offset-two-fifths,html.theme--catppuccin-mocha .column.is-offset-two-fifths-tablet{margin-left:40%}html.theme--catppuccin-mocha .column.is-offset-three-fifths,html.theme--catppuccin-mocha .column.is-offset-three-fifths-tablet{margin-left:60%}html.theme--catppuccin-mocha .column.is-offset-four-fifths,html.theme--catppuccin-mocha .column.is-offset-four-fifths-tablet{margin-left:80%}html.theme--catppuccin-mocha .column.is-0,html.theme--catppuccin-mocha .column.is-0-tablet{flex:none;width:0%}html.theme--catppuccin-mocha .column.is-offset-0,html.theme--catppuccin-mocha .column.is-offset-0-tablet{margin-left:0%}html.theme--catppuccin-mocha .column.is-1,html.theme--catppuccin-mocha .column.is-1-tablet{flex:none;width:8.33333337%}html.theme--catppuccin-mocha .column.is-offset-1,html.theme--catppuccin-mocha .column.is-offset-1-tablet{margin-left:8.33333337%}html.theme--catppuccin-mocha .column.is-2,html.theme--catppuccin-mocha .column.is-2-tablet{flex:none;width:16.66666674%}html.theme--catppuccin-mocha .column.is-offset-2,html.theme--catppuccin-mocha .column.is-offset-2-tablet{margin-left:16.66666674%}html.theme--catppuccin-mocha .column.is-3,html.theme--catppuccin-mocha .column.is-3-tablet{flex:none;width:25%}html.theme--catppuccin-mocha .column.is-offset-3,html.theme--catppuccin-mocha .column.is-offset-3-tablet{margin-left:25%}html.theme--catppuccin-mocha .column.is-4,html.theme--catppuccin-mocha .column.is-4-tablet{flex:none;width:33.33333337%}html.theme--catppuccin-mocha .column.is-offset-4,html.theme--catppuccin-mocha .column.is-offset-4-tablet{margin-left:33.33333337%}html.theme--catppuccin-mocha .column.is-5,html.theme--catppuccin-mocha .column.is-5-tablet{flex:none;width:41.66666674%}html.theme--catppuccin-mocha .column.is-offset-5,html.theme--catppuccin-mocha .column.is-offset-5-tablet{margin-left:41.66666674%}html.theme--catppuccin-mocha .column.is-6,html.theme--catppuccin-mocha .column.is-6-tablet{flex:none;width:50%}html.theme--catppuccin-mocha .column.is-offset-6,html.theme--catppuccin-mocha .column.is-offset-6-tablet{margin-left:50%}html.theme--catppuccin-mocha .column.is-7,html.theme--catppuccin-mocha .column.is-7-tablet{flex:none;width:58.33333337%}html.theme--catppuccin-mocha .column.is-offset-7,html.theme--catppuccin-mocha .column.is-offset-7-tablet{margin-left:58.33333337%}html.theme--catppuccin-mocha .column.is-8,html.theme--catppuccin-mocha .column.is-8-tablet{flex:none;width:66.66666674%}html.theme--catppuccin-mocha .column.is-offset-8,html.theme--catppuccin-mocha .column.is-offset-8-tablet{margin-left:66.66666674%}html.theme--catppuccin-mocha .column.is-9,html.theme--catppuccin-mocha .column.is-9-tablet{flex:none;width:75%}html.theme--catppuccin-mocha .column.is-offset-9,html.theme--catppuccin-mocha .column.is-offset-9-tablet{margin-left:75%}html.theme--catppuccin-mocha .column.is-10,html.theme--catppuccin-mocha .column.is-10-tablet{flex:none;width:83.33333337%}html.theme--catppuccin-mocha .column.is-offset-10,html.theme--catppuccin-mocha .column.is-offset-10-tablet{margin-left:83.33333337%}html.theme--catppuccin-mocha .column.is-11,html.theme--catppuccin-mocha .column.is-11-tablet{flex:none;width:91.66666674%}html.theme--catppuccin-mocha .column.is-offset-11,html.theme--catppuccin-mocha .column.is-offset-11-tablet{margin-left:91.66666674%}html.theme--catppuccin-mocha .column.is-12,html.theme--catppuccin-mocha .column.is-12-tablet{flex:none;width:100%}html.theme--catppuccin-mocha .column.is-offset-12,html.theme--catppuccin-mocha .column.is-offset-12-tablet{margin-left:100%}}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .column.is-narrow-touch{flex:none;width:unset}html.theme--catppuccin-mocha .column.is-full-touch{flex:none;width:100%}html.theme--catppuccin-mocha .column.is-three-quarters-touch{flex:none;width:75%}html.theme--catppuccin-mocha .column.is-two-thirds-touch{flex:none;width:66.6666%}html.theme--catppuccin-mocha .column.is-half-touch{flex:none;width:50%}html.theme--catppuccin-mocha .column.is-one-third-touch{flex:none;width:33.3333%}html.theme--catppuccin-mocha .column.is-one-quarter-touch{flex:none;width:25%}html.theme--catppuccin-mocha .column.is-one-fifth-touch{flex:none;width:20%}html.theme--catppuccin-mocha .column.is-two-fifths-touch{flex:none;width:40%}html.theme--catppuccin-mocha .column.is-three-fifths-touch{flex:none;width:60%}html.theme--catppuccin-mocha .column.is-four-fifths-touch{flex:none;width:80%}html.theme--catppuccin-mocha .column.is-offset-three-quarters-touch{margin-left:75%}html.theme--catppuccin-mocha .column.is-offset-two-thirds-touch{margin-left:66.6666%}html.theme--catppuccin-mocha .column.is-offset-half-touch{margin-left:50%}html.theme--catppuccin-mocha .column.is-offset-one-third-touch{margin-left:33.3333%}html.theme--catppuccin-mocha .column.is-offset-one-quarter-touch{margin-left:25%}html.theme--catppuccin-mocha .column.is-offset-one-fifth-touch{margin-left:20%}html.theme--catppuccin-mocha .column.is-offset-two-fifths-touch{margin-left:40%}html.theme--catppuccin-mocha .column.is-offset-three-fifths-touch{margin-left:60%}html.theme--catppuccin-mocha .column.is-offset-four-fifths-touch{margin-left:80%}html.theme--catppuccin-mocha .column.is-0-touch{flex:none;width:0%}html.theme--catppuccin-mocha .column.is-offset-0-touch{margin-left:0%}html.theme--catppuccin-mocha .column.is-1-touch{flex:none;width:8.33333337%}html.theme--catppuccin-mocha .column.is-offset-1-touch{margin-left:8.33333337%}html.theme--catppuccin-mocha .column.is-2-touch{flex:none;width:16.66666674%}html.theme--catppuccin-mocha .column.is-offset-2-touch{margin-left:16.66666674%}html.theme--catppuccin-mocha .column.is-3-touch{flex:none;width:25%}html.theme--catppuccin-mocha .column.is-offset-3-touch{margin-left:25%}html.theme--catppuccin-mocha .column.is-4-touch{flex:none;width:33.33333337%}html.theme--catppuccin-mocha .column.is-offset-4-touch{margin-left:33.33333337%}html.theme--catppuccin-mocha .column.is-5-touch{flex:none;width:41.66666674%}html.theme--catppuccin-mocha .column.is-offset-5-touch{margin-left:41.66666674%}html.theme--catppuccin-mocha .column.is-6-touch{flex:none;width:50%}html.theme--catppuccin-mocha .column.is-offset-6-touch{margin-left:50%}html.theme--catppuccin-mocha .column.is-7-touch{flex:none;width:58.33333337%}html.theme--catppuccin-mocha .column.is-offset-7-touch{margin-left:58.33333337%}html.theme--catppuccin-mocha .column.is-8-touch{flex:none;width:66.66666674%}html.theme--catppuccin-mocha .column.is-offset-8-touch{margin-left:66.66666674%}html.theme--catppuccin-mocha .column.is-9-touch{flex:none;width:75%}html.theme--catppuccin-mocha .column.is-offset-9-touch{margin-left:75%}html.theme--catppuccin-mocha .column.is-10-touch{flex:none;width:83.33333337%}html.theme--catppuccin-mocha .column.is-offset-10-touch{margin-left:83.33333337%}html.theme--catppuccin-mocha .column.is-11-touch{flex:none;width:91.66666674%}html.theme--catppuccin-mocha .column.is-offset-11-touch{margin-left:91.66666674%}html.theme--catppuccin-mocha .column.is-12-touch{flex:none;width:100%}html.theme--catppuccin-mocha .column.is-offset-12-touch{margin-left:100%}}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .column.is-narrow-desktop{flex:none;width:unset}html.theme--catppuccin-mocha .column.is-full-desktop{flex:none;width:100%}html.theme--catppuccin-mocha .column.is-three-quarters-desktop{flex:none;width:75%}html.theme--catppuccin-mocha .column.is-two-thirds-desktop{flex:none;width:66.6666%}html.theme--catppuccin-mocha .column.is-half-desktop{flex:none;width:50%}html.theme--catppuccin-mocha .column.is-one-third-desktop{flex:none;width:33.3333%}html.theme--catppuccin-mocha .column.is-one-quarter-desktop{flex:none;width:25%}html.theme--catppuccin-mocha .column.is-one-fifth-desktop{flex:none;width:20%}html.theme--catppuccin-mocha .column.is-two-fifths-desktop{flex:none;width:40%}html.theme--catppuccin-mocha .column.is-three-fifths-desktop{flex:none;width:60%}html.theme--catppuccin-mocha .column.is-four-fifths-desktop{flex:none;width:80%}html.theme--catppuccin-mocha .column.is-offset-three-quarters-desktop{margin-left:75%}html.theme--catppuccin-mocha .column.is-offset-two-thirds-desktop{margin-left:66.6666%}html.theme--catppuccin-mocha .column.is-offset-half-desktop{margin-left:50%}html.theme--catppuccin-mocha .column.is-offset-one-third-desktop{margin-left:33.3333%}html.theme--catppuccin-mocha .column.is-offset-one-quarter-desktop{margin-left:25%}html.theme--catppuccin-mocha .column.is-offset-one-fifth-desktop{margin-left:20%}html.theme--catppuccin-mocha .column.is-offset-two-fifths-desktop{margin-left:40%}html.theme--catppuccin-mocha .column.is-offset-three-fifths-desktop{margin-left:60%}html.theme--catppuccin-mocha .column.is-offset-four-fifths-desktop{margin-left:80%}html.theme--catppuccin-mocha .column.is-0-desktop{flex:none;width:0%}html.theme--catppuccin-mocha .column.is-offset-0-desktop{margin-left:0%}html.theme--catppuccin-mocha .column.is-1-desktop{flex:none;width:8.33333337%}html.theme--catppuccin-mocha .column.is-offset-1-desktop{margin-left:8.33333337%}html.theme--catppuccin-mocha .column.is-2-desktop{flex:none;width:16.66666674%}html.theme--catppuccin-mocha .column.is-offset-2-desktop{margin-left:16.66666674%}html.theme--catppuccin-mocha .column.is-3-desktop{flex:none;width:25%}html.theme--catppuccin-mocha .column.is-offset-3-desktop{margin-left:25%}html.theme--catppuccin-mocha .column.is-4-desktop{flex:none;width:33.33333337%}html.theme--catppuccin-mocha .column.is-offset-4-desktop{margin-left:33.33333337%}html.theme--catppuccin-mocha .column.is-5-desktop{flex:none;width:41.66666674%}html.theme--catppuccin-mocha .column.is-offset-5-desktop{margin-left:41.66666674%}html.theme--catppuccin-mocha .column.is-6-desktop{flex:none;width:50%}html.theme--catppuccin-mocha .column.is-offset-6-desktop{margin-left:50%}html.theme--catppuccin-mocha .column.is-7-desktop{flex:none;width:58.33333337%}html.theme--catppuccin-mocha .column.is-offset-7-desktop{margin-left:58.33333337%}html.theme--catppuccin-mocha .column.is-8-desktop{flex:none;width:66.66666674%}html.theme--catppuccin-mocha .column.is-offset-8-desktop{margin-left:66.66666674%}html.theme--catppuccin-mocha .column.is-9-desktop{flex:none;width:75%}html.theme--catppuccin-mocha .column.is-offset-9-desktop{margin-left:75%}html.theme--catppuccin-mocha .column.is-10-desktop{flex:none;width:83.33333337%}html.theme--catppuccin-mocha .column.is-offset-10-desktop{margin-left:83.33333337%}html.theme--catppuccin-mocha .column.is-11-desktop{flex:none;width:91.66666674%}html.theme--catppuccin-mocha .column.is-offset-11-desktop{margin-left:91.66666674%}html.theme--catppuccin-mocha .column.is-12-desktop{flex:none;width:100%}html.theme--catppuccin-mocha .column.is-offset-12-desktop{margin-left:100%}}@media screen and (min-width: 1216px){html.theme--catppuccin-mocha .column.is-narrow-widescreen{flex:none;width:unset}html.theme--catppuccin-mocha .column.is-full-widescreen{flex:none;width:100%}html.theme--catppuccin-mocha .column.is-three-quarters-widescreen{flex:none;width:75%}html.theme--catppuccin-mocha .column.is-two-thirds-widescreen{flex:none;width:66.6666%}html.theme--catppuccin-mocha .column.is-half-widescreen{flex:none;width:50%}html.theme--catppuccin-mocha .column.is-one-third-widescreen{flex:none;width:33.3333%}html.theme--catppuccin-mocha .column.is-one-quarter-widescreen{flex:none;width:25%}html.theme--catppuccin-mocha .column.is-one-fifth-widescreen{flex:none;width:20%}html.theme--catppuccin-mocha .column.is-two-fifths-widescreen{flex:none;width:40%}html.theme--catppuccin-mocha .column.is-three-fifths-widescreen{flex:none;width:60%}html.theme--catppuccin-mocha .column.is-four-fifths-widescreen{flex:none;width:80%}html.theme--catppuccin-mocha .column.is-offset-three-quarters-widescreen{margin-left:75%}html.theme--catppuccin-mocha .column.is-offset-two-thirds-widescreen{margin-left:66.6666%}html.theme--catppuccin-mocha .column.is-offset-half-widescreen{margin-left:50%}html.theme--catppuccin-mocha .column.is-offset-one-third-widescreen{margin-left:33.3333%}html.theme--catppuccin-mocha .column.is-offset-one-quarter-widescreen{margin-left:25%}html.theme--catppuccin-mocha .column.is-offset-one-fifth-widescreen{margin-left:20%}html.theme--catppuccin-mocha .column.is-offset-two-fifths-widescreen{margin-left:40%}html.theme--catppuccin-mocha .column.is-offset-three-fifths-widescreen{margin-left:60%}html.theme--catppuccin-mocha .column.is-offset-four-fifths-widescreen{margin-left:80%}html.theme--catppuccin-mocha .column.is-0-widescreen{flex:none;width:0%}html.theme--catppuccin-mocha .column.is-offset-0-widescreen{margin-left:0%}html.theme--catppuccin-mocha .column.is-1-widescreen{flex:none;width:8.33333337%}html.theme--catppuccin-mocha .column.is-offset-1-widescreen{margin-left:8.33333337%}html.theme--catppuccin-mocha .column.is-2-widescreen{flex:none;width:16.66666674%}html.theme--catppuccin-mocha .column.is-offset-2-widescreen{margin-left:16.66666674%}html.theme--catppuccin-mocha .column.is-3-widescreen{flex:none;width:25%}html.theme--catppuccin-mocha .column.is-offset-3-widescreen{margin-left:25%}html.theme--catppuccin-mocha .column.is-4-widescreen{flex:none;width:33.33333337%}html.theme--catppuccin-mocha .column.is-offset-4-widescreen{margin-left:33.33333337%}html.theme--catppuccin-mocha .column.is-5-widescreen{flex:none;width:41.66666674%}html.theme--catppuccin-mocha .column.is-offset-5-widescreen{margin-left:41.66666674%}html.theme--catppuccin-mocha .column.is-6-widescreen{flex:none;width:50%}html.theme--catppuccin-mocha .column.is-offset-6-widescreen{margin-left:50%}html.theme--catppuccin-mocha .column.is-7-widescreen{flex:none;width:58.33333337%}html.theme--catppuccin-mocha .column.is-offset-7-widescreen{margin-left:58.33333337%}html.theme--catppuccin-mocha .column.is-8-widescreen{flex:none;width:66.66666674%}html.theme--catppuccin-mocha .column.is-offset-8-widescreen{margin-left:66.66666674%}html.theme--catppuccin-mocha .column.is-9-widescreen{flex:none;width:75%}html.theme--catppuccin-mocha .column.is-offset-9-widescreen{margin-left:75%}html.theme--catppuccin-mocha .column.is-10-widescreen{flex:none;width:83.33333337%}html.theme--catppuccin-mocha .column.is-offset-10-widescreen{margin-left:83.33333337%}html.theme--catppuccin-mocha .column.is-11-widescreen{flex:none;width:91.66666674%}html.theme--catppuccin-mocha .column.is-offset-11-widescreen{margin-left:91.66666674%}html.theme--catppuccin-mocha .column.is-12-widescreen{flex:none;width:100%}html.theme--catppuccin-mocha .column.is-offset-12-widescreen{margin-left:100%}}@media screen and (min-width: 1408px){html.theme--catppuccin-mocha .column.is-narrow-fullhd{flex:none;width:unset}html.theme--catppuccin-mocha .column.is-full-fullhd{flex:none;width:100%}html.theme--catppuccin-mocha .column.is-three-quarters-fullhd{flex:none;width:75%}html.theme--catppuccin-mocha .column.is-two-thirds-fullhd{flex:none;width:66.6666%}html.theme--catppuccin-mocha .column.is-half-fullhd{flex:none;width:50%}html.theme--catppuccin-mocha .column.is-one-third-fullhd{flex:none;width:33.3333%}html.theme--catppuccin-mocha .column.is-one-quarter-fullhd{flex:none;width:25%}html.theme--catppuccin-mocha .column.is-one-fifth-fullhd{flex:none;width:20%}html.theme--catppuccin-mocha .column.is-two-fifths-fullhd{flex:none;width:40%}html.theme--catppuccin-mocha .column.is-three-fifths-fullhd{flex:none;width:60%}html.theme--catppuccin-mocha .column.is-four-fifths-fullhd{flex:none;width:80%}html.theme--catppuccin-mocha .column.is-offset-three-quarters-fullhd{margin-left:75%}html.theme--catppuccin-mocha .column.is-offset-two-thirds-fullhd{margin-left:66.6666%}html.theme--catppuccin-mocha .column.is-offset-half-fullhd{margin-left:50%}html.theme--catppuccin-mocha .column.is-offset-one-third-fullhd{margin-left:33.3333%}html.theme--catppuccin-mocha .column.is-offset-one-quarter-fullhd{margin-left:25%}html.theme--catppuccin-mocha .column.is-offset-one-fifth-fullhd{margin-left:20%}html.theme--catppuccin-mocha .column.is-offset-two-fifths-fullhd{margin-left:40%}html.theme--catppuccin-mocha .column.is-offset-three-fifths-fullhd{margin-left:60%}html.theme--catppuccin-mocha .column.is-offset-four-fifths-fullhd{margin-left:80%}html.theme--catppuccin-mocha .column.is-0-fullhd{flex:none;width:0%}html.theme--catppuccin-mocha .column.is-offset-0-fullhd{margin-left:0%}html.theme--catppuccin-mocha .column.is-1-fullhd{flex:none;width:8.33333337%}html.theme--catppuccin-mocha .column.is-offset-1-fullhd{margin-left:8.33333337%}html.theme--catppuccin-mocha .column.is-2-fullhd{flex:none;width:16.66666674%}html.theme--catppuccin-mocha .column.is-offset-2-fullhd{margin-left:16.66666674%}html.theme--catppuccin-mocha .column.is-3-fullhd{flex:none;width:25%}html.theme--catppuccin-mocha .column.is-offset-3-fullhd{margin-left:25%}html.theme--catppuccin-mocha .column.is-4-fullhd{flex:none;width:33.33333337%}html.theme--catppuccin-mocha .column.is-offset-4-fullhd{margin-left:33.33333337%}html.theme--catppuccin-mocha .column.is-5-fullhd{flex:none;width:41.66666674%}html.theme--catppuccin-mocha .column.is-offset-5-fullhd{margin-left:41.66666674%}html.theme--catppuccin-mocha .column.is-6-fullhd{flex:none;width:50%}html.theme--catppuccin-mocha .column.is-offset-6-fullhd{margin-left:50%}html.theme--catppuccin-mocha .column.is-7-fullhd{flex:none;width:58.33333337%}html.theme--catppuccin-mocha .column.is-offset-7-fullhd{margin-left:58.33333337%}html.theme--catppuccin-mocha .column.is-8-fullhd{flex:none;width:66.66666674%}html.theme--catppuccin-mocha .column.is-offset-8-fullhd{margin-left:66.66666674%}html.theme--catppuccin-mocha .column.is-9-fullhd{flex:none;width:75%}html.theme--catppuccin-mocha .column.is-offset-9-fullhd{margin-left:75%}html.theme--catppuccin-mocha .column.is-10-fullhd{flex:none;width:83.33333337%}html.theme--catppuccin-mocha .column.is-offset-10-fullhd{margin-left:83.33333337%}html.theme--catppuccin-mocha .column.is-11-fullhd{flex:none;width:91.66666674%}html.theme--catppuccin-mocha .column.is-offset-11-fullhd{margin-left:91.66666674%}html.theme--catppuccin-mocha .column.is-12-fullhd{flex:none;width:100%}html.theme--catppuccin-mocha .column.is-offset-12-fullhd{margin-left:100%}}html.theme--catppuccin-mocha .columns{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--catppuccin-mocha .columns:last-child{margin-bottom:-.75rem}html.theme--catppuccin-mocha .columns:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}html.theme--catppuccin-mocha .columns.is-centered{justify-content:center}html.theme--catppuccin-mocha .columns.is-gapless{margin-left:0;margin-right:0;margin-top:0}html.theme--catppuccin-mocha .columns.is-gapless>.column{margin:0;padding:0 !important}html.theme--catppuccin-mocha .columns.is-gapless:not(:last-child){margin-bottom:1.5rem}html.theme--catppuccin-mocha .columns.is-gapless:last-child{margin-bottom:0}html.theme--catppuccin-mocha .columns.is-mobile{display:flex}html.theme--catppuccin-mocha .columns.is-multiline{flex-wrap:wrap}html.theme--catppuccin-mocha .columns.is-vcentered{align-items:center}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .columns:not(.is-desktop){display:flex}}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .columns.is-desktop{display:flex}}html.theme--catppuccin-mocha .columns.is-variable{--columnGap: 0.75rem;margin-left:calc(-1 * var(--columnGap));margin-right:calc(-1 * var(--columnGap))}html.theme--catppuccin-mocha .columns.is-variable>.column{padding-left:var(--columnGap);padding-right:var(--columnGap)}html.theme--catppuccin-mocha .columns.is-variable.is-0{--columnGap: 0rem}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .columns.is-variable.is-0-mobile{--columnGap: 0rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .columns.is-variable.is-0-tablet{--columnGap: 0rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-mocha .columns.is-variable.is-0-tablet-only{--columnGap: 0rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .columns.is-variable.is-0-touch{--columnGap: 0rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .columns.is-variable.is-0-desktop{--columnGap: 0rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-mocha .columns.is-variable.is-0-desktop-only{--columnGap: 0rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-mocha .columns.is-variable.is-0-widescreen{--columnGap: 0rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-mocha .columns.is-variable.is-0-widescreen-only{--columnGap: 0rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-mocha .columns.is-variable.is-0-fullhd{--columnGap: 0rem}}html.theme--catppuccin-mocha .columns.is-variable.is-1{--columnGap: .25rem}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .columns.is-variable.is-1-mobile{--columnGap: .25rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .columns.is-variable.is-1-tablet{--columnGap: .25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-mocha .columns.is-variable.is-1-tablet-only{--columnGap: .25rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .columns.is-variable.is-1-touch{--columnGap: .25rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .columns.is-variable.is-1-desktop{--columnGap: .25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-mocha .columns.is-variable.is-1-desktop-only{--columnGap: .25rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-mocha .columns.is-variable.is-1-widescreen{--columnGap: .25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-mocha .columns.is-variable.is-1-widescreen-only{--columnGap: .25rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-mocha .columns.is-variable.is-1-fullhd{--columnGap: .25rem}}html.theme--catppuccin-mocha .columns.is-variable.is-2{--columnGap: .5rem}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .columns.is-variable.is-2-mobile{--columnGap: .5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .columns.is-variable.is-2-tablet{--columnGap: .5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-mocha .columns.is-variable.is-2-tablet-only{--columnGap: .5rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .columns.is-variable.is-2-touch{--columnGap: .5rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .columns.is-variable.is-2-desktop{--columnGap: .5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-mocha .columns.is-variable.is-2-desktop-only{--columnGap: .5rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-mocha .columns.is-variable.is-2-widescreen{--columnGap: .5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-mocha .columns.is-variable.is-2-widescreen-only{--columnGap: .5rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-mocha .columns.is-variable.is-2-fullhd{--columnGap: .5rem}}html.theme--catppuccin-mocha .columns.is-variable.is-3{--columnGap: .75rem}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .columns.is-variable.is-3-mobile{--columnGap: .75rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .columns.is-variable.is-3-tablet{--columnGap: .75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-mocha .columns.is-variable.is-3-tablet-only{--columnGap: .75rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .columns.is-variable.is-3-touch{--columnGap: .75rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .columns.is-variable.is-3-desktop{--columnGap: .75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-mocha .columns.is-variable.is-3-desktop-only{--columnGap: .75rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-mocha .columns.is-variable.is-3-widescreen{--columnGap: .75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-mocha .columns.is-variable.is-3-widescreen-only{--columnGap: .75rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-mocha .columns.is-variable.is-3-fullhd{--columnGap: .75rem}}html.theme--catppuccin-mocha .columns.is-variable.is-4{--columnGap: 1rem}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .columns.is-variable.is-4-mobile{--columnGap: 1rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .columns.is-variable.is-4-tablet{--columnGap: 1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-mocha .columns.is-variable.is-4-tablet-only{--columnGap: 1rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .columns.is-variable.is-4-touch{--columnGap: 1rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .columns.is-variable.is-4-desktop{--columnGap: 1rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-mocha .columns.is-variable.is-4-desktop-only{--columnGap: 1rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-mocha .columns.is-variable.is-4-widescreen{--columnGap: 1rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-mocha .columns.is-variable.is-4-widescreen-only{--columnGap: 1rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-mocha .columns.is-variable.is-4-fullhd{--columnGap: 1rem}}html.theme--catppuccin-mocha .columns.is-variable.is-5{--columnGap: 1.25rem}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .columns.is-variable.is-5-mobile{--columnGap: 1.25rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .columns.is-variable.is-5-tablet{--columnGap: 1.25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-mocha .columns.is-variable.is-5-tablet-only{--columnGap: 1.25rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .columns.is-variable.is-5-touch{--columnGap: 1.25rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .columns.is-variable.is-5-desktop{--columnGap: 1.25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-mocha .columns.is-variable.is-5-desktop-only{--columnGap: 1.25rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-mocha .columns.is-variable.is-5-widescreen{--columnGap: 1.25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-mocha .columns.is-variable.is-5-widescreen-only{--columnGap: 1.25rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-mocha .columns.is-variable.is-5-fullhd{--columnGap: 1.25rem}}html.theme--catppuccin-mocha .columns.is-variable.is-6{--columnGap: 1.5rem}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .columns.is-variable.is-6-mobile{--columnGap: 1.5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .columns.is-variable.is-6-tablet{--columnGap: 1.5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-mocha .columns.is-variable.is-6-tablet-only{--columnGap: 1.5rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .columns.is-variable.is-6-touch{--columnGap: 1.5rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .columns.is-variable.is-6-desktop{--columnGap: 1.5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-mocha .columns.is-variable.is-6-desktop-only{--columnGap: 1.5rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-mocha .columns.is-variable.is-6-widescreen{--columnGap: 1.5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-mocha .columns.is-variable.is-6-widescreen-only{--columnGap: 1.5rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-mocha .columns.is-variable.is-6-fullhd{--columnGap: 1.5rem}}html.theme--catppuccin-mocha .columns.is-variable.is-7{--columnGap: 1.75rem}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .columns.is-variable.is-7-mobile{--columnGap: 1.75rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .columns.is-variable.is-7-tablet{--columnGap: 1.75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-mocha .columns.is-variable.is-7-tablet-only{--columnGap: 1.75rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .columns.is-variable.is-7-touch{--columnGap: 1.75rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .columns.is-variable.is-7-desktop{--columnGap: 1.75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-mocha .columns.is-variable.is-7-desktop-only{--columnGap: 1.75rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-mocha .columns.is-variable.is-7-widescreen{--columnGap: 1.75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-mocha .columns.is-variable.is-7-widescreen-only{--columnGap: 1.75rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-mocha .columns.is-variable.is-7-fullhd{--columnGap: 1.75rem}}html.theme--catppuccin-mocha .columns.is-variable.is-8{--columnGap: 2rem}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .columns.is-variable.is-8-mobile{--columnGap: 2rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .columns.is-variable.is-8-tablet{--columnGap: 2rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--catppuccin-mocha .columns.is-variable.is-8-tablet-only{--columnGap: 2rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .columns.is-variable.is-8-touch{--columnGap: 2rem}}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .columns.is-variable.is-8-desktop{--columnGap: 2rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--catppuccin-mocha .columns.is-variable.is-8-desktop-only{--columnGap: 2rem}}@media screen and (min-width: 1216px){html.theme--catppuccin-mocha .columns.is-variable.is-8-widescreen{--columnGap: 2rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--catppuccin-mocha .columns.is-variable.is-8-widescreen-only{--columnGap: 2rem}}@media screen and (min-width: 1408px){html.theme--catppuccin-mocha .columns.is-variable.is-8-fullhd{--columnGap: 2rem}}html.theme--catppuccin-mocha .tile{align-items:stretch;display:block;flex-basis:0;flex-grow:1;flex-shrink:1;min-height:min-content}html.theme--catppuccin-mocha .tile.is-ancestor{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--catppuccin-mocha .tile.is-ancestor:last-child{margin-bottom:-.75rem}html.theme--catppuccin-mocha .tile.is-ancestor:not(:last-child){margin-bottom:.75rem}html.theme--catppuccin-mocha .tile.is-child{margin:0 !important}html.theme--catppuccin-mocha .tile.is-parent{padding:.75rem}html.theme--catppuccin-mocha .tile.is-vertical{flex-direction:column}html.theme--catppuccin-mocha .tile.is-vertical>.tile.is-child:not(:last-child){margin-bottom:1.5rem !important}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .tile:not(.is-child){display:flex}html.theme--catppuccin-mocha .tile.is-1{flex:none;width:8.33333337%}html.theme--catppuccin-mocha .tile.is-2{flex:none;width:16.66666674%}html.theme--catppuccin-mocha .tile.is-3{flex:none;width:25%}html.theme--catppuccin-mocha .tile.is-4{flex:none;width:33.33333337%}html.theme--catppuccin-mocha .tile.is-5{flex:none;width:41.66666674%}html.theme--catppuccin-mocha .tile.is-6{flex:none;width:50%}html.theme--catppuccin-mocha .tile.is-7{flex:none;width:58.33333337%}html.theme--catppuccin-mocha .tile.is-8{flex:none;width:66.66666674%}html.theme--catppuccin-mocha .tile.is-9{flex:none;width:75%}html.theme--catppuccin-mocha .tile.is-10{flex:none;width:83.33333337%}html.theme--catppuccin-mocha .tile.is-11{flex:none;width:91.66666674%}html.theme--catppuccin-mocha .tile.is-12{flex:none;width:100%}}html.theme--catppuccin-mocha .hero{align-items:stretch;display:flex;flex-direction:column;justify-content:space-between}html.theme--catppuccin-mocha .hero .navbar{background:none}html.theme--catppuccin-mocha .hero .tabs ul{border-bottom:none}html.theme--catppuccin-mocha .hero.is-white{background-color:#fff;color:#0a0a0a}html.theme--catppuccin-mocha .hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-mocha .hero.is-white strong{color:inherit}html.theme--catppuccin-mocha .hero.is-white .title{color:#0a0a0a}html.theme--catppuccin-mocha .hero.is-white .subtitle{color:rgba(10,10,10,0.9)}html.theme--catppuccin-mocha .hero.is-white .subtitle a:not(.button),html.theme--catppuccin-mocha .hero.is-white .subtitle strong{color:#0a0a0a}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .hero.is-white .navbar-menu{background-color:#fff}}html.theme--catppuccin-mocha .hero.is-white .navbar-item,html.theme--catppuccin-mocha .hero.is-white .navbar-link{color:rgba(10,10,10,0.7)}html.theme--catppuccin-mocha .hero.is-white a.navbar-item:hover,html.theme--catppuccin-mocha .hero.is-white a.navbar-item.is-active,html.theme--catppuccin-mocha .hero.is-white .navbar-link:hover,html.theme--catppuccin-mocha .hero.is-white .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--catppuccin-mocha .hero.is-white .tabs a{color:#0a0a0a;opacity:0.9}html.theme--catppuccin-mocha .hero.is-white .tabs a:hover{opacity:1}html.theme--catppuccin-mocha .hero.is-white .tabs li.is-active a{color:#fff !important;opacity:1}html.theme--catppuccin-mocha .hero.is-white .tabs.is-boxed a,html.theme--catppuccin-mocha .hero.is-white .tabs.is-toggle a{color:#0a0a0a}html.theme--catppuccin-mocha .hero.is-white .tabs.is-boxed a:hover,html.theme--catppuccin-mocha .hero.is-white .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-mocha .hero.is-white .tabs.is-boxed li.is-active a,html.theme--catppuccin-mocha .hero.is-white .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-mocha .hero.is-white .tabs.is-toggle li.is-active a,html.theme--catppuccin-mocha .hero.is-white .tabs.is-toggle li.is-active a:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--catppuccin-mocha .hero.is-white.is-bold{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .hero.is-white.is-bold .navbar-menu{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}}html.theme--catppuccin-mocha .hero.is-black{background-color:#0a0a0a;color:#fff}html.theme--catppuccin-mocha .hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-mocha .hero.is-black strong{color:inherit}html.theme--catppuccin-mocha .hero.is-black .title{color:#fff}html.theme--catppuccin-mocha .hero.is-black .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-mocha .hero.is-black .subtitle a:not(.button),html.theme--catppuccin-mocha .hero.is-black .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .hero.is-black .navbar-menu{background-color:#0a0a0a}}html.theme--catppuccin-mocha .hero.is-black .navbar-item,html.theme--catppuccin-mocha .hero.is-black .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-mocha .hero.is-black a.navbar-item:hover,html.theme--catppuccin-mocha .hero.is-black a.navbar-item.is-active,html.theme--catppuccin-mocha .hero.is-black .navbar-link:hover,html.theme--catppuccin-mocha .hero.is-black .navbar-link.is-active{background-color:#000;color:#fff}html.theme--catppuccin-mocha .hero.is-black .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-mocha .hero.is-black .tabs a:hover{opacity:1}html.theme--catppuccin-mocha .hero.is-black .tabs li.is-active a{color:#0a0a0a !important;opacity:1}html.theme--catppuccin-mocha .hero.is-black .tabs.is-boxed a,html.theme--catppuccin-mocha .hero.is-black .tabs.is-toggle a{color:#fff}html.theme--catppuccin-mocha .hero.is-black .tabs.is-boxed a:hover,html.theme--catppuccin-mocha .hero.is-black .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-mocha .hero.is-black .tabs.is-boxed li.is-active a,html.theme--catppuccin-mocha .hero.is-black .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-mocha .hero.is-black .tabs.is-toggle li.is-active a,html.theme--catppuccin-mocha .hero.is-black .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--catppuccin-mocha .hero.is-black.is-bold{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .hero.is-black.is-bold .navbar-menu{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}}html.theme--catppuccin-mocha .hero.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-mocha .hero.is-light strong{color:inherit}html.theme--catppuccin-mocha .hero.is-light .title{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-light .subtitle{color:rgba(0,0,0,0.9)}html.theme--catppuccin-mocha .hero.is-light .subtitle a:not(.button),html.theme--catppuccin-mocha .hero.is-light .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .hero.is-light .navbar-menu{background-color:#f5f5f5}}html.theme--catppuccin-mocha .hero.is-light .navbar-item,html.theme--catppuccin-mocha .hero.is-light .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-light a.navbar-item:hover,html.theme--catppuccin-mocha .hero.is-light a.navbar-item.is-active,html.theme--catppuccin-mocha .hero.is-light .navbar-link:hover,html.theme--catppuccin-mocha .hero.is-light .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-light .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--catppuccin-mocha .hero.is-light .tabs a:hover{opacity:1}html.theme--catppuccin-mocha .hero.is-light .tabs li.is-active a{color:#f5f5f5 !important;opacity:1}html.theme--catppuccin-mocha .hero.is-light .tabs.is-boxed a,html.theme--catppuccin-mocha .hero.is-light .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-light .tabs.is-boxed a:hover,html.theme--catppuccin-mocha .hero.is-light .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-mocha .hero.is-light .tabs.is-boxed li.is-active a,html.theme--catppuccin-mocha .hero.is-light .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-mocha .hero.is-light .tabs.is-toggle li.is-active a,html.theme--catppuccin-mocha .hero.is-light .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#f5f5f5}html.theme--catppuccin-mocha .hero.is-light.is-bold{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .hero.is-light.is-bold .navbar-menu{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}}html.theme--catppuccin-mocha .hero.is-dark,html.theme--catppuccin-mocha .content kbd.hero{background-color:#313244;color:#fff}html.theme--catppuccin-mocha .hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-mocha .content kbd.hero a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-mocha .hero.is-dark strong,html.theme--catppuccin-mocha .content kbd.hero strong{color:inherit}html.theme--catppuccin-mocha .hero.is-dark .title,html.theme--catppuccin-mocha .content kbd.hero .title{color:#fff}html.theme--catppuccin-mocha .hero.is-dark .subtitle,html.theme--catppuccin-mocha .content kbd.hero .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-mocha .hero.is-dark .subtitle a:not(.button),html.theme--catppuccin-mocha .content kbd.hero .subtitle a:not(.button),html.theme--catppuccin-mocha .hero.is-dark .subtitle strong,html.theme--catppuccin-mocha .content kbd.hero .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .hero.is-dark .navbar-menu,html.theme--catppuccin-mocha .content kbd.hero .navbar-menu{background-color:#313244}}html.theme--catppuccin-mocha .hero.is-dark .navbar-item,html.theme--catppuccin-mocha .content kbd.hero .navbar-item,html.theme--catppuccin-mocha .hero.is-dark .navbar-link,html.theme--catppuccin-mocha .content kbd.hero .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-mocha .hero.is-dark a.navbar-item:hover,html.theme--catppuccin-mocha .content kbd.hero a.navbar-item:hover,html.theme--catppuccin-mocha .hero.is-dark a.navbar-item.is-active,html.theme--catppuccin-mocha .content kbd.hero a.navbar-item.is-active,html.theme--catppuccin-mocha .hero.is-dark .navbar-link:hover,html.theme--catppuccin-mocha .content kbd.hero .navbar-link:hover,html.theme--catppuccin-mocha .hero.is-dark .navbar-link.is-active,html.theme--catppuccin-mocha .content kbd.hero .navbar-link.is-active{background-color:#262735;color:#fff}html.theme--catppuccin-mocha .hero.is-dark .tabs a,html.theme--catppuccin-mocha .content kbd.hero .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-mocha .hero.is-dark .tabs a:hover,html.theme--catppuccin-mocha .content kbd.hero .tabs a:hover{opacity:1}html.theme--catppuccin-mocha .hero.is-dark .tabs li.is-active a,html.theme--catppuccin-mocha .content kbd.hero .tabs li.is-active a{color:#313244 !important;opacity:1}html.theme--catppuccin-mocha .hero.is-dark .tabs.is-boxed a,html.theme--catppuccin-mocha .content kbd.hero .tabs.is-boxed a,html.theme--catppuccin-mocha .hero.is-dark .tabs.is-toggle a,html.theme--catppuccin-mocha .content kbd.hero .tabs.is-toggle a{color:#fff}html.theme--catppuccin-mocha .hero.is-dark .tabs.is-boxed a:hover,html.theme--catppuccin-mocha .content kbd.hero .tabs.is-boxed a:hover,html.theme--catppuccin-mocha .hero.is-dark .tabs.is-toggle a:hover,html.theme--catppuccin-mocha .content kbd.hero .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-mocha .hero.is-dark .tabs.is-boxed li.is-active a,html.theme--catppuccin-mocha .content kbd.hero .tabs.is-boxed li.is-active a,html.theme--catppuccin-mocha .hero.is-dark .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-mocha .hero.is-dark .tabs.is-toggle li.is-active a,html.theme--catppuccin-mocha .content kbd.hero .tabs.is-toggle li.is-active a,html.theme--catppuccin-mocha .hero.is-dark .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#313244}html.theme--catppuccin-mocha .hero.is-dark.is-bold,html.theme--catppuccin-mocha .content kbd.hero.is-bold{background-image:linear-gradient(141deg, #181c2a 0%, #313244 71%, #3c3856 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .hero.is-dark.is-bold .navbar-menu,html.theme--catppuccin-mocha .content kbd.hero.is-bold .navbar-menu{background-image:linear-gradient(141deg, #181c2a 0%, #313244 71%, #3c3856 100%)}}html.theme--catppuccin-mocha .hero.is-primary,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink{background-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-mocha .hero.is-primary strong,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink strong{color:inherit}html.theme--catppuccin-mocha .hero.is-primary .title,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink .title{color:#fff}html.theme--catppuccin-mocha .hero.is-primary .subtitle,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-mocha .hero.is-primary .subtitle a:not(.button),html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink .subtitle a:not(.button),html.theme--catppuccin-mocha .hero.is-primary .subtitle strong,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .hero.is-primary .navbar-menu,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink .navbar-menu{background-color:#89b4fa}}html.theme--catppuccin-mocha .hero.is-primary .navbar-item,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink .navbar-item,html.theme--catppuccin-mocha .hero.is-primary .navbar-link,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-mocha .hero.is-primary a.navbar-item:hover,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink a.navbar-item:hover,html.theme--catppuccin-mocha .hero.is-primary a.navbar-item.is-active,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink a.navbar-item.is-active,html.theme--catppuccin-mocha .hero.is-primary .navbar-link:hover,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink .navbar-link:hover,html.theme--catppuccin-mocha .hero.is-primary .navbar-link.is-active,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink .navbar-link.is-active{background-color:#71a4f9;color:#fff}html.theme--catppuccin-mocha .hero.is-primary .tabs a,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-mocha .hero.is-primary .tabs a:hover,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink .tabs a:hover{opacity:1}html.theme--catppuccin-mocha .hero.is-primary .tabs li.is-active a,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink .tabs li.is-active a{color:#89b4fa !important;opacity:1}html.theme--catppuccin-mocha .hero.is-primary .tabs.is-boxed a,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a,html.theme--catppuccin-mocha .hero.is-primary .tabs.is-toggle a,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a{color:#fff}html.theme--catppuccin-mocha .hero.is-primary .tabs.is-boxed a:hover,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a:hover,html.theme--catppuccin-mocha .hero.is-primary .tabs.is-toggle a:hover,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-mocha .hero.is-primary .tabs.is-boxed li.is-active a,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed li.is-active a,html.theme--catppuccin-mocha .hero.is-primary .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-mocha .hero.is-primary .tabs.is-toggle li.is-active a,html.theme--catppuccin-mocha .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle li.is-active a,html.theme--catppuccin-mocha .hero.is-primary .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#89b4fa}html.theme--catppuccin-mocha .hero.is-primary.is-bold,html.theme--catppuccin-mocha .docstring>section>a.hero.is-bold.docs-sourcelink{background-image:linear-gradient(141deg, #51b0ff 0%, #89b4fa 71%, #9fb3fd 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .hero.is-primary.is-bold .navbar-menu,html.theme--catppuccin-mocha .docstring>section>a.hero.is-bold.docs-sourcelink .navbar-menu{background-image:linear-gradient(141deg, #51b0ff 0%, #89b4fa 71%, #9fb3fd 100%)}}html.theme--catppuccin-mocha .hero.is-link{background-color:#89b4fa;color:#fff}html.theme--catppuccin-mocha .hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-mocha .hero.is-link strong{color:inherit}html.theme--catppuccin-mocha .hero.is-link .title{color:#fff}html.theme--catppuccin-mocha .hero.is-link .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-mocha .hero.is-link .subtitle a:not(.button),html.theme--catppuccin-mocha .hero.is-link .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .hero.is-link .navbar-menu{background-color:#89b4fa}}html.theme--catppuccin-mocha .hero.is-link .navbar-item,html.theme--catppuccin-mocha .hero.is-link .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-mocha .hero.is-link a.navbar-item:hover,html.theme--catppuccin-mocha .hero.is-link a.navbar-item.is-active,html.theme--catppuccin-mocha .hero.is-link .navbar-link:hover,html.theme--catppuccin-mocha .hero.is-link .navbar-link.is-active{background-color:#71a4f9;color:#fff}html.theme--catppuccin-mocha .hero.is-link .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-mocha .hero.is-link .tabs a:hover{opacity:1}html.theme--catppuccin-mocha .hero.is-link .tabs li.is-active a{color:#89b4fa !important;opacity:1}html.theme--catppuccin-mocha .hero.is-link .tabs.is-boxed a,html.theme--catppuccin-mocha .hero.is-link .tabs.is-toggle a{color:#fff}html.theme--catppuccin-mocha .hero.is-link .tabs.is-boxed a:hover,html.theme--catppuccin-mocha .hero.is-link .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-mocha .hero.is-link .tabs.is-boxed li.is-active a,html.theme--catppuccin-mocha .hero.is-link .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-mocha .hero.is-link .tabs.is-toggle li.is-active a,html.theme--catppuccin-mocha .hero.is-link .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#89b4fa}html.theme--catppuccin-mocha .hero.is-link.is-bold{background-image:linear-gradient(141deg, #51b0ff 0%, #89b4fa 71%, #9fb3fd 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .hero.is-link.is-bold .navbar-menu{background-image:linear-gradient(141deg, #51b0ff 0%, #89b4fa 71%, #9fb3fd 100%)}}html.theme--catppuccin-mocha .hero.is-info{background-color:#94e2d5;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-mocha .hero.is-info strong{color:inherit}html.theme--catppuccin-mocha .hero.is-info .title{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-info .subtitle{color:rgba(0,0,0,0.9)}html.theme--catppuccin-mocha .hero.is-info .subtitle a:not(.button),html.theme--catppuccin-mocha .hero.is-info .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .hero.is-info .navbar-menu{background-color:#94e2d5}}html.theme--catppuccin-mocha .hero.is-info .navbar-item,html.theme--catppuccin-mocha .hero.is-info .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-info a.navbar-item:hover,html.theme--catppuccin-mocha .hero.is-info a.navbar-item.is-active,html.theme--catppuccin-mocha .hero.is-info .navbar-link:hover,html.theme--catppuccin-mocha .hero.is-info .navbar-link.is-active{background-color:#80ddcd;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-info .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--catppuccin-mocha .hero.is-info .tabs a:hover{opacity:1}html.theme--catppuccin-mocha .hero.is-info .tabs li.is-active a{color:#94e2d5 !important;opacity:1}html.theme--catppuccin-mocha .hero.is-info .tabs.is-boxed a,html.theme--catppuccin-mocha .hero.is-info .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-info .tabs.is-boxed a:hover,html.theme--catppuccin-mocha .hero.is-info .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-mocha .hero.is-info .tabs.is-boxed li.is-active a,html.theme--catppuccin-mocha .hero.is-info .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-mocha .hero.is-info .tabs.is-toggle li.is-active a,html.theme--catppuccin-mocha .hero.is-info .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#94e2d5}html.theme--catppuccin-mocha .hero.is-info.is-bold{background-image:linear-gradient(141deg, #63e0b6 0%, #94e2d5 71%, #a5eaea 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .hero.is-info.is-bold .navbar-menu{background-image:linear-gradient(141deg, #63e0b6 0%, #94e2d5 71%, #a5eaea 100%)}}html.theme--catppuccin-mocha .hero.is-success{background-color:#a6e3a1;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-mocha .hero.is-success strong{color:inherit}html.theme--catppuccin-mocha .hero.is-success .title{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-success .subtitle{color:rgba(0,0,0,0.9)}html.theme--catppuccin-mocha .hero.is-success .subtitle a:not(.button),html.theme--catppuccin-mocha .hero.is-success .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .hero.is-success .navbar-menu{background-color:#a6e3a1}}html.theme--catppuccin-mocha .hero.is-success .navbar-item,html.theme--catppuccin-mocha .hero.is-success .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-success a.navbar-item:hover,html.theme--catppuccin-mocha .hero.is-success a.navbar-item.is-active,html.theme--catppuccin-mocha .hero.is-success .navbar-link:hover,html.theme--catppuccin-mocha .hero.is-success .navbar-link.is-active{background-color:#93dd8d;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-success .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--catppuccin-mocha .hero.is-success .tabs a:hover{opacity:1}html.theme--catppuccin-mocha .hero.is-success .tabs li.is-active a{color:#a6e3a1 !important;opacity:1}html.theme--catppuccin-mocha .hero.is-success .tabs.is-boxed a,html.theme--catppuccin-mocha .hero.is-success .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-success .tabs.is-boxed a:hover,html.theme--catppuccin-mocha .hero.is-success .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-mocha .hero.is-success .tabs.is-boxed li.is-active a,html.theme--catppuccin-mocha .hero.is-success .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-mocha .hero.is-success .tabs.is-toggle li.is-active a,html.theme--catppuccin-mocha .hero.is-success .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#a6e3a1}html.theme--catppuccin-mocha .hero.is-success.is-bold{background-image:linear-gradient(141deg, #8ce071 0%, #a6e3a1 71%, #b2ebb7 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .hero.is-success.is-bold .navbar-menu{background-image:linear-gradient(141deg, #8ce071 0%, #a6e3a1 71%, #b2ebb7 100%)}}html.theme--catppuccin-mocha .hero.is-warning{background-color:#f9e2af;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-mocha .hero.is-warning strong{color:inherit}html.theme--catppuccin-mocha .hero.is-warning .title{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-warning .subtitle{color:rgba(0,0,0,0.9)}html.theme--catppuccin-mocha .hero.is-warning .subtitle a:not(.button),html.theme--catppuccin-mocha .hero.is-warning .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .hero.is-warning .navbar-menu{background-color:#f9e2af}}html.theme--catppuccin-mocha .hero.is-warning .navbar-item,html.theme--catppuccin-mocha .hero.is-warning .navbar-link{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-warning a.navbar-item:hover,html.theme--catppuccin-mocha .hero.is-warning a.navbar-item.is-active,html.theme--catppuccin-mocha .hero.is-warning .navbar-link:hover,html.theme--catppuccin-mocha .hero.is-warning .navbar-link.is-active{background-color:#f7d997;color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-warning .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--catppuccin-mocha .hero.is-warning .tabs a:hover{opacity:1}html.theme--catppuccin-mocha .hero.is-warning .tabs li.is-active a{color:#f9e2af !important;opacity:1}html.theme--catppuccin-mocha .hero.is-warning .tabs.is-boxed a,html.theme--catppuccin-mocha .hero.is-warning .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--catppuccin-mocha .hero.is-warning .tabs.is-boxed a:hover,html.theme--catppuccin-mocha .hero.is-warning .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-mocha .hero.is-warning .tabs.is-boxed li.is-active a,html.theme--catppuccin-mocha .hero.is-warning .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-mocha .hero.is-warning .tabs.is-toggle li.is-active a,html.theme--catppuccin-mocha .hero.is-warning .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#f9e2af}html.theme--catppuccin-mocha .hero.is-warning.is-bold{background-image:linear-gradient(141deg, #fcbd79 0%, #f9e2af 71%, #fcf4c5 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .hero.is-warning.is-bold .navbar-menu{background-image:linear-gradient(141deg, #fcbd79 0%, #f9e2af 71%, #fcf4c5 100%)}}html.theme--catppuccin-mocha .hero.is-danger{background-color:#f38ba8;color:#fff}html.theme--catppuccin-mocha .hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--catppuccin-mocha .hero.is-danger strong{color:inherit}html.theme--catppuccin-mocha .hero.is-danger .title{color:#fff}html.theme--catppuccin-mocha .hero.is-danger .subtitle{color:rgba(255,255,255,0.9)}html.theme--catppuccin-mocha .hero.is-danger .subtitle a:not(.button),html.theme--catppuccin-mocha .hero.is-danger .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .hero.is-danger .navbar-menu{background-color:#f38ba8}}html.theme--catppuccin-mocha .hero.is-danger .navbar-item,html.theme--catppuccin-mocha .hero.is-danger .navbar-link{color:rgba(255,255,255,0.7)}html.theme--catppuccin-mocha .hero.is-danger a.navbar-item:hover,html.theme--catppuccin-mocha .hero.is-danger a.navbar-item.is-active,html.theme--catppuccin-mocha .hero.is-danger .navbar-link:hover,html.theme--catppuccin-mocha .hero.is-danger .navbar-link.is-active{background-color:#f17497;color:#fff}html.theme--catppuccin-mocha .hero.is-danger .tabs a{color:#fff;opacity:0.9}html.theme--catppuccin-mocha .hero.is-danger .tabs a:hover{opacity:1}html.theme--catppuccin-mocha .hero.is-danger .tabs li.is-active a{color:#f38ba8 !important;opacity:1}html.theme--catppuccin-mocha .hero.is-danger .tabs.is-boxed a,html.theme--catppuccin-mocha .hero.is-danger .tabs.is-toggle a{color:#fff}html.theme--catppuccin-mocha .hero.is-danger .tabs.is-boxed a:hover,html.theme--catppuccin-mocha .hero.is-danger .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--catppuccin-mocha .hero.is-danger .tabs.is-boxed li.is-active a,html.theme--catppuccin-mocha .hero.is-danger .tabs.is-boxed li.is-active a:hover,html.theme--catppuccin-mocha .hero.is-danger .tabs.is-toggle li.is-active a,html.theme--catppuccin-mocha .hero.is-danger .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#f38ba8}html.theme--catppuccin-mocha .hero.is-danger.is-bold{background-image:linear-gradient(141deg, #f7549d 0%, #f38ba8 71%, #f8a0a9 100%)}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .hero.is-danger.is-bold .navbar-menu{background-image:linear-gradient(141deg, #f7549d 0%, #f38ba8 71%, #f8a0a9 100%)}}html.theme--catppuccin-mocha .hero.is-small .hero-body,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.hero .hero-body{padding:1.5rem}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .hero.is-medium .hero-body{padding:9rem 4.5rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .hero.is-large .hero-body{padding:18rem 6rem}}html.theme--catppuccin-mocha .hero.is-halfheight .hero-body,html.theme--catppuccin-mocha .hero.is-fullheight .hero-body,html.theme--catppuccin-mocha .hero.is-fullheight-with-navbar .hero-body{align-items:center;display:flex}html.theme--catppuccin-mocha .hero.is-halfheight .hero-body>.container,html.theme--catppuccin-mocha .hero.is-fullheight .hero-body>.container,html.theme--catppuccin-mocha .hero.is-fullheight-with-navbar .hero-body>.container{flex-grow:1;flex-shrink:1}html.theme--catppuccin-mocha .hero.is-halfheight{min-height:50vh}html.theme--catppuccin-mocha .hero.is-fullheight{min-height:100vh}html.theme--catppuccin-mocha .hero-video{overflow:hidden}html.theme--catppuccin-mocha .hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;transform:translate3d(-50%, -50%, 0)}html.theme--catppuccin-mocha .hero-video.is-transparent{opacity:0.3}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .hero-video{display:none}}html.theme--catppuccin-mocha .hero-buttons{margin-top:1.5rem}@media screen and (max-width: 768px){html.theme--catppuccin-mocha .hero-buttons .button{display:flex}html.theme--catppuccin-mocha .hero-buttons .button:not(:last-child){margin-bottom:0.75rem}}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .hero-buttons{display:flex;justify-content:center}html.theme--catppuccin-mocha .hero-buttons .button:not(:last-child){margin-right:1.5rem}}html.theme--catppuccin-mocha .hero-head,html.theme--catppuccin-mocha .hero-foot{flex-grow:0;flex-shrink:0}html.theme--catppuccin-mocha .hero-body{flex-grow:1;flex-shrink:0;padding:3rem 1.5rem}@media screen and (min-width: 769px),print{html.theme--catppuccin-mocha .hero-body{padding:3rem 3rem}}html.theme--catppuccin-mocha .section{padding:3rem 1.5rem}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha .section{padding:3rem 3rem}html.theme--catppuccin-mocha .section.is-medium{padding:9rem 4.5rem}html.theme--catppuccin-mocha .section.is-large{padding:18rem 6rem}}html.theme--catppuccin-mocha .footer{background-color:#181825;padding:3rem 1.5rem 6rem}html.theme--catppuccin-mocha h1 .docs-heading-anchor,html.theme--catppuccin-mocha h1 .docs-heading-anchor:hover,html.theme--catppuccin-mocha h1 .docs-heading-anchor:visited,html.theme--catppuccin-mocha h2 .docs-heading-anchor,html.theme--catppuccin-mocha h2 .docs-heading-anchor:hover,html.theme--catppuccin-mocha h2 .docs-heading-anchor:visited,html.theme--catppuccin-mocha h3 .docs-heading-anchor,html.theme--catppuccin-mocha h3 .docs-heading-anchor:hover,html.theme--catppuccin-mocha h3 .docs-heading-anchor:visited,html.theme--catppuccin-mocha h4 .docs-heading-anchor,html.theme--catppuccin-mocha h4 .docs-heading-anchor:hover,html.theme--catppuccin-mocha h4 .docs-heading-anchor:visited,html.theme--catppuccin-mocha h5 .docs-heading-anchor,html.theme--catppuccin-mocha h5 .docs-heading-anchor:hover,html.theme--catppuccin-mocha h5 .docs-heading-anchor:visited,html.theme--catppuccin-mocha h6 .docs-heading-anchor,html.theme--catppuccin-mocha h6 .docs-heading-anchor:hover,html.theme--catppuccin-mocha h6 .docs-heading-anchor:visited{color:#cdd6f4}html.theme--catppuccin-mocha h1 .docs-heading-anchor-permalink,html.theme--catppuccin-mocha h2 .docs-heading-anchor-permalink,html.theme--catppuccin-mocha h3 .docs-heading-anchor-permalink,html.theme--catppuccin-mocha h4 .docs-heading-anchor-permalink,html.theme--catppuccin-mocha h5 .docs-heading-anchor-permalink,html.theme--catppuccin-mocha h6 .docs-heading-anchor-permalink{visibility:hidden;vertical-align:middle;margin-left:0.5em;font-size:0.7rem}html.theme--catppuccin-mocha h1 .docs-heading-anchor-permalink::before,html.theme--catppuccin-mocha h2 .docs-heading-anchor-permalink::before,html.theme--catppuccin-mocha h3 .docs-heading-anchor-permalink::before,html.theme--catppuccin-mocha h4 .docs-heading-anchor-permalink::before,html.theme--catppuccin-mocha h5 .docs-heading-anchor-permalink::before,html.theme--catppuccin-mocha h6 .docs-heading-anchor-permalink::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f0c1"}html.theme--catppuccin-mocha h1:hover .docs-heading-anchor-permalink,html.theme--catppuccin-mocha h2:hover .docs-heading-anchor-permalink,html.theme--catppuccin-mocha h3:hover .docs-heading-anchor-permalink,html.theme--catppuccin-mocha h4:hover .docs-heading-anchor-permalink,html.theme--catppuccin-mocha h5:hover .docs-heading-anchor-permalink,html.theme--catppuccin-mocha h6:hover .docs-heading-anchor-permalink{visibility:visible}html.theme--catppuccin-mocha .docs-light-only{display:none !important}html.theme--catppuccin-mocha pre{position:relative;overflow:hidden}html.theme--catppuccin-mocha pre code,html.theme--catppuccin-mocha pre code.hljs{padding:0 .75rem !important;overflow:auto;display:block}html.theme--catppuccin-mocha pre code:first-of-type,html.theme--catppuccin-mocha pre code.hljs:first-of-type{padding-top:0.5rem !important}html.theme--catppuccin-mocha pre code:last-of-type,html.theme--catppuccin-mocha pre code.hljs:last-of-type{padding-bottom:0.5rem !important}html.theme--catppuccin-mocha pre .copy-button{opacity:0.2;transition:opacity 0.2s;position:absolute;right:0em;top:0em;padding:0.5em;width:2.5em;height:2.5em;background:transparent;border:none;font-family:"Font Awesome 6 Free";color:#cdd6f4;cursor:pointer;text-align:center}html.theme--catppuccin-mocha pre .copy-button:focus,html.theme--catppuccin-mocha pre .copy-button:hover{opacity:1;background:rgba(205,214,244,0.1);color:#89b4fa}html.theme--catppuccin-mocha pre .copy-button.success{color:#a6e3a1;opacity:1}html.theme--catppuccin-mocha pre .copy-button.error{color:#f38ba8;opacity:1}html.theme--catppuccin-mocha pre:hover .copy-button{opacity:1}html.theme--catppuccin-mocha .admonition{background-color:#181825;border-style:solid;border-width:2px;border-color:#bac2de;border-radius:4px;font-size:1rem}html.theme--catppuccin-mocha .admonition strong{color:currentColor}html.theme--catppuccin-mocha .admonition.is-small,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input.admonition{font-size:.75rem}html.theme--catppuccin-mocha .admonition.is-medium{font-size:1.25rem}html.theme--catppuccin-mocha .admonition.is-large{font-size:1.5rem}html.theme--catppuccin-mocha .admonition.is-default{background-color:#181825;border-color:#bac2de}html.theme--catppuccin-mocha .admonition.is-default>.admonition-header{background-color:rgba(0,0,0,0);color:#bac2de}html.theme--catppuccin-mocha .admonition.is-default>.admonition-body{color:#cdd6f4}html.theme--catppuccin-mocha .admonition.is-info{background-color:#181825;border-color:#94e2d5}html.theme--catppuccin-mocha .admonition.is-info>.admonition-header{background-color:rgba(0,0,0,0);color:#94e2d5}html.theme--catppuccin-mocha .admonition.is-info>.admonition-body{color:#cdd6f4}html.theme--catppuccin-mocha .admonition.is-success{background-color:#181825;border-color:#a6e3a1}html.theme--catppuccin-mocha .admonition.is-success>.admonition-header{background-color:rgba(0,0,0,0);color:#a6e3a1}html.theme--catppuccin-mocha .admonition.is-success>.admonition-body{color:#cdd6f4}html.theme--catppuccin-mocha .admonition.is-warning{background-color:#181825;border-color:#f9e2af}html.theme--catppuccin-mocha .admonition.is-warning>.admonition-header{background-color:rgba(0,0,0,0);color:#f9e2af}html.theme--catppuccin-mocha .admonition.is-warning>.admonition-body{color:#cdd6f4}html.theme--catppuccin-mocha .admonition.is-danger{background-color:#181825;border-color:#f38ba8}html.theme--catppuccin-mocha .admonition.is-danger>.admonition-header{background-color:rgba(0,0,0,0);color:#f38ba8}html.theme--catppuccin-mocha .admonition.is-danger>.admonition-body{color:#cdd6f4}html.theme--catppuccin-mocha .admonition.is-compat{background-color:#181825;border-color:#89dceb}html.theme--catppuccin-mocha .admonition.is-compat>.admonition-header{background-color:rgba(0,0,0,0);color:#89dceb}html.theme--catppuccin-mocha .admonition.is-compat>.admonition-body{color:#cdd6f4}html.theme--catppuccin-mocha .admonition.is-todo{background-color:#181825;border-color:#cba6f7}html.theme--catppuccin-mocha .admonition.is-todo>.admonition-header{background-color:rgba(0,0,0,0);color:#cba6f7}html.theme--catppuccin-mocha .admonition.is-todo>.admonition-body{color:#cdd6f4}html.theme--catppuccin-mocha .admonition-header{color:#bac2de;background-color:rgba(0,0,0,0);align-items:center;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.5rem .75rem;position:relative}html.theme--catppuccin-mocha .admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;margin-right:.75rem;content:"\f06a"}html.theme--catppuccin-mocha details.admonition.is-details>.admonition-header{list-style:none}html.theme--catppuccin-mocha details.admonition.is-details>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f055"}html.theme--catppuccin-mocha details.admonition.is-details[open]>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f056"}html.theme--catppuccin-mocha .admonition-body{color:#cdd6f4;padding:0.5rem .75rem}html.theme--catppuccin-mocha .admonition-body pre{background-color:#181825}html.theme--catppuccin-mocha .admonition-body code{background-color:#181825}html.theme--catppuccin-mocha .docstring{margin-bottom:1em;background-color:rgba(0,0,0,0);border:2px solid #585b70;border-radius:4px;box-shadow:none;max-width:100%}html.theme--catppuccin-mocha .docstring>header{cursor:pointer;display:flex;flex-grow:1;align-items:stretch;padding:0.5rem .75rem;background-color:#181825;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);box-shadow:none;border-bottom:1px solid #585b70;overflow:auto}html.theme--catppuccin-mocha .docstring>header code{background-color:transparent}html.theme--catppuccin-mocha .docstring>header .docstring-article-toggle-button{min-width:1.1rem;padding:0.2rem 0.2rem 0.2rem 0}html.theme--catppuccin-mocha .docstring>header .docstring-binding{margin-right:0.3em}html.theme--catppuccin-mocha .docstring>header .docstring-category{margin-left:0.3em}html.theme--catppuccin-mocha .docstring>section{position:relative;padding:.75rem .75rem;border-bottom:1px solid #585b70}html.theme--catppuccin-mocha .docstring>section:last-child{border-bottom:none}html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink{transition:opacity 0.3s;opacity:0;position:absolute;right:.375rem;bottom:.375rem}html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink:focus{opacity:1 !important}html.theme--catppuccin-mocha .docstring:hover>section>a.docs-sourcelink{opacity:0.2}html.theme--catppuccin-mocha .docstring:focus-within>section>a.docs-sourcelink{opacity:0.2}html.theme--catppuccin-mocha .docstring>section:hover a.docs-sourcelink{opacity:1}html.theme--catppuccin-mocha .documenter-example-output{background-color:#1e1e2e}html.theme--catppuccin-mocha .outdated-warning-overlay{position:fixed;top:0;left:0;right:0;box-shadow:0 0 10px rgba(0,0,0,0.3);z-index:999;background-color:#181825;color:#cdd6f4;border-bottom:3px solid rgba(0,0,0,0);padding:10px 35px;text-align:center;font-size:15px}html.theme--catppuccin-mocha .outdated-warning-overlay .outdated-warning-closer{position:absolute;top:calc(50% - 10px);right:18px;cursor:pointer;width:12px}html.theme--catppuccin-mocha .outdated-warning-overlay a{color:#89b4fa}html.theme--catppuccin-mocha .outdated-warning-overlay a:hover{color:#89dceb}html.theme--catppuccin-mocha .content pre{border:2px solid #585b70;border-radius:4px}html.theme--catppuccin-mocha .content code{font-weight:inherit}html.theme--catppuccin-mocha .content a code{color:#89b4fa}html.theme--catppuccin-mocha .content a:hover code{color:#89dceb}html.theme--catppuccin-mocha .content h1 code,html.theme--catppuccin-mocha .content h2 code,html.theme--catppuccin-mocha .content h3 code,html.theme--catppuccin-mocha .content h4 code,html.theme--catppuccin-mocha .content h5 code,html.theme--catppuccin-mocha .content h6 code{color:#cdd6f4}html.theme--catppuccin-mocha .content table{display:block;width:initial;max-width:100%;overflow-x:auto}html.theme--catppuccin-mocha .content blockquote>ul:first-child,html.theme--catppuccin-mocha .content blockquote>ol:first-child,html.theme--catppuccin-mocha .content .admonition-body>ul:first-child,html.theme--catppuccin-mocha .content .admonition-body>ol:first-child{margin-top:0}html.theme--catppuccin-mocha pre,html.theme--catppuccin-mocha code{font-variant-ligatures:no-contextual}html.theme--catppuccin-mocha .breadcrumb a.is-disabled{cursor:default;pointer-events:none}html.theme--catppuccin-mocha .breadcrumb a.is-disabled,html.theme--catppuccin-mocha .breadcrumb a.is-disabled:hover{color:#b8c5ef}html.theme--catppuccin-mocha .hljs{background:initial !important}html.theme--catppuccin-mocha .katex .katex-mathml{top:0;right:0}html.theme--catppuccin-mocha .katex-display,html.theme--catppuccin-mocha mjx-container,html.theme--catppuccin-mocha .MathJax_Display{margin:0.5em 0 !important}html.theme--catppuccin-mocha html{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto}html.theme--catppuccin-mocha li.no-marker{list-style:none}html.theme--catppuccin-mocha #documenter .docs-main>article{overflow-wrap:break-word}html.theme--catppuccin-mocha #documenter .docs-main>article .math-container{overflow-x:auto;overflow-y:hidden}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha #documenter .docs-main{max-width:52rem;margin-left:20rem;padding-right:1rem}}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha #documenter .docs-main{width:100%}html.theme--catppuccin-mocha #documenter .docs-main>article{max-width:52rem;margin-left:auto;margin-right:auto;margin-bottom:1rem;padding:0 1rem}html.theme--catppuccin-mocha #documenter .docs-main>header,html.theme--catppuccin-mocha #documenter .docs-main>nav{max-width:100%;width:100%;margin:0}}html.theme--catppuccin-mocha #documenter .docs-main header.docs-navbar{background-color:#1e1e2e;border-bottom:1px solid #585b70;z-index:2;min-height:4rem;margin-bottom:1rem;display:flex}html.theme--catppuccin-mocha #documenter .docs-main header.docs-navbar .breadcrumb{flex-grow:1;overflow-x:hidden}html.theme--catppuccin-mocha #documenter .docs-main header.docs-navbar .docs-sidebar-button{display:block;font-size:1.5rem;padding-bottom:0.1rem;margin-right:1rem}html.theme--catppuccin-mocha #documenter .docs-main header.docs-navbar .docs-right{display:flex;white-space:nowrap;gap:1rem;align-items:center}html.theme--catppuccin-mocha #documenter .docs-main header.docs-navbar .docs-right .docs-icon,html.theme--catppuccin-mocha #documenter .docs-main header.docs-navbar .docs-right .docs-label{display:inline-block}html.theme--catppuccin-mocha #documenter .docs-main header.docs-navbar .docs-right .docs-label{padding:0;margin-left:0.3em}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha #documenter .docs-main header.docs-navbar .docs-right .docs-navbar-link{margin-left:0.4rem;margin-right:0.4rem}}html.theme--catppuccin-mocha #documenter .docs-main header.docs-navbar>*{margin:auto 0}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha #documenter .docs-main header.docs-navbar{position:sticky;top:0;padding:0 1rem;transition-property:top, box-shadow;-webkit-transition-property:top, box-shadow;transition-duration:0.3s;-webkit-transition-duration:0.3s}html.theme--catppuccin-mocha #documenter .docs-main header.docs-navbar.headroom--not-top{box-shadow:.2rem 0rem .4rem #171717;transition-duration:0.7s;-webkit-transition-duration:0.7s}html.theme--catppuccin-mocha #documenter .docs-main header.docs-navbar.headroom--unpinned.headroom--not-top.headroom--not-bottom{top:-4.5rem;transition-duration:0.7s;-webkit-transition-duration:0.7s}}html.theme--catppuccin-mocha #documenter .docs-main section.footnotes{border-top:1px solid #585b70}html.theme--catppuccin-mocha #documenter .docs-main section.footnotes li .tag:first-child,html.theme--catppuccin-mocha #documenter .docs-main section.footnotes li .docstring>section>a.docs-sourcelink:first-child,html.theme--catppuccin-mocha #documenter .docs-main section.footnotes li .content kbd:first-child,html.theme--catppuccin-mocha .content #documenter .docs-main section.footnotes li kbd:first-child{margin-right:1em;margin-bottom:0.4em}html.theme--catppuccin-mocha #documenter .docs-main .docs-footer{display:flex;flex-wrap:wrap;margin-left:0;margin-right:0;border-top:1px solid #585b70;padding-top:1rem;padding-bottom:1rem}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha #documenter .docs-main .docs-footer{padding-left:1rem;padding-right:1rem}}html.theme--catppuccin-mocha #documenter .docs-main .docs-footer .docs-footer-nextpage,html.theme--catppuccin-mocha #documenter .docs-main .docs-footer .docs-footer-prevpage{flex-grow:1}html.theme--catppuccin-mocha #documenter .docs-main .docs-footer .docs-footer-nextpage{text-align:right}html.theme--catppuccin-mocha #documenter .docs-main .docs-footer .flexbox-break{flex-basis:100%;height:0}html.theme--catppuccin-mocha #documenter .docs-main .docs-footer .footer-message{font-size:0.8em;margin:0.5em auto 0 auto;text-align:center}html.theme--catppuccin-mocha #documenter .docs-sidebar{display:flex;flex-direction:column;color:#cdd6f4;background-color:#181825;border-right:1px solid #585b70;padding:0;flex:0 0 18rem;z-index:5;font-size:1rem;position:fixed;left:-18rem;width:18rem;height:100%;transition:left 0.3s}html.theme--catppuccin-mocha #documenter .docs-sidebar.visible{left:0;box-shadow:.4rem 0rem .8rem #171717}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha #documenter .docs-sidebar.visible{box-shadow:none}}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha #documenter .docs-sidebar{left:0;top:0}}html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo{margin-top:1rem;padding:0 1rem}html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-logo>img{max-height:6rem;margin:auto}html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-package-name{flex-shrink:0;font-size:1.5rem;font-weight:700;text-align:center;white-space:nowrap;overflow:hidden;padding:0.5rem 0}html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-package-name .docs-autofit{max-width:16.2rem}html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-package-name a,html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-package-name a:hover{color:#cdd6f4}html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-version-selector{border-top:1px solid #585b70;display:none;padding:0.5rem}html.theme--catppuccin-mocha #documenter .docs-sidebar .docs-version-selector.visible{display:flex}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu{flex-grow:1;user-select:none;border-top:1px solid #585b70;padding-bottom:1.5rem}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu>li>.tocitem{font-weight:bold}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu>li li{font-size:.95rem;margin-left:1em;border-left:1px solid #585b70}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu input.collapse-toggle{display:none}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu ul.collapsed{display:none}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu input:checked~ul.collapsed{display:block}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu label.tocitem{display:flex}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-label{flex-grow:2}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-size:.75rem;margin-left:1rem;margin-top:auto;margin-bottom:auto}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f054"}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu input:checked~label.tocitem .docs-chevron::before{content:"\f078"}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu .tocitem{display:block;padding:0.5rem 0.5rem}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu .tocitem,html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu .tocitem:hover{color:#cdd6f4;background:#181825}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu a.tocitem:hover,html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu label.tocitem:hover{color:#cdd6f4;background-color:#202031}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu li.is-active{border-top:1px solid #585b70;border-bottom:1px solid #585b70;background-color:#11111b}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem,html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem:hover{background-color:#11111b;color:#cdd6f4}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu li.is-active ul.internal .tocitem:hover{background-color:#202031;color:#cdd6f4}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu>li.is-active:first-child{border-top:none}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu ul.internal{margin:0 0.5rem 0.5rem;border-top:1px solid #585b70}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu ul.internal li{font-size:.85rem;border-left:none;margin-left:0;margin-top:0.5rem}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem{width:100%;padding:0}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem::before{content:"⚬";margin-right:0.4em}html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search{margin:auto;margin-top:0.5rem;margin-bottom:0.5rem}html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input{width:14.4rem}html.theme--catppuccin-mocha #documenter .docs-sidebar #documenter-search-query{color:#868c98;width:14.4rem;box-shadow:inset 0 1px 2px rgba(10,10,10,0.1)}@media screen and (min-width: 1056px){html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar{width:.3rem;background:none}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#28283e}html.theme--catppuccin-mocha #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb:hover{background:#383856}}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha #documenter .docs-sidebar{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--catppuccin-mocha #documenter .docs-sidebar::-webkit-scrollbar{width:.3rem;background:none}html.theme--catppuccin-mocha #documenter .docs-sidebar::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#28283e}html.theme--catppuccin-mocha #documenter .docs-sidebar::-webkit-scrollbar-thumb:hover{background:#383856}}html.theme--catppuccin-mocha kbd.search-modal-key-hints{border-radius:0.25rem;border:1px solid rgba(245,245,245,0.6);box-shadow:0 2px 0 1px rgba(245,245,245,0.6);cursor:default;font-size:0.9rem;line-height:1.5;min-width:0.75rem;text-align:center;padding:0.1rem 0.3rem;position:relative;top:-1px}html.theme--catppuccin-mocha .search-min-width-50{min-width:50%}html.theme--catppuccin-mocha .search-min-height-100{min-height:100%}html.theme--catppuccin-mocha .search-modal-card-body{max-height:calc(100vh - 15rem)}html.theme--catppuccin-mocha .search-result-link{border-radius:0.7em;transition:all 300ms}html.theme--catppuccin-mocha .search-result-link:hover,html.theme--catppuccin-mocha .search-result-link:focus{background-color:rgba(0,128,128,0.1)}html.theme--catppuccin-mocha .search-result-link .property-search-result-badge,html.theme--catppuccin-mocha .search-result-link .search-filter{transition:all 300ms}html.theme--catppuccin-mocha .property-search-result-badge,html.theme--catppuccin-mocha .search-filter{padding:0.15em 0.5em;font-size:0.8em;font-style:italic;text-transform:none !important;line-height:1.5;color:#f5f5f5;background-color:rgba(51,65,85,0.501961);border-radius:0.6rem}html.theme--catppuccin-mocha .search-result-link:hover .property-search-result-badge,html.theme--catppuccin-mocha .search-result-link:hover .search-filter,html.theme--catppuccin-mocha .search-result-link:focus .property-search-result-badge,html.theme--catppuccin-mocha .search-result-link:focus .search-filter{color:#333;background-color:#f1f5f9}html.theme--catppuccin-mocha .search-filter{color:#333;background-color:#f5f5f5;transition:all 300ms}html.theme--catppuccin-mocha .search-filter:hover,html.theme--catppuccin-mocha .search-filter:focus{color:#333}html.theme--catppuccin-mocha .search-filter-selected{color:#313244;background-color:#b4befe}html.theme--catppuccin-mocha .search-filter-selected:hover,html.theme--catppuccin-mocha .search-filter-selected:focus{color:#313244}html.theme--catppuccin-mocha .search-result-highlight{background-color:#ffdd57;color:black}html.theme--catppuccin-mocha .search-divider{border-bottom:1px solid #585b70}html.theme--catppuccin-mocha .search-result-title{width:85%;color:#f5f5f5}html.theme--catppuccin-mocha .search-result-code-title{font-size:0.875rem;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}html.theme--catppuccin-mocha #search-modal .modal-card-body::-webkit-scrollbar,html.theme--catppuccin-mocha #search-modal .filter-tabs::-webkit-scrollbar{height:10px;width:10px;background-color:transparent}html.theme--catppuccin-mocha #search-modal .modal-card-body::-webkit-scrollbar-thumb,html.theme--catppuccin-mocha #search-modal .filter-tabs::-webkit-scrollbar-thumb{background-color:gray;border-radius:1rem}html.theme--catppuccin-mocha #search-modal .modal-card-body::-webkit-scrollbar-track,html.theme--catppuccin-mocha #search-modal .filter-tabs::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,0.6);background-color:transparent}html.theme--catppuccin-mocha .w-100{width:100%}html.theme--catppuccin-mocha .gap-2{gap:0.5rem}html.theme--catppuccin-mocha .gap-4{gap:1rem}html.theme--catppuccin-mocha .gap-8{gap:2rem}html.theme--catppuccin-mocha{background-color:#1e1e2e;font-size:16px;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--catppuccin-mocha a{transition:all 200ms ease}html.theme--catppuccin-mocha .label{color:#cdd6f4}html.theme--catppuccin-mocha .button,html.theme--catppuccin-mocha .control.has-icons-left .icon,html.theme--catppuccin-mocha .control.has-icons-right .icon,html.theme--catppuccin-mocha .input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-mocha .pagination-ellipsis,html.theme--catppuccin-mocha .pagination-link,html.theme--catppuccin-mocha .pagination-next,html.theme--catppuccin-mocha .pagination-previous,html.theme--catppuccin-mocha .select,html.theme--catppuccin-mocha .select select,html.theme--catppuccin-mocha .textarea{height:2.5em;color:#cdd6f4}html.theme--catppuccin-mocha .input,html.theme--catppuccin-mocha #documenter .docs-sidebar form.docs-search>input,html.theme--catppuccin-mocha .textarea{transition:all 200ms ease;box-shadow:none;border-width:1px;padding-left:1em;padding-right:1em;color:#cdd6f4}html.theme--catppuccin-mocha .select:after,html.theme--catppuccin-mocha .select select{border-width:1px}html.theme--catppuccin-mocha .menu-list a{transition:all 300ms ease}html.theme--catppuccin-mocha .modal-card-foot,html.theme--catppuccin-mocha .modal-card-head{border-color:#585b70}html.theme--catppuccin-mocha .navbar{border-radius:.4em}html.theme--catppuccin-mocha .navbar.is-transparent{background:none}html.theme--catppuccin-mocha .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--catppuccin-mocha .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#89b4fa}@media screen and (max-width: 1055px){html.theme--catppuccin-mocha .navbar .navbar-menu{background-color:#89b4fa;border-radius:0 0 .4em .4em}}html.theme--catppuccin-mocha .docstring>section>a.docs-sourcelink:not(body){color:#313244}html.theme--catppuccin-mocha .tag.is-link:not(body),html.theme--catppuccin-mocha .docstring>section>a.is-link.docs-sourcelink:not(body),html.theme--catppuccin-mocha .content kbd.is-link:not(body){color:#313244}html.theme--catppuccin-mocha .ansi span.sgr1{font-weight:bolder}html.theme--catppuccin-mocha .ansi span.sgr2{font-weight:lighter}html.theme--catppuccin-mocha .ansi span.sgr3{font-style:italic}html.theme--catppuccin-mocha .ansi span.sgr4{text-decoration:underline}html.theme--catppuccin-mocha .ansi span.sgr7{color:#1e1e2e;background-color:#cdd6f4}html.theme--catppuccin-mocha .ansi span.sgr8{color:transparent}html.theme--catppuccin-mocha .ansi span.sgr8 span{color:transparent}html.theme--catppuccin-mocha .ansi span.sgr9{text-decoration:line-through}html.theme--catppuccin-mocha .ansi span.sgr30{color:#45475a}html.theme--catppuccin-mocha .ansi span.sgr31{color:#f38ba8}html.theme--catppuccin-mocha .ansi span.sgr32{color:#a6e3a1}html.theme--catppuccin-mocha .ansi span.sgr33{color:#f9e2af}html.theme--catppuccin-mocha .ansi span.sgr34{color:#89b4fa}html.theme--catppuccin-mocha .ansi span.sgr35{color:#f5c2e7}html.theme--catppuccin-mocha .ansi span.sgr36{color:#94e2d5}html.theme--catppuccin-mocha .ansi span.sgr37{color:#bac2de}html.theme--catppuccin-mocha .ansi span.sgr40{background-color:#45475a}html.theme--catppuccin-mocha .ansi span.sgr41{background-color:#f38ba8}html.theme--catppuccin-mocha .ansi span.sgr42{background-color:#a6e3a1}html.theme--catppuccin-mocha .ansi span.sgr43{background-color:#f9e2af}html.theme--catppuccin-mocha .ansi span.sgr44{background-color:#89b4fa}html.theme--catppuccin-mocha .ansi span.sgr45{background-color:#f5c2e7}html.theme--catppuccin-mocha .ansi span.sgr46{background-color:#94e2d5}html.theme--catppuccin-mocha .ansi span.sgr47{background-color:#bac2de}html.theme--catppuccin-mocha .ansi span.sgr90{color:#585b70}html.theme--catppuccin-mocha .ansi span.sgr91{color:#f38ba8}html.theme--catppuccin-mocha .ansi span.sgr92{color:#a6e3a1}html.theme--catppuccin-mocha .ansi span.sgr93{color:#f9e2af}html.theme--catppuccin-mocha .ansi span.sgr94{color:#89b4fa}html.theme--catppuccin-mocha .ansi span.sgr95{color:#f5c2e7}html.theme--catppuccin-mocha .ansi span.sgr96{color:#94e2d5}html.theme--catppuccin-mocha .ansi span.sgr97{color:#a6adc8}html.theme--catppuccin-mocha .ansi span.sgr100{background-color:#585b70}html.theme--catppuccin-mocha .ansi span.sgr101{background-color:#f38ba8}html.theme--catppuccin-mocha .ansi span.sgr102{background-color:#a6e3a1}html.theme--catppuccin-mocha .ansi span.sgr103{background-color:#f9e2af}html.theme--catppuccin-mocha .ansi span.sgr104{background-color:#89b4fa}html.theme--catppuccin-mocha .ansi span.sgr105{background-color:#f5c2e7}html.theme--catppuccin-mocha .ansi span.sgr106{background-color:#94e2d5}html.theme--catppuccin-mocha .ansi span.sgr107{background-color:#a6adc8}html.theme--catppuccin-mocha code.language-julia-repl>span.hljs-meta{color:#a6e3a1;font-weight:bolder}html.theme--catppuccin-mocha code .hljs{color:#cdd6f4;background:#1e1e2e}html.theme--catppuccin-mocha code .hljs-keyword{color:#cba6f7}html.theme--catppuccin-mocha code .hljs-built_in{color:#f38ba8}html.theme--catppuccin-mocha code .hljs-type{color:#f9e2af}html.theme--catppuccin-mocha code .hljs-literal{color:#fab387}html.theme--catppuccin-mocha code .hljs-number{color:#fab387}html.theme--catppuccin-mocha code .hljs-operator{color:#94e2d5}html.theme--catppuccin-mocha code .hljs-punctuation{color:#bac2de}html.theme--catppuccin-mocha code .hljs-property{color:#94e2d5}html.theme--catppuccin-mocha code .hljs-regexp{color:#f5c2e7}html.theme--catppuccin-mocha code .hljs-string{color:#a6e3a1}html.theme--catppuccin-mocha code .hljs-char.escape_{color:#a6e3a1}html.theme--catppuccin-mocha code .hljs-subst{color:#a6adc8}html.theme--catppuccin-mocha code .hljs-symbol{color:#f2cdcd}html.theme--catppuccin-mocha code .hljs-variable{color:#cba6f7}html.theme--catppuccin-mocha code .hljs-variable.language_{color:#cba6f7}html.theme--catppuccin-mocha code .hljs-variable.constant_{color:#fab387}html.theme--catppuccin-mocha code .hljs-title{color:#89b4fa}html.theme--catppuccin-mocha code .hljs-title.class_{color:#f9e2af}html.theme--catppuccin-mocha code .hljs-title.function_{color:#89b4fa}html.theme--catppuccin-mocha code .hljs-params{color:#cdd6f4}html.theme--catppuccin-mocha code .hljs-comment{color:#585b70}html.theme--catppuccin-mocha code .hljs-doctag{color:#f38ba8}html.theme--catppuccin-mocha code .hljs-meta{color:#fab387}html.theme--catppuccin-mocha code .hljs-section{color:#89b4fa}html.theme--catppuccin-mocha code .hljs-tag{color:#a6adc8}html.theme--catppuccin-mocha code .hljs-name{color:#cba6f7}html.theme--catppuccin-mocha code .hljs-attr{color:#89b4fa}html.theme--catppuccin-mocha code .hljs-attribute{color:#a6e3a1}html.theme--catppuccin-mocha code .hljs-bullet{color:#94e2d5}html.theme--catppuccin-mocha code .hljs-code{color:#a6e3a1}html.theme--catppuccin-mocha code .hljs-emphasis{color:#f38ba8;font-style:italic}html.theme--catppuccin-mocha code .hljs-strong{color:#f38ba8;font-weight:bold}html.theme--catppuccin-mocha code .hljs-formula{color:#94e2d5}html.theme--catppuccin-mocha code .hljs-link{color:#74c7ec;font-style:italic}html.theme--catppuccin-mocha code .hljs-quote{color:#a6e3a1;font-style:italic}html.theme--catppuccin-mocha code .hljs-selector-tag{color:#f9e2af}html.theme--catppuccin-mocha code .hljs-selector-id{color:#89b4fa}html.theme--catppuccin-mocha code .hljs-selector-class{color:#94e2d5}html.theme--catppuccin-mocha code .hljs-selector-attr{color:#cba6f7}html.theme--catppuccin-mocha code .hljs-selector-pseudo{color:#94e2d5}html.theme--catppuccin-mocha code .hljs-template-tag{color:#f2cdcd}html.theme--catppuccin-mocha code .hljs-template-variable{color:#f2cdcd}html.theme--catppuccin-mocha code .hljs-addition{color:#a6e3a1;background:rgba(166,227,161,0.15)}html.theme--catppuccin-mocha code .hljs-deletion{color:#f38ba8;background:rgba(243,139,168,0.15)}html.theme--catppuccin-mocha .search-result-link{border-radius:0.7em;transition:all 300ms}html.theme--catppuccin-mocha .search-result-link:hover,html.theme--catppuccin-mocha .search-result-link:focus{background-color:#313244}html.theme--catppuccin-mocha .search-result-link .property-search-result-badge,html.theme--catppuccin-mocha .search-result-link .search-filter{transition:all 300ms}html.theme--catppuccin-mocha .search-result-link:hover .property-search-result-badge,html.theme--catppuccin-mocha .search-result-link:hover .search-filter,html.theme--catppuccin-mocha .search-result-link:focus .property-search-result-badge,html.theme--catppuccin-mocha .search-result-link:focus .search-filter{color:#313244 !important;background-color:#b4befe !important}html.theme--catppuccin-mocha .search-result-title{color:#cdd6f4}html.theme--catppuccin-mocha .search-result-highlight{background-color:#f38ba8;color:#181825}html.theme--catppuccin-mocha .search-divider{border-bottom:1px solid #5e6d6f50}html.theme--catppuccin-mocha .w-100{width:100%}html.theme--catppuccin-mocha .gap-2{gap:0.5rem}html.theme--catppuccin-mocha .gap-4{gap:1rem} diff --git a/v0.2.0/assets/themes/documenter-dark.css b/v0.2.0/assets/themes/documenter-dark.css new file mode 100644 index 000000000..c41c82f25 --- /dev/null +++ b/v0.2.0/assets/themes/documenter-dark.css @@ -0,0 +1,7 @@ +html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark .file-cta,html.theme--documenter-dark .file-name,html.theme--documenter-dark .select select,html.theme--documenter-dark .textarea,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark .button{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;border-radius:.4em;box-shadow:none;display:inline-flex;font-size:1rem;height:2.5em;justify-content:flex-start;line-height:1.5;padding-bottom:calc(0.5em - 1px);padding-left:calc(0.75em - 1px);padding-right:calc(0.75em - 1px);padding-top:calc(0.5em - 1px);position:relative;vertical-align:top}html.theme--documenter-dark .pagination-previous:focus,html.theme--documenter-dark .pagination-next:focus,html.theme--documenter-dark .pagination-link:focus,html.theme--documenter-dark .pagination-ellipsis:focus,html.theme--documenter-dark .file-cta:focus,html.theme--documenter-dark .file-name:focus,html.theme--documenter-dark .select select:focus,html.theme--documenter-dark .textarea:focus,html.theme--documenter-dark .input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:focus,html.theme--documenter-dark .button:focus,html.theme--documenter-dark .is-focused.pagination-previous,html.theme--documenter-dark .is-focused.pagination-next,html.theme--documenter-dark .is-focused.pagination-link,html.theme--documenter-dark .is-focused.pagination-ellipsis,html.theme--documenter-dark .is-focused.file-cta,html.theme--documenter-dark .is-focused.file-name,html.theme--documenter-dark .select select.is-focused,html.theme--documenter-dark .is-focused.textarea,html.theme--documenter-dark .is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-focused.button,html.theme--documenter-dark .pagination-previous:active,html.theme--documenter-dark .pagination-next:active,html.theme--documenter-dark .pagination-link:active,html.theme--documenter-dark .pagination-ellipsis:active,html.theme--documenter-dark .file-cta:active,html.theme--documenter-dark .file-name:active,html.theme--documenter-dark .select select:active,html.theme--documenter-dark .textarea:active,html.theme--documenter-dark .input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:active,html.theme--documenter-dark .button:active,html.theme--documenter-dark .is-active.pagination-previous,html.theme--documenter-dark .is-active.pagination-next,html.theme--documenter-dark .is-active.pagination-link,html.theme--documenter-dark .is-active.pagination-ellipsis,html.theme--documenter-dark .is-active.file-cta,html.theme--documenter-dark .is-active.file-name,html.theme--documenter-dark .select select.is-active,html.theme--documenter-dark .is-active.textarea,html.theme--documenter-dark .is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--documenter-dark .is-active.button{outline:none}html.theme--documenter-dark .pagination-previous[disabled],html.theme--documenter-dark .pagination-next[disabled],html.theme--documenter-dark .pagination-link[disabled],html.theme--documenter-dark .pagination-ellipsis[disabled],html.theme--documenter-dark .file-cta[disabled],html.theme--documenter-dark .file-name[disabled],html.theme--documenter-dark .select select[disabled],html.theme--documenter-dark .textarea[disabled],html.theme--documenter-dark .input[disabled],html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled],html.theme--documenter-dark .button[disabled],fieldset[disabled] html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark fieldset[disabled] .pagination-previous,fieldset[disabled] html.theme--documenter-dark .pagination-next,html.theme--documenter-dark fieldset[disabled] .pagination-next,fieldset[disabled] html.theme--documenter-dark .pagination-link,html.theme--documenter-dark fieldset[disabled] .pagination-link,fieldset[disabled] html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark fieldset[disabled] .pagination-ellipsis,fieldset[disabled] html.theme--documenter-dark .file-cta,html.theme--documenter-dark fieldset[disabled] .file-cta,fieldset[disabled] html.theme--documenter-dark .file-name,html.theme--documenter-dark fieldset[disabled] .file-name,fieldset[disabled] html.theme--documenter-dark .select select,fieldset[disabled] html.theme--documenter-dark .textarea,fieldset[disabled] html.theme--documenter-dark .input,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark fieldset[disabled] .select select,html.theme--documenter-dark .select fieldset[disabled] select,html.theme--documenter-dark fieldset[disabled] .textarea,html.theme--documenter-dark fieldset[disabled] .input,html.theme--documenter-dark fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar fieldset[disabled] form.docs-search>input,fieldset[disabled] html.theme--documenter-dark .button,html.theme--documenter-dark fieldset[disabled] .button{cursor:not-allowed}html.theme--documenter-dark .tabs,html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark .breadcrumb,html.theme--documenter-dark .file,html.theme--documenter-dark .button,.is-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}html.theme--documenter-dark .navbar-link:not(.is-arrowless)::after,html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading)::after{border:3px solid rgba(0,0,0,0);border-radius:2px;border-right:0;border-top:0;content:" ";display:block;height:0.625em;margin-top:-0.4375em;pointer-events:none;position:absolute;top:50%;transform:rotate(-45deg);transform-origin:center;width:0.625em}html.theme--documenter-dark .admonition:not(:last-child),html.theme--documenter-dark .tabs:not(:last-child),html.theme--documenter-dark .pagination:not(:last-child),html.theme--documenter-dark .message:not(:last-child),html.theme--documenter-dark .level:not(:last-child),html.theme--documenter-dark .breadcrumb:not(:last-child),html.theme--documenter-dark .block:not(:last-child),html.theme--documenter-dark .title:not(:last-child),html.theme--documenter-dark .subtitle:not(:last-child),html.theme--documenter-dark .table-container:not(:last-child),html.theme--documenter-dark .table:not(:last-child),html.theme--documenter-dark .progress:not(:last-child),html.theme--documenter-dark .notification:not(:last-child),html.theme--documenter-dark .content:not(:last-child),html.theme--documenter-dark .box:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .modal-close,html.theme--documenter-dark .delete{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,0.2);border:none;border-radius:9999px;cursor:pointer;pointer-events:auto;display:inline-block;flex-grow:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:none;position:relative;vertical-align:top;width:20px}html.theme--documenter-dark .modal-close::before,html.theme--documenter-dark .delete::before,html.theme--documenter-dark .modal-close::after,html.theme--documenter-dark .delete::after{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--documenter-dark .modal-close::before,html.theme--documenter-dark .delete::before{height:2px;width:50%}html.theme--documenter-dark .modal-close::after,html.theme--documenter-dark .delete::after{height:50%;width:2px}html.theme--documenter-dark .modal-close:hover,html.theme--documenter-dark .delete:hover,html.theme--documenter-dark .modal-close:focus,html.theme--documenter-dark .delete:focus{background-color:rgba(10,10,10,0.3)}html.theme--documenter-dark .modal-close:active,html.theme--documenter-dark .delete:active{background-color:rgba(10,10,10,0.4)}html.theme--documenter-dark .is-small.modal-close,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.modal-close,html.theme--documenter-dark .is-small.delete,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.delete{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}html.theme--documenter-dark .is-medium.modal-close,html.theme--documenter-dark .is-medium.delete{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}html.theme--documenter-dark .is-large.modal-close,html.theme--documenter-dark .is-large.delete{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}html.theme--documenter-dark .control.is-loading::after,html.theme--documenter-dark .select.is-loading::after,html.theme--documenter-dark .loader,html.theme--documenter-dark .button.is-loading::after{animation:spinAround 500ms infinite linear;border:2px solid #dbdee0;border-radius:9999px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em}html.theme--documenter-dark .hero-video,html.theme--documenter-dark .modal-background,html.theme--documenter-dark .modal,html.theme--documenter-dark .image.is-square img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--documenter-dark .image.is-square .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--documenter-dark .image.is-1by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--documenter-dark .image.is-1by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--documenter-dark .image.is-5by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--documenter-dark .image.is-5by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--documenter-dark .image.is-4by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--documenter-dark .image.is-4by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--documenter-dark .image.is-3by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--documenter-dark .image.is-3by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--documenter-dark .image.is-5by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--documenter-dark .image.is-5by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--documenter-dark .image.is-16by9 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--documenter-dark .image.is-16by9 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--documenter-dark .image.is-2by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--documenter-dark .image.is-2by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--documenter-dark .image.is-3by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--documenter-dark .image.is-3by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--documenter-dark .image.is-4by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--documenter-dark .image.is-4by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--documenter-dark .image.is-3by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--documenter-dark .image.is-3by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--documenter-dark .image.is-2by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--documenter-dark .image.is-2by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--documenter-dark .image.is-3by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--documenter-dark .image.is-3by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--documenter-dark .image.is-9by16 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--documenter-dark .image.is-9by16 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--documenter-dark .image.is-1by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--documenter-dark .image.is-1by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--documenter-dark .image.is-1by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--documenter-dark .image.is-1by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio,.is-overlay{bottom:0;left:0;position:absolute;right:0;top:0}html.theme--documenter-dark .navbar-burger{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0}/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:inherit}.has-text-white{color:#fff !important}a.has-text-white:hover,a.has-text-white:focus{color:#e6e6e6 !important}.has-background-white{background-color:#fff !important}.has-text-black{color:#0a0a0a !important}a.has-text-black:hover,a.has-text-black:focus{color:#000 !important}.has-background-black{background-color:#0a0a0a !important}.has-text-light{color:#ecf0f1 !important}a.has-text-light:hover,a.has-text-light:focus{color:#cfd9db !important}.has-background-light{background-color:#ecf0f1 !important}.has-text-dark{color:#282f2f !important}a.has-text-dark:hover,a.has-text-dark:focus{color:#111414 !important}.has-background-dark{background-color:#282f2f !important}.has-text-primary{color:#375a7f !important}a.has-text-primary:hover,a.has-text-primary:focus{color:#28415b !important}.has-background-primary{background-color:#375a7f !important}.has-text-primary-light{color:#f1f5f9 !important}a.has-text-primary-light:hover,a.has-text-primary-light:focus{color:#cddbe9 !important}.has-background-primary-light{background-color:#f1f5f9 !important}.has-text-primary-dark{color:#4d7eb2 !important}a.has-text-primary-dark:hover,a.has-text-primary-dark:focus{color:#7198c1 !important}.has-background-primary-dark{background-color:#4d7eb2 !important}.has-text-link{color:#1abc9c !important}a.has-text-link:hover,a.has-text-link:focus{color:#148f77 !important}.has-background-link{background-color:#1abc9c !important}.has-text-link-light{color:#edfdf9 !important}a.has-text-link-light:hover,a.has-text-link-light:focus{color:#c0f6ec !important}.has-background-link-light{background-color:#edfdf9 !important}.has-text-link-dark{color:#15987e !important}a.has-text-link-dark:hover,a.has-text-link-dark:focus{color:#1bc5a4 !important}.has-background-link-dark{background-color:#15987e !important}.has-text-info{color:#3c5dcd !important}a.has-text-info:hover,a.has-text-info:focus{color:#2c48aa !important}.has-background-info{background-color:#3c5dcd !important}.has-text-info-light{color:#eff2fb !important}a.has-text-info-light:hover,a.has-text-info-light:focus{color:#c6d0f0 !important}.has-background-info-light{background-color:#eff2fb !important}.has-text-info-dark{color:#3253c3 !important}a.has-text-info-dark:hover,a.has-text-info-dark:focus{color:#5571d3 !important}.has-background-info-dark{background-color:#3253c3 !important}.has-text-success{color:#259a12 !important}a.has-text-success:hover,a.has-text-success:focus{color:#1a6c0d !important}.has-background-success{background-color:#259a12 !important}.has-text-success-light{color:#effded !important}a.has-text-success-light:hover,a.has-text-success-light:focus{color:#c7f8bf !important}.has-background-success-light{background-color:#effded !important}.has-text-success-dark{color:#2ec016 !important}a.has-text-success-dark:hover,a.has-text-success-dark:focus{color:#3fe524 !important}.has-background-success-dark{background-color:#2ec016 !important}.has-text-warning{color:#f4c72f !important}a.has-text-warning:hover,a.has-text-warning:focus{color:#e4b30c !important}.has-background-warning{background-color:#f4c72f !important}.has-text-warning-light{color:#fefaec !important}a.has-text-warning-light:hover,a.has-text-warning-light:focus{color:#fbedbb !important}.has-background-warning-light{background-color:#fefaec !important}.has-text-warning-dark{color:#8c6e07 !important}a.has-text-warning-dark:hover,a.has-text-warning-dark:focus{color:#bd940a !important}.has-background-warning-dark{background-color:#8c6e07 !important}.has-text-danger{color:#cb3c33 !important}a.has-text-danger:hover,a.has-text-danger:focus{color:#a23029 !important}.has-background-danger{background-color:#cb3c33 !important}.has-text-danger-light{color:#fbefef !important}a.has-text-danger-light:hover,a.has-text-danger-light:focus{color:#f1c8c6 !important}.has-background-danger-light{background-color:#fbefef !important}.has-text-danger-dark{color:#c03930 !important}a.has-text-danger-dark:hover,a.has-text-danger-dark:focus{color:#d35850 !important}.has-background-danger-dark{background-color:#c03930 !important}.has-text-black-bis{color:#121212 !important}.has-background-black-bis{background-color:#121212 !important}.has-text-black-ter{color:#242424 !important}.has-background-black-ter{background-color:#242424 !important}.has-text-grey-darker{color:#282f2f !important}.has-background-grey-darker{background-color:#282f2f !important}.has-text-grey-dark{color:#343c3d !important}.has-background-grey-dark{background-color:#343c3d !important}.has-text-grey{color:#5e6d6f !important}.has-background-grey{background-color:#5e6d6f !important}.has-text-grey-light{color:#8c9b9d !important}.has-background-grey-light{background-color:#8c9b9d !important}.has-text-grey-lighter{color:#dbdee0 !important}.has-background-grey-lighter{background-color:#dbdee0 !important}.has-text-white-ter{color:#ecf0f1 !important}.has-background-white-ter{background-color:#ecf0f1 !important}.has-text-white-bis{color:#fafafa !important}.has-background-white-bis{background-color:#fafafa !important}.is-flex-direction-row{flex-direction:row !important}.is-flex-direction-row-reverse{flex-direction:row-reverse !important}.is-flex-direction-column{flex-direction:column !important}.is-flex-direction-column-reverse{flex-direction:column-reverse !important}.is-flex-wrap-nowrap{flex-wrap:nowrap !important}.is-flex-wrap-wrap{flex-wrap:wrap !important}.is-flex-wrap-wrap-reverse{flex-wrap:wrap-reverse !important}.is-justify-content-flex-start{justify-content:flex-start !important}.is-justify-content-flex-end{justify-content:flex-end !important}.is-justify-content-center{justify-content:center !important}.is-justify-content-space-between{justify-content:space-between !important}.is-justify-content-space-around{justify-content:space-around !important}.is-justify-content-space-evenly{justify-content:space-evenly !important}.is-justify-content-start{justify-content:start !important}.is-justify-content-end{justify-content:end !important}.is-justify-content-left{justify-content:left !important}.is-justify-content-right{justify-content:right !important}.is-align-content-flex-start{align-content:flex-start !important}.is-align-content-flex-end{align-content:flex-end !important}.is-align-content-center{align-content:center !important}.is-align-content-space-between{align-content:space-between !important}.is-align-content-space-around{align-content:space-around !important}.is-align-content-space-evenly{align-content:space-evenly !important}.is-align-content-stretch{align-content:stretch !important}.is-align-content-start{align-content:start !important}.is-align-content-end{align-content:end !important}.is-align-content-baseline{align-content:baseline !important}.is-align-items-stretch{align-items:stretch !important}.is-align-items-flex-start{align-items:flex-start !important}.is-align-items-flex-end{align-items:flex-end !important}.is-align-items-center{align-items:center !important}.is-align-items-baseline{align-items:baseline !important}.is-align-items-start{align-items:start !important}.is-align-items-end{align-items:end !important}.is-align-items-self-start{align-items:self-start !important}.is-align-items-self-end{align-items:self-end !important}.is-align-self-auto{align-self:auto !important}.is-align-self-flex-start{align-self:flex-start !important}.is-align-self-flex-end{align-self:flex-end !important}.is-align-self-center{align-self:center !important}.is-align-self-baseline{align-self:baseline !important}.is-align-self-stretch{align-self:stretch !important}.is-flex-grow-0{flex-grow:0 !important}.is-flex-grow-1{flex-grow:1 !important}.is-flex-grow-2{flex-grow:2 !important}.is-flex-grow-3{flex-grow:3 !important}.is-flex-grow-4{flex-grow:4 !important}.is-flex-grow-5{flex-grow:5 !important}.is-flex-shrink-0{flex-shrink:0 !important}.is-flex-shrink-1{flex-shrink:1 !important}.is-flex-shrink-2{flex-shrink:2 !important}.is-flex-shrink-3{flex-shrink:3 !important}.is-flex-shrink-4{flex-shrink:4 !important}.is-flex-shrink-5{flex-shrink:5 !important}.is-clearfix::after{clear:both;content:" ";display:table}.is-pulled-left{float:left !important}.is-pulled-right{float:right !important}.is-radiusless{border-radius:0 !important}.is-shadowless{box-shadow:none !important}.is-clickable{cursor:pointer !important;pointer-events:all !important}.is-clipped{overflow:hidden !important}.is-relative{position:relative !important}.is-marginless{margin:0 !important}.is-paddingless{padding:0 !important}.m-0{margin:0 !important}.mt-0{margin-top:0 !important}.mr-0{margin-right:0 !important}.mb-0{margin-bottom:0 !important}.ml-0{margin-left:0 !important}.mx-0{margin-left:0 !important;margin-right:0 !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.m-1{margin:.25rem !important}.mt-1{margin-top:.25rem !important}.mr-1{margin-right:.25rem !important}.mb-1{margin-bottom:.25rem !important}.ml-1{margin-left:.25rem !important}.mx-1{margin-left:.25rem !important;margin-right:.25rem !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.m-2{margin:.5rem !important}.mt-2{margin-top:.5rem !important}.mr-2{margin-right:.5rem !important}.mb-2{margin-bottom:.5rem !important}.ml-2{margin-left:.5rem !important}.mx-2{margin-left:.5rem !important;margin-right:.5rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.m-3{margin:.75rem !important}.mt-3{margin-top:.75rem !important}.mr-3{margin-right:.75rem !important}.mb-3{margin-bottom:.75rem !important}.ml-3{margin-left:.75rem !important}.mx-3{margin-left:.75rem !important;margin-right:.75rem !important}.my-3{margin-top:.75rem !important;margin-bottom:.75rem !important}.m-4{margin:1rem !important}.mt-4{margin-top:1rem !important}.mr-4{margin-right:1rem !important}.mb-4{margin-bottom:1rem !important}.ml-4{margin-left:1rem !important}.mx-4{margin-left:1rem !important;margin-right:1rem !important}.my-4{margin-top:1rem !important;margin-bottom:1rem !important}.m-5{margin:1.5rem !important}.mt-5{margin-top:1.5rem !important}.mr-5{margin-right:1.5rem !important}.mb-5{margin-bottom:1.5rem !important}.ml-5{margin-left:1.5rem !important}.mx-5{margin-left:1.5rem !important;margin-right:1.5rem !important}.my-5{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.m-6{margin:3rem !important}.mt-6{margin-top:3rem !important}.mr-6{margin-right:3rem !important}.mb-6{margin-bottom:3rem !important}.ml-6{margin-left:3rem !important}.mx-6{margin-left:3rem !important;margin-right:3rem !important}.my-6{margin-top:3rem !important;margin-bottom:3rem !important}.m-auto{margin:auto !important}.mt-auto{margin-top:auto !important}.mr-auto{margin-right:auto !important}.mb-auto{margin-bottom:auto !important}.ml-auto{margin-left:auto !important}.mx-auto{margin-left:auto !important;margin-right:auto !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.p-0{padding:0 !important}.pt-0{padding-top:0 !important}.pr-0{padding-right:0 !important}.pb-0{padding-bottom:0 !important}.pl-0{padding-left:0 !important}.px-0{padding-left:0 !important;padding-right:0 !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.p-1{padding:.25rem !important}.pt-1{padding-top:.25rem !important}.pr-1{padding-right:.25rem !important}.pb-1{padding-bottom:.25rem !important}.pl-1{padding-left:.25rem !important}.px-1{padding-left:.25rem !important;padding-right:.25rem !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.p-2{padding:.5rem !important}.pt-2{padding-top:.5rem !important}.pr-2{padding-right:.5rem !important}.pb-2{padding-bottom:.5rem !important}.pl-2{padding-left:.5rem !important}.px-2{padding-left:.5rem !important;padding-right:.5rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.p-3{padding:.75rem !important}.pt-3{padding-top:.75rem !important}.pr-3{padding-right:.75rem !important}.pb-3{padding-bottom:.75rem !important}.pl-3{padding-left:.75rem !important}.px-3{padding-left:.75rem !important;padding-right:.75rem !important}.py-3{padding-top:.75rem !important;padding-bottom:.75rem !important}.p-4{padding:1rem !important}.pt-4{padding-top:1rem !important}.pr-4{padding-right:1rem !important}.pb-4{padding-bottom:1rem !important}.pl-4{padding-left:1rem !important}.px-4{padding-left:1rem !important;padding-right:1rem !important}.py-4{padding-top:1rem !important;padding-bottom:1rem !important}.p-5{padding:1.5rem !important}.pt-5{padding-top:1.5rem !important}.pr-5{padding-right:1.5rem !important}.pb-5{padding-bottom:1.5rem !important}.pl-5{padding-left:1.5rem !important}.px-5{padding-left:1.5rem !important;padding-right:1.5rem !important}.py-5{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.p-6{padding:3rem !important}.pt-6{padding-top:3rem !important}.pr-6{padding-right:3rem !important}.pb-6{padding-bottom:3rem !important}.pl-6{padding-left:3rem !important}.px-6{padding-left:3rem !important;padding-right:3rem !important}.py-6{padding-top:3rem !important;padding-bottom:3rem !important}.p-auto{padding:auto !important}.pt-auto{padding-top:auto !important}.pr-auto{padding-right:auto !important}.pb-auto{padding-bottom:auto !important}.pl-auto{padding-left:auto !important}.px-auto{padding-left:auto !important;padding-right:auto !important}.py-auto{padding-top:auto !important;padding-bottom:auto !important}.is-size-1{font-size:3rem !important}.is-size-2{font-size:2.5rem !important}.is-size-3{font-size:2rem !important}.is-size-4{font-size:1.5rem !important}.is-size-5{font-size:1.25rem !important}.is-size-6{font-size:1rem !important}.is-size-7,html.theme--documenter-dark .docstring>section>a.docs-sourcelink{font-size:.75rem !important}@media screen and (max-width: 768px){.is-size-1-mobile{font-size:3rem !important}.is-size-2-mobile{font-size:2.5rem !important}.is-size-3-mobile{font-size:2rem !important}.is-size-4-mobile{font-size:1.5rem !important}.is-size-5-mobile{font-size:1.25rem !important}.is-size-6-mobile{font-size:1rem !important}.is-size-7-mobile{font-size:.75rem !important}}@media screen and (min-width: 769px),print{.is-size-1-tablet{font-size:3rem !important}.is-size-2-tablet{font-size:2.5rem !important}.is-size-3-tablet{font-size:2rem !important}.is-size-4-tablet{font-size:1.5rem !important}.is-size-5-tablet{font-size:1.25rem !important}.is-size-6-tablet{font-size:1rem !important}.is-size-7-tablet{font-size:.75rem !important}}@media screen and (max-width: 1055px){.is-size-1-touch{font-size:3rem !important}.is-size-2-touch{font-size:2.5rem !important}.is-size-3-touch{font-size:2rem !important}.is-size-4-touch{font-size:1.5rem !important}.is-size-5-touch{font-size:1.25rem !important}.is-size-6-touch{font-size:1rem !important}.is-size-7-touch{font-size:.75rem !important}}@media screen and (min-width: 1056px){.is-size-1-desktop{font-size:3rem !important}.is-size-2-desktop{font-size:2.5rem !important}.is-size-3-desktop{font-size:2rem !important}.is-size-4-desktop{font-size:1.5rem !important}.is-size-5-desktop{font-size:1.25rem !important}.is-size-6-desktop{font-size:1rem !important}.is-size-7-desktop{font-size:.75rem !important}}@media screen and (min-width: 1216px){.is-size-1-widescreen{font-size:3rem !important}.is-size-2-widescreen{font-size:2.5rem !important}.is-size-3-widescreen{font-size:2rem !important}.is-size-4-widescreen{font-size:1.5rem !important}.is-size-5-widescreen{font-size:1.25rem !important}.is-size-6-widescreen{font-size:1rem !important}.is-size-7-widescreen{font-size:.75rem !important}}@media screen and (min-width: 1408px){.is-size-1-fullhd{font-size:3rem !important}.is-size-2-fullhd{font-size:2.5rem !important}.is-size-3-fullhd{font-size:2rem !important}.is-size-4-fullhd{font-size:1.5rem !important}.is-size-5-fullhd{font-size:1.25rem !important}.is-size-6-fullhd{font-size:1rem !important}.is-size-7-fullhd{font-size:.75rem !important}}.has-text-centered{text-align:center !important}.has-text-justified{text-align:justify !important}.has-text-left{text-align:left !important}.has-text-right{text-align:right !important}@media screen and (max-width: 768px){.has-text-centered-mobile{text-align:center !important}}@media screen and (min-width: 769px),print{.has-text-centered-tablet{text-align:center !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-centered-tablet-only{text-align:center !important}}@media screen and (max-width: 1055px){.has-text-centered-touch{text-align:center !important}}@media screen and (min-width: 1056px){.has-text-centered-desktop{text-align:center !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-centered-desktop-only{text-align:center !important}}@media screen and (min-width: 1216px){.has-text-centered-widescreen{text-align:center !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-centered-widescreen-only{text-align:center !important}}@media screen and (min-width: 1408px){.has-text-centered-fullhd{text-align:center !important}}@media screen and (max-width: 768px){.has-text-justified-mobile{text-align:justify !important}}@media screen and (min-width: 769px),print{.has-text-justified-tablet{text-align:justify !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-justified-tablet-only{text-align:justify !important}}@media screen and (max-width: 1055px){.has-text-justified-touch{text-align:justify !important}}@media screen and (min-width: 1056px){.has-text-justified-desktop{text-align:justify !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-justified-desktop-only{text-align:justify !important}}@media screen and (min-width: 1216px){.has-text-justified-widescreen{text-align:justify !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-justified-widescreen-only{text-align:justify !important}}@media screen and (min-width: 1408px){.has-text-justified-fullhd{text-align:justify !important}}@media screen and (max-width: 768px){.has-text-left-mobile{text-align:left !important}}@media screen and (min-width: 769px),print{.has-text-left-tablet{text-align:left !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-left-tablet-only{text-align:left !important}}@media screen and (max-width: 1055px){.has-text-left-touch{text-align:left !important}}@media screen and (min-width: 1056px){.has-text-left-desktop{text-align:left !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-left-desktop-only{text-align:left !important}}@media screen and (min-width: 1216px){.has-text-left-widescreen{text-align:left !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-left-widescreen-only{text-align:left !important}}@media screen and (min-width: 1408px){.has-text-left-fullhd{text-align:left !important}}@media screen and (max-width: 768px){.has-text-right-mobile{text-align:right !important}}@media screen and (min-width: 769px),print{.has-text-right-tablet{text-align:right !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-right-tablet-only{text-align:right !important}}@media screen and (max-width: 1055px){.has-text-right-touch{text-align:right !important}}@media screen and (min-width: 1056px){.has-text-right-desktop{text-align:right !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-right-desktop-only{text-align:right !important}}@media screen and (min-width: 1216px){.has-text-right-widescreen{text-align:right !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-right-widescreen-only{text-align:right !important}}@media screen and (min-width: 1408px){.has-text-right-fullhd{text-align:right !important}}.is-capitalized{text-transform:capitalize !important}.is-lowercase{text-transform:lowercase !important}.is-uppercase{text-transform:uppercase !important}.is-italic{font-style:italic !important}.is-underlined{text-decoration:underline !important}.has-text-weight-light{font-weight:300 !important}.has-text-weight-normal{font-weight:400 !important}.has-text-weight-medium{font-weight:500 !important}.has-text-weight-semibold{font-weight:600 !important}.has-text-weight-bold{font-weight:700 !important}.is-family-primary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-secondary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-sans-serif{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-monospace{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-family-code{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-block{display:block !important}@media screen and (max-width: 768px){.is-block-mobile{display:block !important}}@media screen and (min-width: 769px),print{.is-block-tablet{display:block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-block-tablet-only{display:block !important}}@media screen and (max-width: 1055px){.is-block-touch{display:block !important}}@media screen and (min-width: 1056px){.is-block-desktop{display:block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-block-desktop-only{display:block !important}}@media screen and (min-width: 1216px){.is-block-widescreen{display:block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-block-widescreen-only{display:block !important}}@media screen and (min-width: 1408px){.is-block-fullhd{display:block !important}}.is-flex{display:flex !important}@media screen and (max-width: 768px){.is-flex-mobile{display:flex !important}}@media screen and (min-width: 769px),print{.is-flex-tablet{display:flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-flex-tablet-only{display:flex !important}}@media screen and (max-width: 1055px){.is-flex-touch{display:flex !important}}@media screen and (min-width: 1056px){.is-flex-desktop{display:flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-flex-desktop-only{display:flex !important}}@media screen and (min-width: 1216px){.is-flex-widescreen{display:flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-flex-widescreen-only{display:flex !important}}@media screen and (min-width: 1408px){.is-flex-fullhd{display:flex !important}}.is-inline{display:inline !important}@media screen and (max-width: 768px){.is-inline-mobile{display:inline !important}}@media screen and (min-width: 769px),print{.is-inline-tablet{display:inline !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-tablet-only{display:inline !important}}@media screen and (max-width: 1055px){.is-inline-touch{display:inline !important}}@media screen and (min-width: 1056px){.is-inline-desktop{display:inline !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-desktop-only{display:inline !important}}@media screen and (min-width: 1216px){.is-inline-widescreen{display:inline !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-widescreen-only{display:inline !important}}@media screen and (min-width: 1408px){.is-inline-fullhd{display:inline !important}}.is-inline-block{display:inline-block !important}@media screen and (max-width: 768px){.is-inline-block-mobile{display:inline-block !important}}@media screen and (min-width: 769px),print{.is-inline-block-tablet{display:inline-block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-block-tablet-only{display:inline-block !important}}@media screen and (max-width: 1055px){.is-inline-block-touch{display:inline-block !important}}@media screen and (min-width: 1056px){.is-inline-block-desktop{display:inline-block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-block-desktop-only{display:inline-block !important}}@media screen and (min-width: 1216px){.is-inline-block-widescreen{display:inline-block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-block-widescreen-only{display:inline-block !important}}@media screen and (min-width: 1408px){.is-inline-block-fullhd{display:inline-block !important}}.is-inline-flex{display:inline-flex !important}@media screen and (max-width: 768px){.is-inline-flex-mobile{display:inline-flex !important}}@media screen and (min-width: 769px),print{.is-inline-flex-tablet{display:inline-flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-flex-tablet-only{display:inline-flex !important}}@media screen and (max-width: 1055px){.is-inline-flex-touch{display:inline-flex !important}}@media screen and (min-width: 1056px){.is-inline-flex-desktop{display:inline-flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-flex-desktop-only{display:inline-flex !important}}@media screen and (min-width: 1216px){.is-inline-flex-widescreen{display:inline-flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-flex-widescreen-only{display:inline-flex !important}}@media screen and (min-width: 1408px){.is-inline-flex-fullhd{display:inline-flex !important}}.is-hidden{display:none !important}.is-sr-only{border:none !important;clip:rect(0, 0, 0, 0) !important;height:0.01em !important;overflow:hidden !important;padding:0 !important;position:absolute !important;white-space:nowrap !important;width:0.01em !important}@media screen and (max-width: 768px){.is-hidden-mobile{display:none !important}}@media screen and (min-width: 769px),print{.is-hidden-tablet{display:none !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-hidden-tablet-only{display:none !important}}@media screen and (max-width: 1055px){.is-hidden-touch{display:none !important}}@media screen and (min-width: 1056px){.is-hidden-desktop{display:none !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-hidden-desktop-only{display:none !important}}@media screen and (min-width: 1216px){.is-hidden-widescreen{display:none !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-hidden-widescreen-only{display:none !important}}@media screen and (min-width: 1408px){.is-hidden-fullhd{display:none !important}}.is-invisible{visibility:hidden !important}@media screen and (max-width: 768px){.is-invisible-mobile{visibility:hidden !important}}@media screen and (min-width: 769px),print{.is-invisible-tablet{visibility:hidden !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-invisible-tablet-only{visibility:hidden !important}}@media screen and (max-width: 1055px){.is-invisible-touch{visibility:hidden !important}}@media screen and (min-width: 1056px){.is-invisible-desktop{visibility:hidden !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-invisible-desktop-only{visibility:hidden !important}}@media screen and (min-width: 1216px){.is-invisible-widescreen{visibility:hidden !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-invisible-widescreen-only{visibility:hidden !important}}@media screen and (min-width: 1408px){.is-invisible-fullhd{visibility:hidden !important}}html.theme--documenter-dark{/*! + Theme: a11y-dark + Author: @ericwbailey + Maintainer: @ericwbailey + + Based on the Tomorrow Night Eighties theme: https://github.com/isagalaev/highlight.js/blob/master/src/styles/tomorrow-night-eighties.css +*/}html.theme--documenter-dark html{background-color:#1f2424;font-size:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--documenter-dark article,html.theme--documenter-dark aside,html.theme--documenter-dark figure,html.theme--documenter-dark footer,html.theme--documenter-dark header,html.theme--documenter-dark hgroup,html.theme--documenter-dark section{display:block}html.theme--documenter-dark body,html.theme--documenter-dark button,html.theme--documenter-dark input,html.theme--documenter-dark optgroup,html.theme--documenter-dark select,html.theme--documenter-dark textarea{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif}html.theme--documenter-dark code,html.theme--documenter-dark pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}html.theme--documenter-dark body{color:#fff;font-size:1em;font-weight:400;line-height:1.5}html.theme--documenter-dark a{color:#1abc9c;cursor:pointer;text-decoration:none}html.theme--documenter-dark a strong{color:currentColor}html.theme--documenter-dark a:hover{color:#1dd2af}html.theme--documenter-dark code{background-color:rgba(255,255,255,0.05);color:#ececec;font-size:.875em;font-weight:normal;padding:.1em}html.theme--documenter-dark hr{background-color:#282f2f;border:none;display:block;height:2px;margin:1.5rem 0}html.theme--documenter-dark img{height:auto;max-width:100%}html.theme--documenter-dark input[type="checkbox"],html.theme--documenter-dark input[type="radio"]{vertical-align:baseline}html.theme--documenter-dark small{font-size:.875em}html.theme--documenter-dark span{font-style:inherit;font-weight:inherit}html.theme--documenter-dark strong{color:#f2f2f2;font-weight:700}html.theme--documenter-dark fieldset{border:none}html.theme--documenter-dark pre{-webkit-overflow-scrolling:touch;background-color:#282f2f;color:#fff;font-size:.875em;overflow-x:auto;padding:1.25rem 1.5rem;white-space:pre;word-wrap:normal}html.theme--documenter-dark pre code{background-color:transparent;color:currentColor;font-size:1em;padding:0}html.theme--documenter-dark table td,html.theme--documenter-dark table th{vertical-align:top}html.theme--documenter-dark table td:not([align]),html.theme--documenter-dark table th:not([align]){text-align:inherit}html.theme--documenter-dark table th{color:#f2f2f2}html.theme--documenter-dark .box{background-color:#343c3d;border-radius:8px;box-shadow:none;color:#fff;display:block;padding:1.25rem}html.theme--documenter-dark a.box:hover,html.theme--documenter-dark a.box:focus{box-shadow:0 0.5em 1em -0.125em rgba(10,10,10,0.1),0 0 0 1px #1abc9c}html.theme--documenter-dark a.box:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2),0 0 0 1px #1abc9c}html.theme--documenter-dark .button{background-color:#282f2f;border-color:#4c5759;border-width:1px;color:#375a7f;cursor:pointer;justify-content:center;padding-bottom:calc(0.5em - 1px);padding-left:1em;padding-right:1em;padding-top:calc(0.5em - 1px);text-align:center;white-space:nowrap}html.theme--documenter-dark .button strong{color:inherit}html.theme--documenter-dark .button .icon,html.theme--documenter-dark .button .icon.is-small,html.theme--documenter-dark .button #documenter .docs-sidebar form.docs-search>input.icon,html.theme--documenter-dark #documenter .docs-sidebar .button form.docs-search>input.icon,html.theme--documenter-dark .button .icon.is-medium,html.theme--documenter-dark .button .icon.is-large{height:1.5em;width:1.5em}html.theme--documenter-dark .button .icon:first-child:not(:last-child){margin-left:calc(-0.5em - 1px);margin-right:.25em}html.theme--documenter-dark .button .icon:last-child:not(:first-child){margin-left:.25em;margin-right:calc(-0.5em - 1px)}html.theme--documenter-dark .button .icon:first-child:last-child{margin-left:calc(-0.5em - 1px);margin-right:calc(-0.5em - 1px)}html.theme--documenter-dark .button:hover,html.theme--documenter-dark .button.is-hovered{border-color:#8c9b9d;color:#f2f2f2}html.theme--documenter-dark .button:focus,html.theme--documenter-dark .button.is-focused{border-color:#8c9b9d;color:#17a689}html.theme--documenter-dark .button:focus:not(:active),html.theme--documenter-dark .button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .button:active,html.theme--documenter-dark .button.is-active{border-color:#343c3d;color:#f2f2f2}html.theme--documenter-dark .button.is-text{background-color:transparent;border-color:transparent;color:#fff;text-decoration:underline}html.theme--documenter-dark .button.is-text:hover,html.theme--documenter-dark .button.is-text.is-hovered,html.theme--documenter-dark .button.is-text:focus,html.theme--documenter-dark .button.is-text.is-focused{background-color:#282f2f;color:#f2f2f2}html.theme--documenter-dark .button.is-text:active,html.theme--documenter-dark .button.is-text.is-active{background-color:#1d2122;color:#f2f2f2}html.theme--documenter-dark .button.is-text[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-text{background-color:transparent;border-color:transparent;box-shadow:none}html.theme--documenter-dark .button.is-ghost{background:none;border-color:rgba(0,0,0,0);color:#1abc9c;text-decoration:none}html.theme--documenter-dark .button.is-ghost:hover,html.theme--documenter-dark .button.is-ghost.is-hovered{color:#1abc9c;text-decoration:underline}html.theme--documenter-dark .button.is-white{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white:hover,html.theme--documenter-dark .button.is-white.is-hovered{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white:focus,html.theme--documenter-dark .button.is-white.is-focused{border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white:focus:not(:active),html.theme--documenter-dark .button.is-white.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--documenter-dark .button.is-white:active,html.theme--documenter-dark .button.is-white.is-active{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white{background-color:#fff;border-color:#fff;box-shadow:none}html.theme--documenter-dark .button.is-white.is-inverted{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .button.is-white.is-inverted:hover,html.theme--documenter-dark .button.is-white.is-inverted.is-hovered{background-color:#000}html.theme--documenter-dark .button.is-white.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white.is-inverted{background-color:#0a0a0a;border-color:transparent;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-white.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-white.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-white.is-outlined:hover,html.theme--documenter-dark .button.is-white.is-outlined.is-hovered,html.theme--documenter-dark .button.is-white.is-outlined:focus,html.theme--documenter-dark .button.is-white.is-outlined.is-focused{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--documenter-dark .button.is-white.is-outlined.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-white.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-white.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-white.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-white.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-white.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-focused{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--documenter-dark .button.is-black{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black:hover,html.theme--documenter-dark .button.is-black.is-hovered{background-color:#040404;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black:focus,html.theme--documenter-dark .button.is-black.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black:focus:not(:active),html.theme--documenter-dark .button.is-black.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--documenter-dark .button.is-black:active,html.theme--documenter-dark .button.is-black.is-active{background-color:#000;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black{background-color:#0a0a0a;border-color:#0a0a0a;box-shadow:none}html.theme--documenter-dark .button.is-black.is-inverted{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-inverted:hover,html.theme--documenter-dark .button.is-black.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-black.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-outlined:hover,html.theme--documenter-dark .button.is-black.is-outlined.is-hovered,html.theme--documenter-dark .button.is-black.is-outlined:focus,html.theme--documenter-dark .button.is-black.is-outlined.is-focused{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--documenter-dark .button.is-black.is-outlined.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-black.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-black.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-black.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-black.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-black.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-focused{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-light{background-color:#ecf0f1;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light:hover,html.theme--documenter-dark .button.is-light.is-hovered{background-color:#e5eaec;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light:focus,html.theme--documenter-dark .button.is-light.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light:focus:not(:active),html.theme--documenter-dark .button.is-light.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(236,240,241,0.25)}html.theme--documenter-dark .button.is-light:active,html.theme--documenter-dark .button.is-light.is-active{background-color:#dde4e6;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light{background-color:#ecf0f1;border-color:#ecf0f1;box-shadow:none}html.theme--documenter-dark .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-inverted:hover,html.theme--documenter-dark .button.is-light.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--documenter-dark .button.is-light.is-outlined{background-color:transparent;border-color:#ecf0f1;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-outlined:hover,html.theme--documenter-dark .button.is-light.is-outlined.is-hovered,html.theme--documenter-dark .button.is-light.is-outlined:focus,html.theme--documenter-dark .button.is-light.is-outlined.is-focused{background-color:#ecf0f1;border-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light.is-outlined.is-loading::after{border-color:transparent transparent #ecf0f1 #ecf0f1 !important}html.theme--documenter-dark .button.is-light.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-light.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-light.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-light.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--documenter-dark .button.is-light.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light.is-outlined{background-color:transparent;border-color:#ecf0f1;box-shadow:none;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #ecf0f1 #ecf0f1 !important}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-dark,html.theme--documenter-dark .content kbd.button{background-color:#282f2f;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark:hover,html.theme--documenter-dark .content kbd.button:hover,html.theme--documenter-dark .button.is-dark.is-hovered,html.theme--documenter-dark .content kbd.button.is-hovered{background-color:#232829;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark:focus,html.theme--documenter-dark .content kbd.button:focus,html.theme--documenter-dark .button.is-dark.is-focused,html.theme--documenter-dark .content kbd.button.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark:focus:not(:active),html.theme--documenter-dark .content kbd.button:focus:not(:active),html.theme--documenter-dark .button.is-dark.is-focused:not(:active),html.theme--documenter-dark .content kbd.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(40,47,47,0.25)}html.theme--documenter-dark .button.is-dark:active,html.theme--documenter-dark .content kbd.button:active,html.theme--documenter-dark .button.is-dark.is-active,html.theme--documenter-dark .content kbd.button.is-active{background-color:#1d2122;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark[disabled],html.theme--documenter-dark .content kbd.button[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark,fieldset[disabled] html.theme--documenter-dark .content kbd.button{background-color:#282f2f;border-color:#282f2f;box-shadow:none}html.theme--documenter-dark .button.is-dark.is-inverted,html.theme--documenter-dark .content kbd.button.is-inverted{background-color:#fff;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-inverted:hover,html.theme--documenter-dark .content kbd.button.is-inverted:hover,html.theme--documenter-dark .button.is-dark.is-inverted.is-hovered,html.theme--documenter-dark .content kbd.button.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-dark.is-inverted[disabled],html.theme--documenter-dark .content kbd.button.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-inverted,fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-loading::after,html.theme--documenter-dark .content kbd.button.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-dark.is-outlined,html.theme--documenter-dark .content kbd.button.is-outlined{background-color:transparent;border-color:#282f2f;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-outlined:hover,html.theme--documenter-dark .content kbd.button.is-outlined:hover,html.theme--documenter-dark .button.is-dark.is-outlined.is-hovered,html.theme--documenter-dark .content kbd.button.is-outlined.is-hovered,html.theme--documenter-dark .button.is-dark.is-outlined:focus,html.theme--documenter-dark .content kbd.button.is-outlined:focus,html.theme--documenter-dark .button.is-dark.is-outlined.is-focused,html.theme--documenter-dark .content kbd.button.is-outlined.is-focused{background-color:#282f2f;border-color:#282f2f;color:#fff}html.theme--documenter-dark .button.is-dark.is-outlined.is-loading::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading::after{border-color:transparent transparent #282f2f #282f2f !important}html.theme--documenter-dark .button.is-dark.is-outlined.is-loading:hover::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-dark.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-dark.is-outlined.is-loading:focus::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-dark.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-dark.is-outlined[disabled],html.theme--documenter-dark .content kbd.button.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-outlined,fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-outlined{background-color:transparent;border-color:#282f2f;box-shadow:none;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined:hover,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined:focus,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-focused,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-focused{background-color:#fff;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #282f2f #282f2f !important}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined[disabled],html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined,fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-primary,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink{background-color:#375a7f;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary:hover,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-hovered.docs-sourcelink{background-color:#335476;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary:focus,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:focus,html.theme--documenter-dark .button.is-primary.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-focused.docs-sourcelink{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary:focus:not(:active),html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:focus:not(:active),html.theme--documenter-dark .button.is-primary.is-focused:not(:active),html.theme--documenter-dark .docstring>section>a.button.is-focused.docs-sourcelink:not(:active){box-shadow:0 0 0 0.125em rgba(55,90,127,0.25)}html.theme--documenter-dark .button.is-primary:active,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:active,html.theme--documenter-dark .button.is-primary.is-active,html.theme--documenter-dark .docstring>section>a.button.is-active.docs-sourcelink{background-color:#2f4d6d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary[disabled],html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink{background-color:#375a7f;border-color:#375a7f;box-shadow:none}html.theme--documenter-dark .button.is-primary.is-inverted,html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-inverted:hover,html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-inverted.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-hovered.docs-sourcelink{background-color:#f2f2f2}html.theme--documenter-dark .button.is-primary.is-inverted[disabled],html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-inverted,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;border-color:transparent;box-shadow:none;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-loading::after,html.theme--documenter-dark .docstring>section>a.button.is-loading.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-primary.is-outlined,html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#375a7f;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-outlined:hover,html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-outlined.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-hovered.docs-sourcelink,html.theme--documenter-dark .button.is-primary.is-outlined:focus,html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink:focus,html.theme--documenter-dark .button.is-primary.is-outlined.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-focused.docs-sourcelink{background-color:#375a7f;border-color:#375a7f;color:#fff}html.theme--documenter-dark .button.is-primary.is-outlined.is-loading::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink::after{border-color:transparent transparent #375a7f #375a7f !important}html.theme--documenter-dark .button.is-primary.is-outlined.is-loading:hover::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--documenter-dark .button.is-primary.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--documenter-dark .button.is-primary.is-outlined.is-loading:focus::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--documenter-dark .button.is-primary.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-primary.is-outlined[disabled],html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-outlined,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#375a7f;box-shadow:none;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined:hover,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-hovered.docs-sourcelink,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined:focus,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:focus,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-focused.docs-sourcelink{background-color:#fff;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #375a7f #375a7f !important}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined[disabled],html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-primary.is-light,html.theme--documenter-dark .docstring>section>a.button.is-light.docs-sourcelink{background-color:#f1f5f9;color:#4d7eb2}html.theme--documenter-dark .button.is-primary.is-light:hover,html.theme--documenter-dark .docstring>section>a.button.is-light.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-light.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-light.is-hovered.docs-sourcelink{background-color:#e8eef5;border-color:transparent;color:#4d7eb2}html.theme--documenter-dark .button.is-primary.is-light:active,html.theme--documenter-dark .docstring>section>a.button.is-light.docs-sourcelink:active,html.theme--documenter-dark .button.is-primary.is-light.is-active,html.theme--documenter-dark .docstring>section>a.button.is-light.is-active.docs-sourcelink{background-color:#dfe8f1;border-color:transparent;color:#4d7eb2}html.theme--documenter-dark .button.is-link{background-color:#1abc9c;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link:hover,html.theme--documenter-dark .button.is-link.is-hovered{background-color:#18b193;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link:focus,html.theme--documenter-dark .button.is-link.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link:focus:not(:active),html.theme--documenter-dark .button.is-link.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .button.is-link:active,html.theme--documenter-dark .button.is-link.is-active{background-color:#17a689;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link{background-color:#1abc9c;border-color:#1abc9c;box-shadow:none}html.theme--documenter-dark .button.is-link.is-inverted{background-color:#fff;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-inverted:hover,html.theme--documenter-dark .button.is-link.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-link.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-link.is-outlined{background-color:transparent;border-color:#1abc9c;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-outlined:hover,html.theme--documenter-dark .button.is-link.is-outlined.is-hovered,html.theme--documenter-dark .button.is-link.is-outlined:focus,html.theme--documenter-dark .button.is-link.is-outlined.is-focused{background-color:#1abc9c;border-color:#1abc9c;color:#fff}html.theme--documenter-dark .button.is-link.is-outlined.is-loading::after{border-color:transparent transparent #1abc9c #1abc9c !important}html.theme--documenter-dark .button.is-link.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-link.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-link.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-link.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-link.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link.is-outlined{background-color:transparent;border-color:#1abc9c;box-shadow:none;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-focused{background-color:#fff;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #1abc9c #1abc9c !important}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-link.is-light{background-color:#edfdf9;color:#15987e}html.theme--documenter-dark .button.is-link.is-light:hover,html.theme--documenter-dark .button.is-link.is-light.is-hovered{background-color:#e2fbf6;border-color:transparent;color:#15987e}html.theme--documenter-dark .button.is-link.is-light:active,html.theme--documenter-dark .button.is-link.is-light.is-active{background-color:#d7f9f3;border-color:transparent;color:#15987e}html.theme--documenter-dark .button.is-info{background-color:#3c5dcd;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info:hover,html.theme--documenter-dark .button.is-info.is-hovered{background-color:#3355c9;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info:focus,html.theme--documenter-dark .button.is-info.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info:focus:not(:active),html.theme--documenter-dark .button.is-info.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(60,93,205,0.25)}html.theme--documenter-dark .button.is-info:active,html.theme--documenter-dark .button.is-info.is-active{background-color:#3151bf;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info{background-color:#3c5dcd;border-color:#3c5dcd;box-shadow:none}html.theme--documenter-dark .button.is-info.is-inverted{background-color:#fff;color:#3c5dcd}html.theme--documenter-dark .button.is-info.is-inverted:hover,html.theme--documenter-dark .button.is-info.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-info.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#3c5dcd}html.theme--documenter-dark .button.is-info.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-info.is-outlined{background-color:transparent;border-color:#3c5dcd;color:#3c5dcd}html.theme--documenter-dark .button.is-info.is-outlined:hover,html.theme--documenter-dark .button.is-info.is-outlined.is-hovered,html.theme--documenter-dark .button.is-info.is-outlined:focus,html.theme--documenter-dark .button.is-info.is-outlined.is-focused{background-color:#3c5dcd;border-color:#3c5dcd;color:#fff}html.theme--documenter-dark .button.is-info.is-outlined.is-loading::after{border-color:transparent transparent #3c5dcd #3c5dcd !important}html.theme--documenter-dark .button.is-info.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-info.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-info.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-info.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-info.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info.is-outlined{background-color:transparent;border-color:#3c5dcd;box-shadow:none;color:#3c5dcd}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-focused{background-color:#fff;color:#3c5dcd}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #3c5dcd #3c5dcd !important}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-info.is-light{background-color:#eff2fb;color:#3253c3}html.theme--documenter-dark .button.is-info.is-light:hover,html.theme--documenter-dark .button.is-info.is-light.is-hovered{background-color:#e5e9f8;border-color:transparent;color:#3253c3}html.theme--documenter-dark .button.is-info.is-light:active,html.theme--documenter-dark .button.is-info.is-light.is-active{background-color:#dae1f6;border-color:transparent;color:#3253c3}html.theme--documenter-dark .button.is-success{background-color:#259a12;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success:hover,html.theme--documenter-dark .button.is-success.is-hovered{background-color:#228f11;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success:focus,html.theme--documenter-dark .button.is-success.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success:focus:not(:active),html.theme--documenter-dark .button.is-success.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(37,154,18,0.25)}html.theme--documenter-dark .button.is-success:active,html.theme--documenter-dark .button.is-success.is-active{background-color:#20830f;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success{background-color:#259a12;border-color:#259a12;box-shadow:none}html.theme--documenter-dark .button.is-success.is-inverted{background-color:#fff;color:#259a12}html.theme--documenter-dark .button.is-success.is-inverted:hover,html.theme--documenter-dark .button.is-success.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-success.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#259a12}html.theme--documenter-dark .button.is-success.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-success.is-outlined{background-color:transparent;border-color:#259a12;color:#259a12}html.theme--documenter-dark .button.is-success.is-outlined:hover,html.theme--documenter-dark .button.is-success.is-outlined.is-hovered,html.theme--documenter-dark .button.is-success.is-outlined:focus,html.theme--documenter-dark .button.is-success.is-outlined.is-focused{background-color:#259a12;border-color:#259a12;color:#fff}html.theme--documenter-dark .button.is-success.is-outlined.is-loading::after{border-color:transparent transparent #259a12 #259a12 !important}html.theme--documenter-dark .button.is-success.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-success.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-success.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-success.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-success.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success.is-outlined{background-color:transparent;border-color:#259a12;box-shadow:none;color:#259a12}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-focused{background-color:#fff;color:#259a12}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #259a12 #259a12 !important}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-success.is-light{background-color:#effded;color:#2ec016}html.theme--documenter-dark .button.is-success.is-light:hover,html.theme--documenter-dark .button.is-success.is-light.is-hovered{background-color:#e5fce1;border-color:transparent;color:#2ec016}html.theme--documenter-dark .button.is-success.is-light:active,html.theme--documenter-dark .button.is-success.is-light.is-active{background-color:#dbfad6;border-color:transparent;color:#2ec016}html.theme--documenter-dark .button.is-warning{background-color:#f4c72f;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-warning:hover,html.theme--documenter-dark .button.is-warning.is-hovered{background-color:#f3c423;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-warning:focus,html.theme--documenter-dark .button.is-warning.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-warning:focus:not(:active),html.theme--documenter-dark .button.is-warning.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(244,199,47,0.25)}html.theme--documenter-dark .button.is-warning:active,html.theme--documenter-dark .button.is-warning.is-active{background-color:#f3c017;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-warning[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning{background-color:#f4c72f;border-color:#f4c72f;box-shadow:none}html.theme--documenter-dark .button.is-warning.is-inverted{background-color:rgba(0,0,0,0.7);color:#f4c72f}html.theme--documenter-dark .button.is-warning.is-inverted:hover,html.theme--documenter-dark .button.is-warning.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-warning.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#f4c72f}html.theme--documenter-dark .button.is-warning.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--documenter-dark .button.is-warning.is-outlined{background-color:transparent;border-color:#f4c72f;color:#f4c72f}html.theme--documenter-dark .button.is-warning.is-outlined:hover,html.theme--documenter-dark .button.is-warning.is-outlined.is-hovered,html.theme--documenter-dark .button.is-warning.is-outlined:focus,html.theme--documenter-dark .button.is-warning.is-outlined.is-focused{background-color:#f4c72f;border-color:#f4c72f;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-warning.is-outlined.is-loading::after{border-color:transparent transparent #f4c72f #f4c72f !important}html.theme--documenter-dark .button.is-warning.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-warning.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-warning.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-warning.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--documenter-dark .button.is-warning.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-outlined{background-color:transparent;border-color:#f4c72f;box-shadow:none;color:#f4c72f}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#f4c72f}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #f4c72f #f4c72f !important}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-warning.is-light{background-color:#fefaec;color:#8c6e07}html.theme--documenter-dark .button.is-warning.is-light:hover,html.theme--documenter-dark .button.is-warning.is-light.is-hovered{background-color:#fdf7e0;border-color:transparent;color:#8c6e07}html.theme--documenter-dark .button.is-warning.is-light:active,html.theme--documenter-dark .button.is-warning.is-light.is-active{background-color:#fdf3d3;border-color:transparent;color:#8c6e07}html.theme--documenter-dark .button.is-danger{background-color:#cb3c33;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger:hover,html.theme--documenter-dark .button.is-danger.is-hovered{background-color:#c13930;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger:focus,html.theme--documenter-dark .button.is-danger.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger:focus:not(:active),html.theme--documenter-dark .button.is-danger.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(203,60,51,0.25)}html.theme--documenter-dark .button.is-danger:active,html.theme--documenter-dark .button.is-danger.is-active{background-color:#b7362e;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger{background-color:#cb3c33;border-color:#cb3c33;box-shadow:none}html.theme--documenter-dark .button.is-danger.is-inverted{background-color:#fff;color:#cb3c33}html.theme--documenter-dark .button.is-danger.is-inverted:hover,html.theme--documenter-dark .button.is-danger.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-danger.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#cb3c33}html.theme--documenter-dark .button.is-danger.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-danger.is-outlined{background-color:transparent;border-color:#cb3c33;color:#cb3c33}html.theme--documenter-dark .button.is-danger.is-outlined:hover,html.theme--documenter-dark .button.is-danger.is-outlined.is-hovered,html.theme--documenter-dark .button.is-danger.is-outlined:focus,html.theme--documenter-dark .button.is-danger.is-outlined.is-focused{background-color:#cb3c33;border-color:#cb3c33;color:#fff}html.theme--documenter-dark .button.is-danger.is-outlined.is-loading::after{border-color:transparent transparent #cb3c33 #cb3c33 !important}html.theme--documenter-dark .button.is-danger.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-danger.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-danger.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-danger.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-danger.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-outlined{background-color:transparent;border-color:#cb3c33;box-shadow:none;color:#cb3c33}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-focused{background-color:#fff;color:#cb3c33}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #cb3c33 #cb3c33 !important}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-danger.is-light{background-color:#fbefef;color:#c03930}html.theme--documenter-dark .button.is-danger.is-light:hover,html.theme--documenter-dark .button.is-danger.is-light.is-hovered{background-color:#f8e6e5;border-color:transparent;color:#c03930}html.theme--documenter-dark .button.is-danger.is-light:active,html.theme--documenter-dark .button.is-danger.is-light.is-active{background-color:#f6dcda;border-color:transparent;color:#c03930}html.theme--documenter-dark .button.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.button{font-size:.75rem}html.theme--documenter-dark .button.is-small:not(.is-rounded),html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.button:not(.is-rounded){border-radius:3px}html.theme--documenter-dark .button.is-normal{font-size:1rem}html.theme--documenter-dark .button.is-medium{font-size:1.25rem}html.theme--documenter-dark .button.is-large{font-size:1.5rem}html.theme--documenter-dark .button[disabled],fieldset[disabled] html.theme--documenter-dark .button{background-color:#8c9b9d;border-color:#5e6d6f;box-shadow:none;opacity:.5}html.theme--documenter-dark .button.is-fullwidth{display:flex;width:100%}html.theme--documenter-dark .button.is-loading{color:transparent !important;pointer-events:none}html.theme--documenter-dark .button.is-loading::after{position:absolute;left:calc(50% - (1em * 0.5));top:calc(50% - (1em * 0.5));position:absolute !important}html.theme--documenter-dark .button.is-static{background-color:#282f2f;border-color:#5e6d6f;color:#dbdee0;box-shadow:none;pointer-events:none}html.theme--documenter-dark .button.is-rounded,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.button{border-radius:9999px;padding-left:calc(1em + 0.25em);padding-right:calc(1em + 0.25em)}html.theme--documenter-dark .buttons{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--documenter-dark .buttons .button{margin-bottom:0.5rem}html.theme--documenter-dark .buttons .button:not(:last-child):not(.is-fullwidth){margin-right:.5rem}html.theme--documenter-dark .buttons:last-child{margin-bottom:-0.5rem}html.theme--documenter-dark .buttons:not(:last-child){margin-bottom:1rem}html.theme--documenter-dark .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large){font-size:.75rem}html.theme--documenter-dark .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large):not(.is-rounded){border-radius:3px}html.theme--documenter-dark .buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large){font-size:1.25rem}html.theme--documenter-dark .buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium){font-size:1.5rem}html.theme--documenter-dark .buttons.has-addons .button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}html.theme--documenter-dark .buttons.has-addons .button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}html.theme--documenter-dark .buttons.has-addons .button:last-child{margin-right:0}html.theme--documenter-dark .buttons.has-addons .button:hover,html.theme--documenter-dark .buttons.has-addons .button.is-hovered{z-index:2}html.theme--documenter-dark .buttons.has-addons .button:focus,html.theme--documenter-dark .buttons.has-addons .button.is-focused,html.theme--documenter-dark .buttons.has-addons .button:active,html.theme--documenter-dark .buttons.has-addons .button.is-active,html.theme--documenter-dark .buttons.has-addons .button.is-selected{z-index:3}html.theme--documenter-dark .buttons.has-addons .button:focus:hover,html.theme--documenter-dark .buttons.has-addons .button.is-focused:hover,html.theme--documenter-dark .buttons.has-addons .button:active:hover,html.theme--documenter-dark .buttons.has-addons .button.is-active:hover,html.theme--documenter-dark .buttons.has-addons .button.is-selected:hover{z-index:4}html.theme--documenter-dark .buttons.has-addons .button.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .buttons.is-centered{justify-content:center}html.theme--documenter-dark .buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}html.theme--documenter-dark .buttons.is-right{justify-content:flex-end}html.theme--documenter-dark .buttons.is-right:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}@media screen and (max-width: 768px){html.theme--documenter-dark .button.is-responsive.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.5625rem}html.theme--documenter-dark .button.is-responsive,html.theme--documenter-dark .button.is-responsive.is-normal{font-size:.65625rem}html.theme--documenter-dark .button.is-responsive.is-medium{font-size:.75rem}html.theme--documenter-dark .button.is-responsive.is-large{font-size:1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .button.is-responsive.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.65625rem}html.theme--documenter-dark .button.is-responsive,html.theme--documenter-dark .button.is-responsive.is-normal{font-size:.75rem}html.theme--documenter-dark .button.is-responsive.is-medium{font-size:1rem}html.theme--documenter-dark .button.is-responsive.is-large{font-size:1.25rem}}html.theme--documenter-dark .container{flex-grow:1;margin:0 auto;position:relative;width:auto}html.theme--documenter-dark .container.is-fluid{max-width:none !important;padding-left:32px;padding-right:32px;width:100%}@media screen and (min-width: 1056px){html.theme--documenter-dark .container{max-width:992px}}@media screen and (max-width: 1215px){html.theme--documenter-dark .container.is-widescreen:not(.is-max-desktop){max-width:1152px}}@media screen and (max-width: 1407px){html.theme--documenter-dark .container.is-fullhd:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}@media screen and (min-width: 1216px){html.theme--documenter-dark .container:not(.is-max-desktop){max-width:1152px}}@media screen and (min-width: 1408px){html.theme--documenter-dark .container:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}html.theme--documenter-dark .content li+li{margin-top:0.25em}html.theme--documenter-dark .content p:not(:last-child),html.theme--documenter-dark .content dl:not(:last-child),html.theme--documenter-dark .content ol:not(:last-child),html.theme--documenter-dark .content ul:not(:last-child),html.theme--documenter-dark .content blockquote:not(:last-child),html.theme--documenter-dark .content pre:not(:last-child),html.theme--documenter-dark .content table:not(:last-child){margin-bottom:1em}html.theme--documenter-dark .content h1,html.theme--documenter-dark .content h2,html.theme--documenter-dark .content h3,html.theme--documenter-dark .content h4,html.theme--documenter-dark .content h5,html.theme--documenter-dark .content h6{color:#f2f2f2;font-weight:600;line-height:1.125}html.theme--documenter-dark .content h1{font-size:2em;margin-bottom:0.5em}html.theme--documenter-dark .content h1:not(:first-child){margin-top:1em}html.theme--documenter-dark .content h2{font-size:1.75em;margin-bottom:0.5714em}html.theme--documenter-dark .content h2:not(:first-child){margin-top:1.1428em}html.theme--documenter-dark .content h3{font-size:1.5em;margin-bottom:0.6666em}html.theme--documenter-dark .content h3:not(:first-child){margin-top:1.3333em}html.theme--documenter-dark .content h4{font-size:1.25em;margin-bottom:0.8em}html.theme--documenter-dark .content h5{font-size:1.125em;margin-bottom:0.8888em}html.theme--documenter-dark .content h6{font-size:1em;margin-bottom:1em}html.theme--documenter-dark .content blockquote{background-color:#282f2f;border-left:5px solid #5e6d6f;padding:1.25em 1.5em}html.theme--documenter-dark .content ol{list-style-position:outside;margin-left:2em;margin-top:1em}html.theme--documenter-dark .content ol:not([type]){list-style-type:decimal}html.theme--documenter-dark .content ol.is-lower-alpha:not([type]){list-style-type:lower-alpha}html.theme--documenter-dark .content ol.is-lower-roman:not([type]){list-style-type:lower-roman}html.theme--documenter-dark .content ol.is-upper-alpha:not([type]){list-style-type:upper-alpha}html.theme--documenter-dark .content ol.is-upper-roman:not([type]){list-style-type:upper-roman}html.theme--documenter-dark .content ul{list-style:disc outside;margin-left:2em;margin-top:1em}html.theme--documenter-dark .content ul ul{list-style-type:circle;margin-top:0.5em}html.theme--documenter-dark .content ul ul ul{list-style-type:square}html.theme--documenter-dark .content dd{margin-left:2em}html.theme--documenter-dark .content figure{margin-left:2em;margin-right:2em;text-align:center}html.theme--documenter-dark .content figure:not(:first-child){margin-top:2em}html.theme--documenter-dark .content figure:not(:last-child){margin-bottom:2em}html.theme--documenter-dark .content figure img{display:inline-block}html.theme--documenter-dark .content figure figcaption{font-style:italic}html.theme--documenter-dark .content pre{-webkit-overflow-scrolling:touch;overflow-x:auto;padding:0;white-space:pre;word-wrap:normal}html.theme--documenter-dark .content sup,html.theme--documenter-dark .content sub{font-size:75%}html.theme--documenter-dark .content table{width:100%}html.theme--documenter-dark .content table td,html.theme--documenter-dark .content table th{border:1px solid #5e6d6f;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--documenter-dark .content table th{color:#f2f2f2}html.theme--documenter-dark .content table th:not([align]){text-align:inherit}html.theme--documenter-dark .content table thead td,html.theme--documenter-dark .content table thead th{border-width:0 0 2px;color:#f2f2f2}html.theme--documenter-dark .content table tfoot td,html.theme--documenter-dark .content table tfoot th{border-width:2px 0 0;color:#f2f2f2}html.theme--documenter-dark .content table tbody tr:last-child td,html.theme--documenter-dark .content table tbody tr:last-child th{border-bottom-width:0}html.theme--documenter-dark .content .tabs li+li{margin-top:0}html.theme--documenter-dark .content.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.content{font-size:.75rem}html.theme--documenter-dark .content.is-normal{font-size:1rem}html.theme--documenter-dark .content.is-medium{font-size:1.25rem}html.theme--documenter-dark .content.is-large{font-size:1.5rem}html.theme--documenter-dark .icon{align-items:center;display:inline-flex;justify-content:center;height:1.5rem;width:1.5rem}html.theme--documenter-dark .icon.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.icon{height:1rem;width:1rem}html.theme--documenter-dark .icon.is-medium{height:2rem;width:2rem}html.theme--documenter-dark .icon.is-large{height:3rem;width:3rem}html.theme--documenter-dark .icon-text{align-items:flex-start;color:inherit;display:inline-flex;flex-wrap:wrap;line-height:1.5rem;vertical-align:top}html.theme--documenter-dark .icon-text .icon{flex-grow:0;flex-shrink:0}html.theme--documenter-dark .icon-text .icon:not(:last-child){margin-right:.25em}html.theme--documenter-dark .icon-text .icon:not(:first-child){margin-left:.25em}html.theme--documenter-dark div.icon-text{display:flex}html.theme--documenter-dark .image,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img{display:block;position:relative}html.theme--documenter-dark .image img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img img{display:block;height:auto;width:100%}html.theme--documenter-dark .image img.is-rounded,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img img.is-rounded{border-radius:9999px}html.theme--documenter-dark .image.is-fullwidth,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-fullwidth{width:100%}html.theme--documenter-dark .image.is-square img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--documenter-dark .image.is-square .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--documenter-dark .image.is-1by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--documenter-dark .image.is-1by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--documenter-dark .image.is-5by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--documenter-dark .image.is-5by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--documenter-dark .image.is-4by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--documenter-dark .image.is-4by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--documenter-dark .image.is-3by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--documenter-dark .image.is-3by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--documenter-dark .image.is-5by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--documenter-dark .image.is-5by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--documenter-dark .image.is-16by9 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--documenter-dark .image.is-16by9 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--documenter-dark .image.is-2by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--documenter-dark .image.is-2by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--documenter-dark .image.is-3by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--documenter-dark .image.is-3by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--documenter-dark .image.is-4by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--documenter-dark .image.is-4by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--documenter-dark .image.is-3by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--documenter-dark .image.is-3by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--documenter-dark .image.is-2by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--documenter-dark .image.is-2by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--documenter-dark .image.is-3by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--documenter-dark .image.is-3by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--documenter-dark .image.is-9by16 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--documenter-dark .image.is-9by16 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--documenter-dark .image.is-1by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--documenter-dark .image.is-1by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--documenter-dark .image.is-1by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--documenter-dark .image.is-1by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio{height:100%;width:100%}html.theme--documenter-dark .image.is-square,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square,html.theme--documenter-dark .image.is-1by1,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1{padding-top:100%}html.theme--documenter-dark .image.is-5by4,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4{padding-top:80%}html.theme--documenter-dark .image.is-4by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3{padding-top:75%}html.theme--documenter-dark .image.is-3by2,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2{padding-top:66.6666%}html.theme--documenter-dark .image.is-5by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3{padding-top:60%}html.theme--documenter-dark .image.is-16by9,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9{padding-top:56.25%}html.theme--documenter-dark .image.is-2by1,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1{padding-top:50%}html.theme--documenter-dark .image.is-3by1,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1{padding-top:33.3333%}html.theme--documenter-dark .image.is-4by5,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5{padding-top:125%}html.theme--documenter-dark .image.is-3by4,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4{padding-top:133.3333%}html.theme--documenter-dark .image.is-2by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3{padding-top:150%}html.theme--documenter-dark .image.is-3by5,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5{padding-top:166.6666%}html.theme--documenter-dark .image.is-9by16,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16{padding-top:177.7777%}html.theme--documenter-dark .image.is-1by2,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2{padding-top:200%}html.theme--documenter-dark .image.is-1by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3{padding-top:300%}html.theme--documenter-dark .image.is-16x16,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16x16{height:16px;width:16px}html.theme--documenter-dark .image.is-24x24,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-24x24{height:24px;width:24px}html.theme--documenter-dark .image.is-32x32,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-32x32{height:32px;width:32px}html.theme--documenter-dark .image.is-48x48,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-48x48{height:48px;width:48px}html.theme--documenter-dark .image.is-64x64,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-64x64{height:64px;width:64px}html.theme--documenter-dark .image.is-96x96,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-96x96{height:96px;width:96px}html.theme--documenter-dark .image.is-128x128,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-128x128{height:128px;width:128px}html.theme--documenter-dark .notification{background-color:#282f2f;border-radius:.4em;position:relative;padding:1.25rem 2.5rem 1.25rem 1.5rem}html.theme--documenter-dark .notification a:not(.button):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--documenter-dark .notification strong{color:currentColor}html.theme--documenter-dark .notification code,html.theme--documenter-dark .notification pre{background:#fff}html.theme--documenter-dark .notification pre code{background:transparent}html.theme--documenter-dark .notification>.delete{right:.5rem;position:absolute;top:0.5rem}html.theme--documenter-dark .notification .title,html.theme--documenter-dark .notification .subtitle,html.theme--documenter-dark .notification .content{color:currentColor}html.theme--documenter-dark .notification.is-white{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .notification.is-black{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .notification.is-light{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .notification.is-dark,html.theme--documenter-dark .content kbd.notification{background-color:#282f2f;color:#fff}html.theme--documenter-dark .notification.is-primary,html.theme--documenter-dark .docstring>section>a.notification.docs-sourcelink{background-color:#375a7f;color:#fff}html.theme--documenter-dark .notification.is-primary.is-light,html.theme--documenter-dark .docstring>section>a.notification.is-light.docs-sourcelink{background-color:#f1f5f9;color:#4d7eb2}html.theme--documenter-dark .notification.is-link{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .notification.is-link.is-light{background-color:#edfdf9;color:#15987e}html.theme--documenter-dark .notification.is-info{background-color:#3c5dcd;color:#fff}html.theme--documenter-dark .notification.is-info.is-light{background-color:#eff2fb;color:#3253c3}html.theme--documenter-dark .notification.is-success{background-color:#259a12;color:#fff}html.theme--documenter-dark .notification.is-success.is-light{background-color:#effded;color:#2ec016}html.theme--documenter-dark .notification.is-warning{background-color:#f4c72f;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .notification.is-warning.is-light{background-color:#fefaec;color:#8c6e07}html.theme--documenter-dark .notification.is-danger{background-color:#cb3c33;color:#fff}html.theme--documenter-dark .notification.is-danger.is-light{background-color:#fbefef;color:#c03930}html.theme--documenter-dark .progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:9999px;display:block;height:1rem;overflow:hidden;padding:0;width:100%}html.theme--documenter-dark .progress::-webkit-progress-bar{background-color:#343c3d}html.theme--documenter-dark .progress::-webkit-progress-value{background-color:#dbdee0}html.theme--documenter-dark .progress::-moz-progress-bar{background-color:#dbdee0}html.theme--documenter-dark .progress::-ms-fill{background-color:#dbdee0;border:none}html.theme--documenter-dark .progress.is-white::-webkit-progress-value{background-color:#fff}html.theme--documenter-dark .progress.is-white::-moz-progress-bar{background-color:#fff}html.theme--documenter-dark .progress.is-white::-ms-fill{background-color:#fff}html.theme--documenter-dark .progress.is-white:indeterminate{background-image:linear-gradient(to right, #fff 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-black::-webkit-progress-value{background-color:#0a0a0a}html.theme--documenter-dark .progress.is-black::-moz-progress-bar{background-color:#0a0a0a}html.theme--documenter-dark .progress.is-black::-ms-fill{background-color:#0a0a0a}html.theme--documenter-dark .progress.is-black:indeterminate{background-image:linear-gradient(to right, #0a0a0a 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-light::-webkit-progress-value{background-color:#ecf0f1}html.theme--documenter-dark .progress.is-light::-moz-progress-bar{background-color:#ecf0f1}html.theme--documenter-dark .progress.is-light::-ms-fill{background-color:#ecf0f1}html.theme--documenter-dark .progress.is-light:indeterminate{background-image:linear-gradient(to right, #ecf0f1 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-dark::-webkit-progress-value,html.theme--documenter-dark .content kbd.progress::-webkit-progress-value{background-color:#282f2f}html.theme--documenter-dark .progress.is-dark::-moz-progress-bar,html.theme--documenter-dark .content kbd.progress::-moz-progress-bar{background-color:#282f2f}html.theme--documenter-dark .progress.is-dark::-ms-fill,html.theme--documenter-dark .content kbd.progress::-ms-fill{background-color:#282f2f}html.theme--documenter-dark .progress.is-dark:indeterminate,html.theme--documenter-dark .content kbd.progress:indeterminate{background-image:linear-gradient(to right, #282f2f 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-primary::-webkit-progress-value,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink::-webkit-progress-value{background-color:#375a7f}html.theme--documenter-dark .progress.is-primary::-moz-progress-bar,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink::-moz-progress-bar{background-color:#375a7f}html.theme--documenter-dark .progress.is-primary::-ms-fill,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink::-ms-fill{background-color:#375a7f}html.theme--documenter-dark .progress.is-primary:indeterminate,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink:indeterminate{background-image:linear-gradient(to right, #375a7f 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-link::-webkit-progress-value{background-color:#1abc9c}html.theme--documenter-dark .progress.is-link::-moz-progress-bar{background-color:#1abc9c}html.theme--documenter-dark .progress.is-link::-ms-fill{background-color:#1abc9c}html.theme--documenter-dark .progress.is-link:indeterminate{background-image:linear-gradient(to right, #1abc9c 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-info::-webkit-progress-value{background-color:#3c5dcd}html.theme--documenter-dark .progress.is-info::-moz-progress-bar{background-color:#3c5dcd}html.theme--documenter-dark .progress.is-info::-ms-fill{background-color:#3c5dcd}html.theme--documenter-dark .progress.is-info:indeterminate{background-image:linear-gradient(to right, #3c5dcd 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-success::-webkit-progress-value{background-color:#259a12}html.theme--documenter-dark .progress.is-success::-moz-progress-bar{background-color:#259a12}html.theme--documenter-dark .progress.is-success::-ms-fill{background-color:#259a12}html.theme--documenter-dark .progress.is-success:indeterminate{background-image:linear-gradient(to right, #259a12 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-warning::-webkit-progress-value{background-color:#f4c72f}html.theme--documenter-dark .progress.is-warning::-moz-progress-bar{background-color:#f4c72f}html.theme--documenter-dark .progress.is-warning::-ms-fill{background-color:#f4c72f}html.theme--documenter-dark .progress.is-warning:indeterminate{background-image:linear-gradient(to right, #f4c72f 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-danger::-webkit-progress-value{background-color:#cb3c33}html.theme--documenter-dark .progress.is-danger::-moz-progress-bar{background-color:#cb3c33}html.theme--documenter-dark .progress.is-danger::-ms-fill{background-color:#cb3c33}html.theme--documenter-dark .progress.is-danger:indeterminate{background-image:linear-gradient(to right, #cb3c33 30%, #343c3d 30%)}html.theme--documenter-dark .progress:indeterminate{animation-duration:1.5s;animation-iteration-count:infinite;animation-name:moveIndeterminate;animation-timing-function:linear;background-color:#343c3d;background-image:linear-gradient(to right, #fff 30%, #343c3d 30%);background-position:top left;background-repeat:no-repeat;background-size:150% 150%}html.theme--documenter-dark .progress:indeterminate::-webkit-progress-bar{background-color:transparent}html.theme--documenter-dark .progress:indeterminate::-moz-progress-bar{background-color:transparent}html.theme--documenter-dark .progress:indeterminate::-ms-fill{animation-name:none}html.theme--documenter-dark .progress.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.progress{height:.75rem}html.theme--documenter-dark .progress.is-medium{height:1.25rem}html.theme--documenter-dark .progress.is-large{height:1.5rem}@keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}html.theme--documenter-dark .table{background-color:#343c3d;color:#fff}html.theme--documenter-dark .table td,html.theme--documenter-dark .table th{border:1px solid #5e6d6f;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--documenter-dark .table td.is-white,html.theme--documenter-dark .table th.is-white{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--documenter-dark .table td.is-black,html.theme--documenter-dark .table th.is-black{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--documenter-dark .table td.is-light,html.theme--documenter-dark .table th.is-light{background-color:#ecf0f1;border-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .table td.is-dark,html.theme--documenter-dark .table th.is-dark{background-color:#282f2f;border-color:#282f2f;color:#fff}html.theme--documenter-dark .table td.is-primary,html.theme--documenter-dark .table th.is-primary{background-color:#375a7f;border-color:#375a7f;color:#fff}html.theme--documenter-dark .table td.is-link,html.theme--documenter-dark .table th.is-link{background-color:#1abc9c;border-color:#1abc9c;color:#fff}html.theme--documenter-dark .table td.is-info,html.theme--documenter-dark .table th.is-info{background-color:#3c5dcd;border-color:#3c5dcd;color:#fff}html.theme--documenter-dark .table td.is-success,html.theme--documenter-dark .table th.is-success{background-color:#259a12;border-color:#259a12;color:#fff}html.theme--documenter-dark .table td.is-warning,html.theme--documenter-dark .table th.is-warning{background-color:#f4c72f;border-color:#f4c72f;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .table td.is-danger,html.theme--documenter-dark .table th.is-danger{background-color:#cb3c33;border-color:#cb3c33;color:#fff}html.theme--documenter-dark .table td.is-narrow,html.theme--documenter-dark .table th.is-narrow{white-space:nowrap;width:1%}html.theme--documenter-dark .table td.is-selected,html.theme--documenter-dark .table th.is-selected{background-color:#375a7f;color:#fff}html.theme--documenter-dark .table td.is-selected a,html.theme--documenter-dark .table td.is-selected strong,html.theme--documenter-dark .table th.is-selected a,html.theme--documenter-dark .table th.is-selected strong{color:currentColor}html.theme--documenter-dark .table td.is-vcentered,html.theme--documenter-dark .table th.is-vcentered{vertical-align:middle}html.theme--documenter-dark .table th{color:#f2f2f2}html.theme--documenter-dark .table th:not([align]){text-align:left}html.theme--documenter-dark .table tr.is-selected{background-color:#375a7f;color:#fff}html.theme--documenter-dark .table tr.is-selected a,html.theme--documenter-dark .table tr.is-selected strong{color:currentColor}html.theme--documenter-dark .table tr.is-selected td,html.theme--documenter-dark .table tr.is-selected th{border-color:#fff;color:currentColor}html.theme--documenter-dark .table thead{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .table thead td,html.theme--documenter-dark .table thead th{border-width:0 0 2px;color:#f2f2f2}html.theme--documenter-dark .table tfoot{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .table tfoot td,html.theme--documenter-dark .table tfoot th{border-width:2px 0 0;color:#f2f2f2}html.theme--documenter-dark .table tbody{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .table tbody tr:last-child td,html.theme--documenter-dark .table tbody tr:last-child th{border-bottom-width:0}html.theme--documenter-dark .table.is-bordered td,html.theme--documenter-dark .table.is-bordered th{border-width:1px}html.theme--documenter-dark .table.is-bordered tr:last-child td,html.theme--documenter-dark .table.is-bordered tr:last-child th{border-bottom-width:1px}html.theme--documenter-dark .table.is-fullwidth{width:100%}html.theme--documenter-dark .table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#282f2f}html.theme--documenter-dark .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover{background-color:#282f2f}html.theme--documenter-dark .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even){background-color:#2d3435}html.theme--documenter-dark .table.is-narrow td,html.theme--documenter-dark .table.is-narrow th{padding:0.25em 0.5em}html.theme--documenter-dark .table.is-striped tbody tr:not(.is-selected):nth-child(even){background-color:#282f2f}html.theme--documenter-dark .table-container{-webkit-overflow-scrolling:touch;overflow:auto;overflow-y:hidden;max-width:100%}html.theme--documenter-dark .tags{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--documenter-dark .tags .tag,html.theme--documenter-dark .tags .content kbd,html.theme--documenter-dark .content .tags kbd,html.theme--documenter-dark .tags .docstring>section>a.docs-sourcelink{margin-bottom:0.5rem}html.theme--documenter-dark .tags .tag:not(:last-child),html.theme--documenter-dark .tags .content kbd:not(:last-child),html.theme--documenter-dark .content .tags kbd:not(:last-child),html.theme--documenter-dark .tags .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:.5rem}html.theme--documenter-dark .tags:last-child{margin-bottom:-0.5rem}html.theme--documenter-dark .tags:not(:last-child){margin-bottom:1rem}html.theme--documenter-dark .tags.are-medium .tag:not(.is-normal):not(.is-large),html.theme--documenter-dark .tags.are-medium .content kbd:not(.is-normal):not(.is-large),html.theme--documenter-dark .content .tags.are-medium kbd:not(.is-normal):not(.is-large),html.theme--documenter-dark .tags.are-medium .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-large){font-size:1rem}html.theme--documenter-dark .tags.are-large .tag:not(.is-normal):not(.is-medium),html.theme--documenter-dark .tags.are-large .content kbd:not(.is-normal):not(.is-medium),html.theme--documenter-dark .content .tags.are-large kbd:not(.is-normal):not(.is-medium),html.theme--documenter-dark .tags.are-large .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-medium){font-size:1.25rem}html.theme--documenter-dark .tags.is-centered{justify-content:center}html.theme--documenter-dark .tags.is-centered .tag,html.theme--documenter-dark .tags.is-centered .content kbd,html.theme--documenter-dark .content .tags.is-centered kbd,html.theme--documenter-dark .tags.is-centered .docstring>section>a.docs-sourcelink{margin-right:0.25rem;margin-left:0.25rem}html.theme--documenter-dark .tags.is-right{justify-content:flex-end}html.theme--documenter-dark .tags.is-right .tag:not(:first-child),html.theme--documenter-dark .tags.is-right .content kbd:not(:first-child),html.theme--documenter-dark .content .tags.is-right kbd:not(:first-child),html.theme--documenter-dark .tags.is-right .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0.5rem}html.theme--documenter-dark .tags.is-right .tag:not(:last-child),html.theme--documenter-dark .tags.is-right .content kbd:not(:last-child),html.theme--documenter-dark .content .tags.is-right kbd:not(:last-child),html.theme--documenter-dark .tags.is-right .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:0}html.theme--documenter-dark .tags.has-addons .tag,html.theme--documenter-dark .tags.has-addons .content kbd,html.theme--documenter-dark .content .tags.has-addons kbd,html.theme--documenter-dark .tags.has-addons .docstring>section>a.docs-sourcelink{margin-right:0}html.theme--documenter-dark .tags.has-addons .tag:not(:first-child),html.theme--documenter-dark .tags.has-addons .content kbd:not(:first-child),html.theme--documenter-dark .content .tags.has-addons kbd:not(:first-child),html.theme--documenter-dark .tags.has-addons .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0;border-top-left-radius:0;border-bottom-left-radius:0}html.theme--documenter-dark .tags.has-addons .tag:not(:last-child),html.theme--documenter-dark .tags.has-addons .content kbd:not(:last-child),html.theme--documenter-dark .content .tags.has-addons kbd:not(:last-child),html.theme--documenter-dark .tags.has-addons .docstring>section>a.docs-sourcelink:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}html.theme--documenter-dark .tag:not(body),html.theme--documenter-dark .content kbd:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body){align-items:center;background-color:#282f2f;border-radius:.4em;color:#fff;display:inline-flex;font-size:.75rem;height:2em;justify-content:center;line-height:1.5;padding-left:0.75em;padding-right:0.75em;white-space:nowrap}html.theme--documenter-dark .tag:not(body) .delete,html.theme--documenter-dark .content kbd:not(body) .delete,html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .delete{margin-left:.25rem;margin-right:-.375rem}html.theme--documenter-dark .tag.is-white:not(body),html.theme--documenter-dark .content kbd.is-white:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-white:not(body){background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .tag.is-black:not(body),html.theme--documenter-dark .content kbd.is-black:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-black:not(body){background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .tag.is-light:not(body),html.theme--documenter-dark .content kbd.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .tag.is-dark:not(body),html.theme--documenter-dark .content kbd:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-dark:not(body),html.theme--documenter-dark .content .docstring>section>kbd:not(body){background-color:#282f2f;color:#fff}html.theme--documenter-dark .tag.is-primary:not(body),html.theme--documenter-dark .content kbd.is-primary:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body){background-color:#375a7f;color:#fff}html.theme--documenter-dark .tag.is-primary.is-light:not(body),html.theme--documenter-dark .content kbd.is-primary.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#f1f5f9;color:#4d7eb2}html.theme--documenter-dark .tag.is-link:not(body),html.theme--documenter-dark .content kbd.is-link:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-link:not(body){background-color:#1abc9c;color:#fff}html.theme--documenter-dark .tag.is-link.is-light:not(body),html.theme--documenter-dark .content kbd.is-link.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-link.is-light:not(body){background-color:#edfdf9;color:#15987e}html.theme--documenter-dark .tag.is-info:not(body),html.theme--documenter-dark .content kbd.is-info:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-info:not(body){background-color:#3c5dcd;color:#fff}html.theme--documenter-dark .tag.is-info.is-light:not(body),html.theme--documenter-dark .content kbd.is-info.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-info.is-light:not(body){background-color:#eff2fb;color:#3253c3}html.theme--documenter-dark .tag.is-success:not(body),html.theme--documenter-dark .content kbd.is-success:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-success:not(body){background-color:#259a12;color:#fff}html.theme--documenter-dark .tag.is-success.is-light:not(body),html.theme--documenter-dark .content kbd.is-success.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-success.is-light:not(body){background-color:#effded;color:#2ec016}html.theme--documenter-dark .tag.is-warning:not(body),html.theme--documenter-dark .content kbd.is-warning:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-warning:not(body){background-color:#f4c72f;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .tag.is-warning.is-light:not(body),html.theme--documenter-dark .content kbd.is-warning.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-warning.is-light:not(body){background-color:#fefaec;color:#8c6e07}html.theme--documenter-dark .tag.is-danger:not(body),html.theme--documenter-dark .content kbd.is-danger:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-danger:not(body){background-color:#cb3c33;color:#fff}html.theme--documenter-dark .tag.is-danger.is-light:not(body),html.theme--documenter-dark .content kbd.is-danger.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-danger.is-light:not(body){background-color:#fbefef;color:#c03930}html.theme--documenter-dark .tag.is-normal:not(body),html.theme--documenter-dark .content kbd.is-normal:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-normal:not(body){font-size:.75rem}html.theme--documenter-dark .tag.is-medium:not(body),html.theme--documenter-dark .content kbd.is-medium:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-medium:not(body){font-size:1rem}html.theme--documenter-dark .tag.is-large:not(body),html.theme--documenter-dark .content kbd.is-large:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-large:not(body){font-size:1.25rem}html.theme--documenter-dark .tag:not(body) .icon:first-child:not(:last-child),html.theme--documenter-dark .content kbd:not(body) .icon:first-child:not(:last-child),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:not(:last-child){margin-left:-.375em;margin-right:.1875em}html.theme--documenter-dark .tag:not(body) .icon:last-child:not(:first-child),html.theme--documenter-dark .content kbd:not(body) .icon:last-child:not(:first-child),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .icon:last-child:not(:first-child){margin-left:.1875em;margin-right:-.375em}html.theme--documenter-dark .tag:not(body) .icon:first-child:last-child,html.theme--documenter-dark .content kbd:not(body) .icon:first-child:last-child,html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:last-child{margin-left:-.375em;margin-right:-.375em}html.theme--documenter-dark .tag.is-delete:not(body),html.theme--documenter-dark .content kbd.is-delete:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body){margin-left:1px;padding:0;position:relative;width:2em}html.theme--documenter-dark .tag.is-delete:not(body)::before,html.theme--documenter-dark .content kbd.is-delete:not(body)::before,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::before,html.theme--documenter-dark .tag.is-delete:not(body)::after,html.theme--documenter-dark .content kbd.is-delete:not(body)::after,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{background-color:currentColor;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--documenter-dark .tag.is-delete:not(body)::before,html.theme--documenter-dark .content kbd.is-delete:not(body)::before,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::before{height:1px;width:50%}html.theme--documenter-dark .tag.is-delete:not(body)::after,html.theme--documenter-dark .content kbd.is-delete:not(body)::after,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{height:50%;width:1px}html.theme--documenter-dark .tag.is-delete:not(body):hover,html.theme--documenter-dark .content kbd.is-delete:not(body):hover,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body):hover,html.theme--documenter-dark .tag.is-delete:not(body):focus,html.theme--documenter-dark .content kbd.is-delete:not(body):focus,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body):focus{background-color:#1d2122}html.theme--documenter-dark .tag.is-delete:not(body):active,html.theme--documenter-dark .content kbd.is-delete:not(body):active,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body):active{background-color:#111414}html.theme--documenter-dark .tag.is-rounded:not(body),html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:not(body),html.theme--documenter-dark .content kbd.is-rounded:not(body),html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search>input:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-rounded:not(body){border-radius:9999px}html.theme--documenter-dark a.tag:hover,html.theme--documenter-dark .docstring>section>a.docs-sourcelink:hover{text-decoration:underline}html.theme--documenter-dark .title,html.theme--documenter-dark .subtitle{word-break:break-word}html.theme--documenter-dark .title em,html.theme--documenter-dark .title span,html.theme--documenter-dark .subtitle em,html.theme--documenter-dark .subtitle span{font-weight:inherit}html.theme--documenter-dark .title sub,html.theme--documenter-dark .subtitle sub{font-size:.75em}html.theme--documenter-dark .title sup,html.theme--documenter-dark .subtitle sup{font-size:.75em}html.theme--documenter-dark .title .tag,html.theme--documenter-dark .title .content kbd,html.theme--documenter-dark .content .title kbd,html.theme--documenter-dark .title .docstring>section>a.docs-sourcelink,html.theme--documenter-dark .subtitle .tag,html.theme--documenter-dark .subtitle .content kbd,html.theme--documenter-dark .content .subtitle kbd,html.theme--documenter-dark .subtitle .docstring>section>a.docs-sourcelink{vertical-align:middle}html.theme--documenter-dark .title{color:#fff;font-size:2rem;font-weight:500;line-height:1.125}html.theme--documenter-dark .title strong{color:inherit;font-weight:inherit}html.theme--documenter-dark .title:not(.is-spaced)+.subtitle{margin-top:-1.25rem}html.theme--documenter-dark .title.is-1{font-size:3rem}html.theme--documenter-dark .title.is-2{font-size:2.5rem}html.theme--documenter-dark .title.is-3{font-size:2rem}html.theme--documenter-dark .title.is-4{font-size:1.5rem}html.theme--documenter-dark .title.is-5{font-size:1.25rem}html.theme--documenter-dark .title.is-6{font-size:1rem}html.theme--documenter-dark .title.is-7{font-size:.75rem}html.theme--documenter-dark .subtitle{color:#8c9b9d;font-size:1.25rem;font-weight:400;line-height:1.25}html.theme--documenter-dark .subtitle strong{color:#8c9b9d;font-weight:600}html.theme--documenter-dark .subtitle:not(.is-spaced)+.title{margin-top:-1.25rem}html.theme--documenter-dark .subtitle.is-1{font-size:3rem}html.theme--documenter-dark .subtitle.is-2{font-size:2.5rem}html.theme--documenter-dark .subtitle.is-3{font-size:2rem}html.theme--documenter-dark .subtitle.is-4{font-size:1.5rem}html.theme--documenter-dark .subtitle.is-5{font-size:1.25rem}html.theme--documenter-dark .subtitle.is-6{font-size:1rem}html.theme--documenter-dark .subtitle.is-7{font-size:.75rem}html.theme--documenter-dark .heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}html.theme--documenter-dark .number{align-items:center;background-color:#282f2f;border-radius:9999px;display:inline-flex;font-size:1.25rem;height:2em;justify-content:center;margin-right:1.5rem;min-width:2.5em;padding:0.25rem 0.5rem;text-align:center;vertical-align:top}html.theme--documenter-dark .select select,html.theme--documenter-dark .textarea,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{background-color:#1f2424;border-color:#5e6d6f;border-radius:.4em;color:#dbdee0}html.theme--documenter-dark .select select::-moz-placeholder,html.theme--documenter-dark .textarea::-moz-placeholder,html.theme--documenter-dark .input::-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:#868c98}html.theme--documenter-dark .select select::-webkit-input-placeholder,html.theme--documenter-dark .textarea::-webkit-input-placeholder,html.theme--documenter-dark .input::-webkit-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:#868c98}html.theme--documenter-dark .select select:-moz-placeholder,html.theme--documenter-dark .textarea:-moz-placeholder,html.theme--documenter-dark .input:-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:#868c98}html.theme--documenter-dark .select select:-ms-input-placeholder,html.theme--documenter-dark .textarea:-ms-input-placeholder,html.theme--documenter-dark .input:-ms-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:#868c98}html.theme--documenter-dark .select select:hover,html.theme--documenter-dark .textarea:hover,html.theme--documenter-dark .input:hover,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:hover,html.theme--documenter-dark .select select.is-hovered,html.theme--documenter-dark .is-hovered.textarea,html.theme--documenter-dark .is-hovered.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-hovered{border-color:#8c9b9d}html.theme--documenter-dark .select select:focus,html.theme--documenter-dark .textarea:focus,html.theme--documenter-dark .input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:focus,html.theme--documenter-dark .select select.is-focused,html.theme--documenter-dark .is-focused.textarea,html.theme--documenter-dark .is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .select select:active,html.theme--documenter-dark .textarea:active,html.theme--documenter-dark .input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:active,html.theme--documenter-dark .select select.is-active,html.theme--documenter-dark .is-active.textarea,html.theme--documenter-dark .is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{border-color:#1abc9c;box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .select select[disabled],html.theme--documenter-dark .textarea[disabled],html.theme--documenter-dark .input[disabled],html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled],fieldset[disabled] html.theme--documenter-dark .select select,fieldset[disabled] html.theme--documenter-dark .textarea,fieldset[disabled] html.theme--documenter-dark .input,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{background-color:#8c9b9d;border-color:#282f2f;box-shadow:none;color:#fff}html.theme--documenter-dark .select select[disabled]::-moz-placeholder,html.theme--documenter-dark .textarea[disabled]::-moz-placeholder,html.theme--documenter-dark .input[disabled]::-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .select select::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .input::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .select select[disabled]::-webkit-input-placeholder,html.theme--documenter-dark .textarea[disabled]::-webkit-input-placeholder,html.theme--documenter-dark .input[disabled]::-webkit-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark .select select::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark .input::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .select select[disabled]:-moz-placeholder,html.theme--documenter-dark .textarea[disabled]:-moz-placeholder,html.theme--documenter-dark .input[disabled]:-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .select select:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .input:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .select select[disabled]:-ms-input-placeholder,html.theme--documenter-dark .textarea[disabled]:-ms-input-placeholder,html.theme--documenter-dark .input[disabled]:-ms-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark .select select:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark .input:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .textarea,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{box-shadow:inset 0 0.0625em 0.125em rgba(10,10,10,0.05);max-width:100%;width:100%}html.theme--documenter-dark .textarea[readonly],html.theme--documenter-dark .input[readonly],html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[readonly]{box-shadow:none}html.theme--documenter-dark .is-white.textarea,html.theme--documenter-dark .is-white.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-white{border-color:#fff}html.theme--documenter-dark .is-white.textarea:focus,html.theme--documenter-dark .is-white.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-white:focus,html.theme--documenter-dark .is-white.is-focused.textarea,html.theme--documenter-dark .is-white.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-white.textarea:active,html.theme--documenter-dark .is-white.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-white:active,html.theme--documenter-dark .is-white.is-active.textarea,html.theme--documenter-dark .is-white.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--documenter-dark .is-black.textarea,html.theme--documenter-dark .is-black.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-black{border-color:#0a0a0a}html.theme--documenter-dark .is-black.textarea:focus,html.theme--documenter-dark .is-black.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-black:focus,html.theme--documenter-dark .is-black.is-focused.textarea,html.theme--documenter-dark .is-black.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-black.textarea:active,html.theme--documenter-dark .is-black.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-black:active,html.theme--documenter-dark .is-black.is-active.textarea,html.theme--documenter-dark .is-black.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--documenter-dark .is-light.textarea,html.theme--documenter-dark .is-light.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-light{border-color:#ecf0f1}html.theme--documenter-dark .is-light.textarea:focus,html.theme--documenter-dark .is-light.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-light:focus,html.theme--documenter-dark .is-light.is-focused.textarea,html.theme--documenter-dark .is-light.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-light.textarea:active,html.theme--documenter-dark .is-light.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-light:active,html.theme--documenter-dark .is-light.is-active.textarea,html.theme--documenter-dark .is-light.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(236,240,241,0.25)}html.theme--documenter-dark .is-dark.textarea,html.theme--documenter-dark .content kbd.textarea,html.theme--documenter-dark .is-dark.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-dark,html.theme--documenter-dark .content kbd.input{border-color:#282f2f}html.theme--documenter-dark .is-dark.textarea:focus,html.theme--documenter-dark .content kbd.textarea:focus,html.theme--documenter-dark .is-dark.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-dark:focus,html.theme--documenter-dark .content kbd.input:focus,html.theme--documenter-dark .is-dark.is-focused.textarea,html.theme--documenter-dark .content kbd.is-focused.textarea,html.theme--documenter-dark .is-dark.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .content kbd.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search>input.is-focused,html.theme--documenter-dark .is-dark.textarea:active,html.theme--documenter-dark .content kbd.textarea:active,html.theme--documenter-dark .is-dark.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-dark:active,html.theme--documenter-dark .content kbd.input:active,html.theme--documenter-dark .is-dark.is-active.textarea,html.theme--documenter-dark .content kbd.is-active.textarea,html.theme--documenter-dark .is-dark.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--documenter-dark .content kbd.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(40,47,47,0.25)}html.theme--documenter-dark .is-primary.textarea,html.theme--documenter-dark .docstring>section>a.textarea.docs-sourcelink,html.theme--documenter-dark .is-primary.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-primary,html.theme--documenter-dark .docstring>section>a.input.docs-sourcelink{border-color:#375a7f}html.theme--documenter-dark .is-primary.textarea:focus,html.theme--documenter-dark .docstring>section>a.textarea.docs-sourcelink:focus,html.theme--documenter-dark .is-primary.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-primary:focus,html.theme--documenter-dark .docstring>section>a.input.docs-sourcelink:focus,html.theme--documenter-dark .is-primary.is-focused.textarea,html.theme--documenter-dark .docstring>section>a.is-focused.textarea.docs-sourcelink,html.theme--documenter-dark .is-primary.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .docstring>section>a.is-focused.input.docs-sourcelink,html.theme--documenter-dark .is-primary.textarea:active,html.theme--documenter-dark .docstring>section>a.textarea.docs-sourcelink:active,html.theme--documenter-dark .is-primary.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-primary:active,html.theme--documenter-dark .docstring>section>a.input.docs-sourcelink:active,html.theme--documenter-dark .is-primary.is-active.textarea,html.theme--documenter-dark .docstring>section>a.is-active.textarea.docs-sourcelink,html.theme--documenter-dark .is-primary.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--documenter-dark .docstring>section>a.is-active.input.docs-sourcelink{box-shadow:0 0 0 0.125em rgba(55,90,127,0.25)}html.theme--documenter-dark .is-link.textarea,html.theme--documenter-dark .is-link.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-link{border-color:#1abc9c}html.theme--documenter-dark .is-link.textarea:focus,html.theme--documenter-dark .is-link.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-link:focus,html.theme--documenter-dark .is-link.is-focused.textarea,html.theme--documenter-dark .is-link.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-link.textarea:active,html.theme--documenter-dark .is-link.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-link:active,html.theme--documenter-dark .is-link.is-active.textarea,html.theme--documenter-dark .is-link.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .is-info.textarea,html.theme--documenter-dark .is-info.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-info{border-color:#3c5dcd}html.theme--documenter-dark .is-info.textarea:focus,html.theme--documenter-dark .is-info.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-info:focus,html.theme--documenter-dark .is-info.is-focused.textarea,html.theme--documenter-dark .is-info.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-info.textarea:active,html.theme--documenter-dark .is-info.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-info:active,html.theme--documenter-dark .is-info.is-active.textarea,html.theme--documenter-dark .is-info.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(60,93,205,0.25)}html.theme--documenter-dark .is-success.textarea,html.theme--documenter-dark .is-success.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-success{border-color:#259a12}html.theme--documenter-dark .is-success.textarea:focus,html.theme--documenter-dark .is-success.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-success:focus,html.theme--documenter-dark .is-success.is-focused.textarea,html.theme--documenter-dark .is-success.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-success.textarea:active,html.theme--documenter-dark .is-success.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-success:active,html.theme--documenter-dark .is-success.is-active.textarea,html.theme--documenter-dark .is-success.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(37,154,18,0.25)}html.theme--documenter-dark .is-warning.textarea,html.theme--documenter-dark .is-warning.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-warning{border-color:#f4c72f}html.theme--documenter-dark .is-warning.textarea:focus,html.theme--documenter-dark .is-warning.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-warning:focus,html.theme--documenter-dark .is-warning.is-focused.textarea,html.theme--documenter-dark .is-warning.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-warning.textarea:active,html.theme--documenter-dark .is-warning.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-warning:active,html.theme--documenter-dark .is-warning.is-active.textarea,html.theme--documenter-dark .is-warning.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(244,199,47,0.25)}html.theme--documenter-dark .is-danger.textarea,html.theme--documenter-dark .is-danger.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-danger{border-color:#cb3c33}html.theme--documenter-dark .is-danger.textarea:focus,html.theme--documenter-dark .is-danger.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-danger:focus,html.theme--documenter-dark .is-danger.is-focused.textarea,html.theme--documenter-dark .is-danger.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-danger.textarea:active,html.theme--documenter-dark .is-danger.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-danger:active,html.theme--documenter-dark .is-danger.is-active.textarea,html.theme--documenter-dark .is-danger.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(203,60,51,0.25)}html.theme--documenter-dark .is-small.textarea,html.theme--documenter-dark .is-small.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{border-radius:3px;font-size:.75rem}html.theme--documenter-dark .is-medium.textarea,html.theme--documenter-dark .is-medium.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-medium{font-size:1.25rem}html.theme--documenter-dark .is-large.textarea,html.theme--documenter-dark .is-large.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-large{font-size:1.5rem}html.theme--documenter-dark .is-fullwidth.textarea,html.theme--documenter-dark .is-fullwidth.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-fullwidth{display:block;width:100%}html.theme--documenter-dark .is-inline.textarea,html.theme--documenter-dark .is-inline.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-inline{display:inline;width:auto}html.theme--documenter-dark .input.is-rounded,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{border-radius:9999px;padding-left:calc(calc(0.75em - 1px) + 0.375em);padding-right:calc(calc(0.75em - 1px) + 0.375em)}html.theme--documenter-dark .input.is-static,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-static{background-color:transparent;border-color:transparent;box-shadow:none;padding-left:0;padding-right:0}html.theme--documenter-dark .textarea{display:block;max-width:100%;min-width:100%;padding:calc(0.75em - 1px);resize:vertical}html.theme--documenter-dark .textarea:not([rows]){max-height:40em;min-height:8em}html.theme--documenter-dark .textarea[rows]{height:initial}html.theme--documenter-dark .textarea.has-fixed-size{resize:none}html.theme--documenter-dark .radio,html.theme--documenter-dark .checkbox{cursor:pointer;display:inline-block;line-height:1.25;position:relative}html.theme--documenter-dark .radio input,html.theme--documenter-dark .checkbox input{cursor:pointer}html.theme--documenter-dark .radio:hover,html.theme--documenter-dark .checkbox:hover{color:#8c9b9d}html.theme--documenter-dark .radio[disabled],html.theme--documenter-dark .checkbox[disabled],fieldset[disabled] html.theme--documenter-dark .radio,fieldset[disabled] html.theme--documenter-dark .checkbox,html.theme--documenter-dark .radio input[disabled],html.theme--documenter-dark .checkbox input[disabled]{color:#fff;cursor:not-allowed}html.theme--documenter-dark .radio+.radio{margin-left:.5em}html.theme--documenter-dark .select{display:inline-block;max-width:100%;position:relative;vertical-align:top}html.theme--documenter-dark .select:not(.is-multiple){height:2.5em}html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading)::after{border-color:#1abc9c;right:1.125em;z-index:4}html.theme--documenter-dark .select.is-rounded select,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.select select{border-radius:9999px;padding-left:1em}html.theme--documenter-dark .select select{cursor:pointer;display:block;font-size:1em;max-width:100%;outline:none}html.theme--documenter-dark .select select::-ms-expand{display:none}html.theme--documenter-dark .select select[disabled]:hover,fieldset[disabled] html.theme--documenter-dark .select select:hover{border-color:#282f2f}html.theme--documenter-dark .select select:not([multiple]){padding-right:2.5em}html.theme--documenter-dark .select select[multiple]{height:auto;padding:0}html.theme--documenter-dark .select select[multiple] option{padding:0.5em 1em}html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading):hover::after{border-color:#8c9b9d}html.theme--documenter-dark .select.is-white:not(:hover)::after{border-color:#fff}html.theme--documenter-dark .select.is-white select{border-color:#fff}html.theme--documenter-dark .select.is-white select:hover,html.theme--documenter-dark .select.is-white select.is-hovered{border-color:#f2f2f2}html.theme--documenter-dark .select.is-white select:focus,html.theme--documenter-dark .select.is-white select.is-focused,html.theme--documenter-dark .select.is-white select:active,html.theme--documenter-dark .select.is-white select.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--documenter-dark .select.is-black:not(:hover)::after{border-color:#0a0a0a}html.theme--documenter-dark .select.is-black select{border-color:#0a0a0a}html.theme--documenter-dark .select.is-black select:hover,html.theme--documenter-dark .select.is-black select.is-hovered{border-color:#000}html.theme--documenter-dark .select.is-black select:focus,html.theme--documenter-dark .select.is-black select.is-focused,html.theme--documenter-dark .select.is-black select:active,html.theme--documenter-dark .select.is-black select.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--documenter-dark .select.is-light:not(:hover)::after{border-color:#ecf0f1}html.theme--documenter-dark .select.is-light select{border-color:#ecf0f1}html.theme--documenter-dark .select.is-light select:hover,html.theme--documenter-dark .select.is-light select.is-hovered{border-color:#dde4e6}html.theme--documenter-dark .select.is-light select:focus,html.theme--documenter-dark .select.is-light select.is-focused,html.theme--documenter-dark .select.is-light select:active,html.theme--documenter-dark .select.is-light select.is-active{box-shadow:0 0 0 0.125em rgba(236,240,241,0.25)}html.theme--documenter-dark .select.is-dark:not(:hover)::after,html.theme--documenter-dark .content kbd.select:not(:hover)::after{border-color:#282f2f}html.theme--documenter-dark .select.is-dark select,html.theme--documenter-dark .content kbd.select select{border-color:#282f2f}html.theme--documenter-dark .select.is-dark select:hover,html.theme--documenter-dark .content kbd.select select:hover,html.theme--documenter-dark .select.is-dark select.is-hovered,html.theme--documenter-dark .content kbd.select select.is-hovered{border-color:#1d2122}html.theme--documenter-dark .select.is-dark select:focus,html.theme--documenter-dark .content kbd.select select:focus,html.theme--documenter-dark .select.is-dark select.is-focused,html.theme--documenter-dark .content kbd.select select.is-focused,html.theme--documenter-dark .select.is-dark select:active,html.theme--documenter-dark .content kbd.select select:active,html.theme--documenter-dark .select.is-dark select.is-active,html.theme--documenter-dark .content kbd.select select.is-active{box-shadow:0 0 0 0.125em rgba(40,47,47,0.25)}html.theme--documenter-dark .select.is-primary:not(:hover)::after,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink:not(:hover)::after{border-color:#375a7f}html.theme--documenter-dark .select.is-primary select,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select{border-color:#375a7f}html.theme--documenter-dark .select.is-primary select:hover,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select:hover,html.theme--documenter-dark .select.is-primary select.is-hovered,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select.is-hovered{border-color:#2f4d6d}html.theme--documenter-dark .select.is-primary select:focus,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select:focus,html.theme--documenter-dark .select.is-primary select.is-focused,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select.is-focused,html.theme--documenter-dark .select.is-primary select:active,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select:active,html.theme--documenter-dark .select.is-primary select.is-active,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select.is-active{box-shadow:0 0 0 0.125em rgba(55,90,127,0.25)}html.theme--documenter-dark .select.is-link:not(:hover)::after{border-color:#1abc9c}html.theme--documenter-dark .select.is-link select{border-color:#1abc9c}html.theme--documenter-dark .select.is-link select:hover,html.theme--documenter-dark .select.is-link select.is-hovered{border-color:#17a689}html.theme--documenter-dark .select.is-link select:focus,html.theme--documenter-dark .select.is-link select.is-focused,html.theme--documenter-dark .select.is-link select:active,html.theme--documenter-dark .select.is-link select.is-active{box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .select.is-info:not(:hover)::after{border-color:#3c5dcd}html.theme--documenter-dark .select.is-info select{border-color:#3c5dcd}html.theme--documenter-dark .select.is-info select:hover,html.theme--documenter-dark .select.is-info select.is-hovered{border-color:#3151bf}html.theme--documenter-dark .select.is-info select:focus,html.theme--documenter-dark .select.is-info select.is-focused,html.theme--documenter-dark .select.is-info select:active,html.theme--documenter-dark .select.is-info select.is-active{box-shadow:0 0 0 0.125em rgba(60,93,205,0.25)}html.theme--documenter-dark .select.is-success:not(:hover)::after{border-color:#259a12}html.theme--documenter-dark .select.is-success select{border-color:#259a12}html.theme--documenter-dark .select.is-success select:hover,html.theme--documenter-dark .select.is-success select.is-hovered{border-color:#20830f}html.theme--documenter-dark .select.is-success select:focus,html.theme--documenter-dark .select.is-success select.is-focused,html.theme--documenter-dark .select.is-success select:active,html.theme--documenter-dark .select.is-success select.is-active{box-shadow:0 0 0 0.125em rgba(37,154,18,0.25)}html.theme--documenter-dark .select.is-warning:not(:hover)::after{border-color:#f4c72f}html.theme--documenter-dark .select.is-warning select{border-color:#f4c72f}html.theme--documenter-dark .select.is-warning select:hover,html.theme--documenter-dark .select.is-warning select.is-hovered{border-color:#f3c017}html.theme--documenter-dark .select.is-warning select:focus,html.theme--documenter-dark .select.is-warning select.is-focused,html.theme--documenter-dark .select.is-warning select:active,html.theme--documenter-dark .select.is-warning select.is-active{box-shadow:0 0 0 0.125em rgba(244,199,47,0.25)}html.theme--documenter-dark .select.is-danger:not(:hover)::after{border-color:#cb3c33}html.theme--documenter-dark .select.is-danger select{border-color:#cb3c33}html.theme--documenter-dark .select.is-danger select:hover,html.theme--documenter-dark .select.is-danger select.is-hovered{border-color:#b7362e}html.theme--documenter-dark .select.is-danger select:focus,html.theme--documenter-dark .select.is-danger select.is-focused,html.theme--documenter-dark .select.is-danger select:active,html.theme--documenter-dark .select.is-danger select.is-active{box-shadow:0 0 0 0.125em rgba(203,60,51,0.25)}html.theme--documenter-dark .select.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.select{border-radius:3px;font-size:.75rem}html.theme--documenter-dark .select.is-medium{font-size:1.25rem}html.theme--documenter-dark .select.is-large{font-size:1.5rem}html.theme--documenter-dark .select.is-disabled::after{border-color:#fff !important;opacity:0.5}html.theme--documenter-dark .select.is-fullwidth{width:100%}html.theme--documenter-dark .select.is-fullwidth select{width:100%}html.theme--documenter-dark .select.is-loading::after{margin-top:0;position:absolute;right:.625em;top:0.625em;transform:none}html.theme--documenter-dark .select.is-loading.is-small:after,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}html.theme--documenter-dark .select.is-loading.is-medium:after{font-size:1.25rem}html.theme--documenter-dark .select.is-loading.is-large:after{font-size:1.5rem}html.theme--documenter-dark .file{align-items:stretch;display:flex;justify-content:flex-start;position:relative}html.theme--documenter-dark .file.is-white .file-cta{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .file.is-white:hover .file-cta,html.theme--documenter-dark .file.is-white.is-hovered .file-cta{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .file.is-white:focus .file-cta,html.theme--documenter-dark .file.is-white.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,255,255,0.25);color:#0a0a0a}html.theme--documenter-dark .file.is-white:active .file-cta,html.theme--documenter-dark .file.is-white.is-active .file-cta{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .file.is-black .file-cta{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-black:hover .file-cta,html.theme--documenter-dark .file.is-black.is-hovered .file-cta{background-color:#040404;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-black:focus .file-cta,html.theme--documenter-dark .file.is-black.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(10,10,10,0.25);color:#fff}html.theme--documenter-dark .file.is-black:active .file-cta,html.theme--documenter-dark .file.is-black.is-active .file-cta{background-color:#000;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-light .file-cta{background-color:#ecf0f1;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-light:hover .file-cta,html.theme--documenter-dark .file.is-light.is-hovered .file-cta{background-color:#e5eaec;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-light:focus .file-cta,html.theme--documenter-dark .file.is-light.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(236,240,241,0.25);color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-light:active .file-cta,html.theme--documenter-dark .file.is-light.is-active .file-cta{background-color:#dde4e6;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-dark .file-cta,html.theme--documenter-dark .content kbd.file .file-cta{background-color:#282f2f;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-dark:hover .file-cta,html.theme--documenter-dark .content kbd.file:hover .file-cta,html.theme--documenter-dark .file.is-dark.is-hovered .file-cta,html.theme--documenter-dark .content kbd.file.is-hovered .file-cta{background-color:#232829;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-dark:focus .file-cta,html.theme--documenter-dark .content kbd.file:focus .file-cta,html.theme--documenter-dark .file.is-dark.is-focused .file-cta,html.theme--documenter-dark .content kbd.file.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(40,47,47,0.25);color:#fff}html.theme--documenter-dark .file.is-dark:active .file-cta,html.theme--documenter-dark .content kbd.file:active .file-cta,html.theme--documenter-dark .file.is-dark.is-active .file-cta,html.theme--documenter-dark .content kbd.file.is-active .file-cta{background-color:#1d2122;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-primary .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink .file-cta{background-color:#375a7f;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-primary:hover .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink:hover .file-cta,html.theme--documenter-dark .file.is-primary.is-hovered .file-cta,html.theme--documenter-dark .docstring>section>a.file.is-hovered.docs-sourcelink .file-cta{background-color:#335476;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-primary:focus .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink:focus .file-cta,html.theme--documenter-dark .file.is-primary.is-focused .file-cta,html.theme--documenter-dark .docstring>section>a.file.is-focused.docs-sourcelink .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(55,90,127,0.25);color:#fff}html.theme--documenter-dark .file.is-primary:active .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink:active .file-cta,html.theme--documenter-dark .file.is-primary.is-active .file-cta,html.theme--documenter-dark .docstring>section>a.file.is-active.docs-sourcelink .file-cta{background-color:#2f4d6d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-link .file-cta{background-color:#1abc9c;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-link:hover .file-cta,html.theme--documenter-dark .file.is-link.is-hovered .file-cta{background-color:#18b193;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-link:focus .file-cta,html.theme--documenter-dark .file.is-link.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(26,188,156,0.25);color:#fff}html.theme--documenter-dark .file.is-link:active .file-cta,html.theme--documenter-dark .file.is-link.is-active .file-cta{background-color:#17a689;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-info .file-cta{background-color:#3c5dcd;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-info:hover .file-cta,html.theme--documenter-dark .file.is-info.is-hovered .file-cta{background-color:#3355c9;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-info:focus .file-cta,html.theme--documenter-dark .file.is-info.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(60,93,205,0.25);color:#fff}html.theme--documenter-dark .file.is-info:active .file-cta,html.theme--documenter-dark .file.is-info.is-active .file-cta{background-color:#3151bf;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-success .file-cta{background-color:#259a12;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-success:hover .file-cta,html.theme--documenter-dark .file.is-success.is-hovered .file-cta{background-color:#228f11;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-success:focus .file-cta,html.theme--documenter-dark .file.is-success.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(37,154,18,0.25);color:#fff}html.theme--documenter-dark .file.is-success:active .file-cta,html.theme--documenter-dark .file.is-success.is-active .file-cta{background-color:#20830f;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-warning .file-cta{background-color:#f4c72f;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-warning:hover .file-cta,html.theme--documenter-dark .file.is-warning.is-hovered .file-cta{background-color:#f3c423;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-warning:focus .file-cta,html.theme--documenter-dark .file.is-warning.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(244,199,47,0.25);color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-warning:active .file-cta,html.theme--documenter-dark .file.is-warning.is-active .file-cta{background-color:#f3c017;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-danger .file-cta{background-color:#cb3c33;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-danger:hover .file-cta,html.theme--documenter-dark .file.is-danger.is-hovered .file-cta{background-color:#c13930;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-danger:focus .file-cta,html.theme--documenter-dark .file.is-danger.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(203,60,51,0.25);color:#fff}html.theme--documenter-dark .file.is-danger:active .file-cta,html.theme--documenter-dark .file.is-danger.is-active .file-cta{background-color:#b7362e;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.file{font-size:.75rem}html.theme--documenter-dark .file.is-normal{font-size:1rem}html.theme--documenter-dark .file.is-medium{font-size:1.25rem}html.theme--documenter-dark .file.is-medium .file-icon .fa{font-size:21px}html.theme--documenter-dark .file.is-large{font-size:1.5rem}html.theme--documenter-dark .file.is-large .file-icon .fa{font-size:28px}html.theme--documenter-dark .file.has-name .file-cta{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--documenter-dark .file.has-name .file-name{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--documenter-dark .file.has-name.is-empty .file-cta{border-radius:.4em}html.theme--documenter-dark .file.has-name.is-empty .file-name{display:none}html.theme--documenter-dark .file.is-boxed .file-label{flex-direction:column}html.theme--documenter-dark .file.is-boxed .file-cta{flex-direction:column;height:auto;padding:1em 3em}html.theme--documenter-dark .file.is-boxed .file-name{border-width:0 1px 1px}html.theme--documenter-dark .file.is-boxed .file-icon{height:1.5em;width:1.5em}html.theme--documenter-dark .file.is-boxed .file-icon .fa{font-size:21px}html.theme--documenter-dark .file.is-boxed.is-small .file-icon .fa,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-boxed .file-icon .fa{font-size:14px}html.theme--documenter-dark .file.is-boxed.is-medium .file-icon .fa{font-size:28px}html.theme--documenter-dark .file.is-boxed.is-large .file-icon .fa{font-size:35px}html.theme--documenter-dark .file.is-boxed.has-name .file-cta{border-radius:.4em .4em 0 0}html.theme--documenter-dark .file.is-boxed.has-name .file-name{border-radius:0 0 .4em .4em;border-width:0 1px 1px}html.theme--documenter-dark .file.is-centered{justify-content:center}html.theme--documenter-dark .file.is-fullwidth .file-label{width:100%}html.theme--documenter-dark .file.is-fullwidth .file-name{flex-grow:1;max-width:none}html.theme--documenter-dark .file.is-right{justify-content:flex-end}html.theme--documenter-dark .file.is-right .file-cta{border-radius:0 .4em .4em 0}html.theme--documenter-dark .file.is-right .file-name{border-radius:.4em 0 0 .4em;border-width:1px 0 1px 1px;order:-1}html.theme--documenter-dark .file-label{align-items:stretch;display:flex;cursor:pointer;justify-content:flex-start;overflow:hidden;position:relative}html.theme--documenter-dark .file-label:hover .file-cta{background-color:#232829;color:#f2f2f2}html.theme--documenter-dark .file-label:hover .file-name{border-color:#596668}html.theme--documenter-dark .file-label:active .file-cta{background-color:#1d2122;color:#f2f2f2}html.theme--documenter-dark .file-label:active .file-name{border-color:#535f61}html.theme--documenter-dark .file-input{height:100%;left:0;opacity:0;outline:none;position:absolute;top:0;width:100%}html.theme--documenter-dark .file-cta,html.theme--documenter-dark .file-name{border-color:#5e6d6f;border-radius:.4em;font-size:1em;padding-left:1em;padding-right:1em;white-space:nowrap}html.theme--documenter-dark .file-cta{background-color:#282f2f;color:#fff}html.theme--documenter-dark .file-name{border-color:#5e6d6f;border-style:solid;border-width:1px 1px 1px 0;display:block;max-width:16em;overflow:hidden;text-align:inherit;text-overflow:ellipsis}html.theme--documenter-dark .file-icon{align-items:center;display:flex;height:1em;justify-content:center;margin-right:.5em;width:1em}html.theme--documenter-dark .file-icon .fa{font-size:14px}html.theme--documenter-dark .label{color:#f2f2f2;display:block;font-size:1rem;font-weight:700}html.theme--documenter-dark .label:not(:last-child){margin-bottom:0.5em}html.theme--documenter-dark .label.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.label{font-size:.75rem}html.theme--documenter-dark .label.is-medium{font-size:1.25rem}html.theme--documenter-dark .label.is-large{font-size:1.5rem}html.theme--documenter-dark .help{display:block;font-size:.75rem;margin-top:0.25rem}html.theme--documenter-dark .help.is-white{color:#fff}html.theme--documenter-dark .help.is-black{color:#0a0a0a}html.theme--documenter-dark .help.is-light{color:#ecf0f1}html.theme--documenter-dark .help.is-dark,html.theme--documenter-dark .content kbd.help{color:#282f2f}html.theme--documenter-dark .help.is-primary,html.theme--documenter-dark .docstring>section>a.help.docs-sourcelink{color:#375a7f}html.theme--documenter-dark .help.is-link{color:#1abc9c}html.theme--documenter-dark .help.is-info{color:#3c5dcd}html.theme--documenter-dark .help.is-success{color:#259a12}html.theme--documenter-dark .help.is-warning{color:#f4c72f}html.theme--documenter-dark .help.is-danger{color:#cb3c33}html.theme--documenter-dark .field:not(:last-child){margin-bottom:0.75rem}html.theme--documenter-dark .field.has-addons{display:flex;justify-content:flex-start}html.theme--documenter-dark .field.has-addons .control:not(:last-child){margin-right:-1px}html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .button,html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .input,html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:not(:first-child):not(:last-child) form.docs-search>input,html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .select select{border-radius:0}html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .button,html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .input,html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:first-child:not(:only-child) form.docs-search>input,html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .select select{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .button,html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .input,html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:last-child:not(:only-child) form.docs-search>input,html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .select select{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .button.is-hovered:not([disabled]),html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .input.is-hovered:not([disabled]),html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-hovered:not([disabled]),html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-hovered:not([disabled]),html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .select select.is-hovered:not([disabled]){z-index:2}html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control .button.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control .button.is-active:not([disabled]),html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control .input.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]),html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control .input.is-active:not([disabled]),html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]),html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]),html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control .select select.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control .select select.is-active:not([disabled]){z-index:3}html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control .button.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control .button.is-active:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus:hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control .input.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]):hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active:hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control .input.is-active:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]):hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control .select select.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control .select select.is-active:not([disabled]):hover{z-index:4}html.theme--documenter-dark .field.has-addons .control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .field.has-addons.has-addons-centered{justify-content:center}html.theme--documenter-dark .field.has-addons.has-addons-right{justify-content:flex-end}html.theme--documenter-dark .field.has-addons.has-addons-fullwidth .control{flex-grow:1;flex-shrink:0}html.theme--documenter-dark .field.is-grouped{display:flex;justify-content:flex-start}html.theme--documenter-dark .field.is-grouped>.control{flex-shrink:0}html.theme--documenter-dark .field.is-grouped>.control:not(:last-child){margin-bottom:0;margin-right:.75rem}html.theme--documenter-dark .field.is-grouped>.control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .field.is-grouped.is-grouped-centered{justify-content:center}html.theme--documenter-dark .field.is-grouped.is-grouped-right{justify-content:flex-end}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline{flex-wrap:wrap}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline>.control:last-child,html.theme--documenter-dark .field.is-grouped.is-grouped-multiline>.control:not(:last-child){margin-bottom:0.75rem}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline:last-child{margin-bottom:-0.75rem}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline:not(:last-child){margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--documenter-dark .field.is-horizontal{display:flex}}html.theme--documenter-dark .field-label .label{font-size:inherit}@media screen and (max-width: 768px){html.theme--documenter-dark .field-label{margin-bottom:0.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .field-label{flex-basis:0;flex-grow:1;flex-shrink:0;margin-right:1.5rem;text-align:right}html.theme--documenter-dark .field-label.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.field-label{font-size:.75rem;padding-top:0.375em}html.theme--documenter-dark .field-label.is-normal{padding-top:0.375em}html.theme--documenter-dark .field-label.is-medium{font-size:1.25rem;padding-top:0.375em}html.theme--documenter-dark .field-label.is-large{font-size:1.5rem;padding-top:0.375em}}html.theme--documenter-dark .field-body .field .field{margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--documenter-dark .field-body{display:flex;flex-basis:0;flex-grow:5;flex-shrink:1}html.theme--documenter-dark .field-body .field{margin-bottom:0}html.theme--documenter-dark .field-body>.field{flex-shrink:1}html.theme--documenter-dark .field-body>.field:not(.is-narrow){flex-grow:1}html.theme--documenter-dark .field-body>.field:not(:last-child){margin-right:.75rem}}html.theme--documenter-dark .control{box-sizing:border-box;clear:both;font-size:1rem;position:relative;text-align:inherit}html.theme--documenter-dark .control.has-icons-left .input:focus~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input:focus~.icon,html.theme--documenter-dark .control.has-icons-left .select:focus~.icon,html.theme--documenter-dark .control.has-icons-right .input:focus~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input:focus~.icon,html.theme--documenter-dark .control.has-icons-right .select:focus~.icon{color:#282f2f}html.theme--documenter-dark .control.has-icons-left .input.is-small~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input~.icon,html.theme--documenter-dark .control.has-icons-left .select.is-small~.icon,html.theme--documenter-dark .control.has-icons-right .input.is-small~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input~.icon,html.theme--documenter-dark .control.has-icons-right .select.is-small~.icon{font-size:.75rem}html.theme--documenter-dark .control.has-icons-left .input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-left .select.is-medium~.icon,html.theme--documenter-dark .control.has-icons-right .input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-right .select.is-medium~.icon{font-size:1.25rem}html.theme--documenter-dark .control.has-icons-left .input.is-large~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-large~.icon,html.theme--documenter-dark .control.has-icons-left .select.is-large~.icon,html.theme--documenter-dark .control.has-icons-right .input.is-large~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-large~.icon,html.theme--documenter-dark .control.has-icons-right .select.is-large~.icon{font-size:1.5rem}html.theme--documenter-dark .control.has-icons-left .icon,html.theme--documenter-dark .control.has-icons-right .icon{color:#5e6d6f;height:2.5em;pointer-events:none;position:absolute;top:0;width:2.5em;z-index:4}html.theme--documenter-dark .control.has-icons-left .input,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input,html.theme--documenter-dark .control.has-icons-left .select select{padding-left:2.5em}html.theme--documenter-dark .control.has-icons-left .icon.is-left{left:0}html.theme--documenter-dark .control.has-icons-right .input,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input,html.theme--documenter-dark .control.has-icons-right .select select{padding-right:2.5em}html.theme--documenter-dark .control.has-icons-right .icon.is-right{right:0}html.theme--documenter-dark .control.is-loading::after{position:absolute !important;right:.625em;top:0.625em;z-index:4}html.theme--documenter-dark .control.is-loading.is-small:after,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}html.theme--documenter-dark .control.is-loading.is-medium:after{font-size:1.25rem}html.theme--documenter-dark .control.is-loading.is-large:after{font-size:1.5rem}html.theme--documenter-dark .breadcrumb{font-size:1rem;white-space:nowrap}html.theme--documenter-dark .breadcrumb a{align-items:center;color:#1abc9c;display:flex;justify-content:center;padding:0 .75em}html.theme--documenter-dark .breadcrumb a:hover{color:#1dd2af}html.theme--documenter-dark .breadcrumb li{align-items:center;display:flex}html.theme--documenter-dark .breadcrumb li:first-child a{padding-left:0}html.theme--documenter-dark .breadcrumb li.is-active a{color:#f2f2f2;cursor:default;pointer-events:none}html.theme--documenter-dark .breadcrumb li+li::before{color:#8c9b9d;content:"\0002f"}html.theme--documenter-dark .breadcrumb ul,html.theme--documenter-dark .breadcrumb ol{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--documenter-dark .breadcrumb .icon:first-child{margin-right:.5em}html.theme--documenter-dark .breadcrumb .icon:last-child{margin-left:.5em}html.theme--documenter-dark .breadcrumb.is-centered ol,html.theme--documenter-dark .breadcrumb.is-centered ul{justify-content:center}html.theme--documenter-dark .breadcrumb.is-right ol,html.theme--documenter-dark .breadcrumb.is-right ul{justify-content:flex-end}html.theme--documenter-dark .breadcrumb.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.breadcrumb{font-size:.75rem}html.theme--documenter-dark .breadcrumb.is-medium{font-size:1.25rem}html.theme--documenter-dark .breadcrumb.is-large{font-size:1.5rem}html.theme--documenter-dark .breadcrumb.has-arrow-separator li+li::before{content:"\02192"}html.theme--documenter-dark .breadcrumb.has-bullet-separator li+li::before{content:"\02022"}html.theme--documenter-dark .breadcrumb.has-dot-separator li+li::before{content:"\000b7"}html.theme--documenter-dark .breadcrumb.has-succeeds-separator li+li::before{content:"\0227B"}html.theme--documenter-dark .card{background-color:#fff;border-radius:.25rem;box-shadow:#171717;color:#fff;max-width:100%;position:relative}html.theme--documenter-dark .card-footer:first-child,html.theme--documenter-dark .card-content:first-child,html.theme--documenter-dark .card-header:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}html.theme--documenter-dark .card-footer:last-child,html.theme--documenter-dark .card-content:last-child,html.theme--documenter-dark .card-header:last-child{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}html.theme--documenter-dark .card-header{background-color:rgba(0,0,0,0);align-items:stretch;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);display:flex}html.theme--documenter-dark .card-header-title{align-items:center;color:#f2f2f2;display:flex;flex-grow:1;font-weight:700;padding:0.75rem 1rem}html.theme--documenter-dark .card-header-title.is-centered{justify-content:center}html.theme--documenter-dark .card-header-icon{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0;align-items:center;cursor:pointer;display:flex;justify-content:center;padding:0.75rem 1rem}html.theme--documenter-dark .card-image{display:block;position:relative}html.theme--documenter-dark .card-image:first-child img{border-top-left-radius:.25rem;border-top-right-radius:.25rem}html.theme--documenter-dark .card-image:last-child img{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}html.theme--documenter-dark .card-content{background-color:rgba(0,0,0,0);padding:1.5rem}html.theme--documenter-dark .card-footer{background-color:rgba(0,0,0,0);border-top:1px solid #ededed;align-items:stretch;display:flex}html.theme--documenter-dark .card-footer-item{align-items:center;display:flex;flex-basis:0;flex-grow:1;flex-shrink:0;justify-content:center;padding:.75rem}html.theme--documenter-dark .card-footer-item:not(:last-child){border-right:1px solid #ededed}html.theme--documenter-dark .card .media:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .dropdown{display:inline-flex;position:relative;vertical-align:top}html.theme--documenter-dark .dropdown.is-active .dropdown-menu,html.theme--documenter-dark .dropdown.is-hoverable:hover .dropdown-menu{display:block}html.theme--documenter-dark .dropdown.is-right .dropdown-menu{left:auto;right:0}html.theme--documenter-dark .dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:initial;top:auto}html.theme--documenter-dark .dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:20}html.theme--documenter-dark .dropdown-content{background-color:#282f2f;border-radius:.4em;box-shadow:#171717;padding-bottom:.5rem;padding-top:.5rem}html.theme--documenter-dark .dropdown-item{color:#fff;display:block;font-size:0.875rem;line-height:1.5;padding:0.375rem 1rem;position:relative}html.theme--documenter-dark a.dropdown-item,html.theme--documenter-dark button.dropdown-item{padding-right:3rem;text-align:inherit;white-space:nowrap;width:100%}html.theme--documenter-dark a.dropdown-item:hover,html.theme--documenter-dark button.dropdown-item:hover{background-color:#282f2f;color:#0a0a0a}html.theme--documenter-dark a.dropdown-item.is-active,html.theme--documenter-dark button.dropdown-item.is-active{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .dropdown-divider{background-color:#ededed;border:none;display:block;height:1px;margin:0.5rem 0}html.theme--documenter-dark .level{align-items:center;justify-content:space-between}html.theme--documenter-dark .level code{border-radius:.4em}html.theme--documenter-dark .level img{display:inline-block;vertical-align:top}html.theme--documenter-dark .level.is-mobile{display:flex}html.theme--documenter-dark .level.is-mobile .level-left,html.theme--documenter-dark .level.is-mobile .level-right{display:flex}html.theme--documenter-dark .level.is-mobile .level-left+.level-right{margin-top:0}html.theme--documenter-dark .level.is-mobile .level-item:not(:last-child){margin-bottom:0;margin-right:.75rem}html.theme--documenter-dark .level.is-mobile .level-item:not(.is-narrow){flex-grow:1}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level{display:flex}html.theme--documenter-dark .level>.level-item:not(.is-narrow){flex-grow:1}}html.theme--documenter-dark .level-item{align-items:center;display:flex;flex-basis:auto;flex-grow:0;flex-shrink:0;justify-content:center}html.theme--documenter-dark .level-item .title,html.theme--documenter-dark .level-item .subtitle{margin-bottom:0}@media screen and (max-width: 768px){html.theme--documenter-dark .level-item:not(:last-child){margin-bottom:.75rem}}html.theme--documenter-dark .level-left,html.theme--documenter-dark .level-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--documenter-dark .level-left .level-item.is-flexible,html.theme--documenter-dark .level-right .level-item.is-flexible{flex-grow:1}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level-left .level-item:not(:last-child),html.theme--documenter-dark .level-right .level-item:not(:last-child){margin-right:.75rem}}html.theme--documenter-dark .level-left{align-items:center;justify-content:flex-start}@media screen and (max-width: 768px){html.theme--documenter-dark .level-left+.level-right{margin-top:1.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level-left{display:flex}}html.theme--documenter-dark .level-right{align-items:center;justify-content:flex-end}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level-right{display:flex}}html.theme--documenter-dark .media{align-items:flex-start;display:flex;text-align:inherit}html.theme--documenter-dark .media .content:not(:last-child){margin-bottom:.75rem}html.theme--documenter-dark .media .media{border-top:1px solid rgba(94,109,111,0.5);display:flex;padding-top:.75rem}html.theme--documenter-dark .media .media .content:not(:last-child),html.theme--documenter-dark .media .media .control:not(:last-child){margin-bottom:.5rem}html.theme--documenter-dark .media .media .media{padding-top:.5rem}html.theme--documenter-dark .media .media .media+.media{margin-top:.5rem}html.theme--documenter-dark .media+.media{border-top:1px solid rgba(94,109,111,0.5);margin-top:1rem;padding-top:1rem}html.theme--documenter-dark .media.is-large+.media{margin-top:1.5rem;padding-top:1.5rem}html.theme--documenter-dark .media-left,html.theme--documenter-dark .media-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--documenter-dark .media-left{margin-right:1rem}html.theme--documenter-dark .media-right{margin-left:1rem}html.theme--documenter-dark .media-content{flex-basis:auto;flex-grow:1;flex-shrink:1;text-align:inherit}@media screen and (max-width: 768px){html.theme--documenter-dark .media-content{overflow-x:auto}}html.theme--documenter-dark .menu{font-size:1rem}html.theme--documenter-dark .menu.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.menu{font-size:.75rem}html.theme--documenter-dark .menu.is-medium{font-size:1.25rem}html.theme--documenter-dark .menu.is-large{font-size:1.5rem}html.theme--documenter-dark .menu-list{line-height:1.25}html.theme--documenter-dark .menu-list a{border-radius:3px;color:#fff;display:block;padding:0.5em 0.75em}html.theme--documenter-dark .menu-list a:hover{background-color:#282f2f;color:#f2f2f2}html.theme--documenter-dark .menu-list a.is-active{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .menu-list li ul{border-left:1px solid #5e6d6f;margin:.75em;padding-left:.75em}html.theme--documenter-dark .menu-label{color:#fff;font-size:.75em;letter-spacing:.1em;text-transform:uppercase}html.theme--documenter-dark .menu-label:not(:first-child){margin-top:1em}html.theme--documenter-dark .menu-label:not(:last-child){margin-bottom:1em}html.theme--documenter-dark .message{background-color:#282f2f;border-radius:.4em;font-size:1rem}html.theme--documenter-dark .message strong{color:currentColor}html.theme--documenter-dark .message a:not(.button):not(.tag):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--documenter-dark .message.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.message{font-size:.75rem}html.theme--documenter-dark .message.is-medium{font-size:1.25rem}html.theme--documenter-dark .message.is-large{font-size:1.5rem}html.theme--documenter-dark .message.is-white{background-color:#fff}html.theme--documenter-dark .message.is-white .message-header{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .message.is-white .message-body{border-color:#fff}html.theme--documenter-dark .message.is-black{background-color:#fafafa}html.theme--documenter-dark .message.is-black .message-header{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .message.is-black .message-body{border-color:#0a0a0a}html.theme--documenter-dark .message.is-light{background-color:#f9fafb}html.theme--documenter-dark .message.is-light .message-header{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .message.is-light .message-body{border-color:#ecf0f1}html.theme--documenter-dark .message.is-dark,html.theme--documenter-dark .content kbd.message{background-color:#f9fafa}html.theme--documenter-dark .message.is-dark .message-header,html.theme--documenter-dark .content kbd.message .message-header{background-color:#282f2f;color:#fff}html.theme--documenter-dark .message.is-dark .message-body,html.theme--documenter-dark .content kbd.message .message-body{border-color:#282f2f}html.theme--documenter-dark .message.is-primary,html.theme--documenter-dark .docstring>section>a.message.docs-sourcelink{background-color:#f1f5f9}html.theme--documenter-dark .message.is-primary .message-header,html.theme--documenter-dark .docstring>section>a.message.docs-sourcelink .message-header{background-color:#375a7f;color:#fff}html.theme--documenter-dark .message.is-primary .message-body,html.theme--documenter-dark .docstring>section>a.message.docs-sourcelink .message-body{border-color:#375a7f;color:#4d7eb2}html.theme--documenter-dark .message.is-link{background-color:#edfdf9}html.theme--documenter-dark .message.is-link .message-header{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .message.is-link .message-body{border-color:#1abc9c;color:#15987e}html.theme--documenter-dark .message.is-info{background-color:#eff2fb}html.theme--documenter-dark .message.is-info .message-header{background-color:#3c5dcd;color:#fff}html.theme--documenter-dark .message.is-info .message-body{border-color:#3c5dcd;color:#3253c3}html.theme--documenter-dark .message.is-success{background-color:#effded}html.theme--documenter-dark .message.is-success .message-header{background-color:#259a12;color:#fff}html.theme--documenter-dark .message.is-success .message-body{border-color:#259a12;color:#2ec016}html.theme--documenter-dark .message.is-warning{background-color:#fefaec}html.theme--documenter-dark .message.is-warning .message-header{background-color:#f4c72f;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .message.is-warning .message-body{border-color:#f4c72f;color:#8c6e07}html.theme--documenter-dark .message.is-danger{background-color:#fbefef}html.theme--documenter-dark .message.is-danger .message-header{background-color:#cb3c33;color:#fff}html.theme--documenter-dark .message.is-danger .message-body{border-color:#cb3c33;color:#c03930}html.theme--documenter-dark .message-header{align-items:center;background-color:#fff;border-radius:.4em .4em 0 0;color:rgba(0,0,0,0.7);display:flex;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.75em 1em;position:relative}html.theme--documenter-dark .message-header .delete{flex-grow:0;flex-shrink:0;margin-left:.75em}html.theme--documenter-dark .message-header+.message-body{border-width:0;border-top-left-radius:0;border-top-right-radius:0}html.theme--documenter-dark .message-body{border-color:#5e6d6f;border-radius:.4em;border-style:solid;border-width:0 0 0 4px;color:#fff;padding:1.25em 1.5em}html.theme--documenter-dark .message-body code,html.theme--documenter-dark .message-body pre{background-color:#fff}html.theme--documenter-dark .message-body pre code{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .modal{align-items:center;display:none;flex-direction:column;justify-content:center;overflow:hidden;position:fixed;z-index:40}html.theme--documenter-dark .modal.is-active{display:flex}html.theme--documenter-dark .modal-background{background-color:rgba(10,10,10,0.86)}html.theme--documenter-dark .modal-content,html.theme--documenter-dark .modal-card{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width: 769px){html.theme--documenter-dark .modal-content,html.theme--documenter-dark .modal-card{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}html.theme--documenter-dark .modal-close{background:none;height:40px;position:fixed;right:20px;top:20px;width:40px}html.theme--documenter-dark .modal-card{display:flex;flex-direction:column;max-height:calc(100vh - 40px);overflow:hidden;-ms-overflow-y:visible}html.theme--documenter-dark .modal-card-head,html.theme--documenter-dark .modal-card-foot{align-items:center;background-color:#282f2f;display:flex;flex-shrink:0;justify-content:flex-start;padding:20px;position:relative}html.theme--documenter-dark .modal-card-head{border-bottom:1px solid #5e6d6f;border-top-left-radius:8px;border-top-right-radius:8px}html.theme--documenter-dark .modal-card-title{color:#f2f2f2;flex-grow:1;flex-shrink:0;font-size:1.5rem;line-height:1}html.theme--documenter-dark .modal-card-foot{border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid #5e6d6f}html.theme--documenter-dark .modal-card-foot .button:not(:last-child){margin-right:.5em}html.theme--documenter-dark .modal-card-body{-webkit-overflow-scrolling:touch;background-color:#fff;flex-grow:1;flex-shrink:1;overflow:auto;padding:20px}html.theme--documenter-dark .navbar{background-color:#375a7f;min-height:4rem;position:relative;z-index:30}html.theme--documenter-dark .navbar.is-white{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link{color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-white .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-white .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link::after{border-color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-burger{color:#0a0a0a}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-white .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-white .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link{color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-white .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-white .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-white .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-white .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-white .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link::after{border-color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-dropdown a.navbar-item.is-active{background-color:#fff;color:#0a0a0a}}html.theme--documenter-dark .navbar.is-black{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-black .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-black .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link.is-active{background-color:#000;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-black .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-black .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-black .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-black .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-black .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-black .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-black .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link.is-active{background-color:#000;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link{background-color:#000;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-dropdown a.navbar-item.is-active{background-color:#0a0a0a;color:#fff}}html.theme--documenter-dark .navbar.is-light{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-light .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-light .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link.is-active{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-light .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-light .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-light .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-light .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-light .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-light .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-light .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link.is-active{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-dropdown a.navbar-item.is-active{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}}html.theme--documenter-dark .navbar.is-dark,html.theme--documenter-dark .content kbd.navbar{background-color:#282f2f;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-brand>.navbar-item,html.theme--documenter-dark .content kbd.navbar .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .content kbd.navbar .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-dark .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .content kbd.navbar .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-dark .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link:focus,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link:hover,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link.is-active{background-color:#1d2122;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link::after,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-burger,html.theme--documenter-dark .content kbd.navbar .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-dark .navbar-start>.navbar-item,html.theme--documenter-dark .content kbd.navbar .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-dark .navbar-end>.navbar-item,html.theme--documenter-dark .content kbd.navbar .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .content kbd.navbar .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-dark .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .content kbd.navbar .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-dark .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link:focus,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link:hover,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .content kbd.navbar .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-dark .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .content kbd.navbar .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-dark .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link:focus,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link:hover,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link.is-active{background-color:#1d2122;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link::after,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link::after,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown.is-active .navbar-link{background-color:#1d2122;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-dropdown a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-dropdown a.navbar-item.is-active{background-color:#282f2f;color:#fff}}html.theme--documenter-dark .navbar.is-primary,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink{background-color:#375a7f;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-brand>.navbar-item,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-primary .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-primary .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link.is-active{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link::after,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-burger,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-primary .navbar-start>.navbar-item,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-primary .navbar-end>.navbar-item,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-primary .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-primary .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-primary .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-primary .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link.is-active{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link::after,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link::after,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown.is-active .navbar-link{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#375a7f;color:#fff}}html.theme--documenter-dark .navbar.is-link{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-link .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-link .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link.is-active{background-color:#17a689;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-link .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-link .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-link .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-link .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-link .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-link .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-link .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link.is-active{background-color:#17a689;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link{background-color:#17a689;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-dropdown a.navbar-item.is-active{background-color:#1abc9c;color:#fff}}html.theme--documenter-dark .navbar.is-info{background-color:#3c5dcd;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-info .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-info .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link.is-active{background-color:#3151bf;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-info .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-info .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-info .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-info .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-info .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-info .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-info .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link.is-active{background-color:#3151bf;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link{background-color:#3151bf;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-dropdown a.navbar-item.is-active{background-color:#3c5dcd;color:#fff}}html.theme--documenter-dark .navbar.is-success{background-color:#259a12;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-success .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-success .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link.is-active{background-color:#20830f;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-success .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-success .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-success .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-success .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-success .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-success .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-success .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link.is-active{background-color:#20830f;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link{background-color:#20830f;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-dropdown a.navbar-item.is-active{background-color:#259a12;color:#fff}}html.theme--documenter-dark .navbar.is-warning{background-color:#f4c72f;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-warning .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-warning .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-warning .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-warning .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link.is-active{background-color:#f3c017;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-warning .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-warning .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-warning .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-warning .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-warning .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-warning .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-warning .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-warning .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link.is-active{background-color:#f3c017;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link{background-color:#f3c017;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-warning .navbar-dropdown a.navbar-item.is-active{background-color:#f4c72f;color:rgba(0,0,0,0.7)}}html.theme--documenter-dark .navbar.is-danger{background-color:#cb3c33;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-danger .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-danger .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link.is-active{background-color:#b7362e;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-danger .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-danger .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-danger .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-danger .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-danger .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-danger .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link.is-active{background-color:#b7362e;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link{background-color:#b7362e;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-dropdown a.navbar-item.is-active{background-color:#cb3c33;color:#fff}}html.theme--documenter-dark .navbar>.container{align-items:stretch;display:flex;min-height:4rem;width:100%}html.theme--documenter-dark .navbar.has-shadow{box-shadow:0 2px 0 0 #282f2f}html.theme--documenter-dark .navbar.is-fixed-bottom,html.theme--documenter-dark .navbar.is-fixed-top{left:0;position:fixed;right:0;z-index:30}html.theme--documenter-dark .navbar.is-fixed-bottom{bottom:0}html.theme--documenter-dark .navbar.is-fixed-bottom.has-shadow{box-shadow:0 -2px 0 0 #282f2f}html.theme--documenter-dark .navbar.is-fixed-top{top:0}html.theme--documenter-dark html.has-navbar-fixed-top,html.theme--documenter-dark body.has-navbar-fixed-top{padding-top:4rem}html.theme--documenter-dark html.has-navbar-fixed-bottom,html.theme--documenter-dark body.has-navbar-fixed-bottom{padding-bottom:4rem}html.theme--documenter-dark .navbar-brand,html.theme--documenter-dark .navbar-tabs{align-items:stretch;display:flex;flex-shrink:0;min-height:4rem}html.theme--documenter-dark .navbar-brand a.navbar-item:focus,html.theme--documenter-dark .navbar-brand a.navbar-item:hover{background-color:transparent}html.theme--documenter-dark .navbar-tabs{-webkit-overflow-scrolling:touch;max-width:100vw;overflow-x:auto;overflow-y:hidden}html.theme--documenter-dark .navbar-burger{color:#fff;-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;cursor:pointer;display:block;height:4rem;position:relative;width:4rem;margin-left:auto}html.theme--documenter-dark .navbar-burger span{background-color:currentColor;display:block;height:1px;left:calc(50% - 8px);position:absolute;transform-origin:center;transition-duration:86ms;transition-property:background-color, opacity, transform;transition-timing-function:ease-out;width:16px}html.theme--documenter-dark .navbar-burger span:nth-child(1){top:calc(50% - 6px)}html.theme--documenter-dark .navbar-burger span:nth-child(2){top:calc(50% - 1px)}html.theme--documenter-dark .navbar-burger span:nth-child(3){top:calc(50% + 4px)}html.theme--documenter-dark .navbar-burger:hover{background-color:rgba(0,0,0,0.05)}html.theme--documenter-dark .navbar-burger.is-active span:nth-child(1){transform:translateY(5px) rotate(45deg)}html.theme--documenter-dark .navbar-burger.is-active span:nth-child(2){opacity:0}html.theme--documenter-dark .navbar-burger.is-active span:nth-child(3){transform:translateY(-5px) rotate(-45deg)}html.theme--documenter-dark .navbar-menu{display:none}html.theme--documenter-dark .navbar-item,html.theme--documenter-dark .navbar-link{color:#fff;display:block;line-height:1.5;padding:0.5rem 0.75rem;position:relative}html.theme--documenter-dark .navbar-item .icon:only-child,html.theme--documenter-dark .navbar-link .icon:only-child{margin-left:-0.25rem;margin-right:-0.25rem}html.theme--documenter-dark a.navbar-item,html.theme--documenter-dark .navbar-link{cursor:pointer}html.theme--documenter-dark a.navbar-item:focus,html.theme--documenter-dark a.navbar-item:focus-within,html.theme--documenter-dark a.navbar-item:hover,html.theme--documenter-dark a.navbar-item.is-active,html.theme--documenter-dark .navbar-link:focus,html.theme--documenter-dark .navbar-link:focus-within,html.theme--documenter-dark .navbar-link:hover,html.theme--documenter-dark .navbar-link.is-active{background-color:rgba(0,0,0,0);color:#1abc9c}html.theme--documenter-dark .navbar-item{flex-grow:0;flex-shrink:0}html.theme--documenter-dark .navbar-item img{max-height:1.75rem}html.theme--documenter-dark .navbar-item.has-dropdown{padding:0}html.theme--documenter-dark .navbar-item.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .navbar-item.is-tab{border-bottom:1px solid transparent;min-height:4rem;padding-bottom:calc(0.5rem - 1px)}html.theme--documenter-dark .navbar-item.is-tab:focus,html.theme--documenter-dark .navbar-item.is-tab:hover{background-color:rgba(0,0,0,0);border-bottom-color:#1abc9c}html.theme--documenter-dark .navbar-item.is-tab.is-active{background-color:rgba(0,0,0,0);border-bottom-color:#1abc9c;border-bottom-style:solid;border-bottom-width:3px;color:#1abc9c;padding-bottom:calc(0.5rem - 3px)}html.theme--documenter-dark .navbar-content{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .navbar-link:not(.is-arrowless){padding-right:2.5em}html.theme--documenter-dark .navbar-link:not(.is-arrowless)::after{border-color:#fff;margin-top:-0.375em;right:1.125em}html.theme--documenter-dark .navbar-dropdown{font-size:0.875rem;padding-bottom:0.5rem;padding-top:0.5rem}html.theme--documenter-dark .navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}html.theme--documenter-dark .navbar-divider{background-color:rgba(0,0,0,0.2);border:none;display:none;height:2px;margin:0.5rem 0}@media screen and (max-width: 1055px){html.theme--documenter-dark .navbar>.container{display:block}html.theme--documenter-dark .navbar-brand .navbar-item,html.theme--documenter-dark .navbar-tabs .navbar-item{align-items:center;display:flex}html.theme--documenter-dark .navbar-link::after{display:none}html.theme--documenter-dark .navbar-menu{background-color:#375a7f;box-shadow:0 8px 16px rgba(10,10,10,0.1);padding:0.5rem 0}html.theme--documenter-dark .navbar-menu.is-active{display:block}html.theme--documenter-dark .navbar.is-fixed-bottom-touch,html.theme--documenter-dark .navbar.is-fixed-top-touch{left:0;position:fixed;right:0;z-index:30}html.theme--documenter-dark .navbar.is-fixed-bottom-touch{bottom:0}html.theme--documenter-dark .navbar.is-fixed-bottom-touch.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--documenter-dark .navbar.is-fixed-top-touch{top:0}html.theme--documenter-dark .navbar.is-fixed-top .navbar-menu,html.theme--documenter-dark .navbar.is-fixed-top-touch .navbar-menu{-webkit-overflow-scrolling:touch;max-height:calc(100vh - 4rem);overflow:auto}html.theme--documenter-dark html.has-navbar-fixed-top-touch,html.theme--documenter-dark body.has-navbar-fixed-top-touch{padding-top:4rem}html.theme--documenter-dark html.has-navbar-fixed-bottom-touch,html.theme--documenter-dark body.has-navbar-fixed-bottom-touch{padding-bottom:4rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar,html.theme--documenter-dark .navbar-menu,html.theme--documenter-dark .navbar-start,html.theme--documenter-dark .navbar-end{align-items:stretch;display:flex}html.theme--documenter-dark .navbar{min-height:4rem}html.theme--documenter-dark .navbar.is-spaced{padding:1rem 2rem}html.theme--documenter-dark .navbar.is-spaced .navbar-start,html.theme--documenter-dark .navbar.is-spaced .navbar-end{align-items:center}html.theme--documenter-dark .navbar.is-spaced a.navbar-item,html.theme--documenter-dark .navbar.is-spaced .navbar-link{border-radius:.4em}html.theme--documenter-dark .navbar.is-transparent a.navbar-item:focus,html.theme--documenter-dark .navbar.is-transparent a.navbar-item:hover,html.theme--documenter-dark .navbar.is-transparent a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-transparent .navbar-link:focus,html.theme--documenter-dark .navbar.is-transparent .navbar-link:hover,html.theme--documenter-dark .navbar.is-transparent .navbar-link.is-active{background-color:transparent !important}html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link,html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link,html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link,html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link{background-color:transparent !important}html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item:focus,html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#dbdee0}html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#1abc9c}html.theme--documenter-dark .navbar-burger{display:none}html.theme--documenter-dark .navbar-item,html.theme--documenter-dark .navbar-link{align-items:center;display:flex}html.theme--documenter-dark .navbar-item.has-dropdown{align-items:stretch}html.theme--documenter-dark .navbar-item.has-dropdown-up .navbar-link::after{transform:rotate(135deg) translate(0.25em, -0.25em)}html.theme--documenter-dark .navbar-item.has-dropdown-up .navbar-dropdown{border-bottom:1px solid rgba(0,0,0,0.2);border-radius:8px 8px 0 0;border-top:none;bottom:100%;box-shadow:0 -8px 8px rgba(10,10,10,0.1);top:auto}html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed{opacity:1;pointer-events:auto;transform:translateY(0)}html.theme--documenter-dark .navbar-menu{flex-grow:1;flex-shrink:0}html.theme--documenter-dark .navbar-start{justify-content:flex-start;margin-right:auto}html.theme--documenter-dark .navbar-end{justify-content:flex-end;margin-left:auto}html.theme--documenter-dark .navbar-dropdown{background-color:#375a7f;border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid rgba(0,0,0,0.2);box-shadow:0 8px 8px rgba(10,10,10,0.1);display:none;font-size:0.875rem;left:0;min-width:100%;position:absolute;top:100%;z-index:20}html.theme--documenter-dark .navbar-dropdown .navbar-item{padding:0.375rem 1rem;white-space:nowrap}html.theme--documenter-dark .navbar-dropdown a.navbar-item{padding-right:3rem}html.theme--documenter-dark .navbar-dropdown a.navbar-item:focus,html.theme--documenter-dark .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#dbdee0}html.theme--documenter-dark .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#1abc9c}.navbar.is-spaced html.theme--documenter-dark .navbar-dropdown,html.theme--documenter-dark .navbar-dropdown.is-boxed{border-radius:8px;border-top:none;box-shadow:0 8px 8px rgba(10,10,10,0.1), 0 0 0 1px rgba(10,10,10,0.1);display:block;opacity:0;pointer-events:none;top:calc(100% + (-4px));transform:translateY(-5px);transition-duration:86ms;transition-property:opacity, transform}html.theme--documenter-dark .navbar-dropdown.is-right{left:auto;right:0}html.theme--documenter-dark .navbar-divider{display:block}html.theme--documenter-dark .navbar>.container .navbar-brand,html.theme--documenter-dark .container>.navbar .navbar-brand{margin-left:-.75rem}html.theme--documenter-dark .navbar>.container .navbar-menu,html.theme--documenter-dark .container>.navbar .navbar-menu{margin-right:-.75rem}html.theme--documenter-dark .navbar.is-fixed-bottom-desktop,html.theme--documenter-dark .navbar.is-fixed-top-desktop{left:0;position:fixed;right:0;z-index:30}html.theme--documenter-dark .navbar.is-fixed-bottom-desktop{bottom:0}html.theme--documenter-dark .navbar.is-fixed-bottom-desktop.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--documenter-dark .navbar.is-fixed-top-desktop{top:0}html.theme--documenter-dark html.has-navbar-fixed-top-desktop,html.theme--documenter-dark body.has-navbar-fixed-top-desktop{padding-top:4rem}html.theme--documenter-dark html.has-navbar-fixed-bottom-desktop,html.theme--documenter-dark body.has-navbar-fixed-bottom-desktop{padding-bottom:4rem}html.theme--documenter-dark html.has-spaced-navbar-fixed-top,html.theme--documenter-dark body.has-spaced-navbar-fixed-top{padding-top:6rem}html.theme--documenter-dark html.has-spaced-navbar-fixed-bottom,html.theme--documenter-dark body.has-spaced-navbar-fixed-bottom{padding-bottom:6rem}html.theme--documenter-dark a.navbar-item.is-active,html.theme--documenter-dark .navbar-link.is-active{color:#1abc9c}html.theme--documenter-dark a.navbar-item.is-active:not(:focus):not(:hover),html.theme--documenter-dark .navbar-link.is-active:not(:focus):not(:hover){background-color:rgba(0,0,0,0)}html.theme--documenter-dark .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar-item.has-dropdown.is-active .navbar-link{background-color:rgba(0,0,0,0)}}html.theme--documenter-dark .hero.is-fullheight-with-navbar{min-height:calc(100vh - 4rem)}html.theme--documenter-dark .pagination{font-size:1rem;margin:-.25rem}html.theme--documenter-dark .pagination.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination{font-size:.75rem}html.theme--documenter-dark .pagination.is-medium{font-size:1.25rem}html.theme--documenter-dark .pagination.is-large{font-size:1.5rem}html.theme--documenter-dark .pagination.is-rounded .pagination-previous,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination .pagination-previous,html.theme--documenter-dark .pagination.is-rounded .pagination-next,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination .pagination-next{padding-left:1em;padding-right:1em;border-radius:9999px}html.theme--documenter-dark .pagination.is-rounded .pagination-link,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination .pagination-link{border-radius:9999px}html.theme--documenter-dark .pagination,html.theme--documenter-dark .pagination-list{align-items:center;display:flex;justify-content:center;text-align:center}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis{font-size:1em;justify-content:center;margin:.25rem;padding-left:.5em;padding-right:.5em;text-align:center}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link{border-color:#5e6d6f;color:#1abc9c;min-width:2.5em}html.theme--documenter-dark .pagination-previous:hover,html.theme--documenter-dark .pagination-next:hover,html.theme--documenter-dark .pagination-link:hover{border-color:#8c9b9d;color:#1dd2af}html.theme--documenter-dark .pagination-previous:focus,html.theme--documenter-dark .pagination-next:focus,html.theme--documenter-dark .pagination-link:focus{border-color:#8c9b9d}html.theme--documenter-dark .pagination-previous:active,html.theme--documenter-dark .pagination-next:active,html.theme--documenter-dark .pagination-link:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2)}html.theme--documenter-dark .pagination-previous[disabled],html.theme--documenter-dark .pagination-previous.is-disabled,html.theme--documenter-dark .pagination-next[disabled],html.theme--documenter-dark .pagination-next.is-disabled,html.theme--documenter-dark .pagination-link[disabled],html.theme--documenter-dark .pagination-link.is-disabled{background-color:#5e6d6f;border-color:#5e6d6f;box-shadow:none;color:#fff;opacity:0.5}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next{padding-left:.75em;padding-right:.75em;white-space:nowrap}html.theme--documenter-dark .pagination-link.is-current{background-color:#1abc9c;border-color:#1abc9c;color:#fff}html.theme--documenter-dark .pagination-ellipsis{color:#8c9b9d;pointer-events:none}html.theme--documenter-dark .pagination-list{flex-wrap:wrap}html.theme--documenter-dark .pagination-list li{list-style:none}@media screen and (max-width: 768px){html.theme--documenter-dark .pagination{flex-wrap:wrap}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .pagination-list li{flex-grow:1;flex-shrink:1}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .pagination-list{flex-grow:1;flex-shrink:1;justify-content:flex-start;order:1}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis{margin-bottom:0;margin-top:0}html.theme--documenter-dark .pagination-previous{order:2}html.theme--documenter-dark .pagination-next{order:3}html.theme--documenter-dark .pagination{justify-content:space-between;margin-bottom:0;margin-top:0}html.theme--documenter-dark .pagination.is-centered .pagination-previous{order:1}html.theme--documenter-dark .pagination.is-centered .pagination-list{justify-content:center;order:2}html.theme--documenter-dark .pagination.is-centered .pagination-next{order:3}html.theme--documenter-dark .pagination.is-right .pagination-previous{order:1}html.theme--documenter-dark .pagination.is-right .pagination-next{order:2}html.theme--documenter-dark .pagination.is-right .pagination-list{justify-content:flex-end;order:3}}html.theme--documenter-dark .panel{border-radius:8px;box-shadow:#171717;font-size:1rem}html.theme--documenter-dark .panel:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .panel.is-white .panel-heading{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .panel.is-white .panel-tabs a.is-active{border-bottom-color:#fff}html.theme--documenter-dark .panel.is-white .panel-block.is-active .panel-icon{color:#fff}html.theme--documenter-dark .panel.is-black .panel-heading{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .panel.is-black .panel-tabs a.is-active{border-bottom-color:#0a0a0a}html.theme--documenter-dark .panel.is-black .panel-block.is-active .panel-icon{color:#0a0a0a}html.theme--documenter-dark .panel.is-light .panel-heading{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .panel.is-light .panel-tabs a.is-active{border-bottom-color:#ecf0f1}html.theme--documenter-dark .panel.is-light .panel-block.is-active .panel-icon{color:#ecf0f1}html.theme--documenter-dark .panel.is-dark .panel-heading,html.theme--documenter-dark .content kbd.panel .panel-heading{background-color:#282f2f;color:#fff}html.theme--documenter-dark .panel.is-dark .panel-tabs a.is-active,html.theme--documenter-dark .content kbd.panel .panel-tabs a.is-active{border-bottom-color:#282f2f}html.theme--documenter-dark .panel.is-dark .panel-block.is-active .panel-icon,html.theme--documenter-dark .content kbd.panel .panel-block.is-active .panel-icon{color:#282f2f}html.theme--documenter-dark .panel.is-primary .panel-heading,html.theme--documenter-dark .docstring>section>a.panel.docs-sourcelink .panel-heading{background-color:#375a7f;color:#fff}html.theme--documenter-dark .panel.is-primary .panel-tabs a.is-active,html.theme--documenter-dark .docstring>section>a.panel.docs-sourcelink .panel-tabs a.is-active{border-bottom-color:#375a7f}html.theme--documenter-dark .panel.is-primary .panel-block.is-active .panel-icon,html.theme--documenter-dark .docstring>section>a.panel.docs-sourcelink .panel-block.is-active .panel-icon{color:#375a7f}html.theme--documenter-dark .panel.is-link .panel-heading{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .panel.is-link .panel-tabs a.is-active{border-bottom-color:#1abc9c}html.theme--documenter-dark .panel.is-link .panel-block.is-active .panel-icon{color:#1abc9c}html.theme--documenter-dark .panel.is-info .panel-heading{background-color:#3c5dcd;color:#fff}html.theme--documenter-dark .panel.is-info .panel-tabs a.is-active{border-bottom-color:#3c5dcd}html.theme--documenter-dark .panel.is-info .panel-block.is-active .panel-icon{color:#3c5dcd}html.theme--documenter-dark .panel.is-success .panel-heading{background-color:#259a12;color:#fff}html.theme--documenter-dark .panel.is-success .panel-tabs a.is-active{border-bottom-color:#259a12}html.theme--documenter-dark .panel.is-success .panel-block.is-active .panel-icon{color:#259a12}html.theme--documenter-dark .panel.is-warning .panel-heading{background-color:#f4c72f;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .panel.is-warning .panel-tabs a.is-active{border-bottom-color:#f4c72f}html.theme--documenter-dark .panel.is-warning .panel-block.is-active .panel-icon{color:#f4c72f}html.theme--documenter-dark .panel.is-danger .panel-heading{background-color:#cb3c33;color:#fff}html.theme--documenter-dark .panel.is-danger .panel-tabs a.is-active{border-bottom-color:#cb3c33}html.theme--documenter-dark .panel.is-danger .panel-block.is-active .panel-icon{color:#cb3c33}html.theme--documenter-dark .panel-tabs:not(:last-child),html.theme--documenter-dark .panel-block:not(:last-child){border-bottom:1px solid #ededed}html.theme--documenter-dark .panel-heading{background-color:#343c3d;border-radius:8px 8px 0 0;color:#f2f2f2;font-size:1.25em;font-weight:700;line-height:1.25;padding:0.75em 1em}html.theme--documenter-dark .panel-tabs{align-items:flex-end;display:flex;font-size:.875em;justify-content:center}html.theme--documenter-dark .panel-tabs a{border-bottom:1px solid #5e6d6f;margin-bottom:-1px;padding:0.5em}html.theme--documenter-dark .panel-tabs a.is-active{border-bottom-color:#343c3d;color:#17a689}html.theme--documenter-dark .panel-list a{color:#fff}html.theme--documenter-dark .panel-list a:hover{color:#1abc9c}html.theme--documenter-dark .panel-block{align-items:center;color:#f2f2f2;display:flex;justify-content:flex-start;padding:0.5em 0.75em}html.theme--documenter-dark .panel-block input[type="checkbox"]{margin-right:.75em}html.theme--documenter-dark .panel-block>.control{flex-grow:1;flex-shrink:1;width:100%}html.theme--documenter-dark .panel-block.is-wrapped{flex-wrap:wrap}html.theme--documenter-dark .panel-block.is-active{border-left-color:#1abc9c;color:#17a689}html.theme--documenter-dark .panel-block.is-active .panel-icon{color:#1abc9c}html.theme--documenter-dark .panel-block:last-child{border-bottom-left-radius:8px;border-bottom-right-radius:8px}html.theme--documenter-dark a.panel-block,html.theme--documenter-dark label.panel-block{cursor:pointer}html.theme--documenter-dark a.panel-block:hover,html.theme--documenter-dark label.panel-block:hover{background-color:#282f2f}html.theme--documenter-dark .panel-icon{display:inline-block;font-size:14px;height:1em;line-height:1em;text-align:center;vertical-align:top;width:1em;color:#fff;margin-right:.75em}html.theme--documenter-dark .panel-icon .fa{font-size:inherit;line-height:inherit}html.theme--documenter-dark .tabs{-webkit-overflow-scrolling:touch;align-items:stretch;display:flex;font-size:1rem;justify-content:space-between;overflow:hidden;overflow-x:auto;white-space:nowrap}html.theme--documenter-dark .tabs a{align-items:center;border-bottom-color:#5e6d6f;border-bottom-style:solid;border-bottom-width:1px;color:#fff;display:flex;justify-content:center;margin-bottom:-1px;padding:0.5em 1em;vertical-align:top}html.theme--documenter-dark .tabs a:hover{border-bottom-color:#f2f2f2;color:#f2f2f2}html.theme--documenter-dark .tabs li{display:block}html.theme--documenter-dark .tabs li.is-active a{border-bottom-color:#1abc9c;color:#1abc9c}html.theme--documenter-dark .tabs ul{align-items:center;border-bottom-color:#5e6d6f;border-bottom-style:solid;border-bottom-width:1px;display:flex;flex-grow:1;flex-shrink:0;justify-content:flex-start}html.theme--documenter-dark .tabs ul.is-left{padding-right:0.75em}html.theme--documenter-dark .tabs ul.is-center{flex:none;justify-content:center;padding-left:0.75em;padding-right:0.75em}html.theme--documenter-dark .tabs ul.is-right{justify-content:flex-end;padding-left:0.75em}html.theme--documenter-dark .tabs .icon:first-child{margin-right:.5em}html.theme--documenter-dark .tabs .icon:last-child{margin-left:.5em}html.theme--documenter-dark .tabs.is-centered ul{justify-content:center}html.theme--documenter-dark .tabs.is-right ul{justify-content:flex-end}html.theme--documenter-dark .tabs.is-boxed a{border:1px solid transparent;border-radius:.4em .4em 0 0}html.theme--documenter-dark .tabs.is-boxed a:hover{background-color:#282f2f;border-bottom-color:#5e6d6f}html.theme--documenter-dark .tabs.is-boxed li.is-active a{background-color:#fff;border-color:#5e6d6f;border-bottom-color:rgba(0,0,0,0) !important}html.theme--documenter-dark .tabs.is-fullwidth li{flex-grow:1;flex-shrink:0}html.theme--documenter-dark .tabs.is-toggle a{border-color:#5e6d6f;border-style:solid;border-width:1px;margin-bottom:0;position:relative}html.theme--documenter-dark .tabs.is-toggle a:hover{background-color:#282f2f;border-color:#8c9b9d;z-index:2}html.theme--documenter-dark .tabs.is-toggle li+li{margin-left:-1px}html.theme--documenter-dark .tabs.is-toggle li:first-child a{border-top-left-radius:.4em;border-bottom-left-radius:.4em}html.theme--documenter-dark .tabs.is-toggle li:last-child a{border-top-right-radius:.4em;border-bottom-right-radius:.4em}html.theme--documenter-dark .tabs.is-toggle li.is-active a{background-color:#1abc9c;border-color:#1abc9c;color:#fff;z-index:1}html.theme--documenter-dark .tabs.is-toggle ul{border-bottom:none}html.theme--documenter-dark .tabs.is-toggle.is-toggle-rounded li:first-child a{border-bottom-left-radius:9999px;border-top-left-radius:9999px;padding-left:1.25em}html.theme--documenter-dark .tabs.is-toggle.is-toggle-rounded li:last-child a{border-bottom-right-radius:9999px;border-top-right-radius:9999px;padding-right:1.25em}html.theme--documenter-dark .tabs.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.tabs{font-size:.75rem}html.theme--documenter-dark .tabs.is-medium{font-size:1.25rem}html.theme--documenter-dark .tabs.is-large{font-size:1.5rem}html.theme--documenter-dark .column{display:block;flex-basis:0;flex-grow:1;flex-shrink:1;padding:.75rem}.columns.is-mobile>html.theme--documenter-dark .column.is-narrow{flex:none;width:unset}.columns.is-mobile>html.theme--documenter-dark .column.is-full{flex:none;width:100%}.columns.is-mobile>html.theme--documenter-dark .column.is-three-quarters{flex:none;width:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-two-thirds{flex:none;width:66.6666%}.columns.is-mobile>html.theme--documenter-dark .column.is-half{flex:none;width:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-one-third{flex:none;width:33.3333%}.columns.is-mobile>html.theme--documenter-dark .column.is-one-quarter{flex:none;width:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-one-fifth{flex:none;width:20%}.columns.is-mobile>html.theme--documenter-dark .column.is-two-fifths{flex:none;width:40%}.columns.is-mobile>html.theme--documenter-dark .column.is-three-fifths{flex:none;width:60%}.columns.is-mobile>html.theme--documenter-dark .column.is-four-fifths{flex:none;width:80%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-three-quarters{margin-left:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-two-thirds{margin-left:66.6666%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-half{margin-left:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-one-third{margin-left:33.3333%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-one-quarter{margin-left:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-one-fifth{margin-left:20%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-two-fifths{margin-left:40%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-three-fifths{margin-left:60%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-four-fifths{margin-left:80%}.columns.is-mobile>html.theme--documenter-dark .column.is-0{flex:none;width:0%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-0{margin-left:0%}.columns.is-mobile>html.theme--documenter-dark .column.is-1{flex:none;width:8.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-1{margin-left:8.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-2{flex:none;width:16.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-2{margin-left:16.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-3{flex:none;width:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-3{margin-left:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-4{flex:none;width:33.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-4{margin-left:33.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-5{flex:none;width:41.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-5{margin-left:41.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-6{flex:none;width:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-6{margin-left:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-7{flex:none;width:58.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-7{margin-left:58.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-8{flex:none;width:66.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-8{margin-left:66.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-9{flex:none;width:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-9{margin-left:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-10{flex:none;width:83.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-10{margin-left:83.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-11{flex:none;width:91.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-11{margin-left:91.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-12{flex:none;width:100%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-12{margin-left:100%}@media screen and (max-width: 768px){html.theme--documenter-dark .column.is-narrow-mobile{flex:none;width:unset}html.theme--documenter-dark .column.is-full-mobile{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-mobile{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-mobile{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-mobile{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-mobile{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-mobile{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-mobile{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-mobile{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-mobile{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-mobile{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-mobile{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-mobile{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-mobile{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-mobile{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-mobile{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-mobile{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-mobile{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-mobile{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-mobile{margin-left:80%}html.theme--documenter-dark .column.is-0-mobile{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-mobile{margin-left:0%}html.theme--documenter-dark .column.is-1-mobile{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-mobile{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-mobile{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-mobile{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-mobile{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-mobile{margin-left:25%}html.theme--documenter-dark .column.is-4-mobile{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-mobile{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-mobile{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-mobile{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-mobile{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-mobile{margin-left:50%}html.theme--documenter-dark .column.is-7-mobile{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-mobile{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-mobile{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-mobile{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-mobile{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-mobile{margin-left:75%}html.theme--documenter-dark .column.is-10-mobile{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-mobile{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-mobile{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-mobile{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-mobile{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-mobile{margin-left:100%}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .column.is-narrow,html.theme--documenter-dark .column.is-narrow-tablet{flex:none;width:unset}html.theme--documenter-dark .column.is-full,html.theme--documenter-dark .column.is-full-tablet{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters,html.theme--documenter-dark .column.is-three-quarters-tablet{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds,html.theme--documenter-dark .column.is-two-thirds-tablet{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half,html.theme--documenter-dark .column.is-half-tablet{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third,html.theme--documenter-dark .column.is-one-third-tablet{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter,html.theme--documenter-dark .column.is-one-quarter-tablet{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth,html.theme--documenter-dark .column.is-one-fifth-tablet{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths,html.theme--documenter-dark .column.is-two-fifths-tablet{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths,html.theme--documenter-dark .column.is-three-fifths-tablet{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths,html.theme--documenter-dark .column.is-four-fifths-tablet{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters,html.theme--documenter-dark .column.is-offset-three-quarters-tablet{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds,html.theme--documenter-dark .column.is-offset-two-thirds-tablet{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half,html.theme--documenter-dark .column.is-offset-half-tablet{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third,html.theme--documenter-dark .column.is-offset-one-third-tablet{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter,html.theme--documenter-dark .column.is-offset-one-quarter-tablet{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth,html.theme--documenter-dark .column.is-offset-one-fifth-tablet{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths,html.theme--documenter-dark .column.is-offset-two-fifths-tablet{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths,html.theme--documenter-dark .column.is-offset-three-fifths-tablet{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths,html.theme--documenter-dark .column.is-offset-four-fifths-tablet{margin-left:80%}html.theme--documenter-dark .column.is-0,html.theme--documenter-dark .column.is-0-tablet{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0,html.theme--documenter-dark .column.is-offset-0-tablet{margin-left:0%}html.theme--documenter-dark .column.is-1,html.theme--documenter-dark .column.is-1-tablet{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1,html.theme--documenter-dark .column.is-offset-1-tablet{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2,html.theme--documenter-dark .column.is-2-tablet{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2,html.theme--documenter-dark .column.is-offset-2-tablet{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3,html.theme--documenter-dark .column.is-3-tablet{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3,html.theme--documenter-dark .column.is-offset-3-tablet{margin-left:25%}html.theme--documenter-dark .column.is-4,html.theme--documenter-dark .column.is-4-tablet{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4,html.theme--documenter-dark .column.is-offset-4-tablet{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5,html.theme--documenter-dark .column.is-5-tablet{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5,html.theme--documenter-dark .column.is-offset-5-tablet{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6,html.theme--documenter-dark .column.is-6-tablet{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6,html.theme--documenter-dark .column.is-offset-6-tablet{margin-left:50%}html.theme--documenter-dark .column.is-7,html.theme--documenter-dark .column.is-7-tablet{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7,html.theme--documenter-dark .column.is-offset-7-tablet{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8,html.theme--documenter-dark .column.is-8-tablet{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8,html.theme--documenter-dark .column.is-offset-8-tablet{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9,html.theme--documenter-dark .column.is-9-tablet{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9,html.theme--documenter-dark .column.is-offset-9-tablet{margin-left:75%}html.theme--documenter-dark .column.is-10,html.theme--documenter-dark .column.is-10-tablet{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10,html.theme--documenter-dark .column.is-offset-10-tablet{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11,html.theme--documenter-dark .column.is-11-tablet{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11,html.theme--documenter-dark .column.is-offset-11-tablet{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12,html.theme--documenter-dark .column.is-12-tablet{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12,html.theme--documenter-dark .column.is-offset-12-tablet{margin-left:100%}}@media screen and (max-width: 1055px){html.theme--documenter-dark .column.is-narrow-touch{flex:none;width:unset}html.theme--documenter-dark .column.is-full-touch{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-touch{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-touch{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-touch{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-touch{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-touch{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-touch{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-touch{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-touch{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-touch{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-touch{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-touch{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-touch{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-touch{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-touch{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-touch{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-touch{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-touch{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-touch{margin-left:80%}html.theme--documenter-dark .column.is-0-touch{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-touch{margin-left:0%}html.theme--documenter-dark .column.is-1-touch{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-touch{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-touch{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-touch{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-touch{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-touch{margin-left:25%}html.theme--documenter-dark .column.is-4-touch{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-touch{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-touch{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-touch{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-touch{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-touch{margin-left:50%}html.theme--documenter-dark .column.is-7-touch{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-touch{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-touch{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-touch{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-touch{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-touch{margin-left:75%}html.theme--documenter-dark .column.is-10-touch{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-touch{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-touch{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-touch{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-touch{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-touch{margin-left:100%}}@media screen and (min-width: 1056px){html.theme--documenter-dark .column.is-narrow-desktop{flex:none;width:unset}html.theme--documenter-dark .column.is-full-desktop{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-desktop{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-desktop{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-desktop{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-desktop{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-desktop{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-desktop{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-desktop{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-desktop{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-desktop{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-desktop{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-desktop{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-desktop{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-desktop{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-desktop{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-desktop{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-desktop{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-desktop{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-desktop{margin-left:80%}html.theme--documenter-dark .column.is-0-desktop{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-desktop{margin-left:0%}html.theme--documenter-dark .column.is-1-desktop{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-desktop{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-desktop{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-desktop{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-desktop{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-desktop{margin-left:25%}html.theme--documenter-dark .column.is-4-desktop{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-desktop{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-desktop{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-desktop{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-desktop{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-desktop{margin-left:50%}html.theme--documenter-dark .column.is-7-desktop{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-desktop{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-desktop{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-desktop{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-desktop{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-desktop{margin-left:75%}html.theme--documenter-dark .column.is-10-desktop{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-desktop{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-desktop{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-desktop{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-desktop{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-desktop{margin-left:100%}}@media screen and (min-width: 1216px){html.theme--documenter-dark .column.is-narrow-widescreen{flex:none;width:unset}html.theme--documenter-dark .column.is-full-widescreen{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-widescreen{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-widescreen{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-widescreen{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-widescreen{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-widescreen{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-widescreen{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-widescreen{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-widescreen{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-widescreen{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-widescreen{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-widescreen{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-widescreen{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-widescreen{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-widescreen{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-widescreen{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-widescreen{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-widescreen{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-widescreen{margin-left:80%}html.theme--documenter-dark .column.is-0-widescreen{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-widescreen{margin-left:0%}html.theme--documenter-dark .column.is-1-widescreen{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-widescreen{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-widescreen{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-widescreen{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-widescreen{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-widescreen{margin-left:25%}html.theme--documenter-dark .column.is-4-widescreen{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-widescreen{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-widescreen{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-widescreen{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-widescreen{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-widescreen{margin-left:50%}html.theme--documenter-dark .column.is-7-widescreen{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-widescreen{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-widescreen{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-widescreen{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-widescreen{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-widescreen{margin-left:75%}html.theme--documenter-dark .column.is-10-widescreen{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-widescreen{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-widescreen{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-widescreen{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-widescreen{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-widescreen{margin-left:100%}}@media screen and (min-width: 1408px){html.theme--documenter-dark .column.is-narrow-fullhd{flex:none;width:unset}html.theme--documenter-dark .column.is-full-fullhd{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-fullhd{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-fullhd{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-fullhd{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-fullhd{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-fullhd{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-fullhd{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-fullhd{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-fullhd{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-fullhd{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-fullhd{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-fullhd{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-fullhd{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-fullhd{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-fullhd{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-fullhd{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-fullhd{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-fullhd{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-fullhd{margin-left:80%}html.theme--documenter-dark .column.is-0-fullhd{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-fullhd{margin-left:0%}html.theme--documenter-dark .column.is-1-fullhd{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-fullhd{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-fullhd{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-fullhd{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-fullhd{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-fullhd{margin-left:25%}html.theme--documenter-dark .column.is-4-fullhd{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-fullhd{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-fullhd{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-fullhd{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-fullhd{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-fullhd{margin-left:50%}html.theme--documenter-dark .column.is-7-fullhd{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-fullhd{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-fullhd{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-fullhd{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-fullhd{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-fullhd{margin-left:75%}html.theme--documenter-dark .column.is-10-fullhd{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-fullhd{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-fullhd{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-fullhd{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-fullhd{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-fullhd{margin-left:100%}}html.theme--documenter-dark .columns{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--documenter-dark .columns:last-child{margin-bottom:-.75rem}html.theme--documenter-dark .columns:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}html.theme--documenter-dark .columns.is-centered{justify-content:center}html.theme--documenter-dark .columns.is-gapless{margin-left:0;margin-right:0;margin-top:0}html.theme--documenter-dark .columns.is-gapless>.column{margin:0;padding:0 !important}html.theme--documenter-dark .columns.is-gapless:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .columns.is-gapless:last-child{margin-bottom:0}html.theme--documenter-dark .columns.is-mobile{display:flex}html.theme--documenter-dark .columns.is-multiline{flex-wrap:wrap}html.theme--documenter-dark .columns.is-vcentered{align-items:center}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns:not(.is-desktop){display:flex}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-desktop{display:flex}}html.theme--documenter-dark .columns.is-variable{--columnGap: 0.75rem;margin-left:calc(-1 * var(--columnGap));margin-right:calc(-1 * var(--columnGap))}html.theme--documenter-dark .columns.is-variable>.column{padding-left:var(--columnGap);padding-right:var(--columnGap)}html.theme--documenter-dark .columns.is-variable.is-0{--columnGap: 0rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-0-mobile{--columnGap: 0rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-0-tablet{--columnGap: 0rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-0-tablet-only{--columnGap: 0rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-0-touch{--columnGap: 0rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-0-desktop{--columnGap: 0rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-0-desktop-only{--columnGap: 0rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-0-widescreen{--columnGap: 0rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-0-widescreen-only{--columnGap: 0rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-0-fullhd{--columnGap: 0rem}}html.theme--documenter-dark .columns.is-variable.is-1{--columnGap: .25rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-1-mobile{--columnGap: .25rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-1-tablet{--columnGap: .25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-1-tablet-only{--columnGap: .25rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-1-touch{--columnGap: .25rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-1-desktop{--columnGap: .25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-1-desktop-only{--columnGap: .25rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-1-widescreen{--columnGap: .25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-1-widescreen-only{--columnGap: .25rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-1-fullhd{--columnGap: .25rem}}html.theme--documenter-dark .columns.is-variable.is-2{--columnGap: .5rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-2-mobile{--columnGap: .5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-2-tablet{--columnGap: .5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-2-tablet-only{--columnGap: .5rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-2-touch{--columnGap: .5rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-2-desktop{--columnGap: .5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-2-desktop-only{--columnGap: .5rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-2-widescreen{--columnGap: .5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-2-widescreen-only{--columnGap: .5rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-2-fullhd{--columnGap: .5rem}}html.theme--documenter-dark .columns.is-variable.is-3{--columnGap: .75rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-3-mobile{--columnGap: .75rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-3-tablet{--columnGap: .75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-3-tablet-only{--columnGap: .75rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-3-touch{--columnGap: .75rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-3-desktop{--columnGap: .75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-3-desktop-only{--columnGap: .75rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-3-widescreen{--columnGap: .75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-3-widescreen-only{--columnGap: .75rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-3-fullhd{--columnGap: .75rem}}html.theme--documenter-dark .columns.is-variable.is-4{--columnGap: 1rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-4-mobile{--columnGap: 1rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-4-tablet{--columnGap: 1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-4-tablet-only{--columnGap: 1rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-4-touch{--columnGap: 1rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-4-desktop{--columnGap: 1rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-4-desktop-only{--columnGap: 1rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-4-widescreen{--columnGap: 1rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-4-widescreen-only{--columnGap: 1rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-4-fullhd{--columnGap: 1rem}}html.theme--documenter-dark .columns.is-variable.is-5{--columnGap: 1.25rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-5-mobile{--columnGap: 1.25rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-5-tablet{--columnGap: 1.25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-5-tablet-only{--columnGap: 1.25rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-5-touch{--columnGap: 1.25rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-5-desktop{--columnGap: 1.25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-5-desktop-only{--columnGap: 1.25rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-5-widescreen{--columnGap: 1.25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-5-widescreen-only{--columnGap: 1.25rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-5-fullhd{--columnGap: 1.25rem}}html.theme--documenter-dark .columns.is-variable.is-6{--columnGap: 1.5rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-6-mobile{--columnGap: 1.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-6-tablet{--columnGap: 1.5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-6-tablet-only{--columnGap: 1.5rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-6-touch{--columnGap: 1.5rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-6-desktop{--columnGap: 1.5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-6-desktop-only{--columnGap: 1.5rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-6-widescreen{--columnGap: 1.5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-6-widescreen-only{--columnGap: 1.5rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-6-fullhd{--columnGap: 1.5rem}}html.theme--documenter-dark .columns.is-variable.is-7{--columnGap: 1.75rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-7-mobile{--columnGap: 1.75rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-7-tablet{--columnGap: 1.75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-7-tablet-only{--columnGap: 1.75rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-7-touch{--columnGap: 1.75rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-7-desktop{--columnGap: 1.75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-7-desktop-only{--columnGap: 1.75rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-7-widescreen{--columnGap: 1.75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-7-widescreen-only{--columnGap: 1.75rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-7-fullhd{--columnGap: 1.75rem}}html.theme--documenter-dark .columns.is-variable.is-8{--columnGap: 2rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-8-mobile{--columnGap: 2rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-8-tablet{--columnGap: 2rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-8-tablet-only{--columnGap: 2rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-8-touch{--columnGap: 2rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-8-desktop{--columnGap: 2rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-8-desktop-only{--columnGap: 2rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-8-widescreen{--columnGap: 2rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-8-widescreen-only{--columnGap: 2rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-8-fullhd{--columnGap: 2rem}}html.theme--documenter-dark .tile{align-items:stretch;display:block;flex-basis:0;flex-grow:1;flex-shrink:1;min-height:min-content}html.theme--documenter-dark .tile.is-ancestor{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--documenter-dark .tile.is-ancestor:last-child{margin-bottom:-.75rem}html.theme--documenter-dark .tile.is-ancestor:not(:last-child){margin-bottom:.75rem}html.theme--documenter-dark .tile.is-child{margin:0 !important}html.theme--documenter-dark .tile.is-parent{padding:.75rem}html.theme--documenter-dark .tile.is-vertical{flex-direction:column}html.theme--documenter-dark .tile.is-vertical>.tile.is-child:not(:last-child){margin-bottom:1.5rem !important}@media screen and (min-width: 769px),print{html.theme--documenter-dark .tile:not(.is-child){display:flex}html.theme--documenter-dark .tile.is-1{flex:none;width:8.33333337%}html.theme--documenter-dark .tile.is-2{flex:none;width:16.66666674%}html.theme--documenter-dark .tile.is-3{flex:none;width:25%}html.theme--documenter-dark .tile.is-4{flex:none;width:33.33333337%}html.theme--documenter-dark .tile.is-5{flex:none;width:41.66666674%}html.theme--documenter-dark .tile.is-6{flex:none;width:50%}html.theme--documenter-dark .tile.is-7{flex:none;width:58.33333337%}html.theme--documenter-dark .tile.is-8{flex:none;width:66.66666674%}html.theme--documenter-dark .tile.is-9{flex:none;width:75%}html.theme--documenter-dark .tile.is-10{flex:none;width:83.33333337%}html.theme--documenter-dark .tile.is-11{flex:none;width:91.66666674%}html.theme--documenter-dark .tile.is-12{flex:none;width:100%}}html.theme--documenter-dark .hero{align-items:stretch;display:flex;flex-direction:column;justify-content:space-between}html.theme--documenter-dark .hero .navbar{background:none}html.theme--documenter-dark .hero .tabs ul{border-bottom:none}html.theme--documenter-dark .hero.is-white{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-white strong{color:inherit}html.theme--documenter-dark .hero.is-white .title{color:#0a0a0a}html.theme--documenter-dark .hero.is-white .subtitle{color:rgba(10,10,10,0.9)}html.theme--documenter-dark .hero.is-white .subtitle a:not(.button),html.theme--documenter-dark .hero.is-white .subtitle strong{color:#0a0a0a}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-white .navbar-menu{background-color:#fff}}html.theme--documenter-dark .hero.is-white .navbar-item,html.theme--documenter-dark .hero.is-white .navbar-link{color:rgba(10,10,10,0.7)}html.theme--documenter-dark .hero.is-white a.navbar-item:hover,html.theme--documenter-dark .hero.is-white a.navbar-item.is-active,html.theme--documenter-dark .hero.is-white .navbar-link:hover,html.theme--documenter-dark .hero.is-white .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .hero.is-white .tabs a{color:#0a0a0a;opacity:0.9}html.theme--documenter-dark .hero.is-white .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-white .tabs li.is-active a{color:#fff !important;opacity:1}html.theme--documenter-dark .hero.is-white .tabs.is-boxed a,html.theme--documenter-dark .hero.is-white .tabs.is-toggle a{color:#0a0a0a}html.theme--documenter-dark .hero.is-white .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-white .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-white .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-white .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-white .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-white .tabs.is-toggle li.is-active a:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--documenter-dark .hero.is-white.is-bold{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-white.is-bold .navbar-menu{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}}html.theme--documenter-dark .hero.is-black{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-black strong{color:inherit}html.theme--documenter-dark .hero.is-black .title{color:#fff}html.theme--documenter-dark .hero.is-black .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-black .subtitle a:not(.button),html.theme--documenter-dark .hero.is-black .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-black .navbar-menu{background-color:#0a0a0a}}html.theme--documenter-dark .hero.is-black .navbar-item,html.theme--documenter-dark .hero.is-black .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-black a.navbar-item:hover,html.theme--documenter-dark .hero.is-black a.navbar-item.is-active,html.theme--documenter-dark .hero.is-black .navbar-link:hover,html.theme--documenter-dark .hero.is-black .navbar-link.is-active{background-color:#000;color:#fff}html.theme--documenter-dark .hero.is-black .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-black .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-black .tabs li.is-active a{color:#0a0a0a !important;opacity:1}html.theme--documenter-dark .hero.is-black .tabs.is-boxed a,html.theme--documenter-dark .hero.is-black .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-black .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-black .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-black .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-black .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-black .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-black .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--documenter-dark .hero.is-black.is-bold{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-black.is-bold .navbar-menu{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}}html.theme--documenter-dark .hero.is-light{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-light strong{color:inherit}html.theme--documenter-dark .hero.is-light .title{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light .subtitle{color:rgba(0,0,0,0.9)}html.theme--documenter-dark .hero.is-light .subtitle a:not(.button),html.theme--documenter-dark .hero.is-light .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-light .navbar-menu{background-color:#ecf0f1}}html.theme--documenter-dark .hero.is-light .navbar-item,html.theme--documenter-dark .hero.is-light .navbar-link{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light a.navbar-item:hover,html.theme--documenter-dark .hero.is-light a.navbar-item.is-active,html.theme--documenter-dark .hero.is-light .navbar-link:hover,html.theme--documenter-dark .hero.is-light .navbar-link.is-active{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--documenter-dark .hero.is-light .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-light .tabs li.is-active a{color:#ecf0f1 !important;opacity:1}html.theme--documenter-dark .hero.is-light .tabs.is-boxed a,html.theme--documenter-dark .hero.is-light .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-light .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-light .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-light .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-light .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-light .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#ecf0f1}html.theme--documenter-dark .hero.is-light.is-bold{background-image:linear-gradient(141deg, #cadfe0 0%, #ecf0f1 71%, #fafbfc 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-light.is-bold .navbar-menu{background-image:linear-gradient(141deg, #cadfe0 0%, #ecf0f1 71%, #fafbfc 100%)}}html.theme--documenter-dark .hero.is-dark,html.theme--documenter-dark .content kbd.hero{background-color:#282f2f;color:#fff}html.theme--documenter-dark .hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .content kbd.hero a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-dark strong,html.theme--documenter-dark .content kbd.hero strong{color:inherit}html.theme--documenter-dark .hero.is-dark .title,html.theme--documenter-dark .content kbd.hero .title{color:#fff}html.theme--documenter-dark .hero.is-dark .subtitle,html.theme--documenter-dark .content kbd.hero .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-dark .subtitle a:not(.button),html.theme--documenter-dark .content kbd.hero .subtitle a:not(.button),html.theme--documenter-dark .hero.is-dark .subtitle strong,html.theme--documenter-dark .content kbd.hero .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-dark .navbar-menu,html.theme--documenter-dark .content kbd.hero .navbar-menu{background-color:#282f2f}}html.theme--documenter-dark .hero.is-dark .navbar-item,html.theme--documenter-dark .content kbd.hero .navbar-item,html.theme--documenter-dark .hero.is-dark .navbar-link,html.theme--documenter-dark .content kbd.hero .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-dark a.navbar-item:hover,html.theme--documenter-dark .content kbd.hero a.navbar-item:hover,html.theme--documenter-dark .hero.is-dark a.navbar-item.is-active,html.theme--documenter-dark .content kbd.hero a.navbar-item.is-active,html.theme--documenter-dark .hero.is-dark .navbar-link:hover,html.theme--documenter-dark .content kbd.hero .navbar-link:hover,html.theme--documenter-dark .hero.is-dark .navbar-link.is-active,html.theme--documenter-dark .content kbd.hero .navbar-link.is-active{background-color:#1d2122;color:#fff}html.theme--documenter-dark .hero.is-dark .tabs a,html.theme--documenter-dark .content kbd.hero .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-dark .tabs a:hover,html.theme--documenter-dark .content kbd.hero .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-dark .tabs li.is-active a,html.theme--documenter-dark .content kbd.hero .tabs li.is-active a{color:#282f2f !important;opacity:1}html.theme--documenter-dark .hero.is-dark .tabs.is-boxed a,html.theme--documenter-dark .content kbd.hero .tabs.is-boxed a,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle a,html.theme--documenter-dark .content kbd.hero .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-dark .tabs.is-boxed a:hover,html.theme--documenter-dark .content kbd.hero .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle a:hover,html.theme--documenter-dark .content kbd.hero .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-dark .tabs.is-boxed li.is-active a,html.theme--documenter-dark .content kbd.hero .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-dark .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle li.is-active a,html.theme--documenter-dark .content kbd.hero .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#282f2f}html.theme--documenter-dark .hero.is-dark.is-bold,html.theme--documenter-dark .content kbd.hero.is-bold{background-image:linear-gradient(141deg, #0f1615 0%, #282f2f 71%, #313c40 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-dark.is-bold .navbar-menu,html.theme--documenter-dark .content kbd.hero.is-bold .navbar-menu{background-image:linear-gradient(141deg, #0f1615 0%, #282f2f 71%, #313c40 100%)}}html.theme--documenter-dark .hero.is-primary,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink{background-color:#375a7f;color:#fff}html.theme--documenter-dark .hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-primary strong,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink strong{color:inherit}html.theme--documenter-dark .hero.is-primary .title,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .title{color:#fff}html.theme--documenter-dark .hero.is-primary .subtitle,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-primary .subtitle a:not(.button),html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .subtitle a:not(.button),html.theme--documenter-dark .hero.is-primary .subtitle strong,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-primary .navbar-menu,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-menu{background-color:#375a7f}}html.theme--documenter-dark .hero.is-primary .navbar-item,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-item,html.theme--documenter-dark .hero.is-primary .navbar-link,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-primary a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink a.navbar-item:hover,html.theme--documenter-dark .hero.is-primary a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink a.navbar-item.is-active,html.theme--documenter-dark .hero.is-primary .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-link:hover,html.theme--documenter-dark .hero.is-primary .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-link.is-active{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .hero.is-primary .tabs a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-primary .tabs a:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-primary .tabs li.is-active a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs li.is-active a{color:#375a7f !important;opacity:1}html.theme--documenter-dark .hero.is-primary .tabs.is-boxed a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-primary .tabs.is-boxed a:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle a:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-primary .tabs.is-boxed li.is-active a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-primary .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle li.is-active a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#375a7f}html.theme--documenter-dark .hero.is-primary.is-bold,html.theme--documenter-dark .docstring>section>a.hero.is-bold.docs-sourcelink{background-image:linear-gradient(141deg, #214b62 0%, #375a7f 71%, #3a5796 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-primary.is-bold .navbar-menu,html.theme--documenter-dark .docstring>section>a.hero.is-bold.docs-sourcelink .navbar-menu{background-image:linear-gradient(141deg, #214b62 0%, #375a7f 71%, #3a5796 100%)}}html.theme--documenter-dark .hero.is-link{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-link strong{color:inherit}html.theme--documenter-dark .hero.is-link .title{color:#fff}html.theme--documenter-dark .hero.is-link .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-link .subtitle a:not(.button),html.theme--documenter-dark .hero.is-link .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-link .navbar-menu{background-color:#1abc9c}}html.theme--documenter-dark .hero.is-link .navbar-item,html.theme--documenter-dark .hero.is-link .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-link a.navbar-item:hover,html.theme--documenter-dark .hero.is-link a.navbar-item.is-active,html.theme--documenter-dark .hero.is-link .navbar-link:hover,html.theme--documenter-dark .hero.is-link .navbar-link.is-active{background-color:#17a689;color:#fff}html.theme--documenter-dark .hero.is-link .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-link .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-link .tabs li.is-active a{color:#1abc9c !important;opacity:1}html.theme--documenter-dark .hero.is-link .tabs.is-boxed a,html.theme--documenter-dark .hero.is-link .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-link .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-link .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-link .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-link .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-link .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-link .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#1abc9c}html.theme--documenter-dark .hero.is-link.is-bold{background-image:linear-gradient(141deg, #0c9764 0%, #1abc9c 71%, #17d8d2 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-link.is-bold .navbar-menu{background-image:linear-gradient(141deg, #0c9764 0%, #1abc9c 71%, #17d8d2 100%)}}html.theme--documenter-dark .hero.is-info{background-color:#3c5dcd;color:#fff}html.theme--documenter-dark .hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-info strong{color:inherit}html.theme--documenter-dark .hero.is-info .title{color:#fff}html.theme--documenter-dark .hero.is-info .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-info .subtitle a:not(.button),html.theme--documenter-dark .hero.is-info .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-info .navbar-menu{background-color:#3c5dcd}}html.theme--documenter-dark .hero.is-info .navbar-item,html.theme--documenter-dark .hero.is-info .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-info a.navbar-item:hover,html.theme--documenter-dark .hero.is-info a.navbar-item.is-active,html.theme--documenter-dark .hero.is-info .navbar-link:hover,html.theme--documenter-dark .hero.is-info .navbar-link.is-active{background-color:#3151bf;color:#fff}html.theme--documenter-dark .hero.is-info .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-info .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-info .tabs li.is-active a{color:#3c5dcd !important;opacity:1}html.theme--documenter-dark .hero.is-info .tabs.is-boxed a,html.theme--documenter-dark .hero.is-info .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-info .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-info .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-info .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-info .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-info .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-info .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#3c5dcd}html.theme--documenter-dark .hero.is-info.is-bold{background-image:linear-gradient(141deg, #215bb5 0%, #3c5dcd 71%, #4b53d8 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-info.is-bold .navbar-menu{background-image:linear-gradient(141deg, #215bb5 0%, #3c5dcd 71%, #4b53d8 100%)}}html.theme--documenter-dark .hero.is-success{background-color:#259a12;color:#fff}html.theme--documenter-dark .hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-success strong{color:inherit}html.theme--documenter-dark .hero.is-success .title{color:#fff}html.theme--documenter-dark .hero.is-success .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-success .subtitle a:not(.button),html.theme--documenter-dark .hero.is-success .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-success .navbar-menu{background-color:#259a12}}html.theme--documenter-dark .hero.is-success .navbar-item,html.theme--documenter-dark .hero.is-success .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-success a.navbar-item:hover,html.theme--documenter-dark .hero.is-success a.navbar-item.is-active,html.theme--documenter-dark .hero.is-success .navbar-link:hover,html.theme--documenter-dark .hero.is-success .navbar-link.is-active{background-color:#20830f;color:#fff}html.theme--documenter-dark .hero.is-success .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-success .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-success .tabs li.is-active a{color:#259a12 !important;opacity:1}html.theme--documenter-dark .hero.is-success .tabs.is-boxed a,html.theme--documenter-dark .hero.is-success .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-success .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-success .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-success .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-success .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-success .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-success .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#259a12}html.theme--documenter-dark .hero.is-success.is-bold{background-image:linear-gradient(141deg, #287207 0%, #259a12 71%, #10b614 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-success.is-bold .navbar-menu{background-image:linear-gradient(141deg, #287207 0%, #259a12 71%, #10b614 100%)}}html.theme--documenter-dark .hero.is-warning{background-color:#f4c72f;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-warning strong{color:inherit}html.theme--documenter-dark .hero.is-warning .title{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-warning .subtitle{color:rgba(0,0,0,0.9)}html.theme--documenter-dark .hero.is-warning .subtitle a:not(.button),html.theme--documenter-dark .hero.is-warning .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-warning .navbar-menu{background-color:#f4c72f}}html.theme--documenter-dark .hero.is-warning .navbar-item,html.theme--documenter-dark .hero.is-warning .navbar-link{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-warning a.navbar-item:hover,html.theme--documenter-dark .hero.is-warning a.navbar-item.is-active,html.theme--documenter-dark .hero.is-warning .navbar-link:hover,html.theme--documenter-dark .hero.is-warning .navbar-link.is-active{background-color:#f3c017;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-warning .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--documenter-dark .hero.is-warning .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-warning .tabs li.is-active a{color:#f4c72f !important;opacity:1}html.theme--documenter-dark .hero.is-warning .tabs.is-boxed a,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-warning .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-warning .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-warning .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#f4c72f}html.theme--documenter-dark .hero.is-warning.is-bold{background-image:linear-gradient(141deg, #f09100 0%, #f4c72f 71%, #faef42 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-warning.is-bold .navbar-menu{background-image:linear-gradient(141deg, #f09100 0%, #f4c72f 71%, #faef42 100%)}}html.theme--documenter-dark .hero.is-danger{background-color:#cb3c33;color:#fff}html.theme--documenter-dark .hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-danger strong{color:inherit}html.theme--documenter-dark .hero.is-danger .title{color:#fff}html.theme--documenter-dark .hero.is-danger .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-danger .subtitle a:not(.button),html.theme--documenter-dark .hero.is-danger .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-danger .navbar-menu{background-color:#cb3c33}}html.theme--documenter-dark .hero.is-danger .navbar-item,html.theme--documenter-dark .hero.is-danger .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-danger a.navbar-item:hover,html.theme--documenter-dark .hero.is-danger a.navbar-item.is-active,html.theme--documenter-dark .hero.is-danger .navbar-link:hover,html.theme--documenter-dark .hero.is-danger .navbar-link.is-active{background-color:#b7362e;color:#fff}html.theme--documenter-dark .hero.is-danger .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-danger .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-danger .tabs li.is-active a{color:#cb3c33 !important;opacity:1}html.theme--documenter-dark .hero.is-danger .tabs.is-boxed a,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-danger .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-danger .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-danger .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#cb3c33}html.theme--documenter-dark .hero.is-danger.is-bold{background-image:linear-gradient(141deg, #ac1f2e 0%, #cb3c33 71%, #d66341 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-danger.is-bold .navbar-menu{background-image:linear-gradient(141deg, #ac1f2e 0%, #cb3c33 71%, #d66341 100%)}}html.theme--documenter-dark .hero.is-small .hero-body,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.hero .hero-body{padding:1.5rem}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero.is-medium .hero-body{padding:9rem 4.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero.is-large .hero-body{padding:18rem 6rem}}html.theme--documenter-dark .hero.is-halfheight .hero-body,html.theme--documenter-dark .hero.is-fullheight .hero-body,html.theme--documenter-dark .hero.is-fullheight-with-navbar .hero-body{align-items:center;display:flex}html.theme--documenter-dark .hero.is-halfheight .hero-body>.container,html.theme--documenter-dark .hero.is-fullheight .hero-body>.container,html.theme--documenter-dark .hero.is-fullheight-with-navbar .hero-body>.container{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .hero.is-halfheight{min-height:50vh}html.theme--documenter-dark .hero.is-fullheight{min-height:100vh}html.theme--documenter-dark .hero-video{overflow:hidden}html.theme--documenter-dark .hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;transform:translate3d(-50%, -50%, 0)}html.theme--documenter-dark .hero-video.is-transparent{opacity:0.3}@media screen and (max-width: 768px){html.theme--documenter-dark .hero-video{display:none}}html.theme--documenter-dark .hero-buttons{margin-top:1.5rem}@media screen and (max-width: 768px){html.theme--documenter-dark .hero-buttons .button{display:flex}html.theme--documenter-dark .hero-buttons .button:not(:last-child){margin-bottom:0.75rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero-buttons{display:flex;justify-content:center}html.theme--documenter-dark .hero-buttons .button:not(:last-child){margin-right:1.5rem}}html.theme--documenter-dark .hero-head,html.theme--documenter-dark .hero-foot{flex-grow:0;flex-shrink:0}html.theme--documenter-dark .hero-body{flex-grow:1;flex-shrink:0;padding:3rem 1.5rem}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero-body{padding:3rem 3rem}}html.theme--documenter-dark .section{padding:3rem 1.5rem}@media screen and (min-width: 1056px){html.theme--documenter-dark .section{padding:3rem 3rem}html.theme--documenter-dark .section.is-medium{padding:9rem 4.5rem}html.theme--documenter-dark .section.is-large{padding:18rem 6rem}}html.theme--documenter-dark .footer{background-color:#282f2f;padding:3rem 1.5rem 6rem}html.theme--documenter-dark hr{height:1px}html.theme--documenter-dark h6{text-transform:uppercase;letter-spacing:0.5px}html.theme--documenter-dark .hero{background-color:#343c3d}html.theme--documenter-dark a{transition:all 200ms ease}html.theme--documenter-dark .button{transition:all 200ms ease;border-width:1px;color:#fff}html.theme--documenter-dark .button.is-active,html.theme--documenter-dark .button.is-focused,html.theme--documenter-dark .button:active,html.theme--documenter-dark .button:focus{box-shadow:0 0 0 2px rgba(140,155,157,0.5)}html.theme--documenter-dark .button.is-white.is-hovered,html.theme--documenter-dark .button.is-white:hover{background-color:#fff}html.theme--documenter-dark .button.is-white.is-active,html.theme--documenter-dark .button.is-white.is-focused,html.theme--documenter-dark .button.is-white:active,html.theme--documenter-dark .button.is-white:focus{border-color:#fff;box-shadow:0 0 0 2px rgba(255,255,255,0.5)}html.theme--documenter-dark .button.is-black.is-hovered,html.theme--documenter-dark .button.is-black:hover{background-color:#1d1d1d}html.theme--documenter-dark .button.is-black.is-active,html.theme--documenter-dark .button.is-black.is-focused,html.theme--documenter-dark .button.is-black:active,html.theme--documenter-dark .button.is-black:focus{border-color:#0a0a0a;box-shadow:0 0 0 2px rgba(10,10,10,0.5)}html.theme--documenter-dark .button.is-light.is-hovered,html.theme--documenter-dark .button.is-light:hover{background-color:#fff}html.theme--documenter-dark .button.is-light.is-active,html.theme--documenter-dark .button.is-light.is-focused,html.theme--documenter-dark .button.is-light:active,html.theme--documenter-dark .button.is-light:focus{border-color:#ecf0f1;box-shadow:0 0 0 2px rgba(236,240,241,0.5)}html.theme--documenter-dark .button.is-dark.is-hovered,html.theme--documenter-dark .content kbd.button.is-hovered,html.theme--documenter-dark .button.is-dark:hover,html.theme--documenter-dark .content kbd.button:hover{background-color:#3a4344}html.theme--documenter-dark .button.is-dark.is-active,html.theme--documenter-dark .content kbd.button.is-active,html.theme--documenter-dark .button.is-dark.is-focused,html.theme--documenter-dark .content kbd.button.is-focused,html.theme--documenter-dark .button.is-dark:active,html.theme--documenter-dark .content kbd.button:active,html.theme--documenter-dark .button.is-dark:focus,html.theme--documenter-dark .content kbd.button:focus{border-color:#282f2f;box-shadow:0 0 0 2px rgba(40,47,47,0.5)}html.theme--documenter-dark .button.is-primary.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-hovered.docs-sourcelink,html.theme--documenter-dark .button.is-primary:hover,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:hover{background-color:#436d9a}html.theme--documenter-dark .button.is-primary.is-active,html.theme--documenter-dark .docstring>section>a.button.is-active.docs-sourcelink,html.theme--documenter-dark .button.is-primary.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-focused.docs-sourcelink,html.theme--documenter-dark .button.is-primary:active,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:active,html.theme--documenter-dark .button.is-primary:focus,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:focus{border-color:#375a7f;box-shadow:0 0 0 2px rgba(55,90,127,0.5)}html.theme--documenter-dark .button.is-link.is-hovered,html.theme--documenter-dark .button.is-link:hover{background-color:#1fdeb8}html.theme--documenter-dark .button.is-link.is-active,html.theme--documenter-dark .button.is-link.is-focused,html.theme--documenter-dark .button.is-link:active,html.theme--documenter-dark .button.is-link:focus{border-color:#1abc9c;box-shadow:0 0 0 2px rgba(26,188,156,0.5)}html.theme--documenter-dark .button.is-info.is-hovered,html.theme--documenter-dark .button.is-info:hover{background-color:#5a76d5}html.theme--documenter-dark .button.is-info.is-active,html.theme--documenter-dark .button.is-info.is-focused,html.theme--documenter-dark .button.is-info:active,html.theme--documenter-dark .button.is-info:focus{border-color:#3c5dcd;box-shadow:0 0 0 2px rgba(60,93,205,0.5)}html.theme--documenter-dark .button.is-success.is-hovered,html.theme--documenter-dark .button.is-success:hover{background-color:#2dbc16}html.theme--documenter-dark .button.is-success.is-active,html.theme--documenter-dark .button.is-success.is-focused,html.theme--documenter-dark .button.is-success:active,html.theme--documenter-dark .button.is-success:focus{border-color:#259a12;box-shadow:0 0 0 2px rgba(37,154,18,0.5)}html.theme--documenter-dark .button.is-warning.is-hovered,html.theme--documenter-dark .button.is-warning:hover{background-color:#f6d153}html.theme--documenter-dark .button.is-warning.is-active,html.theme--documenter-dark .button.is-warning.is-focused,html.theme--documenter-dark .button.is-warning:active,html.theme--documenter-dark .button.is-warning:focus{border-color:#f4c72f;box-shadow:0 0 0 2px rgba(244,199,47,0.5)}html.theme--documenter-dark .button.is-danger.is-hovered,html.theme--documenter-dark .button.is-danger:hover{background-color:#d35951}html.theme--documenter-dark .button.is-danger.is-active,html.theme--documenter-dark .button.is-danger.is-focused,html.theme--documenter-dark .button.is-danger:active,html.theme--documenter-dark .button.is-danger:focus{border-color:#cb3c33;box-shadow:0 0 0 2px rgba(203,60,51,0.5)}html.theme--documenter-dark .label{color:#dbdee0}html.theme--documenter-dark .button,html.theme--documenter-dark .control.has-icons-left .icon,html.theme--documenter-dark .control.has-icons-right .icon,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .select,html.theme--documenter-dark .select select,html.theme--documenter-dark .textarea{height:2.5em}html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark .textarea{transition:all 200ms ease;box-shadow:none;border-width:1px;padding-left:1em;padding-right:1em}html.theme--documenter-dark .select:after,html.theme--documenter-dark .select select{border-width:1px}html.theme--documenter-dark .control.has-addons .button,html.theme--documenter-dark .control.has-addons .input,html.theme--documenter-dark .control.has-addons #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .control.has-addons form.docs-search>input,html.theme--documenter-dark .control.has-addons .select{margin-right:-1px}html.theme--documenter-dark .notification{background-color:#343c3d}html.theme--documenter-dark .card{box-shadow:none;border:1px solid #343c3d;background-color:#282f2f;border-radius:.4em}html.theme--documenter-dark .card .card-image img{border-radius:.4em .4em 0 0}html.theme--documenter-dark .card .card-header{box-shadow:none;background-color:rgba(18,18,18,0.2);border-radius:.4em .4em 0 0}html.theme--documenter-dark .card .card-footer{background-color:rgba(18,18,18,0.2)}html.theme--documenter-dark .card .card-footer,html.theme--documenter-dark .card .card-footer-item{border-width:1px;border-color:#343c3d}html.theme--documenter-dark .notification.is-white a:not(.button){color:#0a0a0a;text-decoration:underline}html.theme--documenter-dark .notification.is-black a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-light a:not(.button){color:rgba(0,0,0,0.7);text-decoration:underline}html.theme--documenter-dark .notification.is-dark a:not(.button),html.theme--documenter-dark .content kbd.notification a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-primary a:not(.button),html.theme--documenter-dark .docstring>section>a.notification.docs-sourcelink a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-link a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-info a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-success a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-warning a:not(.button){color:rgba(0,0,0,0.7);text-decoration:underline}html.theme--documenter-dark .notification.is-danger a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .tag,html.theme--documenter-dark .content kbd,html.theme--documenter-dark .docstring>section>a.docs-sourcelink{border-radius:.4em}html.theme--documenter-dark .menu-list a{transition:all 300ms ease}html.theme--documenter-dark .modal-card-body{background-color:#282f2f}html.theme--documenter-dark .modal-card-foot,html.theme--documenter-dark .modal-card-head{border-color:#343c3d}html.theme--documenter-dark .message-header{font-weight:700;background-color:#343c3d;color:#fff}html.theme--documenter-dark .message-body{border-width:1px;border-color:#343c3d}html.theme--documenter-dark .navbar{border-radius:.4em}html.theme--documenter-dark .navbar.is-transparent{background:none}html.theme--documenter-dark .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#1abc9c}@media screen and (max-width: 1055px){html.theme--documenter-dark .navbar .navbar-menu{background-color:#375a7f;border-radius:0 0 .4em .4em}}html.theme--documenter-dark .hero .navbar,html.theme--documenter-dark body>.navbar{border-radius:0}html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-previous{border-width:1px}html.theme--documenter-dark .panel-block,html.theme--documenter-dark .panel-heading,html.theme--documenter-dark .panel-tabs{border-width:1px}html.theme--documenter-dark .panel-block:first-child,html.theme--documenter-dark .panel-heading:first-child,html.theme--documenter-dark .panel-tabs:first-child{border-top-width:1px}html.theme--documenter-dark .panel-heading{font-weight:700}html.theme--documenter-dark .panel-tabs a{border-width:1px;margin-bottom:-1px}html.theme--documenter-dark .panel-tabs a.is-active{border-bottom-color:#17a689}html.theme--documenter-dark .panel-block:hover{color:#1dd2af}html.theme--documenter-dark .panel-block:hover .panel-icon{color:#1dd2af}html.theme--documenter-dark .panel-block.is-active .panel-icon{color:#17a689}html.theme--documenter-dark .tabs a{border-bottom-width:1px;margin-bottom:-1px}html.theme--documenter-dark .tabs ul{border-bottom-width:1px}html.theme--documenter-dark .tabs.is-boxed a{border-width:1px}html.theme--documenter-dark .tabs.is-boxed li.is-active a{background-color:#1f2424}html.theme--documenter-dark .tabs.is-toggle li a{border-width:1px;margin-bottom:0}html.theme--documenter-dark .tabs.is-toggle li+li{margin-left:-1px}html.theme--documenter-dark .hero.is-white .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-black .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-light .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-dark .navbar .navbar-dropdown .navbar-item:hover,html.theme--documenter-dark .content kbd.hero .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-primary .navbar .navbar-dropdown .navbar-item:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-link .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-info .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-success .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-warning .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-danger .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark h1 .docs-heading-anchor,html.theme--documenter-dark h1 .docs-heading-anchor:hover,html.theme--documenter-dark h1 .docs-heading-anchor:visited,html.theme--documenter-dark h2 .docs-heading-anchor,html.theme--documenter-dark h2 .docs-heading-anchor:hover,html.theme--documenter-dark h2 .docs-heading-anchor:visited,html.theme--documenter-dark h3 .docs-heading-anchor,html.theme--documenter-dark h3 .docs-heading-anchor:hover,html.theme--documenter-dark h3 .docs-heading-anchor:visited,html.theme--documenter-dark h4 .docs-heading-anchor,html.theme--documenter-dark h4 .docs-heading-anchor:hover,html.theme--documenter-dark h4 .docs-heading-anchor:visited,html.theme--documenter-dark h5 .docs-heading-anchor,html.theme--documenter-dark h5 .docs-heading-anchor:hover,html.theme--documenter-dark h5 .docs-heading-anchor:visited,html.theme--documenter-dark h6 .docs-heading-anchor,html.theme--documenter-dark h6 .docs-heading-anchor:hover,html.theme--documenter-dark h6 .docs-heading-anchor:visited{color:#f2f2f2}html.theme--documenter-dark h1 .docs-heading-anchor-permalink,html.theme--documenter-dark h2 .docs-heading-anchor-permalink,html.theme--documenter-dark h3 .docs-heading-anchor-permalink,html.theme--documenter-dark h4 .docs-heading-anchor-permalink,html.theme--documenter-dark h5 .docs-heading-anchor-permalink,html.theme--documenter-dark h6 .docs-heading-anchor-permalink{visibility:hidden;vertical-align:middle;margin-left:0.5em;font-size:0.7rem}html.theme--documenter-dark h1 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h2 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h3 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h4 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h5 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h6 .docs-heading-anchor-permalink::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f0c1"}html.theme--documenter-dark h1:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h2:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h3:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h4:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h5:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h6:hover .docs-heading-anchor-permalink{visibility:visible}html.theme--documenter-dark .docs-light-only{display:none !important}html.theme--documenter-dark pre{position:relative;overflow:hidden}html.theme--documenter-dark pre code,html.theme--documenter-dark pre code.hljs{padding:0 .75rem !important;overflow:auto;display:block}html.theme--documenter-dark pre code:first-of-type,html.theme--documenter-dark pre code.hljs:first-of-type{padding-top:0.5rem !important}html.theme--documenter-dark pre code:last-of-type,html.theme--documenter-dark pre code.hljs:last-of-type{padding-bottom:0.5rem !important}html.theme--documenter-dark pre .copy-button{opacity:0.2;transition:opacity 0.2s;position:absolute;right:0em;top:0em;padding:0.5em;width:2.5em;height:2.5em;background:transparent;border:none;font-family:"Font Awesome 6 Free";color:#fff;cursor:pointer;text-align:center}html.theme--documenter-dark pre .copy-button:focus,html.theme--documenter-dark pre .copy-button:hover{opacity:1;background:rgba(255,255,255,0.1);color:#1abc9c}html.theme--documenter-dark pre .copy-button.success{color:#259a12;opacity:1}html.theme--documenter-dark pre .copy-button.error{color:#cb3c33;opacity:1}html.theme--documenter-dark pre:hover .copy-button{opacity:1}html.theme--documenter-dark .admonition{background-color:#282f2f;border-style:solid;border-width:2px;border-color:#dbdee0;border-radius:4px;font-size:1rem}html.theme--documenter-dark .admonition strong{color:currentColor}html.theme--documenter-dark .admonition.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.admonition{font-size:.75rem}html.theme--documenter-dark .admonition.is-medium{font-size:1.25rem}html.theme--documenter-dark .admonition.is-large{font-size:1.5rem}html.theme--documenter-dark .admonition.is-default{background-color:#282f2f;border-color:#dbdee0}html.theme--documenter-dark .admonition.is-default>.admonition-header{background-color:rgba(0,0,0,0);color:#dbdee0}html.theme--documenter-dark .admonition.is-default>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-info{background-color:#282f2f;border-color:#3c5dcd}html.theme--documenter-dark .admonition.is-info>.admonition-header{background-color:rgba(0,0,0,0);color:#3c5dcd}html.theme--documenter-dark .admonition.is-info>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-success{background-color:#282f2f;border-color:#259a12}html.theme--documenter-dark .admonition.is-success>.admonition-header{background-color:rgba(0,0,0,0);color:#259a12}html.theme--documenter-dark .admonition.is-success>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-warning{background-color:#282f2f;border-color:#f4c72f}html.theme--documenter-dark .admonition.is-warning>.admonition-header{background-color:rgba(0,0,0,0);color:#f4c72f}html.theme--documenter-dark .admonition.is-warning>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-danger{background-color:#282f2f;border-color:#cb3c33}html.theme--documenter-dark .admonition.is-danger>.admonition-header{background-color:rgba(0,0,0,0);color:#cb3c33}html.theme--documenter-dark .admonition.is-danger>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-compat{background-color:#282f2f;border-color:#3489da}html.theme--documenter-dark .admonition.is-compat>.admonition-header{background-color:rgba(0,0,0,0);color:#3489da}html.theme--documenter-dark .admonition.is-compat>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-todo{background-color:#282f2f;border-color:#9558b2}html.theme--documenter-dark .admonition.is-todo>.admonition-header{background-color:rgba(0,0,0,0);color:#9558b2}html.theme--documenter-dark .admonition.is-todo>.admonition-body{color:#fff}html.theme--documenter-dark .admonition-header{color:#dbdee0;background-color:rgba(0,0,0,0);align-items:center;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.5rem .75rem;position:relative}html.theme--documenter-dark .admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;margin-right:.75rem;content:"\f06a"}html.theme--documenter-dark details.admonition.is-details>.admonition-header{list-style:none}html.theme--documenter-dark details.admonition.is-details>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f055"}html.theme--documenter-dark details.admonition.is-details[open]>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f056"}html.theme--documenter-dark .admonition-body{color:#fff;padding:0.5rem .75rem}html.theme--documenter-dark .admonition-body pre{background-color:#282f2f}html.theme--documenter-dark .admonition-body code{background-color:rgba(255,255,255,0.05)}html.theme--documenter-dark .docstring{margin-bottom:1em;background-color:rgba(0,0,0,0);border:2px solid #5e6d6f;border-radius:4px;box-shadow:none;max-width:100%}html.theme--documenter-dark .docstring>header{cursor:pointer;display:flex;flex-grow:1;align-items:stretch;padding:0.5rem .75rem;background-color:#282f2f;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);box-shadow:none;border-bottom:1px solid #5e6d6f;overflow:auto}html.theme--documenter-dark .docstring>header code{background-color:transparent}html.theme--documenter-dark .docstring>header .docstring-article-toggle-button{min-width:1.1rem;padding:0.2rem 0.2rem 0.2rem 0}html.theme--documenter-dark .docstring>header .docstring-binding{margin-right:0.3em}html.theme--documenter-dark .docstring>header .docstring-category{margin-left:0.3em}html.theme--documenter-dark .docstring>section{position:relative;padding:.75rem .75rem;border-bottom:1px solid #5e6d6f}html.theme--documenter-dark .docstring>section:last-child{border-bottom:none}html.theme--documenter-dark .docstring>section>a.docs-sourcelink{transition:opacity 0.3s;opacity:0;position:absolute;right:.375rem;bottom:.375rem}html.theme--documenter-dark .docstring>section>a.docs-sourcelink:focus{opacity:1 !important}html.theme--documenter-dark .docstring:hover>section>a.docs-sourcelink{opacity:0.2}html.theme--documenter-dark .docstring:focus-within>section>a.docs-sourcelink{opacity:0.2}html.theme--documenter-dark .docstring>section:hover a.docs-sourcelink{opacity:1}html.theme--documenter-dark .documenter-example-output{background-color:#1f2424}html.theme--documenter-dark .outdated-warning-overlay{position:fixed;top:0;left:0;right:0;box-shadow:0 0 10px rgba(0,0,0,0.3);z-index:999;background-color:#282f2f;color:#fff;border-bottom:3px solid rgba(0,0,0,0);padding:10px 35px;text-align:center;font-size:15px}html.theme--documenter-dark .outdated-warning-overlay .outdated-warning-closer{position:absolute;top:calc(50% - 10px);right:18px;cursor:pointer;width:12px}html.theme--documenter-dark .outdated-warning-overlay a{color:#1abc9c}html.theme--documenter-dark .outdated-warning-overlay a:hover{color:#1dd2af}html.theme--documenter-dark .content pre{border:2px solid #5e6d6f;border-radius:4px}html.theme--documenter-dark .content code{font-weight:inherit}html.theme--documenter-dark .content a code{color:#1abc9c}html.theme--documenter-dark .content a:hover code{color:#1dd2af}html.theme--documenter-dark .content h1 code,html.theme--documenter-dark .content h2 code,html.theme--documenter-dark .content h3 code,html.theme--documenter-dark .content h4 code,html.theme--documenter-dark .content h5 code,html.theme--documenter-dark .content h6 code{color:#f2f2f2}html.theme--documenter-dark .content table{display:block;width:initial;max-width:100%;overflow-x:auto}html.theme--documenter-dark .content blockquote>ul:first-child,html.theme--documenter-dark .content blockquote>ol:first-child,html.theme--documenter-dark .content .admonition-body>ul:first-child,html.theme--documenter-dark .content .admonition-body>ol:first-child{margin-top:0}html.theme--documenter-dark pre,html.theme--documenter-dark code{font-variant-ligatures:no-contextual}html.theme--documenter-dark .breadcrumb a.is-disabled{cursor:default;pointer-events:none}html.theme--documenter-dark .breadcrumb a.is-disabled,html.theme--documenter-dark .breadcrumb a.is-disabled:hover{color:#f2f2f2}html.theme--documenter-dark .hljs{background:initial !important}html.theme--documenter-dark .katex .katex-mathml{top:0;right:0}html.theme--documenter-dark .katex-display,html.theme--documenter-dark mjx-container,html.theme--documenter-dark .MathJax_Display{margin:0.5em 0 !important}html.theme--documenter-dark html{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto}html.theme--documenter-dark li.no-marker{list-style:none}html.theme--documenter-dark #documenter .docs-main>article{overflow-wrap:break-word}html.theme--documenter-dark #documenter .docs-main>article .math-container{overflow-x:auto;overflow-y:hidden}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-main{max-width:52rem;margin-left:20rem;padding-right:1rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main{width:100%}html.theme--documenter-dark #documenter .docs-main>article{max-width:52rem;margin-left:auto;margin-right:auto;margin-bottom:1rem;padding:0 1rem}html.theme--documenter-dark #documenter .docs-main>header,html.theme--documenter-dark #documenter .docs-main>nav{max-width:100%;width:100%;margin:0}}html.theme--documenter-dark #documenter .docs-main header.docs-navbar{background-color:#1f2424;border-bottom:1px solid #5e6d6f;z-index:2;min-height:4rem;margin-bottom:1rem;display:flex}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .breadcrumb{flex-grow:1;overflow-x:hidden}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-sidebar-button{display:block;font-size:1.5rem;padding-bottom:0.1rem;margin-right:1rem}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right{display:flex;white-space:nowrap;gap:1rem;align-items:center}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-icon,html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-label{display:inline-block}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-label{padding:0;margin-left:0.3em}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-navbar-link{margin-left:0.4rem;margin-right:0.4rem}}html.theme--documenter-dark #documenter .docs-main header.docs-navbar>*{margin:auto 0}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main header.docs-navbar{position:sticky;top:0;padding:0 1rem;transition-property:top, box-shadow;-webkit-transition-property:top, box-shadow;transition-duration:0.3s;-webkit-transition-duration:0.3s}html.theme--documenter-dark #documenter .docs-main header.docs-navbar.headroom--not-top{box-shadow:.2rem 0rem .4rem #171717;transition-duration:0.7s;-webkit-transition-duration:0.7s}html.theme--documenter-dark #documenter .docs-main header.docs-navbar.headroom--unpinned.headroom--not-top.headroom--not-bottom{top:-4.5rem;transition-duration:0.7s;-webkit-transition-duration:0.7s}}html.theme--documenter-dark #documenter .docs-main section.footnotes{border-top:1px solid #5e6d6f}html.theme--documenter-dark #documenter .docs-main section.footnotes li .tag:first-child,html.theme--documenter-dark #documenter .docs-main section.footnotes li .docstring>section>a.docs-sourcelink:first-child,html.theme--documenter-dark #documenter .docs-main section.footnotes li .content kbd:first-child,html.theme--documenter-dark .content #documenter .docs-main section.footnotes li kbd:first-child{margin-right:1em;margin-bottom:0.4em}html.theme--documenter-dark #documenter .docs-main .docs-footer{display:flex;flex-wrap:wrap;margin-left:0;margin-right:0;border-top:1px solid #5e6d6f;padding-top:1rem;padding-bottom:1rem}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main .docs-footer{padding-left:1rem;padding-right:1rem}}html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-nextpage,html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-prevpage{flex-grow:1}html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-nextpage{text-align:right}html.theme--documenter-dark #documenter .docs-main .docs-footer .flexbox-break{flex-basis:100%;height:0}html.theme--documenter-dark #documenter .docs-main .docs-footer .footer-message{font-size:0.8em;margin:0.5em auto 0 auto;text-align:center}html.theme--documenter-dark #documenter .docs-sidebar{display:flex;flex-direction:column;color:#fff;background-color:#282f2f;border-right:1px solid #5e6d6f;padding:0;flex:0 0 18rem;z-index:5;font-size:1rem;position:fixed;left:-18rem;width:18rem;height:100%;transition:left 0.3s}html.theme--documenter-dark #documenter .docs-sidebar.visible{left:0;box-shadow:.4rem 0rem .8rem #171717}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-sidebar.visible{box-shadow:none}}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-sidebar{left:0;top:0}}html.theme--documenter-dark #documenter .docs-sidebar .docs-logo{margin-top:1rem;padding:0 1rem}html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img{max-height:6rem;margin:auto}html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name{flex-shrink:0;font-size:1.5rem;font-weight:700;text-align:center;white-space:nowrap;overflow:hidden;padding:0.5rem 0}html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name .docs-autofit{max-width:16.2rem}html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name a,html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name a:hover{color:#fff}html.theme--documenter-dark #documenter .docs-sidebar .docs-version-selector{border-top:1px solid #5e6d6f;display:none;padding:0.5rem}html.theme--documenter-dark #documenter .docs-sidebar .docs-version-selector.visible{display:flex}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu{flex-grow:1;user-select:none;border-top:1px solid #5e6d6f;padding-bottom:1.5rem}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu>li>.tocitem{font-weight:bold}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu>li li{font-size:.95rem;margin-left:1em;border-left:1px solid #5e6d6f}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input.collapse-toggle{display:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.collapsed{display:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input:checked~ul.collapsed{display:block}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem{display:flex}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-label{flex-grow:2}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-size:.75rem;margin-left:1rem;margin-top:auto;margin-bottom:auto}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f054"}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input:checked~label.tocitem .docs-chevron::before{content:"\f078"}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem{display:block;padding:0.5rem 0.5rem}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem,html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem:hover{color:#fff;background:#282f2f}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu a.tocitem:hover,html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem:hover{color:#fff;background-color:#32393a}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active{border-top:1px solid #5e6d6f;border-bottom:1px solid #5e6d6f;background-color:#1f2424}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem,html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem:hover{background-color:#1f2424;color:#fff}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active ul.internal .tocitem:hover{background-color:#32393a;color:#fff}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu>li.is-active:first-child{border-top:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal{margin:0 0.5rem 0.5rem;border-top:1px solid #5e6d6f}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal li{font-size:.85rem;border-left:none;margin-left:0;margin-top:0.5rem}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem{width:100%;padding:0}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem::before{content:"⚬";margin-right:0.4em}html.theme--documenter-dark #documenter .docs-sidebar form.docs-search{margin:auto;margin-top:0.5rem;margin-bottom:0.5rem}html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{width:14.4rem}html.theme--documenter-dark #documenter .docs-sidebar #documenter-search-query{color:#868c98;width:14.4rem;box-shadow:inset 0 1px 2px rgba(10,10,10,0.1)}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar{width:.3rem;background:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#3b4445}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb:hover{background:#4e5a5c}}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-sidebar{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar{width:.3rem;background:none}html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#3b4445}html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar-thumb:hover{background:#4e5a5c}}html.theme--documenter-dark kbd.search-modal-key-hints{border-radius:0.25rem;border:1px solid rgba(245,245,245,0.6);box-shadow:0 2px 0 1px rgba(245,245,245,0.6);cursor:default;font-size:0.9rem;line-height:1.5;min-width:0.75rem;text-align:center;padding:0.1rem 0.3rem;position:relative;top:-1px}html.theme--documenter-dark .search-min-width-50{min-width:50%}html.theme--documenter-dark .search-min-height-100{min-height:100%}html.theme--documenter-dark .search-modal-card-body{max-height:calc(100vh - 15rem)}html.theme--documenter-dark .search-result-link{border-radius:0.7em;transition:all 300ms}html.theme--documenter-dark .search-result-link:hover,html.theme--documenter-dark .search-result-link:focus{background-color:rgba(0,128,128,0.1)}html.theme--documenter-dark .search-result-link .property-search-result-badge,html.theme--documenter-dark .search-result-link .search-filter{transition:all 300ms}html.theme--documenter-dark .property-search-result-badge,html.theme--documenter-dark .search-filter{padding:0.15em 0.5em;font-size:0.8em;font-style:italic;text-transform:none !important;line-height:1.5;color:#f5f5f5;background-color:rgba(51,65,85,0.501961);border-radius:0.6rem}html.theme--documenter-dark .search-result-link:hover .property-search-result-badge,html.theme--documenter-dark .search-result-link:hover .search-filter,html.theme--documenter-dark .search-result-link:focus .property-search-result-badge,html.theme--documenter-dark .search-result-link:focus .search-filter{color:#333;background-color:#f1f5f9}html.theme--documenter-dark .search-filter{color:#333;background-color:#f5f5f5;transition:all 300ms}html.theme--documenter-dark .search-filter:hover,html.theme--documenter-dark .search-filter:focus{color:#333}html.theme--documenter-dark .search-filter-selected{color:#f5f5f5;background-color:rgba(139,0,139,0.5)}html.theme--documenter-dark .search-filter-selected:hover,html.theme--documenter-dark .search-filter-selected:focus{color:#f5f5f5}html.theme--documenter-dark .search-result-highlight{background-color:#ffdd57;color:black}html.theme--documenter-dark .search-divider{border-bottom:1px solid #5e6d6f}html.theme--documenter-dark .search-result-title{width:85%;color:#f5f5f5}html.theme--documenter-dark .search-result-code-title{font-size:0.875rem;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}html.theme--documenter-dark #search-modal .modal-card-body::-webkit-scrollbar,html.theme--documenter-dark #search-modal .filter-tabs::-webkit-scrollbar{height:10px;width:10px;background-color:transparent}html.theme--documenter-dark #search-modal .modal-card-body::-webkit-scrollbar-thumb,html.theme--documenter-dark #search-modal .filter-tabs::-webkit-scrollbar-thumb{background-color:gray;border-radius:1rem}html.theme--documenter-dark #search-modal .modal-card-body::-webkit-scrollbar-track,html.theme--documenter-dark #search-modal .filter-tabs::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,0.6);background-color:transparent}html.theme--documenter-dark .w-100{width:100%}html.theme--documenter-dark .gap-2{gap:0.5rem}html.theme--documenter-dark .gap-4{gap:1rem}html.theme--documenter-dark .gap-8{gap:2rem}html.theme--documenter-dark{background-color:#1f2424;font-size:16px;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--documenter-dark .ansi span.sgr1{font-weight:bolder}html.theme--documenter-dark .ansi span.sgr2{font-weight:lighter}html.theme--documenter-dark .ansi span.sgr3{font-style:italic}html.theme--documenter-dark .ansi span.sgr4{text-decoration:underline}html.theme--documenter-dark .ansi span.sgr7{color:#1f2424;background-color:#fff}html.theme--documenter-dark .ansi span.sgr8{color:transparent}html.theme--documenter-dark .ansi span.sgr8 span{color:transparent}html.theme--documenter-dark .ansi span.sgr9{text-decoration:line-through}html.theme--documenter-dark .ansi span.sgr30{color:#242424}html.theme--documenter-dark .ansi span.sgr31{color:#f6705f}html.theme--documenter-dark .ansi span.sgr32{color:#4fb43a}html.theme--documenter-dark .ansi span.sgr33{color:#f4c72f}html.theme--documenter-dark .ansi span.sgr34{color:#7587f0}html.theme--documenter-dark .ansi span.sgr35{color:#bc89d3}html.theme--documenter-dark .ansi span.sgr36{color:#49b6ca}html.theme--documenter-dark .ansi span.sgr37{color:#b3bdbe}html.theme--documenter-dark .ansi span.sgr40{background-color:#242424}html.theme--documenter-dark .ansi span.sgr41{background-color:#f6705f}html.theme--documenter-dark .ansi span.sgr42{background-color:#4fb43a}html.theme--documenter-dark .ansi span.sgr43{background-color:#f4c72f}html.theme--documenter-dark .ansi span.sgr44{background-color:#7587f0}html.theme--documenter-dark .ansi span.sgr45{background-color:#bc89d3}html.theme--documenter-dark .ansi span.sgr46{background-color:#49b6ca}html.theme--documenter-dark .ansi span.sgr47{background-color:#b3bdbe}html.theme--documenter-dark .ansi span.sgr90{color:#92a0a2}html.theme--documenter-dark .ansi span.sgr91{color:#ff8674}html.theme--documenter-dark .ansi span.sgr92{color:#79d462}html.theme--documenter-dark .ansi span.sgr93{color:#ffe76b}html.theme--documenter-dark .ansi span.sgr94{color:#8a98ff}html.theme--documenter-dark .ansi span.sgr95{color:#d2a4e6}html.theme--documenter-dark .ansi span.sgr96{color:#6bc8db}html.theme--documenter-dark .ansi span.sgr97{color:#ecf0f1}html.theme--documenter-dark .ansi span.sgr100{background-color:#92a0a2}html.theme--documenter-dark .ansi span.sgr101{background-color:#ff8674}html.theme--documenter-dark .ansi span.sgr102{background-color:#79d462}html.theme--documenter-dark .ansi span.sgr103{background-color:#ffe76b}html.theme--documenter-dark .ansi span.sgr104{background-color:#8a98ff}html.theme--documenter-dark .ansi span.sgr105{background-color:#d2a4e6}html.theme--documenter-dark .ansi span.sgr106{background-color:#6bc8db}html.theme--documenter-dark .ansi span.sgr107{background-color:#ecf0f1}html.theme--documenter-dark code.language-julia-repl>span.hljs-meta{color:#4fb43a;font-weight:bolder}html.theme--documenter-dark .hljs{background:#2b2b2b;color:#f8f8f2}html.theme--documenter-dark .hljs-comment,html.theme--documenter-dark .hljs-quote{color:#d4d0ab}html.theme--documenter-dark .hljs-variable,html.theme--documenter-dark .hljs-template-variable,html.theme--documenter-dark .hljs-tag,html.theme--documenter-dark .hljs-name,html.theme--documenter-dark .hljs-selector-id,html.theme--documenter-dark .hljs-selector-class,html.theme--documenter-dark .hljs-regexp,html.theme--documenter-dark .hljs-deletion{color:#ffa07a}html.theme--documenter-dark .hljs-number,html.theme--documenter-dark .hljs-built_in,html.theme--documenter-dark .hljs-literal,html.theme--documenter-dark .hljs-type,html.theme--documenter-dark .hljs-params,html.theme--documenter-dark .hljs-meta,html.theme--documenter-dark .hljs-link{color:#f5ab35}html.theme--documenter-dark .hljs-attribute{color:#ffd700}html.theme--documenter-dark .hljs-string,html.theme--documenter-dark .hljs-symbol,html.theme--documenter-dark .hljs-bullet,html.theme--documenter-dark .hljs-addition{color:#abe338}html.theme--documenter-dark .hljs-title,html.theme--documenter-dark .hljs-section{color:#00e0e0}html.theme--documenter-dark .hljs-keyword,html.theme--documenter-dark .hljs-selector-tag{color:#dcc6e0}html.theme--documenter-dark .hljs-emphasis{font-style:italic}html.theme--documenter-dark .hljs-strong{font-weight:bold}@media screen and (-ms-high-contrast: active){html.theme--documenter-dark .hljs-addition,html.theme--documenter-dark .hljs-attribute,html.theme--documenter-dark .hljs-built_in,html.theme--documenter-dark .hljs-bullet,html.theme--documenter-dark .hljs-comment,html.theme--documenter-dark .hljs-link,html.theme--documenter-dark .hljs-literal,html.theme--documenter-dark .hljs-meta,html.theme--documenter-dark .hljs-number,html.theme--documenter-dark .hljs-params,html.theme--documenter-dark .hljs-string,html.theme--documenter-dark .hljs-symbol,html.theme--documenter-dark .hljs-type,html.theme--documenter-dark .hljs-quote{color:highlight}html.theme--documenter-dark .hljs-keyword,html.theme--documenter-dark .hljs-selector-tag{font-weight:bold}}html.theme--documenter-dark .hljs-subst{color:#f8f8f2}html.theme--documenter-dark .search-result-link{border-radius:0.7em;transition:all 300ms}html.theme--documenter-dark .search-result-link:hover,html.theme--documenter-dark .search-result-link:focus{background-color:rgba(0,128,128,0.1)}html.theme--documenter-dark .search-result-link .property-search-result-badge,html.theme--documenter-dark .search-result-link .search-filter{transition:all 300ms}html.theme--documenter-dark .search-result-link:hover .property-search-result-badge,html.theme--documenter-dark .search-result-link:hover .search-filter,html.theme--documenter-dark .search-result-link:focus .property-search-result-badge,html.theme--documenter-dark .search-result-link:focus .search-filter{color:#333 !important;background-color:#f1f5f9 !important}html.theme--documenter-dark .search-result-title{color:whitesmoke}html.theme--documenter-dark .search-result-highlight{background-color:greenyellow;color:black}html.theme--documenter-dark .search-divider{border-bottom:1px solid #5e6d6f50}html.theme--documenter-dark .w-100{width:100%}html.theme--documenter-dark .gap-2{gap:0.5rem}html.theme--documenter-dark .gap-4{gap:1rem} diff --git a/v0.2.0/assets/themes/documenter-light.css b/v0.2.0/assets/themes/documenter-light.css new file mode 100644 index 000000000..e000447e6 --- /dev/null +++ b/v0.2.0/assets/themes/documenter-light.css @@ -0,0 +1,9 @@ +.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis,.file-cta,.file-name,.select select,.textarea,.input,#documenter .docs-sidebar form.docs-search>input,.button{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;border-radius:4px;box-shadow:none;display:inline-flex;font-size:1rem;height:2.5em;justify-content:flex-start;line-height:1.5;padding-bottom:calc(0.5em - 1px);padding-left:calc(0.75em - 1px);padding-right:calc(0.75em - 1px);padding-top:calc(0.5em - 1px);position:relative;vertical-align:top}.pagination-previous:focus,.pagination-next:focus,.pagination-link:focus,.pagination-ellipsis:focus,.file-cta:focus,.file-name:focus,.select select:focus,.textarea:focus,.input:focus,#documenter .docs-sidebar form.docs-search>input:focus,.button:focus,.is-focused.pagination-previous,.is-focused.pagination-next,.is-focused.pagination-link,.is-focused.pagination-ellipsis,.is-focused.file-cta,.is-focused.file-name,.select select.is-focused,.is-focused.textarea,.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-focused.button,.pagination-previous:active,.pagination-next:active,.pagination-link:active,.pagination-ellipsis:active,.file-cta:active,.file-name:active,.select select:active,.textarea:active,.input:active,#documenter .docs-sidebar form.docs-search>input:active,.button:active,.is-active.pagination-previous,.is-active.pagination-next,.is-active.pagination-link,.is-active.pagination-ellipsis,.is-active.file-cta,.is-active.file-name,.select select.is-active,.is-active.textarea,.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active,.is-active.button{outline:none}.pagination-previous[disabled],.pagination-next[disabled],.pagination-link[disabled],.pagination-ellipsis[disabled],.file-cta[disabled],.file-name[disabled],.select select[disabled],.textarea[disabled],.input[disabled],#documenter .docs-sidebar form.docs-search>input[disabled],.button[disabled],fieldset[disabled] .pagination-previous,fieldset[disabled] .pagination-next,fieldset[disabled] .pagination-link,fieldset[disabled] .pagination-ellipsis,fieldset[disabled] .file-cta,fieldset[disabled] .file-name,fieldset[disabled] .select select,.select fieldset[disabled] select,fieldset[disabled] .textarea,fieldset[disabled] .input,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input,fieldset[disabled] .button{cursor:not-allowed}.tabs,.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis,.breadcrumb,.file,.button,.is-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.navbar-link:not(.is-arrowless)::after,.select:not(.is-multiple):not(.is-loading)::after{border:3px solid rgba(0,0,0,0);border-radius:2px;border-right:0;border-top:0;content:" ";display:block;height:0.625em;margin-top:-0.4375em;pointer-events:none;position:absolute;top:50%;transform:rotate(-45deg);transform-origin:center;width:0.625em}.admonition:not(:last-child),.tabs:not(:last-child),.pagination:not(:last-child),.message:not(:last-child),.level:not(:last-child),.breadcrumb:not(:last-child),.block:not(:last-child),.title:not(:last-child),.subtitle:not(:last-child),.table-container:not(:last-child),.table:not(:last-child),.progress:not(:last-child),.notification:not(:last-child),.content:not(:last-child),.box:not(:last-child){margin-bottom:1.5rem}.modal-close,.delete{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,0.2);border:none;border-radius:9999px;cursor:pointer;pointer-events:auto;display:inline-block;flex-grow:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:none;position:relative;vertical-align:top;width:20px}.modal-close::before,.delete::before,.modal-close::after,.delete::after{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}.modal-close::before,.delete::before{height:2px;width:50%}.modal-close::after,.delete::after{height:50%;width:2px}.modal-close:hover,.delete:hover,.modal-close:focus,.delete:focus{background-color:rgba(10,10,10,0.3)}.modal-close:active,.delete:active{background-color:rgba(10,10,10,0.4)}.is-small.modal-close,#documenter .docs-sidebar form.docs-search>input.modal-close,.is-small.delete,#documenter .docs-sidebar form.docs-search>input.delete{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}.is-medium.modal-close,.is-medium.delete{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}.is-large.modal-close,.is-large.delete{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}.control.is-loading::after,.select.is-loading::after,.loader,.button.is-loading::after{animation:spinAround 500ms infinite linear;border:2px solid #dbdbdb;border-radius:9999px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em}.hero-video,.modal-background,.modal,.image.is-square img,#documenter .docs-sidebar .docs-logo>img.is-square img,.image.is-square .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,.image.is-1by1 img,#documenter .docs-sidebar .docs-logo>img.is-1by1 img,.image.is-1by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,.image.is-5by4 img,#documenter .docs-sidebar .docs-logo>img.is-5by4 img,.image.is-5by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,.image.is-4by3 img,#documenter .docs-sidebar .docs-logo>img.is-4by3 img,.image.is-4by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,.image.is-3by2 img,#documenter .docs-sidebar .docs-logo>img.is-3by2 img,.image.is-3by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,.image.is-5by3 img,#documenter .docs-sidebar .docs-logo>img.is-5by3 img,.image.is-5by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,.image.is-16by9 img,#documenter .docs-sidebar .docs-logo>img.is-16by9 img,.image.is-16by9 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,.image.is-2by1 img,#documenter .docs-sidebar .docs-logo>img.is-2by1 img,.image.is-2by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,.image.is-3by1 img,#documenter .docs-sidebar .docs-logo>img.is-3by1 img,.image.is-3by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,.image.is-4by5 img,#documenter .docs-sidebar .docs-logo>img.is-4by5 img,.image.is-4by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,.image.is-3by4 img,#documenter .docs-sidebar .docs-logo>img.is-3by4 img,.image.is-3by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,.image.is-2by3 img,#documenter .docs-sidebar .docs-logo>img.is-2by3 img,.image.is-2by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,.image.is-3by5 img,#documenter .docs-sidebar .docs-logo>img.is-3by5 img,.image.is-3by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,.image.is-9by16 img,#documenter .docs-sidebar .docs-logo>img.is-9by16 img,.image.is-9by16 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,.image.is-1by2 img,#documenter .docs-sidebar .docs-logo>img.is-1by2 img,.image.is-1by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,.image.is-1by3 img,#documenter .docs-sidebar .docs-logo>img.is-1by3 img,.image.is-1by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio,.is-overlay{bottom:0;left:0;position:absolute;right:0;top:0}.navbar-burger{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0}.has-text-white{color:#fff !important}a.has-text-white:hover,a.has-text-white:focus{color:#e6e6e6 !important}.has-background-white{background-color:#fff !important}.has-text-black{color:#0a0a0a !important}a.has-text-black:hover,a.has-text-black:focus{color:#000 !important}.has-background-black{background-color:#0a0a0a !important}.has-text-light{color:#f5f5f5 !important}a.has-text-light:hover,a.has-text-light:focus{color:#dbdbdb !important}.has-background-light{background-color:#f5f5f5 !important}.has-text-dark{color:#363636 !important}a.has-text-dark:hover,a.has-text-dark:focus{color:#1c1c1c !important}.has-background-dark{background-color:#363636 !important}.has-text-primary{color:#4eb5de !important}a.has-text-primary:hover,a.has-text-primary:focus{color:#27a1d2 !important}.has-background-primary{background-color:#4eb5de !important}.has-text-primary-light{color:#eef8fc !important}a.has-text-primary-light:hover,a.has-text-primary-light:focus{color:#c3e6f4 !important}.has-background-primary-light{background-color:#eef8fc !important}.has-text-primary-dark{color:#1a6d8e !important}a.has-text-primary-dark:hover,a.has-text-primary-dark:focus{color:#228eb9 !important}.has-background-primary-dark{background-color:#1a6d8e !important}.has-text-link{color:#2e63b8 !important}a.has-text-link:hover,a.has-text-link:focus{color:#244d8f !important}.has-background-link{background-color:#2e63b8 !important}.has-text-link-light{color:#eff3fb !important}a.has-text-link-light:hover,a.has-text-link-light:focus{color:#c6d6f1 !important}.has-background-link-light{background-color:#eff3fb !important}.has-text-link-dark{color:#3169c4 !important}a.has-text-link-dark:hover,a.has-text-link-dark:focus{color:#5485d4 !important}.has-background-link-dark{background-color:#3169c4 !important}.has-text-info{color:#3c5dcd !important}a.has-text-info:hover,a.has-text-info:focus{color:#2c48aa !important}.has-background-info{background-color:#3c5dcd !important}.has-text-info-light{color:#eff2fb !important}a.has-text-info-light:hover,a.has-text-info-light:focus{color:#c6d0f0 !important}.has-background-info-light{background-color:#eff2fb !important}.has-text-info-dark{color:#3253c3 !important}a.has-text-info-dark:hover,a.has-text-info-dark:focus{color:#5571d3 !important}.has-background-info-dark{background-color:#3253c3 !important}.has-text-success{color:#259a12 !important}a.has-text-success:hover,a.has-text-success:focus{color:#1a6c0d !important}.has-background-success{background-color:#259a12 !important}.has-text-success-light{color:#effded !important}a.has-text-success-light:hover,a.has-text-success-light:focus{color:#c7f8bf !important}.has-background-success-light{background-color:#effded !important}.has-text-success-dark{color:#2ec016 !important}a.has-text-success-dark:hover,a.has-text-success-dark:focus{color:#3fe524 !important}.has-background-success-dark{background-color:#2ec016 !important}.has-text-warning{color:#a98800 !important}a.has-text-warning:hover,a.has-text-warning:focus{color:#765f00 !important}.has-background-warning{background-color:#a98800 !important}.has-text-warning-light{color:#fffbeb !important}a.has-text-warning-light:hover,a.has-text-warning-light:focus{color:#fff1b8 !important}.has-background-warning-light{background-color:#fffbeb !important}.has-text-warning-dark{color:#cca400 !important}a.has-text-warning-dark:hover,a.has-text-warning-dark:focus{color:#ffcd00 !important}.has-background-warning-dark{background-color:#cca400 !important}.has-text-danger{color:#cb3c33 !important}a.has-text-danger:hover,a.has-text-danger:focus{color:#a23029 !important}.has-background-danger{background-color:#cb3c33 !important}.has-text-danger-light{color:#fbefef !important}a.has-text-danger-light:hover,a.has-text-danger-light:focus{color:#f1c8c6 !important}.has-background-danger-light{background-color:#fbefef !important}.has-text-danger-dark{color:#c03930 !important}a.has-text-danger-dark:hover,a.has-text-danger-dark:focus{color:#d35850 !important}.has-background-danger-dark{background-color:#c03930 !important}.has-text-black-bis{color:#121212 !important}.has-background-black-bis{background-color:#121212 !important}.has-text-black-ter{color:#242424 !important}.has-background-black-ter{background-color:#242424 !important}.has-text-grey-darker{color:#363636 !important}.has-background-grey-darker{background-color:#363636 !important}.has-text-grey-dark{color:#4a4a4a !important}.has-background-grey-dark{background-color:#4a4a4a !important}.has-text-grey{color:#6b6b6b !important}.has-background-grey{background-color:#6b6b6b !important}.has-text-grey-light{color:#b5b5b5 !important}.has-background-grey-light{background-color:#b5b5b5 !important}.has-text-grey-lighter{color:#dbdbdb !important}.has-background-grey-lighter{background-color:#dbdbdb !important}.has-text-white-ter{color:#f5f5f5 !important}.has-background-white-ter{background-color:#f5f5f5 !important}.has-text-white-bis{color:#fafafa !important}.has-background-white-bis{background-color:#fafafa !important}.is-flex-direction-row{flex-direction:row !important}.is-flex-direction-row-reverse{flex-direction:row-reverse !important}.is-flex-direction-column{flex-direction:column !important}.is-flex-direction-column-reverse{flex-direction:column-reverse !important}.is-flex-wrap-nowrap{flex-wrap:nowrap !important}.is-flex-wrap-wrap{flex-wrap:wrap !important}.is-flex-wrap-wrap-reverse{flex-wrap:wrap-reverse !important}.is-justify-content-flex-start{justify-content:flex-start !important}.is-justify-content-flex-end{justify-content:flex-end !important}.is-justify-content-center{justify-content:center !important}.is-justify-content-space-between{justify-content:space-between !important}.is-justify-content-space-around{justify-content:space-around !important}.is-justify-content-space-evenly{justify-content:space-evenly !important}.is-justify-content-start{justify-content:start !important}.is-justify-content-end{justify-content:end !important}.is-justify-content-left{justify-content:left !important}.is-justify-content-right{justify-content:right !important}.is-align-content-flex-start{align-content:flex-start !important}.is-align-content-flex-end{align-content:flex-end !important}.is-align-content-center{align-content:center !important}.is-align-content-space-between{align-content:space-between !important}.is-align-content-space-around{align-content:space-around !important}.is-align-content-space-evenly{align-content:space-evenly !important}.is-align-content-stretch{align-content:stretch !important}.is-align-content-start{align-content:start !important}.is-align-content-end{align-content:end !important}.is-align-content-baseline{align-content:baseline !important}.is-align-items-stretch{align-items:stretch !important}.is-align-items-flex-start{align-items:flex-start !important}.is-align-items-flex-end{align-items:flex-end !important}.is-align-items-center{align-items:center !important}.is-align-items-baseline{align-items:baseline !important}.is-align-items-start{align-items:start !important}.is-align-items-end{align-items:end !important}.is-align-items-self-start{align-items:self-start !important}.is-align-items-self-end{align-items:self-end !important}.is-align-self-auto{align-self:auto !important}.is-align-self-flex-start{align-self:flex-start !important}.is-align-self-flex-end{align-self:flex-end !important}.is-align-self-center{align-self:center !important}.is-align-self-baseline{align-self:baseline !important}.is-align-self-stretch{align-self:stretch !important}.is-flex-grow-0{flex-grow:0 !important}.is-flex-grow-1{flex-grow:1 !important}.is-flex-grow-2{flex-grow:2 !important}.is-flex-grow-3{flex-grow:3 !important}.is-flex-grow-4{flex-grow:4 !important}.is-flex-grow-5{flex-grow:5 !important}.is-flex-shrink-0{flex-shrink:0 !important}.is-flex-shrink-1{flex-shrink:1 !important}.is-flex-shrink-2{flex-shrink:2 !important}.is-flex-shrink-3{flex-shrink:3 !important}.is-flex-shrink-4{flex-shrink:4 !important}.is-flex-shrink-5{flex-shrink:5 !important}.is-clearfix::after{clear:both;content:" ";display:table}.is-pulled-left{float:left !important}.is-pulled-right{float:right !important}.is-radiusless{border-radius:0 !important}.is-shadowless{box-shadow:none !important}.is-clickable{cursor:pointer !important;pointer-events:all !important}.is-clipped{overflow:hidden !important}.is-relative{position:relative !important}.is-marginless{margin:0 !important}.is-paddingless{padding:0 !important}.m-0{margin:0 !important}.mt-0{margin-top:0 !important}.mr-0{margin-right:0 !important}.mb-0{margin-bottom:0 !important}.ml-0{margin-left:0 !important}.mx-0{margin-left:0 !important;margin-right:0 !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.m-1{margin:.25rem !important}.mt-1{margin-top:.25rem !important}.mr-1{margin-right:.25rem !important}.mb-1{margin-bottom:.25rem !important}.ml-1{margin-left:.25rem !important}.mx-1{margin-left:.25rem !important;margin-right:.25rem !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.m-2{margin:.5rem !important}.mt-2{margin-top:.5rem !important}.mr-2{margin-right:.5rem !important}.mb-2{margin-bottom:.5rem !important}.ml-2{margin-left:.5rem !important}.mx-2{margin-left:.5rem !important;margin-right:.5rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.m-3{margin:.75rem !important}.mt-3{margin-top:.75rem !important}.mr-3{margin-right:.75rem !important}.mb-3{margin-bottom:.75rem !important}.ml-3{margin-left:.75rem !important}.mx-3{margin-left:.75rem !important;margin-right:.75rem !important}.my-3{margin-top:.75rem !important;margin-bottom:.75rem !important}.m-4{margin:1rem !important}.mt-4{margin-top:1rem !important}.mr-4{margin-right:1rem !important}.mb-4{margin-bottom:1rem !important}.ml-4{margin-left:1rem !important}.mx-4{margin-left:1rem !important;margin-right:1rem !important}.my-4{margin-top:1rem !important;margin-bottom:1rem !important}.m-5{margin:1.5rem !important}.mt-5{margin-top:1.5rem !important}.mr-5{margin-right:1.5rem !important}.mb-5{margin-bottom:1.5rem !important}.ml-5{margin-left:1.5rem !important}.mx-5{margin-left:1.5rem !important;margin-right:1.5rem !important}.my-5{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.m-6{margin:3rem !important}.mt-6{margin-top:3rem !important}.mr-6{margin-right:3rem !important}.mb-6{margin-bottom:3rem !important}.ml-6{margin-left:3rem !important}.mx-6{margin-left:3rem !important;margin-right:3rem !important}.my-6{margin-top:3rem !important;margin-bottom:3rem !important}.m-auto{margin:auto !important}.mt-auto{margin-top:auto !important}.mr-auto{margin-right:auto !important}.mb-auto{margin-bottom:auto !important}.ml-auto{margin-left:auto !important}.mx-auto{margin-left:auto !important;margin-right:auto !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.p-0{padding:0 !important}.pt-0{padding-top:0 !important}.pr-0{padding-right:0 !important}.pb-0{padding-bottom:0 !important}.pl-0{padding-left:0 !important}.px-0{padding-left:0 !important;padding-right:0 !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.p-1{padding:.25rem !important}.pt-1{padding-top:.25rem !important}.pr-1{padding-right:.25rem !important}.pb-1{padding-bottom:.25rem !important}.pl-1{padding-left:.25rem !important}.px-1{padding-left:.25rem !important;padding-right:.25rem !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.p-2{padding:.5rem !important}.pt-2{padding-top:.5rem !important}.pr-2{padding-right:.5rem !important}.pb-2{padding-bottom:.5rem !important}.pl-2{padding-left:.5rem !important}.px-2{padding-left:.5rem !important;padding-right:.5rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.p-3{padding:.75rem !important}.pt-3{padding-top:.75rem !important}.pr-3{padding-right:.75rem !important}.pb-3{padding-bottom:.75rem !important}.pl-3{padding-left:.75rem !important}.px-3{padding-left:.75rem !important;padding-right:.75rem !important}.py-3{padding-top:.75rem !important;padding-bottom:.75rem !important}.p-4{padding:1rem !important}.pt-4{padding-top:1rem !important}.pr-4{padding-right:1rem !important}.pb-4{padding-bottom:1rem !important}.pl-4{padding-left:1rem !important}.px-4{padding-left:1rem !important;padding-right:1rem !important}.py-4{padding-top:1rem !important;padding-bottom:1rem !important}.p-5{padding:1.5rem !important}.pt-5{padding-top:1.5rem !important}.pr-5{padding-right:1.5rem !important}.pb-5{padding-bottom:1.5rem !important}.pl-5{padding-left:1.5rem !important}.px-5{padding-left:1.5rem !important;padding-right:1.5rem !important}.py-5{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.p-6{padding:3rem !important}.pt-6{padding-top:3rem !important}.pr-6{padding-right:3rem !important}.pb-6{padding-bottom:3rem !important}.pl-6{padding-left:3rem !important}.px-6{padding-left:3rem !important;padding-right:3rem !important}.py-6{padding-top:3rem !important;padding-bottom:3rem !important}.p-auto{padding:auto !important}.pt-auto{padding-top:auto !important}.pr-auto{padding-right:auto !important}.pb-auto{padding-bottom:auto !important}.pl-auto{padding-left:auto !important}.px-auto{padding-left:auto !important;padding-right:auto !important}.py-auto{padding-top:auto !important;padding-bottom:auto !important}.is-size-1{font-size:3rem !important}.is-size-2{font-size:2.5rem !important}.is-size-3{font-size:2rem !important}.is-size-4{font-size:1.5rem !important}.is-size-5{font-size:1.25rem !important}.is-size-6{font-size:1rem !important}.is-size-7,.docstring>section>a.docs-sourcelink{font-size:.75rem !important}@media screen and (max-width: 768px){.is-size-1-mobile{font-size:3rem !important}.is-size-2-mobile{font-size:2.5rem !important}.is-size-3-mobile{font-size:2rem !important}.is-size-4-mobile{font-size:1.5rem !important}.is-size-5-mobile{font-size:1.25rem !important}.is-size-6-mobile{font-size:1rem !important}.is-size-7-mobile{font-size:.75rem !important}}@media screen and (min-width: 769px),print{.is-size-1-tablet{font-size:3rem !important}.is-size-2-tablet{font-size:2.5rem !important}.is-size-3-tablet{font-size:2rem !important}.is-size-4-tablet{font-size:1.5rem !important}.is-size-5-tablet{font-size:1.25rem !important}.is-size-6-tablet{font-size:1rem !important}.is-size-7-tablet{font-size:.75rem !important}}@media screen and (max-width: 1055px){.is-size-1-touch{font-size:3rem !important}.is-size-2-touch{font-size:2.5rem !important}.is-size-3-touch{font-size:2rem !important}.is-size-4-touch{font-size:1.5rem !important}.is-size-5-touch{font-size:1.25rem !important}.is-size-6-touch{font-size:1rem !important}.is-size-7-touch{font-size:.75rem !important}}@media screen and (min-width: 1056px){.is-size-1-desktop{font-size:3rem !important}.is-size-2-desktop{font-size:2.5rem !important}.is-size-3-desktop{font-size:2rem !important}.is-size-4-desktop{font-size:1.5rem !important}.is-size-5-desktop{font-size:1.25rem !important}.is-size-6-desktop{font-size:1rem !important}.is-size-7-desktop{font-size:.75rem !important}}@media screen and (min-width: 1216px){.is-size-1-widescreen{font-size:3rem !important}.is-size-2-widescreen{font-size:2.5rem !important}.is-size-3-widescreen{font-size:2rem !important}.is-size-4-widescreen{font-size:1.5rem !important}.is-size-5-widescreen{font-size:1.25rem !important}.is-size-6-widescreen{font-size:1rem !important}.is-size-7-widescreen{font-size:.75rem !important}}@media screen and (min-width: 1408px){.is-size-1-fullhd{font-size:3rem !important}.is-size-2-fullhd{font-size:2.5rem !important}.is-size-3-fullhd{font-size:2rem !important}.is-size-4-fullhd{font-size:1.5rem !important}.is-size-5-fullhd{font-size:1.25rem !important}.is-size-6-fullhd{font-size:1rem !important}.is-size-7-fullhd{font-size:.75rem !important}}.has-text-centered{text-align:center !important}.has-text-justified{text-align:justify !important}.has-text-left{text-align:left !important}.has-text-right{text-align:right !important}@media screen and (max-width: 768px){.has-text-centered-mobile{text-align:center !important}}@media screen and (min-width: 769px),print{.has-text-centered-tablet{text-align:center !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-centered-tablet-only{text-align:center !important}}@media screen and (max-width: 1055px){.has-text-centered-touch{text-align:center !important}}@media screen and (min-width: 1056px){.has-text-centered-desktop{text-align:center !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-centered-desktop-only{text-align:center !important}}@media screen and (min-width: 1216px){.has-text-centered-widescreen{text-align:center !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-centered-widescreen-only{text-align:center !important}}@media screen and (min-width: 1408px){.has-text-centered-fullhd{text-align:center !important}}@media screen and (max-width: 768px){.has-text-justified-mobile{text-align:justify !important}}@media screen and (min-width: 769px),print{.has-text-justified-tablet{text-align:justify !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-justified-tablet-only{text-align:justify !important}}@media screen and (max-width: 1055px){.has-text-justified-touch{text-align:justify !important}}@media screen and (min-width: 1056px){.has-text-justified-desktop{text-align:justify !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-justified-desktop-only{text-align:justify !important}}@media screen and (min-width: 1216px){.has-text-justified-widescreen{text-align:justify !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-justified-widescreen-only{text-align:justify !important}}@media screen and (min-width: 1408px){.has-text-justified-fullhd{text-align:justify !important}}@media screen and (max-width: 768px){.has-text-left-mobile{text-align:left !important}}@media screen and (min-width: 769px),print{.has-text-left-tablet{text-align:left !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-left-tablet-only{text-align:left !important}}@media screen and (max-width: 1055px){.has-text-left-touch{text-align:left !important}}@media screen and (min-width: 1056px){.has-text-left-desktop{text-align:left !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-left-desktop-only{text-align:left !important}}@media screen and (min-width: 1216px){.has-text-left-widescreen{text-align:left !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-left-widescreen-only{text-align:left !important}}@media screen and (min-width: 1408px){.has-text-left-fullhd{text-align:left !important}}@media screen and (max-width: 768px){.has-text-right-mobile{text-align:right !important}}@media screen and (min-width: 769px),print{.has-text-right-tablet{text-align:right !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-right-tablet-only{text-align:right !important}}@media screen and (max-width: 1055px){.has-text-right-touch{text-align:right !important}}@media screen and (min-width: 1056px){.has-text-right-desktop{text-align:right !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-right-desktop-only{text-align:right !important}}@media screen and (min-width: 1216px){.has-text-right-widescreen{text-align:right !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-right-widescreen-only{text-align:right !important}}@media screen and (min-width: 1408px){.has-text-right-fullhd{text-align:right !important}}.is-capitalized{text-transform:capitalize !important}.is-lowercase{text-transform:lowercase !important}.is-uppercase{text-transform:uppercase !important}.is-italic{font-style:italic !important}.is-underlined{text-decoration:underline !important}.has-text-weight-light{font-weight:300 !important}.has-text-weight-normal{font-weight:400 !important}.has-text-weight-medium{font-weight:500 !important}.has-text-weight-semibold{font-weight:600 !important}.has-text-weight-bold{font-weight:700 !important}.is-family-primary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-secondary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-sans-serif{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-monospace{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-family-code{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-block{display:block !important}@media screen and (max-width: 768px){.is-block-mobile{display:block !important}}@media screen and (min-width: 769px),print{.is-block-tablet{display:block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-block-tablet-only{display:block !important}}@media screen and (max-width: 1055px){.is-block-touch{display:block !important}}@media screen and (min-width: 1056px){.is-block-desktop{display:block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-block-desktop-only{display:block !important}}@media screen and (min-width: 1216px){.is-block-widescreen{display:block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-block-widescreen-only{display:block !important}}@media screen and (min-width: 1408px){.is-block-fullhd{display:block !important}}.is-flex{display:flex !important}@media screen and (max-width: 768px){.is-flex-mobile{display:flex !important}}@media screen and (min-width: 769px),print{.is-flex-tablet{display:flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-flex-tablet-only{display:flex !important}}@media screen and (max-width: 1055px){.is-flex-touch{display:flex !important}}@media screen and (min-width: 1056px){.is-flex-desktop{display:flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-flex-desktop-only{display:flex !important}}@media screen and (min-width: 1216px){.is-flex-widescreen{display:flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-flex-widescreen-only{display:flex !important}}@media screen and (min-width: 1408px){.is-flex-fullhd{display:flex !important}}.is-inline{display:inline !important}@media screen and (max-width: 768px){.is-inline-mobile{display:inline !important}}@media screen and (min-width: 769px),print{.is-inline-tablet{display:inline !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-tablet-only{display:inline !important}}@media screen and (max-width: 1055px){.is-inline-touch{display:inline !important}}@media screen and (min-width: 1056px){.is-inline-desktop{display:inline !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-desktop-only{display:inline !important}}@media screen and (min-width: 1216px){.is-inline-widescreen{display:inline !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-widescreen-only{display:inline !important}}@media screen and (min-width: 1408px){.is-inline-fullhd{display:inline !important}}.is-inline-block{display:inline-block !important}@media screen and (max-width: 768px){.is-inline-block-mobile{display:inline-block !important}}@media screen and (min-width: 769px),print{.is-inline-block-tablet{display:inline-block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-block-tablet-only{display:inline-block !important}}@media screen and (max-width: 1055px){.is-inline-block-touch{display:inline-block !important}}@media screen and (min-width: 1056px){.is-inline-block-desktop{display:inline-block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-block-desktop-only{display:inline-block !important}}@media screen and (min-width: 1216px){.is-inline-block-widescreen{display:inline-block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-block-widescreen-only{display:inline-block !important}}@media screen and (min-width: 1408px){.is-inline-block-fullhd{display:inline-block !important}}.is-inline-flex{display:inline-flex !important}@media screen and (max-width: 768px){.is-inline-flex-mobile{display:inline-flex !important}}@media screen and (min-width: 769px),print{.is-inline-flex-tablet{display:inline-flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-flex-tablet-only{display:inline-flex !important}}@media screen and (max-width: 1055px){.is-inline-flex-touch{display:inline-flex !important}}@media screen and (min-width: 1056px){.is-inline-flex-desktop{display:inline-flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-flex-desktop-only{display:inline-flex !important}}@media screen and (min-width: 1216px){.is-inline-flex-widescreen{display:inline-flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-flex-widescreen-only{display:inline-flex !important}}@media screen and (min-width: 1408px){.is-inline-flex-fullhd{display:inline-flex !important}}.is-hidden{display:none !important}.is-sr-only{border:none !important;clip:rect(0, 0, 0, 0) !important;height:0.01em !important;overflow:hidden !important;padding:0 !important;position:absolute !important;white-space:nowrap !important;width:0.01em !important}@media screen and (max-width: 768px){.is-hidden-mobile{display:none !important}}@media screen and (min-width: 769px),print{.is-hidden-tablet{display:none !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-hidden-tablet-only{display:none !important}}@media screen and (max-width: 1055px){.is-hidden-touch{display:none !important}}@media screen and (min-width: 1056px){.is-hidden-desktop{display:none !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-hidden-desktop-only{display:none !important}}@media screen and (min-width: 1216px){.is-hidden-widescreen{display:none !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-hidden-widescreen-only{display:none !important}}@media screen and (min-width: 1408px){.is-hidden-fullhd{display:none !important}}.is-invisible{visibility:hidden !important}@media screen and (max-width: 768px){.is-invisible-mobile{visibility:hidden !important}}@media screen and (min-width: 769px),print{.is-invisible-tablet{visibility:hidden !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-invisible-tablet-only{visibility:hidden !important}}@media screen and (max-width: 1055px){.is-invisible-touch{visibility:hidden !important}}@media screen and (min-width: 1056px){.is-invisible-desktop{visibility:hidden !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-invisible-desktop-only{visibility:hidden !important}}@media screen and (min-width: 1216px){.is-invisible-widescreen{visibility:hidden !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-invisible-widescreen-only{visibility:hidden !important}}@media screen and (min-width: 1408px){.is-invisible-fullhd{visibility:hidden !important}}/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:inherit}html{background-color:#fff;font-size:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}article,aside,figure,footer,header,hgroup,section{display:block}body,button,input,optgroup,select,textarea{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif}code,pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}body{color:#222;font-size:1em;font-weight:400;line-height:1.5}a{color:#2e63b8;cursor:pointer;text-decoration:none}a strong{color:currentColor}a:hover{color:#363636}code{background-color:rgba(0,0,0,0.05);color:#000;font-size:.875em;font-weight:normal;padding:.1em}hr{background-color:#f5f5f5;border:none;display:block;height:2px;margin:1.5rem 0}img{height:auto;max-width:100%}input[type="checkbox"],input[type="radio"]{vertical-align:baseline}small{font-size:.875em}span{font-style:inherit;font-weight:inherit}strong{color:#222;font-weight:700}fieldset{border:none}pre{-webkit-overflow-scrolling:touch;background-color:#f5f5f5;color:#222;font-size:.875em;overflow-x:auto;padding:1.25rem 1.5rem;white-space:pre;word-wrap:normal}pre code{background-color:transparent;color:currentColor;font-size:1em;padding:0}table td,table th{vertical-align:top}table td:not([align]),table th:not([align]){text-align:inherit}table th{color:#222}@keyframes spinAround{from{transform:rotate(0deg)}to{transform:rotate(359deg)}}.box{background-color:#fff;border-radius:6px;box-shadow:#bbb;color:#222;display:block;padding:1.25rem}a.box:hover,a.box:focus{box-shadow:0 0.5em 1em -0.125em rgba(10,10,10,0.1),0 0 0 1px #2e63b8}a.box:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2),0 0 0 1px #2e63b8}.button{background-color:#fff;border-color:#dbdbdb;border-width:1px;color:#222;cursor:pointer;justify-content:center;padding-bottom:calc(0.5em - 1px);padding-left:1em;padding-right:1em;padding-top:calc(0.5em - 1px);text-align:center;white-space:nowrap}.button strong{color:inherit}.button .icon,.button .icon.is-small,.button #documenter .docs-sidebar form.docs-search>input.icon,#documenter .docs-sidebar .button form.docs-search>input.icon,.button .icon.is-medium,.button .icon.is-large{height:1.5em;width:1.5em}.button .icon:first-child:not(:last-child){margin-left:calc(-0.5em - 1px);margin-right:.25em}.button .icon:last-child:not(:first-child){margin-left:.25em;margin-right:calc(-0.5em - 1px)}.button .icon:first-child:last-child{margin-left:calc(-0.5em - 1px);margin-right:calc(-0.5em - 1px)}.button:hover,.button.is-hovered{border-color:#b5b5b5;color:#363636}.button:focus,.button.is-focused{border-color:#3c5dcd;color:#363636}.button:focus:not(:active),.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.button:active,.button.is-active{border-color:#4a4a4a;color:#363636}.button.is-text{background-color:transparent;border-color:transparent;color:#222;text-decoration:underline}.button.is-text:hover,.button.is-text.is-hovered,.button.is-text:focus,.button.is-text.is-focused{background-color:#f5f5f5;color:#222}.button.is-text:active,.button.is-text.is-active{background-color:#e8e8e8;color:#222}.button.is-text[disabled],fieldset[disabled] .button.is-text{background-color:transparent;border-color:transparent;box-shadow:none}.button.is-ghost{background:none;border-color:rgba(0,0,0,0);color:#2e63b8;text-decoration:none}.button.is-ghost:hover,.button.is-ghost.is-hovered{color:#2e63b8;text-decoration:underline}.button.is-white{background-color:#fff;border-color:transparent;color:#0a0a0a}.button.is-white:hover,.button.is-white.is-hovered{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}.button.is-white:focus,.button.is-white.is-focused{border-color:transparent;color:#0a0a0a}.button.is-white:focus:not(:active),.button.is-white.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}.button.is-white:active,.button.is-white.is-active{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}.button.is-white[disabled],fieldset[disabled] .button.is-white{background-color:#fff;border-color:#fff;box-shadow:none}.button.is-white.is-inverted{background-color:#0a0a0a;color:#fff}.button.is-white.is-inverted:hover,.button.is-white.is-inverted.is-hovered{background-color:#000}.button.is-white.is-inverted[disabled],fieldset[disabled] .button.is-white.is-inverted{background-color:#0a0a0a;border-color:transparent;box-shadow:none;color:#fff}.button.is-white.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-white.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-white.is-outlined:hover,.button.is-white.is-outlined.is-hovered,.button.is-white.is-outlined:focus,.button.is-white.is-outlined.is-focused{background-color:#fff;border-color:#fff;color:#0a0a0a}.button.is-white.is-outlined.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-white.is-outlined.is-loading:hover::after,.button.is-white.is-outlined.is-loading.is-hovered::after,.button.is-white.is-outlined.is-loading:focus::after,.button.is-white.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-white.is-outlined[disabled],fieldset[disabled] .button.is-white.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}.button.is-white.is-inverted.is-outlined:hover,.button.is-white.is-inverted.is-outlined.is-hovered,.button.is-white.is-inverted.is-outlined:focus,.button.is-white.is-inverted.is-outlined.is-focused{background-color:#0a0a0a;color:#fff}.button.is-white.is-inverted.is-outlined.is-loading:hover::after,.button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-white.is-inverted.is-outlined.is-loading:focus::after,.button.is-white.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-white.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}.button.is-black{background-color:#0a0a0a;border-color:transparent;color:#fff}.button.is-black:hover,.button.is-black.is-hovered{background-color:#040404;border-color:transparent;color:#fff}.button.is-black:focus,.button.is-black.is-focused{border-color:transparent;color:#fff}.button.is-black:focus:not(:active),.button.is-black.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}.button.is-black:active,.button.is-black.is-active{background-color:#000;border-color:transparent;color:#fff}.button.is-black[disabled],fieldset[disabled] .button.is-black{background-color:#0a0a0a;border-color:#0a0a0a;box-shadow:none}.button.is-black.is-inverted{background-color:#fff;color:#0a0a0a}.button.is-black.is-inverted:hover,.button.is-black.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-black.is-inverted[disabled],fieldset[disabled] .button.is-black.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#0a0a0a}.button.is-black.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}.button.is-black.is-outlined:hover,.button.is-black.is-outlined.is-hovered,.button.is-black.is-outlined:focus,.button.is-black.is-outlined.is-focused{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.button.is-black.is-outlined.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-black.is-outlined.is-loading:hover::after,.button.is-black.is-outlined.is-loading.is-hovered::after,.button.is-black.is-outlined.is-loading:focus::after,.button.is-black.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-black.is-outlined[disabled],fieldset[disabled] .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}.button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-black.is-inverted.is-outlined:hover,.button.is-black.is-inverted.is-outlined.is-hovered,.button.is-black.is-inverted.is-outlined:focus,.button.is-black.is-inverted.is-outlined.is-focused{background-color:#fff;color:#0a0a0a}.button.is-black.is-inverted.is-outlined.is-loading:hover::after,.button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-black.is-inverted.is-outlined.is-loading:focus::after,.button.is-black.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-black.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-light{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light:hover,.button.is-light.is-hovered{background-color:#eee;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light:focus,.button.is-light.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light:focus:not(:active),.button.is-light.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}.button.is-light:active,.button.is-light.is-active{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light[disabled],fieldset[disabled] .button.is-light{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none}.button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);color:#f5f5f5}.button.is-light.is-inverted:hover,.button.is-light.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}.button.is-light.is-inverted[disabled],fieldset[disabled] .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#f5f5f5}.button.is-light.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;color:#f5f5f5}.button.is-light.is-outlined:hover,.button.is-light.is-outlined.is-hovered,.button.is-light.is-outlined:focus,.button.is-light.is-outlined.is-focused{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,0.7)}.button.is-light.is-outlined.is-loading::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}.button.is-light.is-outlined.is-loading:hover::after,.button.is-light.is-outlined.is-loading.is-hovered::after,.button.is-light.is-outlined.is-loading:focus::after,.button.is-light.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-light.is-outlined[disabled],fieldset[disabled] .button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;box-shadow:none;color:#f5f5f5}.button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}.button.is-light.is-inverted.is-outlined:hover,.button.is-light.is-inverted.is-outlined.is-hovered,.button.is-light.is-inverted.is-outlined:focus,.button.is-light.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#f5f5f5}.button.is-light.is-inverted.is-outlined.is-loading:hover::after,.button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-light.is-inverted.is-outlined.is-loading:focus::after,.button.is-light.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}.button.is-light.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}.button.is-dark,.content kbd.button{background-color:#363636;border-color:transparent;color:#fff}.button.is-dark:hover,.content kbd.button:hover,.button.is-dark.is-hovered,.content kbd.button.is-hovered{background-color:#2f2f2f;border-color:transparent;color:#fff}.button.is-dark:focus,.content kbd.button:focus,.button.is-dark.is-focused,.content kbd.button.is-focused{border-color:transparent;color:#fff}.button.is-dark:focus:not(:active),.content kbd.button:focus:not(:active),.button.is-dark.is-focused:not(:active),.content kbd.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(54,54,54,0.25)}.button.is-dark:active,.content kbd.button:active,.button.is-dark.is-active,.content kbd.button.is-active{background-color:#292929;border-color:transparent;color:#fff}.button.is-dark[disabled],.content kbd.button[disabled],fieldset[disabled] .button.is-dark,fieldset[disabled] .content kbd.button,.content fieldset[disabled] kbd.button{background-color:#363636;border-color:#363636;box-shadow:none}.button.is-dark.is-inverted,.content kbd.button.is-inverted{background-color:#fff;color:#363636}.button.is-dark.is-inverted:hover,.content kbd.button.is-inverted:hover,.button.is-dark.is-inverted.is-hovered,.content kbd.button.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-dark.is-inverted[disabled],.content kbd.button.is-inverted[disabled],fieldset[disabled] .button.is-dark.is-inverted,fieldset[disabled] .content kbd.button.is-inverted,.content fieldset[disabled] kbd.button.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#363636}.button.is-dark.is-loading::after,.content kbd.button.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-dark.is-outlined,.content kbd.button.is-outlined{background-color:transparent;border-color:#363636;color:#363636}.button.is-dark.is-outlined:hover,.content kbd.button.is-outlined:hover,.button.is-dark.is-outlined.is-hovered,.content kbd.button.is-outlined.is-hovered,.button.is-dark.is-outlined:focus,.content kbd.button.is-outlined:focus,.button.is-dark.is-outlined.is-focused,.content kbd.button.is-outlined.is-focused{background-color:#363636;border-color:#363636;color:#fff}.button.is-dark.is-outlined.is-loading::after,.content kbd.button.is-outlined.is-loading::after{border-color:transparent transparent #363636 #363636 !important}.button.is-dark.is-outlined.is-loading:hover::after,.content kbd.button.is-outlined.is-loading:hover::after,.button.is-dark.is-outlined.is-loading.is-hovered::after,.content kbd.button.is-outlined.is-loading.is-hovered::after,.button.is-dark.is-outlined.is-loading:focus::after,.content kbd.button.is-outlined.is-loading:focus::after,.button.is-dark.is-outlined.is-loading.is-focused::after,.content kbd.button.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-dark.is-outlined[disabled],.content kbd.button.is-outlined[disabled],fieldset[disabled] .button.is-dark.is-outlined,fieldset[disabled] .content kbd.button.is-outlined,.content fieldset[disabled] kbd.button.is-outlined{background-color:transparent;border-color:#363636;box-shadow:none;color:#363636}.button.is-dark.is-inverted.is-outlined,.content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-dark.is-inverted.is-outlined:hover,.content kbd.button.is-inverted.is-outlined:hover,.button.is-dark.is-inverted.is-outlined.is-hovered,.content kbd.button.is-inverted.is-outlined.is-hovered,.button.is-dark.is-inverted.is-outlined:focus,.content kbd.button.is-inverted.is-outlined:focus,.button.is-dark.is-inverted.is-outlined.is-focused,.content kbd.button.is-inverted.is-outlined.is-focused{background-color:#fff;color:#363636}.button.is-dark.is-inverted.is-outlined.is-loading:hover::after,.content kbd.button.is-inverted.is-outlined.is-loading:hover::after,.button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after,.content kbd.button.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-dark.is-inverted.is-outlined.is-loading:focus::after,.content kbd.button.is-inverted.is-outlined.is-loading:focus::after,.button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after,.content kbd.button.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #363636 #363636 !important}.button.is-dark.is-inverted.is-outlined[disabled],.content kbd.button.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-dark.is-inverted.is-outlined,fieldset[disabled] .content kbd.button.is-inverted.is-outlined,.content fieldset[disabled] kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-primary,.docstring>section>a.button.docs-sourcelink{background-color:#4eb5de;border-color:transparent;color:#fff}.button.is-primary:hover,.docstring>section>a.button.docs-sourcelink:hover,.button.is-primary.is-hovered,.docstring>section>a.button.is-hovered.docs-sourcelink{background-color:#43b1dc;border-color:transparent;color:#fff}.button.is-primary:focus,.docstring>section>a.button.docs-sourcelink:focus,.button.is-primary.is-focused,.docstring>section>a.button.is-focused.docs-sourcelink{border-color:transparent;color:#fff}.button.is-primary:focus:not(:active),.docstring>section>a.button.docs-sourcelink:focus:not(:active),.button.is-primary.is-focused:not(:active),.docstring>section>a.button.is-focused.docs-sourcelink:not(:active){box-shadow:0 0 0 0.125em rgba(78,181,222,0.25)}.button.is-primary:active,.docstring>section>a.button.docs-sourcelink:active,.button.is-primary.is-active,.docstring>section>a.button.is-active.docs-sourcelink{background-color:#39acda;border-color:transparent;color:#fff}.button.is-primary[disabled],.docstring>section>a.button.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary,fieldset[disabled] .docstring>section>a.button.docs-sourcelink{background-color:#4eb5de;border-color:#4eb5de;box-shadow:none}.button.is-primary.is-inverted,.docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;color:#4eb5de}.button.is-primary.is-inverted:hover,.docstring>section>a.button.is-inverted.docs-sourcelink:hover,.button.is-primary.is-inverted.is-hovered,.docstring>section>a.button.is-inverted.is-hovered.docs-sourcelink{background-color:#f2f2f2}.button.is-primary.is-inverted[disabled],.docstring>section>a.button.is-inverted.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary.is-inverted,fieldset[disabled] .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;border-color:transparent;box-shadow:none;color:#4eb5de}.button.is-primary.is-loading::after,.docstring>section>a.button.is-loading.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}.button.is-primary.is-outlined,.docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#4eb5de;color:#4eb5de}.button.is-primary.is-outlined:hover,.docstring>section>a.button.is-outlined.docs-sourcelink:hover,.button.is-primary.is-outlined.is-hovered,.docstring>section>a.button.is-outlined.is-hovered.docs-sourcelink,.button.is-primary.is-outlined:focus,.docstring>section>a.button.is-outlined.docs-sourcelink:focus,.button.is-primary.is-outlined.is-focused,.docstring>section>a.button.is-outlined.is-focused.docs-sourcelink{background-color:#4eb5de;border-color:#4eb5de;color:#fff}.button.is-primary.is-outlined.is-loading::after,.docstring>section>a.button.is-outlined.is-loading.docs-sourcelink::after{border-color:transparent transparent #4eb5de #4eb5de !important}.button.is-primary.is-outlined.is-loading:hover::after,.docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:hover::after,.button.is-primary.is-outlined.is-loading.is-hovered::after,.docstring>section>a.button.is-outlined.is-loading.is-hovered.docs-sourcelink::after,.button.is-primary.is-outlined.is-loading:focus::after,.docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:focus::after,.button.is-primary.is-outlined.is-loading.is-focused::after,.docstring>section>a.button.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}.button.is-primary.is-outlined[disabled],.docstring>section>a.button.is-outlined.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary.is-outlined,fieldset[disabled] .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#4eb5de;box-shadow:none;color:#4eb5de}.button.is-primary.is-inverted.is-outlined,.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;color:#fff}.button.is-primary.is-inverted.is-outlined:hover,.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:hover,.button.is-primary.is-inverted.is-outlined.is-hovered,.docstring>section>a.button.is-inverted.is-outlined.is-hovered.docs-sourcelink,.button.is-primary.is-inverted.is-outlined:focus,.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:focus,.button.is-primary.is-inverted.is-outlined.is-focused,.docstring>section>a.button.is-inverted.is-outlined.is-focused.docs-sourcelink{background-color:#fff;color:#4eb5de}.button.is-primary.is-inverted.is-outlined.is-loading:hover::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:hover::after,.button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.is-hovered.docs-sourcelink::after,.button.is-primary.is-inverted.is-outlined.is-loading:focus::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:focus::after,.button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #4eb5de #4eb5de !important}.button.is-primary.is-inverted.is-outlined[disabled],.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary.is-inverted.is-outlined,fieldset[disabled] .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-primary.is-light,.docstring>section>a.button.is-light.docs-sourcelink{background-color:#eef8fc;color:#1a6d8e}.button.is-primary.is-light:hover,.docstring>section>a.button.is-light.docs-sourcelink:hover,.button.is-primary.is-light.is-hovered,.docstring>section>a.button.is-light.is-hovered.docs-sourcelink{background-color:#e3f3fa;border-color:transparent;color:#1a6d8e}.button.is-primary.is-light:active,.docstring>section>a.button.is-light.docs-sourcelink:active,.button.is-primary.is-light.is-active,.docstring>section>a.button.is-light.is-active.docs-sourcelink{background-color:#d8eff8;border-color:transparent;color:#1a6d8e}.button.is-link{background-color:#2e63b8;border-color:transparent;color:#fff}.button.is-link:hover,.button.is-link.is-hovered{background-color:#2b5eae;border-color:transparent;color:#fff}.button.is-link:focus,.button.is-link.is-focused{border-color:transparent;color:#fff}.button.is-link:focus:not(:active),.button.is-link.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.button.is-link:active,.button.is-link.is-active{background-color:#2958a4;border-color:transparent;color:#fff}.button.is-link[disabled],fieldset[disabled] .button.is-link{background-color:#2e63b8;border-color:#2e63b8;box-shadow:none}.button.is-link.is-inverted{background-color:#fff;color:#2e63b8}.button.is-link.is-inverted:hover,.button.is-link.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-link.is-inverted[disabled],fieldset[disabled] .button.is-link.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#2e63b8}.button.is-link.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-link.is-outlined{background-color:transparent;border-color:#2e63b8;color:#2e63b8}.button.is-link.is-outlined:hover,.button.is-link.is-outlined.is-hovered,.button.is-link.is-outlined:focus,.button.is-link.is-outlined.is-focused{background-color:#2e63b8;border-color:#2e63b8;color:#fff}.button.is-link.is-outlined.is-loading::after{border-color:transparent transparent #2e63b8 #2e63b8 !important}.button.is-link.is-outlined.is-loading:hover::after,.button.is-link.is-outlined.is-loading.is-hovered::after,.button.is-link.is-outlined.is-loading:focus::after,.button.is-link.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-link.is-outlined[disabled],fieldset[disabled] .button.is-link.is-outlined{background-color:transparent;border-color:#2e63b8;box-shadow:none;color:#2e63b8}.button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-link.is-inverted.is-outlined:hover,.button.is-link.is-inverted.is-outlined.is-hovered,.button.is-link.is-inverted.is-outlined:focus,.button.is-link.is-inverted.is-outlined.is-focused{background-color:#fff;color:#2e63b8}.button.is-link.is-inverted.is-outlined.is-loading:hover::after,.button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-link.is-inverted.is-outlined.is-loading:focus::after,.button.is-link.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #2e63b8 #2e63b8 !important}.button.is-link.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-link.is-light{background-color:#eff3fb;color:#3169c4}.button.is-link.is-light:hover,.button.is-link.is-light.is-hovered{background-color:#e4ecf8;border-color:transparent;color:#3169c4}.button.is-link.is-light:active,.button.is-link.is-light.is-active{background-color:#dae5f6;border-color:transparent;color:#3169c4}.button.is-info{background-color:#3c5dcd;border-color:transparent;color:#fff}.button.is-info:hover,.button.is-info.is-hovered{background-color:#3355c9;border-color:transparent;color:#fff}.button.is-info:focus,.button.is-info.is-focused{border-color:transparent;color:#fff}.button.is-info:focus:not(:active),.button.is-info.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(60,93,205,0.25)}.button.is-info:active,.button.is-info.is-active{background-color:#3151bf;border-color:transparent;color:#fff}.button.is-info[disabled],fieldset[disabled] .button.is-info{background-color:#3c5dcd;border-color:#3c5dcd;box-shadow:none}.button.is-info.is-inverted{background-color:#fff;color:#3c5dcd}.button.is-info.is-inverted:hover,.button.is-info.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-info.is-inverted[disabled],fieldset[disabled] .button.is-info.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#3c5dcd}.button.is-info.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-info.is-outlined{background-color:transparent;border-color:#3c5dcd;color:#3c5dcd}.button.is-info.is-outlined:hover,.button.is-info.is-outlined.is-hovered,.button.is-info.is-outlined:focus,.button.is-info.is-outlined.is-focused{background-color:#3c5dcd;border-color:#3c5dcd;color:#fff}.button.is-info.is-outlined.is-loading::after{border-color:transparent transparent #3c5dcd #3c5dcd !important}.button.is-info.is-outlined.is-loading:hover::after,.button.is-info.is-outlined.is-loading.is-hovered::after,.button.is-info.is-outlined.is-loading:focus::after,.button.is-info.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-info.is-outlined[disabled],fieldset[disabled] .button.is-info.is-outlined{background-color:transparent;border-color:#3c5dcd;box-shadow:none;color:#3c5dcd}.button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-info.is-inverted.is-outlined:hover,.button.is-info.is-inverted.is-outlined.is-hovered,.button.is-info.is-inverted.is-outlined:focus,.button.is-info.is-inverted.is-outlined.is-focused{background-color:#fff;color:#3c5dcd}.button.is-info.is-inverted.is-outlined.is-loading:hover::after,.button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-info.is-inverted.is-outlined.is-loading:focus::after,.button.is-info.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #3c5dcd #3c5dcd !important}.button.is-info.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-info.is-light{background-color:#eff2fb;color:#3253c3}.button.is-info.is-light:hover,.button.is-info.is-light.is-hovered{background-color:#e5e9f8;border-color:transparent;color:#3253c3}.button.is-info.is-light:active,.button.is-info.is-light.is-active{background-color:#dae1f6;border-color:transparent;color:#3253c3}.button.is-success{background-color:#259a12;border-color:transparent;color:#fff}.button.is-success:hover,.button.is-success.is-hovered{background-color:#228f11;border-color:transparent;color:#fff}.button.is-success:focus,.button.is-success.is-focused{border-color:transparent;color:#fff}.button.is-success:focus:not(:active),.button.is-success.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(37,154,18,0.25)}.button.is-success:active,.button.is-success.is-active{background-color:#20830f;border-color:transparent;color:#fff}.button.is-success[disabled],fieldset[disabled] .button.is-success{background-color:#259a12;border-color:#259a12;box-shadow:none}.button.is-success.is-inverted{background-color:#fff;color:#259a12}.button.is-success.is-inverted:hover,.button.is-success.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-success.is-inverted[disabled],fieldset[disabled] .button.is-success.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#259a12}.button.is-success.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-success.is-outlined{background-color:transparent;border-color:#259a12;color:#259a12}.button.is-success.is-outlined:hover,.button.is-success.is-outlined.is-hovered,.button.is-success.is-outlined:focus,.button.is-success.is-outlined.is-focused{background-color:#259a12;border-color:#259a12;color:#fff}.button.is-success.is-outlined.is-loading::after{border-color:transparent transparent #259a12 #259a12 !important}.button.is-success.is-outlined.is-loading:hover::after,.button.is-success.is-outlined.is-loading.is-hovered::after,.button.is-success.is-outlined.is-loading:focus::after,.button.is-success.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-success.is-outlined[disabled],fieldset[disabled] .button.is-success.is-outlined{background-color:transparent;border-color:#259a12;box-shadow:none;color:#259a12}.button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-success.is-inverted.is-outlined:hover,.button.is-success.is-inverted.is-outlined.is-hovered,.button.is-success.is-inverted.is-outlined:focus,.button.is-success.is-inverted.is-outlined.is-focused{background-color:#fff;color:#259a12}.button.is-success.is-inverted.is-outlined.is-loading:hover::after,.button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-success.is-inverted.is-outlined.is-loading:focus::after,.button.is-success.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #259a12 #259a12 !important}.button.is-success.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-success.is-light{background-color:#effded;color:#2ec016}.button.is-success.is-light:hover,.button.is-success.is-light.is-hovered{background-color:#e5fce1;border-color:transparent;color:#2ec016}.button.is-success.is-light:active,.button.is-success.is-light.is-active{background-color:#dbfad6;border-color:transparent;color:#2ec016}.button.is-warning{background-color:#a98800;border-color:transparent;color:#fff}.button.is-warning:hover,.button.is-warning.is-hovered{background-color:#9c7d00;border-color:transparent;color:#fff}.button.is-warning:focus,.button.is-warning.is-focused{border-color:transparent;color:#fff}.button.is-warning:focus:not(:active),.button.is-warning.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(169,136,0,0.25)}.button.is-warning:active,.button.is-warning.is-active{background-color:#8f7300;border-color:transparent;color:#fff}.button.is-warning[disabled],fieldset[disabled] .button.is-warning{background-color:#a98800;border-color:#a98800;box-shadow:none}.button.is-warning.is-inverted{background-color:#fff;color:#a98800}.button.is-warning.is-inverted:hover,.button.is-warning.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-warning.is-inverted[disabled],fieldset[disabled] .button.is-warning.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#a98800}.button.is-warning.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-warning.is-outlined{background-color:transparent;border-color:#a98800;color:#a98800}.button.is-warning.is-outlined:hover,.button.is-warning.is-outlined.is-hovered,.button.is-warning.is-outlined:focus,.button.is-warning.is-outlined.is-focused{background-color:#a98800;border-color:#a98800;color:#fff}.button.is-warning.is-outlined.is-loading::after{border-color:transparent transparent #a98800 #a98800 !important}.button.is-warning.is-outlined.is-loading:hover::after,.button.is-warning.is-outlined.is-loading.is-hovered::after,.button.is-warning.is-outlined.is-loading:focus::after,.button.is-warning.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-warning.is-outlined[disabled],fieldset[disabled] .button.is-warning.is-outlined{background-color:transparent;border-color:#a98800;box-shadow:none;color:#a98800}.button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-warning.is-inverted.is-outlined:hover,.button.is-warning.is-inverted.is-outlined.is-hovered,.button.is-warning.is-inverted.is-outlined:focus,.button.is-warning.is-inverted.is-outlined.is-focused{background-color:#fff;color:#a98800}.button.is-warning.is-inverted.is-outlined.is-loading:hover::after,.button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-warning.is-inverted.is-outlined.is-loading:focus::after,.button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #a98800 #a98800 !important}.button.is-warning.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-warning.is-light{background-color:#fffbeb;color:#cca400}.button.is-warning.is-light:hover,.button.is-warning.is-light.is-hovered{background-color:#fff9de;border-color:transparent;color:#cca400}.button.is-warning.is-light:active,.button.is-warning.is-light.is-active{background-color:#fff6d1;border-color:transparent;color:#cca400}.button.is-danger{background-color:#cb3c33;border-color:transparent;color:#fff}.button.is-danger:hover,.button.is-danger.is-hovered{background-color:#c13930;border-color:transparent;color:#fff}.button.is-danger:focus,.button.is-danger.is-focused{border-color:transparent;color:#fff}.button.is-danger:focus:not(:active),.button.is-danger.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(203,60,51,0.25)}.button.is-danger:active,.button.is-danger.is-active{background-color:#b7362e;border-color:transparent;color:#fff}.button.is-danger[disabled],fieldset[disabled] .button.is-danger{background-color:#cb3c33;border-color:#cb3c33;box-shadow:none}.button.is-danger.is-inverted{background-color:#fff;color:#cb3c33}.button.is-danger.is-inverted:hover,.button.is-danger.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-danger.is-inverted[disabled],fieldset[disabled] .button.is-danger.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#cb3c33}.button.is-danger.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-danger.is-outlined{background-color:transparent;border-color:#cb3c33;color:#cb3c33}.button.is-danger.is-outlined:hover,.button.is-danger.is-outlined.is-hovered,.button.is-danger.is-outlined:focus,.button.is-danger.is-outlined.is-focused{background-color:#cb3c33;border-color:#cb3c33;color:#fff}.button.is-danger.is-outlined.is-loading::after{border-color:transparent transparent #cb3c33 #cb3c33 !important}.button.is-danger.is-outlined.is-loading:hover::after,.button.is-danger.is-outlined.is-loading.is-hovered::after,.button.is-danger.is-outlined.is-loading:focus::after,.button.is-danger.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-danger.is-outlined[disabled],fieldset[disabled] .button.is-danger.is-outlined{background-color:transparent;border-color:#cb3c33;box-shadow:none;color:#cb3c33}.button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-danger.is-inverted.is-outlined:hover,.button.is-danger.is-inverted.is-outlined.is-hovered,.button.is-danger.is-inverted.is-outlined:focus,.button.is-danger.is-inverted.is-outlined.is-focused{background-color:#fff;color:#cb3c33}.button.is-danger.is-inverted.is-outlined.is-loading:hover::after,.button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-danger.is-inverted.is-outlined.is-loading:focus::after,.button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #cb3c33 #cb3c33 !important}.button.is-danger.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-danger.is-light{background-color:#fbefef;color:#c03930}.button.is-danger.is-light:hover,.button.is-danger.is-light.is-hovered{background-color:#f8e6e5;border-color:transparent;color:#c03930}.button.is-danger.is-light:active,.button.is-danger.is-light.is-active{background-color:#f6dcda;border-color:transparent;color:#c03930}.button.is-small,#documenter .docs-sidebar form.docs-search>input.button{font-size:.75rem}.button.is-small:not(.is-rounded),#documenter .docs-sidebar form.docs-search>input.button:not(.is-rounded){border-radius:2px}.button.is-normal{font-size:1rem}.button.is-medium{font-size:1.25rem}.button.is-large{font-size:1.5rem}.button[disabled],fieldset[disabled] .button{background-color:#fff;border-color:#dbdbdb;box-shadow:none;opacity:.5}.button.is-fullwidth{display:flex;width:100%}.button.is-loading{color:transparent !important;pointer-events:none}.button.is-loading::after{position:absolute;left:calc(50% - (1em * 0.5));top:calc(50% - (1em * 0.5));position:absolute !important}.button.is-static{background-color:#f5f5f5;border-color:#dbdbdb;color:#6b6b6b;box-shadow:none;pointer-events:none}.button.is-rounded,#documenter .docs-sidebar form.docs-search>input.button{border-radius:9999px;padding-left:calc(1em + 0.25em);padding-right:calc(1em + 0.25em)}.buttons{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}.buttons .button{margin-bottom:0.5rem}.buttons .button:not(:last-child):not(.is-fullwidth){margin-right:.5rem}.buttons:last-child{margin-bottom:-0.5rem}.buttons:not(:last-child){margin-bottom:1rem}.buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large){font-size:.75rem}.buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large):not(.is-rounded){border-radius:2px}.buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large){font-size:1.25rem}.buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium){font-size:1.5rem}.buttons.has-addons .button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.buttons.has-addons .button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.buttons.has-addons .button:last-child{margin-right:0}.buttons.has-addons .button:hover,.buttons.has-addons .button.is-hovered{z-index:2}.buttons.has-addons .button:focus,.buttons.has-addons .button.is-focused,.buttons.has-addons .button:active,.buttons.has-addons .button.is-active,.buttons.has-addons .button.is-selected{z-index:3}.buttons.has-addons .button:focus:hover,.buttons.has-addons .button.is-focused:hover,.buttons.has-addons .button:active:hover,.buttons.has-addons .button.is-active:hover,.buttons.has-addons .button.is-selected:hover{z-index:4}.buttons.has-addons .button.is-expanded{flex-grow:1;flex-shrink:1}.buttons.is-centered{justify-content:center}.buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}.buttons.is-right{justify-content:flex-end}.buttons.is-right:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}@media screen and (max-width: 768px){.button.is-responsive.is-small,#documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.5625rem}.button.is-responsive,.button.is-responsive.is-normal{font-size:.65625rem}.button.is-responsive.is-medium{font-size:.75rem}.button.is-responsive.is-large{font-size:1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.button.is-responsive.is-small,#documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.65625rem}.button.is-responsive,.button.is-responsive.is-normal{font-size:.75rem}.button.is-responsive.is-medium{font-size:1rem}.button.is-responsive.is-large{font-size:1.25rem}}.container{flex-grow:1;margin:0 auto;position:relative;width:auto}.container.is-fluid{max-width:none !important;padding-left:32px;padding-right:32px;width:100%}@media screen and (min-width: 1056px){.container{max-width:992px}}@media screen and (max-width: 1215px){.container.is-widescreen:not(.is-max-desktop){max-width:1152px}}@media screen and (max-width: 1407px){.container.is-fullhd:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}@media screen and (min-width: 1216px){.container:not(.is-max-desktop){max-width:1152px}}@media screen and (min-width: 1408px){.container:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}.content li+li{margin-top:0.25em}.content p:not(:last-child),.content dl:not(:last-child),.content ol:not(:last-child),.content ul:not(:last-child),.content blockquote:not(:last-child),.content pre:not(:last-child),.content table:not(:last-child){margin-bottom:1em}.content h1,.content h2,.content h3,.content h4,.content h5,.content h6{color:#222;font-weight:600;line-height:1.125}.content h1{font-size:2em;margin-bottom:0.5em}.content h1:not(:first-child){margin-top:1em}.content h2{font-size:1.75em;margin-bottom:0.5714em}.content h2:not(:first-child){margin-top:1.1428em}.content h3{font-size:1.5em;margin-bottom:0.6666em}.content h3:not(:first-child){margin-top:1.3333em}.content h4{font-size:1.25em;margin-bottom:0.8em}.content h5{font-size:1.125em;margin-bottom:0.8888em}.content h6{font-size:1em;margin-bottom:1em}.content blockquote{background-color:#f5f5f5;border-left:5px solid #dbdbdb;padding:1.25em 1.5em}.content ol{list-style-position:outside;margin-left:2em;margin-top:1em}.content ol:not([type]){list-style-type:decimal}.content ol.is-lower-alpha:not([type]){list-style-type:lower-alpha}.content ol.is-lower-roman:not([type]){list-style-type:lower-roman}.content ol.is-upper-alpha:not([type]){list-style-type:upper-alpha}.content ol.is-upper-roman:not([type]){list-style-type:upper-roman}.content ul{list-style:disc outside;margin-left:2em;margin-top:1em}.content ul ul{list-style-type:circle;margin-top:0.5em}.content ul ul ul{list-style-type:square}.content dd{margin-left:2em}.content figure{margin-left:2em;margin-right:2em;text-align:center}.content figure:not(:first-child){margin-top:2em}.content figure:not(:last-child){margin-bottom:2em}.content figure img{display:inline-block}.content figure figcaption{font-style:italic}.content pre{-webkit-overflow-scrolling:touch;overflow-x:auto;padding:0;white-space:pre;word-wrap:normal}.content sup,.content sub{font-size:75%}.content table{width:100%}.content table td,.content table th{border:1px solid #dbdbdb;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}.content table th{color:#222}.content table th:not([align]){text-align:inherit}.content table thead td,.content table thead th{border-width:0 0 2px;color:#222}.content table tfoot td,.content table tfoot th{border-width:2px 0 0;color:#222}.content table tbody tr:last-child td,.content table tbody tr:last-child th{border-bottom-width:0}.content .tabs li+li{margin-top:0}.content.is-small,#documenter .docs-sidebar form.docs-search>input.content{font-size:.75rem}.content.is-normal{font-size:1rem}.content.is-medium{font-size:1.25rem}.content.is-large{font-size:1.5rem}.icon{align-items:center;display:inline-flex;justify-content:center;height:1.5rem;width:1.5rem}.icon.is-small,#documenter .docs-sidebar form.docs-search>input.icon{height:1rem;width:1rem}.icon.is-medium{height:2rem;width:2rem}.icon.is-large{height:3rem;width:3rem}.icon-text{align-items:flex-start;color:inherit;display:inline-flex;flex-wrap:wrap;line-height:1.5rem;vertical-align:top}.icon-text .icon{flex-grow:0;flex-shrink:0}.icon-text .icon:not(:last-child){margin-right:.25em}.icon-text .icon:not(:first-child){margin-left:.25em}div.icon-text{display:flex}.image,#documenter .docs-sidebar .docs-logo>img{display:block;position:relative}.image img,#documenter .docs-sidebar .docs-logo>img img{display:block;height:auto;width:100%}.image img.is-rounded,#documenter .docs-sidebar .docs-logo>img img.is-rounded{border-radius:9999px}.image.is-fullwidth,#documenter .docs-sidebar .docs-logo>img.is-fullwidth{width:100%}.image.is-square img,#documenter .docs-sidebar .docs-logo>img.is-square img,.image.is-square .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,.image.is-1by1 img,#documenter .docs-sidebar .docs-logo>img.is-1by1 img,.image.is-1by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,.image.is-5by4 img,#documenter .docs-sidebar .docs-logo>img.is-5by4 img,.image.is-5by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,.image.is-4by3 img,#documenter .docs-sidebar .docs-logo>img.is-4by3 img,.image.is-4by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,.image.is-3by2 img,#documenter .docs-sidebar .docs-logo>img.is-3by2 img,.image.is-3by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,.image.is-5by3 img,#documenter .docs-sidebar .docs-logo>img.is-5by3 img,.image.is-5by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,.image.is-16by9 img,#documenter .docs-sidebar .docs-logo>img.is-16by9 img,.image.is-16by9 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,.image.is-2by1 img,#documenter .docs-sidebar .docs-logo>img.is-2by1 img,.image.is-2by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,.image.is-3by1 img,#documenter .docs-sidebar .docs-logo>img.is-3by1 img,.image.is-3by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,.image.is-4by5 img,#documenter .docs-sidebar .docs-logo>img.is-4by5 img,.image.is-4by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,.image.is-3by4 img,#documenter .docs-sidebar .docs-logo>img.is-3by4 img,.image.is-3by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,.image.is-2by3 img,#documenter .docs-sidebar .docs-logo>img.is-2by3 img,.image.is-2by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,.image.is-3by5 img,#documenter .docs-sidebar .docs-logo>img.is-3by5 img,.image.is-3by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,.image.is-9by16 img,#documenter .docs-sidebar .docs-logo>img.is-9by16 img,.image.is-9by16 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,.image.is-1by2 img,#documenter .docs-sidebar .docs-logo>img.is-1by2 img,.image.is-1by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,.image.is-1by3 img,#documenter .docs-sidebar .docs-logo>img.is-1by3 img,.image.is-1by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio{height:100%;width:100%}.image.is-square,#documenter .docs-sidebar .docs-logo>img.is-square,.image.is-1by1,#documenter .docs-sidebar .docs-logo>img.is-1by1{padding-top:100%}.image.is-5by4,#documenter .docs-sidebar .docs-logo>img.is-5by4{padding-top:80%}.image.is-4by3,#documenter .docs-sidebar .docs-logo>img.is-4by3{padding-top:75%}.image.is-3by2,#documenter .docs-sidebar .docs-logo>img.is-3by2{padding-top:66.6666%}.image.is-5by3,#documenter .docs-sidebar .docs-logo>img.is-5by3{padding-top:60%}.image.is-16by9,#documenter .docs-sidebar .docs-logo>img.is-16by9{padding-top:56.25%}.image.is-2by1,#documenter .docs-sidebar .docs-logo>img.is-2by1{padding-top:50%}.image.is-3by1,#documenter .docs-sidebar .docs-logo>img.is-3by1{padding-top:33.3333%}.image.is-4by5,#documenter .docs-sidebar .docs-logo>img.is-4by5{padding-top:125%}.image.is-3by4,#documenter .docs-sidebar .docs-logo>img.is-3by4{padding-top:133.3333%}.image.is-2by3,#documenter .docs-sidebar .docs-logo>img.is-2by3{padding-top:150%}.image.is-3by5,#documenter .docs-sidebar .docs-logo>img.is-3by5{padding-top:166.6666%}.image.is-9by16,#documenter .docs-sidebar .docs-logo>img.is-9by16{padding-top:177.7777%}.image.is-1by2,#documenter .docs-sidebar .docs-logo>img.is-1by2{padding-top:200%}.image.is-1by3,#documenter .docs-sidebar .docs-logo>img.is-1by3{padding-top:300%}.image.is-16x16,#documenter .docs-sidebar .docs-logo>img.is-16x16{height:16px;width:16px}.image.is-24x24,#documenter .docs-sidebar .docs-logo>img.is-24x24{height:24px;width:24px}.image.is-32x32,#documenter .docs-sidebar .docs-logo>img.is-32x32{height:32px;width:32px}.image.is-48x48,#documenter .docs-sidebar .docs-logo>img.is-48x48{height:48px;width:48px}.image.is-64x64,#documenter .docs-sidebar .docs-logo>img.is-64x64{height:64px;width:64px}.image.is-96x96,#documenter .docs-sidebar .docs-logo>img.is-96x96{height:96px;width:96px}.image.is-128x128,#documenter .docs-sidebar .docs-logo>img.is-128x128{height:128px;width:128px}.notification{background-color:#f5f5f5;border-radius:4px;position:relative;padding:1.25rem 2.5rem 1.25rem 1.5rem}.notification a:not(.button):not(.dropdown-item){color:currentColor;text-decoration:underline}.notification strong{color:currentColor}.notification code,.notification pre{background:#fff}.notification pre code{background:transparent}.notification>.delete{right:.5rem;position:absolute;top:0.5rem}.notification .title,.notification .subtitle,.notification .content{color:currentColor}.notification.is-white{background-color:#fff;color:#0a0a0a}.notification.is-black{background-color:#0a0a0a;color:#fff}.notification.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.notification.is-dark,.content kbd.notification{background-color:#363636;color:#fff}.notification.is-primary,.docstring>section>a.notification.docs-sourcelink{background-color:#4eb5de;color:#fff}.notification.is-primary.is-light,.docstring>section>a.notification.is-light.docs-sourcelink{background-color:#eef8fc;color:#1a6d8e}.notification.is-link{background-color:#2e63b8;color:#fff}.notification.is-link.is-light{background-color:#eff3fb;color:#3169c4}.notification.is-info{background-color:#3c5dcd;color:#fff}.notification.is-info.is-light{background-color:#eff2fb;color:#3253c3}.notification.is-success{background-color:#259a12;color:#fff}.notification.is-success.is-light{background-color:#effded;color:#2ec016}.notification.is-warning{background-color:#a98800;color:#fff}.notification.is-warning.is-light{background-color:#fffbeb;color:#cca400}.notification.is-danger{background-color:#cb3c33;color:#fff}.notification.is-danger.is-light{background-color:#fbefef;color:#c03930}.progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:9999px;display:block;height:1rem;overflow:hidden;padding:0;width:100%}.progress::-webkit-progress-bar{background-color:#ededed}.progress::-webkit-progress-value{background-color:#222}.progress::-moz-progress-bar{background-color:#222}.progress::-ms-fill{background-color:#222;border:none}.progress.is-white::-webkit-progress-value{background-color:#fff}.progress.is-white::-moz-progress-bar{background-color:#fff}.progress.is-white::-ms-fill{background-color:#fff}.progress.is-white:indeterminate{background-image:linear-gradient(to right, #fff 30%, #ededed 30%)}.progress.is-black::-webkit-progress-value{background-color:#0a0a0a}.progress.is-black::-moz-progress-bar{background-color:#0a0a0a}.progress.is-black::-ms-fill{background-color:#0a0a0a}.progress.is-black:indeterminate{background-image:linear-gradient(to right, #0a0a0a 30%, #ededed 30%)}.progress.is-light::-webkit-progress-value{background-color:#f5f5f5}.progress.is-light::-moz-progress-bar{background-color:#f5f5f5}.progress.is-light::-ms-fill{background-color:#f5f5f5}.progress.is-light:indeterminate{background-image:linear-gradient(to right, #f5f5f5 30%, #ededed 30%)}.progress.is-dark::-webkit-progress-value,.content kbd.progress::-webkit-progress-value{background-color:#363636}.progress.is-dark::-moz-progress-bar,.content kbd.progress::-moz-progress-bar{background-color:#363636}.progress.is-dark::-ms-fill,.content kbd.progress::-ms-fill{background-color:#363636}.progress.is-dark:indeterminate,.content kbd.progress:indeterminate{background-image:linear-gradient(to right, #363636 30%, #ededed 30%)}.progress.is-primary::-webkit-progress-value,.docstring>section>a.progress.docs-sourcelink::-webkit-progress-value{background-color:#4eb5de}.progress.is-primary::-moz-progress-bar,.docstring>section>a.progress.docs-sourcelink::-moz-progress-bar{background-color:#4eb5de}.progress.is-primary::-ms-fill,.docstring>section>a.progress.docs-sourcelink::-ms-fill{background-color:#4eb5de}.progress.is-primary:indeterminate,.docstring>section>a.progress.docs-sourcelink:indeterminate{background-image:linear-gradient(to right, #4eb5de 30%, #ededed 30%)}.progress.is-link::-webkit-progress-value{background-color:#2e63b8}.progress.is-link::-moz-progress-bar{background-color:#2e63b8}.progress.is-link::-ms-fill{background-color:#2e63b8}.progress.is-link:indeterminate{background-image:linear-gradient(to right, #2e63b8 30%, #ededed 30%)}.progress.is-info::-webkit-progress-value{background-color:#3c5dcd}.progress.is-info::-moz-progress-bar{background-color:#3c5dcd}.progress.is-info::-ms-fill{background-color:#3c5dcd}.progress.is-info:indeterminate{background-image:linear-gradient(to right, #3c5dcd 30%, #ededed 30%)}.progress.is-success::-webkit-progress-value{background-color:#259a12}.progress.is-success::-moz-progress-bar{background-color:#259a12}.progress.is-success::-ms-fill{background-color:#259a12}.progress.is-success:indeterminate{background-image:linear-gradient(to right, #259a12 30%, #ededed 30%)}.progress.is-warning::-webkit-progress-value{background-color:#a98800}.progress.is-warning::-moz-progress-bar{background-color:#a98800}.progress.is-warning::-ms-fill{background-color:#a98800}.progress.is-warning:indeterminate{background-image:linear-gradient(to right, #a98800 30%, #ededed 30%)}.progress.is-danger::-webkit-progress-value{background-color:#cb3c33}.progress.is-danger::-moz-progress-bar{background-color:#cb3c33}.progress.is-danger::-ms-fill{background-color:#cb3c33}.progress.is-danger:indeterminate{background-image:linear-gradient(to right, #cb3c33 30%, #ededed 30%)}.progress:indeterminate{animation-duration:1.5s;animation-iteration-count:infinite;animation-name:moveIndeterminate;animation-timing-function:linear;background-color:#ededed;background-image:linear-gradient(to right, #222 30%, #ededed 30%);background-position:top left;background-repeat:no-repeat;background-size:150% 150%}.progress:indeterminate::-webkit-progress-bar{background-color:transparent}.progress:indeterminate::-moz-progress-bar{background-color:transparent}.progress:indeterminate::-ms-fill{animation-name:none}.progress.is-small,#documenter .docs-sidebar form.docs-search>input.progress{height:.75rem}.progress.is-medium{height:1.25rem}.progress.is-large{height:1.5rem}@keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}.table{background-color:#fff;color:#222}.table td,.table th{border:1px solid #dbdbdb;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}.table td.is-white,.table th.is-white{background-color:#fff;border-color:#fff;color:#0a0a0a}.table td.is-black,.table th.is-black{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.table td.is-light,.table th.is-light{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,0.7)}.table td.is-dark,.table th.is-dark{background-color:#363636;border-color:#363636;color:#fff}.table td.is-primary,.table th.is-primary{background-color:#4eb5de;border-color:#4eb5de;color:#fff}.table td.is-link,.table th.is-link{background-color:#2e63b8;border-color:#2e63b8;color:#fff}.table td.is-info,.table th.is-info{background-color:#3c5dcd;border-color:#3c5dcd;color:#fff}.table td.is-success,.table th.is-success{background-color:#259a12;border-color:#259a12;color:#fff}.table td.is-warning,.table th.is-warning{background-color:#a98800;border-color:#a98800;color:#fff}.table td.is-danger,.table th.is-danger{background-color:#cb3c33;border-color:#cb3c33;color:#fff}.table td.is-narrow,.table th.is-narrow{white-space:nowrap;width:1%}.table td.is-selected,.table th.is-selected{background-color:#4eb5de;color:#fff}.table td.is-selected a,.table td.is-selected strong,.table th.is-selected a,.table th.is-selected strong{color:currentColor}.table td.is-vcentered,.table th.is-vcentered{vertical-align:middle}.table th{color:#222}.table th:not([align]){text-align:left}.table tr.is-selected{background-color:#4eb5de;color:#fff}.table tr.is-selected a,.table tr.is-selected strong{color:currentColor}.table tr.is-selected td,.table tr.is-selected th{border-color:#fff;color:currentColor}.table thead{background-color:rgba(0,0,0,0)}.table thead td,.table thead th{border-width:0 0 2px;color:#222}.table tfoot{background-color:rgba(0,0,0,0)}.table tfoot td,.table tfoot th{border-width:2px 0 0;color:#222}.table tbody{background-color:rgba(0,0,0,0)}.table tbody tr:last-child td,.table tbody tr:last-child th{border-bottom-width:0}.table.is-bordered td,.table.is-bordered th{border-width:1px}.table.is-bordered tr:last-child td,.table.is-bordered tr:last-child th{border-bottom-width:1px}.table.is-fullwidth{width:100%}.table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#fafafa}.table.is-hoverable.is-striped tbody tr:not(.is-selected):hover{background-color:#fafafa}.table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even){background-color:#f5f5f5}.table.is-narrow td,.table.is-narrow th{padding:0.25em 0.5em}.table.is-striped tbody tr:not(.is-selected):nth-child(even){background-color:#fafafa}.table-container{-webkit-overflow-scrolling:touch;overflow:auto;overflow-y:hidden;max-width:100%}.tags{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}.tags .tag,.tags .content kbd,.content .tags kbd,.tags .docstring>section>a.docs-sourcelink{margin-bottom:0.5rem}.tags .tag:not(:last-child),.tags .content kbd:not(:last-child),.content .tags kbd:not(:last-child),.tags .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:.5rem}.tags:last-child{margin-bottom:-0.5rem}.tags:not(:last-child){margin-bottom:1rem}.tags.are-medium .tag:not(.is-normal):not(.is-large),.tags.are-medium .content kbd:not(.is-normal):not(.is-large),.content .tags.are-medium kbd:not(.is-normal):not(.is-large),.tags.are-medium .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-large){font-size:1rem}.tags.are-large .tag:not(.is-normal):not(.is-medium),.tags.are-large .content kbd:not(.is-normal):not(.is-medium),.content .tags.are-large kbd:not(.is-normal):not(.is-medium),.tags.are-large .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-medium){font-size:1.25rem}.tags.is-centered{justify-content:center}.tags.is-centered .tag,.tags.is-centered .content kbd,.content .tags.is-centered kbd,.tags.is-centered .docstring>section>a.docs-sourcelink{margin-right:0.25rem;margin-left:0.25rem}.tags.is-right{justify-content:flex-end}.tags.is-right .tag:not(:first-child),.tags.is-right .content kbd:not(:first-child),.content .tags.is-right kbd:not(:first-child),.tags.is-right .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0.5rem}.tags.is-right .tag:not(:last-child),.tags.is-right .content kbd:not(:last-child),.content .tags.is-right kbd:not(:last-child),.tags.is-right .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:0}.tags.has-addons .tag,.tags.has-addons .content kbd,.content .tags.has-addons kbd,.tags.has-addons .docstring>section>a.docs-sourcelink{margin-right:0}.tags.has-addons .tag:not(:first-child),.tags.has-addons .content kbd:not(:first-child),.content .tags.has-addons kbd:not(:first-child),.tags.has-addons .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.tags.has-addons .tag:not(:last-child),.tags.has-addons .content kbd:not(:last-child),.content .tags.has-addons kbd:not(:last-child),.tags.has-addons .docstring>section>a.docs-sourcelink:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.tag:not(body),.content kbd:not(body),.docstring>section>a.docs-sourcelink:not(body){align-items:center;background-color:#f5f5f5;border-radius:4px;color:#222;display:inline-flex;font-size:.75rem;height:2em;justify-content:center;line-height:1.5;padding-left:0.75em;padding-right:0.75em;white-space:nowrap}.tag:not(body) .delete,.content kbd:not(body) .delete,.docstring>section>a.docs-sourcelink:not(body) .delete{margin-left:.25rem;margin-right:-.375rem}.tag.is-white:not(body),.content kbd.is-white:not(body),.docstring>section>a.docs-sourcelink.is-white:not(body){background-color:#fff;color:#0a0a0a}.tag.is-black:not(body),.content kbd.is-black:not(body),.docstring>section>a.docs-sourcelink.is-black:not(body){background-color:#0a0a0a;color:#fff}.tag.is-light:not(body),.content kbd.is-light:not(body),.docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.tag.is-dark:not(body),.content kbd:not(body),.docstring>section>a.docs-sourcelink.is-dark:not(body),.content .docstring>section>kbd:not(body){background-color:#363636;color:#fff}.tag.is-primary:not(body),.content kbd.is-primary:not(body),.docstring>section>a.docs-sourcelink:not(body){background-color:#4eb5de;color:#fff}.tag.is-primary.is-light:not(body),.content kbd.is-primary.is-light:not(body),.docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#eef8fc;color:#1a6d8e}.tag.is-link:not(body),.content kbd.is-link:not(body),.docstring>section>a.docs-sourcelink.is-link:not(body){background-color:#2e63b8;color:#fff}.tag.is-link.is-light:not(body),.content kbd.is-link.is-light:not(body),.docstring>section>a.docs-sourcelink.is-link.is-light:not(body){background-color:#eff3fb;color:#3169c4}.tag.is-info:not(body),.content kbd.is-info:not(body),.docstring>section>a.docs-sourcelink.is-info:not(body){background-color:#3c5dcd;color:#fff}.tag.is-info.is-light:not(body),.content kbd.is-info.is-light:not(body),.docstring>section>a.docs-sourcelink.is-info.is-light:not(body){background-color:#eff2fb;color:#3253c3}.tag.is-success:not(body),.content kbd.is-success:not(body),.docstring>section>a.docs-sourcelink.is-success:not(body){background-color:#259a12;color:#fff}.tag.is-success.is-light:not(body),.content kbd.is-success.is-light:not(body),.docstring>section>a.docs-sourcelink.is-success.is-light:not(body){background-color:#effded;color:#2ec016}.tag.is-warning:not(body),.content kbd.is-warning:not(body),.docstring>section>a.docs-sourcelink.is-warning:not(body){background-color:#a98800;color:#fff}.tag.is-warning.is-light:not(body),.content kbd.is-warning.is-light:not(body),.docstring>section>a.docs-sourcelink.is-warning.is-light:not(body){background-color:#fffbeb;color:#cca400}.tag.is-danger:not(body),.content kbd.is-danger:not(body),.docstring>section>a.docs-sourcelink.is-danger:not(body){background-color:#cb3c33;color:#fff}.tag.is-danger.is-light:not(body),.content kbd.is-danger.is-light:not(body),.docstring>section>a.docs-sourcelink.is-danger.is-light:not(body){background-color:#fbefef;color:#c03930}.tag.is-normal:not(body),.content kbd.is-normal:not(body),.docstring>section>a.docs-sourcelink.is-normal:not(body){font-size:.75rem}.tag.is-medium:not(body),.content kbd.is-medium:not(body),.docstring>section>a.docs-sourcelink.is-medium:not(body){font-size:1rem}.tag.is-large:not(body),.content kbd.is-large:not(body),.docstring>section>a.docs-sourcelink.is-large:not(body){font-size:1.25rem}.tag:not(body) .icon:first-child:not(:last-child),.content kbd:not(body) .icon:first-child:not(:last-child),.docstring>section>a.docs-sourcelink:not(body) .icon:first-child:not(:last-child){margin-left:-.375em;margin-right:.1875em}.tag:not(body) .icon:last-child:not(:first-child),.content kbd:not(body) .icon:last-child:not(:first-child),.docstring>section>a.docs-sourcelink:not(body) .icon:last-child:not(:first-child){margin-left:.1875em;margin-right:-.375em}.tag:not(body) .icon:first-child:last-child,.content kbd:not(body) .icon:first-child:last-child,.docstring>section>a.docs-sourcelink:not(body) .icon:first-child:last-child{margin-left:-.375em;margin-right:-.375em}.tag.is-delete:not(body),.content kbd.is-delete:not(body),.docstring>section>a.docs-sourcelink.is-delete:not(body){margin-left:1px;padding:0;position:relative;width:2em}.tag.is-delete:not(body)::before,.content kbd.is-delete:not(body)::before,.docstring>section>a.docs-sourcelink.is-delete:not(body)::before,.tag.is-delete:not(body)::after,.content kbd.is-delete:not(body)::after,.docstring>section>a.docs-sourcelink.is-delete:not(body)::after{background-color:currentColor;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}.tag.is-delete:not(body)::before,.content kbd.is-delete:not(body)::before,.docstring>section>a.docs-sourcelink.is-delete:not(body)::before{height:1px;width:50%}.tag.is-delete:not(body)::after,.content kbd.is-delete:not(body)::after,.docstring>section>a.docs-sourcelink.is-delete:not(body)::after{height:50%;width:1px}.tag.is-delete:not(body):hover,.content kbd.is-delete:not(body):hover,.docstring>section>a.docs-sourcelink.is-delete:not(body):hover,.tag.is-delete:not(body):focus,.content kbd.is-delete:not(body):focus,.docstring>section>a.docs-sourcelink.is-delete:not(body):focus{background-color:#e8e8e8}.tag.is-delete:not(body):active,.content kbd.is-delete:not(body):active,.docstring>section>a.docs-sourcelink.is-delete:not(body):active{background-color:#dbdbdb}.tag.is-rounded:not(body),#documenter .docs-sidebar form.docs-search>input:not(body),.content kbd.is-rounded:not(body),#documenter .docs-sidebar .content form.docs-search>input:not(body),.docstring>section>a.docs-sourcelink.is-rounded:not(body){border-radius:9999px}a.tag:hover,.docstring>section>a.docs-sourcelink:hover{text-decoration:underline}.title,.subtitle{word-break:break-word}.title em,.title span,.subtitle em,.subtitle span{font-weight:inherit}.title sub,.subtitle sub{font-size:.75em}.title sup,.subtitle sup{font-size:.75em}.title .tag,.title .content kbd,.content .title kbd,.title .docstring>section>a.docs-sourcelink,.subtitle .tag,.subtitle .content kbd,.content .subtitle kbd,.subtitle .docstring>section>a.docs-sourcelink{vertical-align:middle}.title{color:#222;font-size:2rem;font-weight:600;line-height:1.125}.title strong{color:inherit;font-weight:inherit}.title:not(.is-spaced)+.subtitle{margin-top:-1.25rem}.title.is-1{font-size:3rem}.title.is-2{font-size:2.5rem}.title.is-3{font-size:2rem}.title.is-4{font-size:1.5rem}.title.is-5{font-size:1.25rem}.title.is-6{font-size:1rem}.title.is-7{font-size:.75rem}.subtitle{color:#222;font-size:1.25rem;font-weight:400;line-height:1.25}.subtitle strong{color:#222;font-weight:600}.subtitle:not(.is-spaced)+.title{margin-top:-1.25rem}.subtitle.is-1{font-size:3rem}.subtitle.is-2{font-size:2.5rem}.subtitle.is-3{font-size:2rem}.subtitle.is-4{font-size:1.5rem}.subtitle.is-5{font-size:1.25rem}.subtitle.is-6{font-size:1rem}.subtitle.is-7{font-size:.75rem}.heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}.number{align-items:center;background-color:#f5f5f5;border-radius:9999px;display:inline-flex;font-size:1.25rem;height:2em;justify-content:center;margin-right:1.5rem;min-width:2.5em;padding:0.25rem 0.5rem;text-align:center;vertical-align:top}.select select,.textarea,.input,#documenter .docs-sidebar form.docs-search>input{background-color:#fff;border-color:#dbdbdb;border-radius:4px;color:#222}.select select::-moz-placeholder,.textarea::-moz-placeholder,.input::-moz-placeholder,#documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:#707070}.select select::-webkit-input-placeholder,.textarea::-webkit-input-placeholder,.input::-webkit-input-placeholder,#documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:#707070}.select select:-moz-placeholder,.textarea:-moz-placeholder,.input:-moz-placeholder,#documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:#707070}.select select:-ms-input-placeholder,.textarea:-ms-input-placeholder,.input:-ms-input-placeholder,#documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:#707070}.select select:hover,.textarea:hover,.input:hover,#documenter .docs-sidebar form.docs-search>input:hover,.select select.is-hovered,.is-hovered.textarea,.is-hovered.input,#documenter .docs-sidebar form.docs-search>input.is-hovered{border-color:#b5b5b5}.select select:focus,.textarea:focus,.input:focus,#documenter .docs-sidebar form.docs-search>input:focus,.select select.is-focused,.is-focused.textarea,.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.select select:active,.textarea:active,.input:active,#documenter .docs-sidebar form.docs-search>input:active,.select select.is-active,.is-active.textarea,.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{border-color:#2e63b8;box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.select select[disabled],.textarea[disabled],.input[disabled],#documenter .docs-sidebar form.docs-search>input[disabled],fieldset[disabled] .select select,.select fieldset[disabled] select,fieldset[disabled] .textarea,fieldset[disabled] .input,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none;color:#6b6b6b}.select select[disabled]::-moz-placeholder,.textarea[disabled]::-moz-placeholder,.input[disabled]::-moz-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]::-moz-placeholder,fieldset[disabled] .select select::-moz-placeholder,.select fieldset[disabled] select::-moz-placeholder,fieldset[disabled] .textarea::-moz-placeholder,fieldset[disabled] .input::-moz-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input::-moz-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input::-moz-placeholder{color:rgba(107,107,107,0.3)}.select select[disabled]::-webkit-input-placeholder,.textarea[disabled]::-webkit-input-placeholder,.input[disabled]::-webkit-input-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]::-webkit-input-placeholder,fieldset[disabled] .select select::-webkit-input-placeholder,.select fieldset[disabled] select::-webkit-input-placeholder,fieldset[disabled] .textarea::-webkit-input-placeholder,fieldset[disabled] .input::-webkit-input-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input::-webkit-input-placeholder{color:rgba(107,107,107,0.3)}.select select[disabled]:-moz-placeholder,.textarea[disabled]:-moz-placeholder,.input[disabled]:-moz-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]:-moz-placeholder,fieldset[disabled] .select select:-moz-placeholder,.select fieldset[disabled] select:-moz-placeholder,fieldset[disabled] .textarea:-moz-placeholder,fieldset[disabled] .input:-moz-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input:-moz-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input:-moz-placeholder{color:rgba(107,107,107,0.3)}.select select[disabled]:-ms-input-placeholder,.textarea[disabled]:-ms-input-placeholder,.input[disabled]:-ms-input-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]:-ms-input-placeholder,fieldset[disabled] .select select:-ms-input-placeholder,.select fieldset[disabled] select:-ms-input-placeholder,fieldset[disabled] .textarea:-ms-input-placeholder,fieldset[disabled] .input:-ms-input-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input:-ms-input-placeholder{color:rgba(107,107,107,0.3)}.textarea,.input,#documenter .docs-sidebar form.docs-search>input{box-shadow:inset 0 0.0625em 0.125em rgba(10,10,10,0.05);max-width:100%;width:100%}.textarea[readonly],.input[readonly],#documenter .docs-sidebar form.docs-search>input[readonly]{box-shadow:none}.is-white.textarea,.is-white.input,#documenter .docs-sidebar form.docs-search>input.is-white{border-color:#fff}.is-white.textarea:focus,.is-white.input:focus,#documenter .docs-sidebar form.docs-search>input.is-white:focus,.is-white.is-focused.textarea,.is-white.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-white.textarea:active,.is-white.input:active,#documenter .docs-sidebar form.docs-search>input.is-white:active,.is-white.is-active.textarea,.is-white.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}.is-black.textarea,.is-black.input,#documenter .docs-sidebar form.docs-search>input.is-black{border-color:#0a0a0a}.is-black.textarea:focus,.is-black.input:focus,#documenter .docs-sidebar form.docs-search>input.is-black:focus,.is-black.is-focused.textarea,.is-black.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-black.textarea:active,.is-black.input:active,#documenter .docs-sidebar form.docs-search>input.is-black:active,.is-black.is-active.textarea,.is-black.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}.is-light.textarea,.is-light.input,#documenter .docs-sidebar form.docs-search>input.is-light{border-color:#f5f5f5}.is-light.textarea:focus,.is-light.input:focus,#documenter .docs-sidebar form.docs-search>input.is-light:focus,.is-light.is-focused.textarea,.is-light.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-light.textarea:active,.is-light.input:active,#documenter .docs-sidebar form.docs-search>input.is-light:active,.is-light.is-active.textarea,.is-light.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}.is-dark.textarea,.content kbd.textarea,.is-dark.input,#documenter .docs-sidebar form.docs-search>input.is-dark,.content kbd.input{border-color:#363636}.is-dark.textarea:focus,.content kbd.textarea:focus,.is-dark.input:focus,#documenter .docs-sidebar form.docs-search>input.is-dark:focus,.content kbd.input:focus,.is-dark.is-focused.textarea,.content kbd.is-focused.textarea,.is-dark.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.content kbd.is-focused.input,#documenter .docs-sidebar .content form.docs-search>input.is-focused,.is-dark.textarea:active,.content kbd.textarea:active,.is-dark.input:active,#documenter .docs-sidebar form.docs-search>input.is-dark:active,.content kbd.input:active,.is-dark.is-active.textarea,.content kbd.is-active.textarea,.is-dark.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active,.content kbd.is-active.input,#documenter .docs-sidebar .content form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(54,54,54,0.25)}.is-primary.textarea,.docstring>section>a.textarea.docs-sourcelink,.is-primary.input,#documenter .docs-sidebar form.docs-search>input.is-primary,.docstring>section>a.input.docs-sourcelink{border-color:#4eb5de}.is-primary.textarea:focus,.docstring>section>a.textarea.docs-sourcelink:focus,.is-primary.input:focus,#documenter .docs-sidebar form.docs-search>input.is-primary:focus,.docstring>section>a.input.docs-sourcelink:focus,.is-primary.is-focused.textarea,.docstring>section>a.is-focused.textarea.docs-sourcelink,.is-primary.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.docstring>section>a.is-focused.input.docs-sourcelink,.is-primary.textarea:active,.docstring>section>a.textarea.docs-sourcelink:active,.is-primary.input:active,#documenter .docs-sidebar form.docs-search>input.is-primary:active,.docstring>section>a.input.docs-sourcelink:active,.is-primary.is-active.textarea,.docstring>section>a.is-active.textarea.docs-sourcelink,.is-primary.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active,.docstring>section>a.is-active.input.docs-sourcelink{box-shadow:0 0 0 0.125em rgba(78,181,222,0.25)}.is-link.textarea,.is-link.input,#documenter .docs-sidebar form.docs-search>input.is-link{border-color:#2e63b8}.is-link.textarea:focus,.is-link.input:focus,#documenter .docs-sidebar form.docs-search>input.is-link:focus,.is-link.is-focused.textarea,.is-link.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-link.textarea:active,.is-link.input:active,#documenter .docs-sidebar form.docs-search>input.is-link:active,.is-link.is-active.textarea,.is-link.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.is-info.textarea,.is-info.input,#documenter .docs-sidebar form.docs-search>input.is-info{border-color:#3c5dcd}.is-info.textarea:focus,.is-info.input:focus,#documenter .docs-sidebar form.docs-search>input.is-info:focus,.is-info.is-focused.textarea,.is-info.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-info.textarea:active,.is-info.input:active,#documenter .docs-sidebar form.docs-search>input.is-info:active,.is-info.is-active.textarea,.is-info.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(60,93,205,0.25)}.is-success.textarea,.is-success.input,#documenter .docs-sidebar form.docs-search>input.is-success{border-color:#259a12}.is-success.textarea:focus,.is-success.input:focus,#documenter .docs-sidebar form.docs-search>input.is-success:focus,.is-success.is-focused.textarea,.is-success.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-success.textarea:active,.is-success.input:active,#documenter .docs-sidebar form.docs-search>input.is-success:active,.is-success.is-active.textarea,.is-success.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(37,154,18,0.25)}.is-warning.textarea,.is-warning.input,#documenter .docs-sidebar form.docs-search>input.is-warning{border-color:#a98800}.is-warning.textarea:focus,.is-warning.input:focus,#documenter .docs-sidebar form.docs-search>input.is-warning:focus,.is-warning.is-focused.textarea,.is-warning.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-warning.textarea:active,.is-warning.input:active,#documenter .docs-sidebar form.docs-search>input.is-warning:active,.is-warning.is-active.textarea,.is-warning.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(169,136,0,0.25)}.is-danger.textarea,.is-danger.input,#documenter .docs-sidebar form.docs-search>input.is-danger{border-color:#cb3c33}.is-danger.textarea:focus,.is-danger.input:focus,#documenter .docs-sidebar form.docs-search>input.is-danger:focus,.is-danger.is-focused.textarea,.is-danger.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-danger.textarea:active,.is-danger.input:active,#documenter .docs-sidebar form.docs-search>input.is-danger:active,.is-danger.is-active.textarea,.is-danger.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(203,60,51,0.25)}.is-small.textarea,.is-small.input,#documenter .docs-sidebar form.docs-search>input{border-radius:2px;font-size:.75rem}.is-medium.textarea,.is-medium.input,#documenter .docs-sidebar form.docs-search>input.is-medium{font-size:1.25rem}.is-large.textarea,.is-large.input,#documenter .docs-sidebar form.docs-search>input.is-large{font-size:1.5rem}.is-fullwidth.textarea,.is-fullwidth.input,#documenter .docs-sidebar form.docs-search>input.is-fullwidth{display:block;width:100%}.is-inline.textarea,.is-inline.input,#documenter .docs-sidebar form.docs-search>input.is-inline{display:inline;width:auto}.input.is-rounded,#documenter .docs-sidebar form.docs-search>input{border-radius:9999px;padding-left:calc(calc(0.75em - 1px) + 0.375em);padding-right:calc(calc(0.75em - 1px) + 0.375em)}.input.is-static,#documenter .docs-sidebar form.docs-search>input.is-static{background-color:transparent;border-color:transparent;box-shadow:none;padding-left:0;padding-right:0}.textarea{display:block;max-width:100%;min-width:100%;padding:calc(0.75em - 1px);resize:vertical}.textarea:not([rows]){max-height:40em;min-height:8em}.textarea[rows]{height:initial}.textarea.has-fixed-size{resize:none}.radio,.checkbox{cursor:pointer;display:inline-block;line-height:1.25;position:relative}.radio input,.checkbox input{cursor:pointer}.radio:hover,.checkbox:hover{color:#222}.radio[disabled],.checkbox[disabled],fieldset[disabled] .radio,fieldset[disabled] .checkbox,.radio input[disabled],.checkbox input[disabled]{color:#6b6b6b;cursor:not-allowed}.radio+.radio{margin-left:.5em}.select{display:inline-block;max-width:100%;position:relative;vertical-align:top}.select:not(.is-multiple){height:2.5em}.select:not(.is-multiple):not(.is-loading)::after{border-color:#2e63b8;right:1.125em;z-index:4}.select.is-rounded select,#documenter .docs-sidebar form.docs-search>input.select select{border-radius:9999px;padding-left:1em}.select select{cursor:pointer;display:block;font-size:1em;max-width:100%;outline:none}.select select::-ms-expand{display:none}.select select[disabled]:hover,fieldset[disabled] .select select:hover{border-color:#f5f5f5}.select select:not([multiple]){padding-right:2.5em}.select select[multiple]{height:auto;padding:0}.select select[multiple] option{padding:0.5em 1em}.select:not(.is-multiple):not(.is-loading):hover::after{border-color:#222}.select.is-white:not(:hover)::after{border-color:#fff}.select.is-white select{border-color:#fff}.select.is-white select:hover,.select.is-white select.is-hovered{border-color:#f2f2f2}.select.is-white select:focus,.select.is-white select.is-focused,.select.is-white select:active,.select.is-white select.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}.select.is-black:not(:hover)::after{border-color:#0a0a0a}.select.is-black select{border-color:#0a0a0a}.select.is-black select:hover,.select.is-black select.is-hovered{border-color:#000}.select.is-black select:focus,.select.is-black select.is-focused,.select.is-black select:active,.select.is-black select.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}.select.is-light:not(:hover)::after{border-color:#f5f5f5}.select.is-light select{border-color:#f5f5f5}.select.is-light select:hover,.select.is-light select.is-hovered{border-color:#e8e8e8}.select.is-light select:focus,.select.is-light select.is-focused,.select.is-light select:active,.select.is-light select.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}.select.is-dark:not(:hover)::after,.content kbd.select:not(:hover)::after{border-color:#363636}.select.is-dark select,.content kbd.select select{border-color:#363636}.select.is-dark select:hover,.content kbd.select select:hover,.select.is-dark select.is-hovered,.content kbd.select select.is-hovered{border-color:#292929}.select.is-dark select:focus,.content kbd.select select:focus,.select.is-dark select.is-focused,.content kbd.select select.is-focused,.select.is-dark select:active,.content kbd.select select:active,.select.is-dark select.is-active,.content kbd.select select.is-active{box-shadow:0 0 0 0.125em rgba(54,54,54,0.25)}.select.is-primary:not(:hover)::after,.docstring>section>a.select.docs-sourcelink:not(:hover)::after{border-color:#4eb5de}.select.is-primary select,.docstring>section>a.select.docs-sourcelink select{border-color:#4eb5de}.select.is-primary select:hover,.docstring>section>a.select.docs-sourcelink select:hover,.select.is-primary select.is-hovered,.docstring>section>a.select.docs-sourcelink select.is-hovered{border-color:#39acda}.select.is-primary select:focus,.docstring>section>a.select.docs-sourcelink select:focus,.select.is-primary select.is-focused,.docstring>section>a.select.docs-sourcelink select.is-focused,.select.is-primary select:active,.docstring>section>a.select.docs-sourcelink select:active,.select.is-primary select.is-active,.docstring>section>a.select.docs-sourcelink select.is-active{box-shadow:0 0 0 0.125em rgba(78,181,222,0.25)}.select.is-link:not(:hover)::after{border-color:#2e63b8}.select.is-link select{border-color:#2e63b8}.select.is-link select:hover,.select.is-link select.is-hovered{border-color:#2958a4}.select.is-link select:focus,.select.is-link select.is-focused,.select.is-link select:active,.select.is-link select.is-active{box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.select.is-info:not(:hover)::after{border-color:#3c5dcd}.select.is-info select{border-color:#3c5dcd}.select.is-info select:hover,.select.is-info select.is-hovered{border-color:#3151bf}.select.is-info select:focus,.select.is-info select.is-focused,.select.is-info select:active,.select.is-info select.is-active{box-shadow:0 0 0 0.125em rgba(60,93,205,0.25)}.select.is-success:not(:hover)::after{border-color:#259a12}.select.is-success select{border-color:#259a12}.select.is-success select:hover,.select.is-success select.is-hovered{border-color:#20830f}.select.is-success select:focus,.select.is-success select.is-focused,.select.is-success select:active,.select.is-success select.is-active{box-shadow:0 0 0 0.125em rgba(37,154,18,0.25)}.select.is-warning:not(:hover)::after{border-color:#a98800}.select.is-warning select{border-color:#a98800}.select.is-warning select:hover,.select.is-warning select.is-hovered{border-color:#8f7300}.select.is-warning select:focus,.select.is-warning select.is-focused,.select.is-warning select:active,.select.is-warning select.is-active{box-shadow:0 0 0 0.125em rgba(169,136,0,0.25)}.select.is-danger:not(:hover)::after{border-color:#cb3c33}.select.is-danger select{border-color:#cb3c33}.select.is-danger select:hover,.select.is-danger select.is-hovered{border-color:#b7362e}.select.is-danger select:focus,.select.is-danger select.is-focused,.select.is-danger select:active,.select.is-danger select.is-active{box-shadow:0 0 0 0.125em rgba(203,60,51,0.25)}.select.is-small,#documenter .docs-sidebar form.docs-search>input.select{border-radius:2px;font-size:.75rem}.select.is-medium{font-size:1.25rem}.select.is-large{font-size:1.5rem}.select.is-disabled::after{border-color:#6b6b6b !important;opacity:0.5}.select.is-fullwidth{width:100%}.select.is-fullwidth select{width:100%}.select.is-loading::after{margin-top:0;position:absolute;right:.625em;top:0.625em;transform:none}.select.is-loading.is-small:after,#documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}.select.is-loading.is-medium:after{font-size:1.25rem}.select.is-loading.is-large:after{font-size:1.5rem}.file{align-items:stretch;display:flex;justify-content:flex-start;position:relative}.file.is-white .file-cta{background-color:#fff;border-color:transparent;color:#0a0a0a}.file.is-white:hover .file-cta,.file.is-white.is-hovered .file-cta{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}.file.is-white:focus .file-cta,.file.is-white.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,255,255,0.25);color:#0a0a0a}.file.is-white:active .file-cta,.file.is-white.is-active .file-cta{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}.file.is-black .file-cta{background-color:#0a0a0a;border-color:transparent;color:#fff}.file.is-black:hover .file-cta,.file.is-black.is-hovered .file-cta{background-color:#040404;border-color:transparent;color:#fff}.file.is-black:focus .file-cta,.file.is-black.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(10,10,10,0.25);color:#fff}.file.is-black:active .file-cta,.file.is-black.is-active .file-cta{background-color:#000;border-color:transparent;color:#fff}.file.is-light .file-cta{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-light:hover .file-cta,.file.is-light.is-hovered .file-cta{background-color:#eee;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-light:focus .file-cta,.file.is-light.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(245,245,245,0.25);color:rgba(0,0,0,0.7)}.file.is-light:active .file-cta,.file.is-light.is-active .file-cta{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-dark .file-cta,.content kbd.file .file-cta{background-color:#363636;border-color:transparent;color:#fff}.file.is-dark:hover .file-cta,.content kbd.file:hover .file-cta,.file.is-dark.is-hovered .file-cta,.content kbd.file.is-hovered .file-cta{background-color:#2f2f2f;border-color:transparent;color:#fff}.file.is-dark:focus .file-cta,.content kbd.file:focus .file-cta,.file.is-dark.is-focused .file-cta,.content kbd.file.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(54,54,54,0.25);color:#fff}.file.is-dark:active .file-cta,.content kbd.file:active .file-cta,.file.is-dark.is-active .file-cta,.content kbd.file.is-active .file-cta{background-color:#292929;border-color:transparent;color:#fff}.file.is-primary .file-cta,.docstring>section>a.file.docs-sourcelink .file-cta{background-color:#4eb5de;border-color:transparent;color:#fff}.file.is-primary:hover .file-cta,.docstring>section>a.file.docs-sourcelink:hover .file-cta,.file.is-primary.is-hovered .file-cta,.docstring>section>a.file.is-hovered.docs-sourcelink .file-cta{background-color:#43b1dc;border-color:transparent;color:#fff}.file.is-primary:focus .file-cta,.docstring>section>a.file.docs-sourcelink:focus .file-cta,.file.is-primary.is-focused .file-cta,.docstring>section>a.file.is-focused.docs-sourcelink .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(78,181,222,0.25);color:#fff}.file.is-primary:active .file-cta,.docstring>section>a.file.docs-sourcelink:active .file-cta,.file.is-primary.is-active .file-cta,.docstring>section>a.file.is-active.docs-sourcelink .file-cta{background-color:#39acda;border-color:transparent;color:#fff}.file.is-link .file-cta{background-color:#2e63b8;border-color:transparent;color:#fff}.file.is-link:hover .file-cta,.file.is-link.is-hovered .file-cta{background-color:#2b5eae;border-color:transparent;color:#fff}.file.is-link:focus .file-cta,.file.is-link.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(46,99,184,0.25);color:#fff}.file.is-link:active .file-cta,.file.is-link.is-active .file-cta{background-color:#2958a4;border-color:transparent;color:#fff}.file.is-info .file-cta{background-color:#3c5dcd;border-color:transparent;color:#fff}.file.is-info:hover .file-cta,.file.is-info.is-hovered .file-cta{background-color:#3355c9;border-color:transparent;color:#fff}.file.is-info:focus .file-cta,.file.is-info.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(60,93,205,0.25);color:#fff}.file.is-info:active .file-cta,.file.is-info.is-active .file-cta{background-color:#3151bf;border-color:transparent;color:#fff}.file.is-success .file-cta{background-color:#259a12;border-color:transparent;color:#fff}.file.is-success:hover .file-cta,.file.is-success.is-hovered .file-cta{background-color:#228f11;border-color:transparent;color:#fff}.file.is-success:focus .file-cta,.file.is-success.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(37,154,18,0.25);color:#fff}.file.is-success:active .file-cta,.file.is-success.is-active .file-cta{background-color:#20830f;border-color:transparent;color:#fff}.file.is-warning .file-cta{background-color:#a98800;border-color:transparent;color:#fff}.file.is-warning:hover .file-cta,.file.is-warning.is-hovered .file-cta{background-color:#9c7d00;border-color:transparent;color:#fff}.file.is-warning:focus .file-cta,.file.is-warning.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(169,136,0,0.25);color:#fff}.file.is-warning:active .file-cta,.file.is-warning.is-active .file-cta{background-color:#8f7300;border-color:transparent;color:#fff}.file.is-danger .file-cta{background-color:#cb3c33;border-color:transparent;color:#fff}.file.is-danger:hover .file-cta,.file.is-danger.is-hovered .file-cta{background-color:#c13930;border-color:transparent;color:#fff}.file.is-danger:focus .file-cta,.file.is-danger.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(203,60,51,0.25);color:#fff}.file.is-danger:active .file-cta,.file.is-danger.is-active .file-cta{background-color:#b7362e;border-color:transparent;color:#fff}.file.is-small,#documenter .docs-sidebar form.docs-search>input.file{font-size:.75rem}.file.is-normal{font-size:1rem}.file.is-medium{font-size:1.25rem}.file.is-medium .file-icon .fa{font-size:21px}.file.is-large{font-size:1.5rem}.file.is-large .file-icon .fa{font-size:28px}.file.has-name .file-cta{border-bottom-right-radius:0;border-top-right-radius:0}.file.has-name .file-name{border-bottom-left-radius:0;border-top-left-radius:0}.file.has-name.is-empty .file-cta{border-radius:4px}.file.has-name.is-empty .file-name{display:none}.file.is-boxed .file-label{flex-direction:column}.file.is-boxed .file-cta{flex-direction:column;height:auto;padding:1em 3em}.file.is-boxed .file-name{border-width:0 1px 1px}.file.is-boxed .file-icon{height:1.5em;width:1.5em}.file.is-boxed .file-icon .fa{font-size:21px}.file.is-boxed.is-small .file-icon .fa,#documenter .docs-sidebar form.docs-search>input.is-boxed .file-icon .fa{font-size:14px}.file.is-boxed.is-medium .file-icon .fa{font-size:28px}.file.is-boxed.is-large .file-icon .fa{font-size:35px}.file.is-boxed.has-name .file-cta{border-radius:4px 4px 0 0}.file.is-boxed.has-name .file-name{border-radius:0 0 4px 4px;border-width:0 1px 1px}.file.is-centered{justify-content:center}.file.is-fullwidth .file-label{width:100%}.file.is-fullwidth .file-name{flex-grow:1;max-width:none}.file.is-right{justify-content:flex-end}.file.is-right .file-cta{border-radius:0 4px 4px 0}.file.is-right .file-name{border-radius:4px 0 0 4px;border-width:1px 0 1px 1px;order:-1}.file-label{align-items:stretch;display:flex;cursor:pointer;justify-content:flex-start;overflow:hidden;position:relative}.file-label:hover .file-cta{background-color:#eee;color:#222}.file-label:hover .file-name{border-color:#d5d5d5}.file-label:active .file-cta{background-color:#e8e8e8;color:#222}.file-label:active .file-name{border-color:#cfcfcf}.file-input{height:100%;left:0;opacity:0;outline:none;position:absolute;top:0;width:100%}.file-cta,.file-name{border-color:#dbdbdb;border-radius:4px;font-size:1em;padding-left:1em;padding-right:1em;white-space:nowrap}.file-cta{background-color:#f5f5f5;color:#222}.file-name{border-color:#dbdbdb;border-style:solid;border-width:1px 1px 1px 0;display:block;max-width:16em;overflow:hidden;text-align:inherit;text-overflow:ellipsis}.file-icon{align-items:center;display:flex;height:1em;justify-content:center;margin-right:.5em;width:1em}.file-icon .fa{font-size:14px}.label{color:#222;display:block;font-size:1rem;font-weight:700}.label:not(:last-child){margin-bottom:0.5em}.label.is-small,#documenter .docs-sidebar form.docs-search>input.label{font-size:.75rem}.label.is-medium{font-size:1.25rem}.label.is-large{font-size:1.5rem}.help{display:block;font-size:.75rem;margin-top:0.25rem}.help.is-white{color:#fff}.help.is-black{color:#0a0a0a}.help.is-light{color:#f5f5f5}.help.is-dark,.content kbd.help{color:#363636}.help.is-primary,.docstring>section>a.help.docs-sourcelink{color:#4eb5de}.help.is-link{color:#2e63b8}.help.is-info{color:#3c5dcd}.help.is-success{color:#259a12}.help.is-warning{color:#a98800}.help.is-danger{color:#cb3c33}.field:not(:last-child){margin-bottom:0.75rem}.field.has-addons{display:flex;justify-content:flex-start}.field.has-addons .control:not(:last-child){margin-right:-1px}.field.has-addons .control:not(:first-child):not(:last-child) .button,.field.has-addons .control:not(:first-child):not(:last-child) .input,.field.has-addons .control:not(:first-child):not(:last-child) #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .field.has-addons .control:not(:first-child):not(:last-child) form.docs-search>input,.field.has-addons .control:not(:first-child):not(:last-child) .select select{border-radius:0}.field.has-addons .control:first-child:not(:only-child) .button,.field.has-addons .control:first-child:not(:only-child) .input,.field.has-addons .control:first-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .field.has-addons .control:first-child:not(:only-child) form.docs-search>input,.field.has-addons .control:first-child:not(:only-child) .select select{border-bottom-right-radius:0;border-top-right-radius:0}.field.has-addons .control:last-child:not(:only-child) .button,.field.has-addons .control:last-child:not(:only-child) .input,.field.has-addons .control:last-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .field.has-addons .control:last-child:not(:only-child) form.docs-search>input,.field.has-addons .control:last-child:not(:only-child) .select select{border-bottom-left-radius:0;border-top-left-radius:0}.field.has-addons .control .button:not([disabled]):hover,.field.has-addons .control .button.is-hovered:not([disabled]),.field.has-addons .control .input:not([disabled]):hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):hover,.field.has-addons .control .input.is-hovered:not([disabled]),.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-hovered:not([disabled]),#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-hovered:not([disabled]),.field.has-addons .control .select select:not([disabled]):hover,.field.has-addons .control .select select.is-hovered:not([disabled]){z-index:2}.field.has-addons .control .button:not([disabled]):focus,.field.has-addons .control .button.is-focused:not([disabled]),.field.has-addons .control .button:not([disabled]):active,.field.has-addons .control .button.is-active:not([disabled]),.field.has-addons .control .input:not([disabled]):focus,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus,.field.has-addons .control .input.is-focused:not([disabled]),.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]),#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]),.field.has-addons .control .input:not([disabled]):active,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active,.field.has-addons .control .input.is-active:not([disabled]),.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]),#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]),.field.has-addons .control .select select:not([disabled]):focus,.field.has-addons .control .select select.is-focused:not([disabled]),.field.has-addons .control .select select:not([disabled]):active,.field.has-addons .control .select select.is-active:not([disabled]){z-index:3}.field.has-addons .control .button:not([disabled]):focus:hover,.field.has-addons .control .button.is-focused:not([disabled]):hover,.field.has-addons .control .button:not([disabled]):active:hover,.field.has-addons .control .button.is-active:not([disabled]):hover,.field.has-addons .control .input:not([disabled]):focus:hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus:hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus:hover,.field.has-addons .control .input.is-focused:not([disabled]):hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]):hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]):hover,.field.has-addons .control .input:not([disabled]):active:hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active:hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active:hover,.field.has-addons .control .input.is-active:not([disabled]):hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]):hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]):hover,.field.has-addons .control .select select:not([disabled]):focus:hover,.field.has-addons .control .select select.is-focused:not([disabled]):hover,.field.has-addons .control .select select:not([disabled]):active:hover,.field.has-addons .control .select select.is-active:not([disabled]):hover{z-index:4}.field.has-addons .control.is-expanded{flex-grow:1;flex-shrink:1}.field.has-addons.has-addons-centered{justify-content:center}.field.has-addons.has-addons-right{justify-content:flex-end}.field.has-addons.has-addons-fullwidth .control{flex-grow:1;flex-shrink:0}.field.is-grouped{display:flex;justify-content:flex-start}.field.is-grouped>.control{flex-shrink:0}.field.is-grouped>.control:not(:last-child){margin-bottom:0;margin-right:.75rem}.field.is-grouped>.control.is-expanded{flex-grow:1;flex-shrink:1}.field.is-grouped.is-grouped-centered{justify-content:center}.field.is-grouped.is-grouped-right{justify-content:flex-end}.field.is-grouped.is-grouped-multiline{flex-wrap:wrap}.field.is-grouped.is-grouped-multiline>.control:last-child,.field.is-grouped.is-grouped-multiline>.control:not(:last-child){margin-bottom:0.75rem}.field.is-grouped.is-grouped-multiline:last-child{margin-bottom:-0.75rem}.field.is-grouped.is-grouped-multiline:not(:last-child){margin-bottom:0}@media screen and (min-width: 769px),print{.field.is-horizontal{display:flex}}.field-label .label{font-size:inherit}@media screen and (max-width: 768px){.field-label{margin-bottom:0.5rem}}@media screen and (min-width: 769px),print{.field-label{flex-basis:0;flex-grow:1;flex-shrink:0;margin-right:1.5rem;text-align:right}.field-label.is-small,#documenter .docs-sidebar form.docs-search>input.field-label{font-size:.75rem;padding-top:0.375em}.field-label.is-normal{padding-top:0.375em}.field-label.is-medium{font-size:1.25rem;padding-top:0.375em}.field-label.is-large{font-size:1.5rem;padding-top:0.375em}}.field-body .field .field{margin-bottom:0}@media screen and (min-width: 769px),print{.field-body{display:flex;flex-basis:0;flex-grow:5;flex-shrink:1}.field-body .field{margin-bottom:0}.field-body>.field{flex-shrink:1}.field-body>.field:not(.is-narrow){flex-grow:1}.field-body>.field:not(:last-child){margin-right:.75rem}}.control{box-sizing:border-box;clear:both;font-size:1rem;position:relative;text-align:inherit}.control.has-icons-left .input:focus~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input:focus~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input:focus~.icon,.control.has-icons-left .select:focus~.icon,.control.has-icons-right .input:focus~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input:focus~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input:focus~.icon,.control.has-icons-right .select:focus~.icon{color:#222}.control.has-icons-left .input.is-small~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input~.icon,.control.has-icons-left .select.is-small~.icon,.control.has-icons-right .input.is-small~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input~.icon,.control.has-icons-right .select.is-small~.icon{font-size:.75rem}.control.has-icons-left .input.is-medium~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-medium~.icon,.control.has-icons-left .select.is-medium~.icon,.control.has-icons-right .input.is-medium~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-medium~.icon,.control.has-icons-right .select.is-medium~.icon{font-size:1.25rem}.control.has-icons-left .input.is-large~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-large~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-large~.icon,.control.has-icons-left .select.is-large~.icon,.control.has-icons-right .input.is-large~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-large~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-large~.icon,.control.has-icons-right .select.is-large~.icon{font-size:1.5rem}.control.has-icons-left .icon,.control.has-icons-right .icon{color:#dbdbdb;height:2.5em;pointer-events:none;position:absolute;top:0;width:2.5em;z-index:4}.control.has-icons-left .input,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input,.control.has-icons-left .select select{padding-left:2.5em}.control.has-icons-left .icon.is-left{left:0}.control.has-icons-right .input,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input,.control.has-icons-right .select select{padding-right:2.5em}.control.has-icons-right .icon.is-right{right:0}.control.is-loading::after{position:absolute !important;right:.625em;top:0.625em;z-index:4}.control.is-loading.is-small:after,#documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}.control.is-loading.is-medium:after{font-size:1.25rem}.control.is-loading.is-large:after{font-size:1.5rem}.breadcrumb{font-size:1rem;white-space:nowrap}.breadcrumb a{align-items:center;color:#2e63b8;display:flex;justify-content:center;padding:0 .75em}.breadcrumb a:hover{color:#363636}.breadcrumb li{align-items:center;display:flex}.breadcrumb li:first-child a{padding-left:0}.breadcrumb li.is-active a{color:#222;cursor:default;pointer-events:none}.breadcrumb li+li::before{color:#b5b5b5;content:"\0002f"}.breadcrumb ul,.breadcrumb ol{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:flex-start}.breadcrumb .icon:first-child{margin-right:.5em}.breadcrumb .icon:last-child{margin-left:.5em}.breadcrumb.is-centered ol,.breadcrumb.is-centered ul{justify-content:center}.breadcrumb.is-right ol,.breadcrumb.is-right ul{justify-content:flex-end}.breadcrumb.is-small,#documenter .docs-sidebar form.docs-search>input.breadcrumb{font-size:.75rem}.breadcrumb.is-medium{font-size:1.25rem}.breadcrumb.is-large{font-size:1.5rem}.breadcrumb.has-arrow-separator li+li::before{content:"\02192"}.breadcrumb.has-bullet-separator li+li::before{content:"\02022"}.breadcrumb.has-dot-separator li+li::before{content:"\000b7"}.breadcrumb.has-succeeds-separator li+li::before{content:"\0227B"}.card{background-color:#fff;border-radius:.25rem;box-shadow:#bbb;color:#222;max-width:100%;position:relative}.card-footer:first-child,.card-content:first-child,.card-header:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-footer:last-child,.card-content:last-child,.card-header:last-child{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.card-header{background-color:rgba(0,0,0,0);align-items:stretch;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);display:flex}.card-header-title{align-items:center;color:#222;display:flex;flex-grow:1;font-weight:700;padding:0.75rem 1rem}.card-header-title.is-centered{justify-content:center}.card-header-icon{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0;align-items:center;cursor:pointer;display:flex;justify-content:center;padding:0.75rem 1rem}.card-image{display:block;position:relative}.card-image:first-child img{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-image:last-child img{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.card-content{background-color:rgba(0,0,0,0);padding:1.5rem}.card-footer{background-color:rgba(0,0,0,0);border-top:1px solid #ededed;align-items:stretch;display:flex}.card-footer-item{align-items:center;display:flex;flex-basis:0;flex-grow:1;flex-shrink:0;justify-content:center;padding:.75rem}.card-footer-item:not(:last-child){border-right:1px solid #ededed}.card .media:not(:last-child){margin-bottom:1.5rem}.dropdown{display:inline-flex;position:relative;vertical-align:top}.dropdown.is-active .dropdown-menu,.dropdown.is-hoverable:hover .dropdown-menu{display:block}.dropdown.is-right .dropdown-menu{left:auto;right:0}.dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:initial;top:auto}.dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:20}.dropdown-content{background-color:#fff;border-radius:4px;box-shadow:#bbb;padding-bottom:.5rem;padding-top:.5rem}.dropdown-item{color:#222;display:block;font-size:0.875rem;line-height:1.5;padding:0.375rem 1rem;position:relative}a.dropdown-item,button.dropdown-item{padding-right:3rem;text-align:inherit;white-space:nowrap;width:100%}a.dropdown-item:hover,button.dropdown-item:hover{background-color:#f5f5f5;color:#0a0a0a}a.dropdown-item.is-active,button.dropdown-item.is-active{background-color:#2e63b8;color:#fff}.dropdown-divider{background-color:#ededed;border:none;display:block;height:1px;margin:0.5rem 0}.level{align-items:center;justify-content:space-between}.level code{border-radius:4px}.level img{display:inline-block;vertical-align:top}.level.is-mobile{display:flex}.level.is-mobile .level-left,.level.is-mobile .level-right{display:flex}.level.is-mobile .level-left+.level-right{margin-top:0}.level.is-mobile .level-item:not(:last-child){margin-bottom:0;margin-right:.75rem}.level.is-mobile .level-item:not(.is-narrow){flex-grow:1}@media screen and (min-width: 769px),print{.level{display:flex}.level>.level-item:not(.is-narrow){flex-grow:1}}.level-item{align-items:center;display:flex;flex-basis:auto;flex-grow:0;flex-shrink:0;justify-content:center}.level-item .title,.level-item .subtitle{margin-bottom:0}@media screen and (max-width: 768px){.level-item:not(:last-child){margin-bottom:.75rem}}.level-left,.level-right{flex-basis:auto;flex-grow:0;flex-shrink:0}.level-left .level-item.is-flexible,.level-right .level-item.is-flexible{flex-grow:1}@media screen and (min-width: 769px),print{.level-left .level-item:not(:last-child),.level-right .level-item:not(:last-child){margin-right:.75rem}}.level-left{align-items:center;justify-content:flex-start}@media screen and (max-width: 768px){.level-left+.level-right{margin-top:1.5rem}}@media screen and (min-width: 769px),print{.level-left{display:flex}}.level-right{align-items:center;justify-content:flex-end}@media screen and (min-width: 769px),print{.level-right{display:flex}}.media{align-items:flex-start;display:flex;text-align:inherit}.media .content:not(:last-child){margin-bottom:.75rem}.media .media{border-top:1px solid rgba(219,219,219,0.5);display:flex;padding-top:.75rem}.media .media .content:not(:last-child),.media .media .control:not(:last-child){margin-bottom:.5rem}.media .media .media{padding-top:.5rem}.media .media .media+.media{margin-top:.5rem}.media+.media{border-top:1px solid rgba(219,219,219,0.5);margin-top:1rem;padding-top:1rem}.media.is-large+.media{margin-top:1.5rem;padding-top:1.5rem}.media-left,.media-right{flex-basis:auto;flex-grow:0;flex-shrink:0}.media-left{margin-right:1rem}.media-right{margin-left:1rem}.media-content{flex-basis:auto;flex-grow:1;flex-shrink:1;text-align:inherit}@media screen and (max-width: 768px){.media-content{overflow-x:auto}}.menu{font-size:1rem}.menu.is-small,#documenter .docs-sidebar form.docs-search>input.menu{font-size:.75rem}.menu.is-medium{font-size:1.25rem}.menu.is-large{font-size:1.5rem}.menu-list{line-height:1.25}.menu-list a{border-radius:2px;color:#222;display:block;padding:0.5em 0.75em}.menu-list a:hover{background-color:#f5f5f5;color:#222}.menu-list a.is-active{background-color:#2e63b8;color:#fff}.menu-list li ul{border-left:1px solid #dbdbdb;margin:.75em;padding-left:.75em}.menu-label{color:#6b6b6b;font-size:.75em;letter-spacing:.1em;text-transform:uppercase}.menu-label:not(:first-child){margin-top:1em}.menu-label:not(:last-child){margin-bottom:1em}.message{background-color:#f5f5f5;border-radius:4px;font-size:1rem}.message strong{color:currentColor}.message a:not(.button):not(.tag):not(.dropdown-item){color:currentColor;text-decoration:underline}.message.is-small,#documenter .docs-sidebar form.docs-search>input.message{font-size:.75rem}.message.is-medium{font-size:1.25rem}.message.is-large{font-size:1.5rem}.message.is-white{background-color:#fff}.message.is-white .message-header{background-color:#fff;color:#0a0a0a}.message.is-white .message-body{border-color:#fff}.message.is-black{background-color:#fafafa}.message.is-black .message-header{background-color:#0a0a0a;color:#fff}.message.is-black .message-body{border-color:#0a0a0a}.message.is-light{background-color:#fafafa}.message.is-light .message-header{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.message.is-light .message-body{border-color:#f5f5f5}.message.is-dark,.content kbd.message{background-color:#fafafa}.message.is-dark .message-header,.content kbd.message .message-header{background-color:#363636;color:#fff}.message.is-dark .message-body,.content kbd.message .message-body{border-color:#363636}.message.is-primary,.docstring>section>a.message.docs-sourcelink{background-color:#eef8fc}.message.is-primary .message-header,.docstring>section>a.message.docs-sourcelink .message-header{background-color:#4eb5de;color:#fff}.message.is-primary .message-body,.docstring>section>a.message.docs-sourcelink .message-body{border-color:#4eb5de;color:#1a6d8e}.message.is-link{background-color:#eff3fb}.message.is-link .message-header{background-color:#2e63b8;color:#fff}.message.is-link .message-body{border-color:#2e63b8;color:#3169c4}.message.is-info{background-color:#eff2fb}.message.is-info .message-header{background-color:#3c5dcd;color:#fff}.message.is-info .message-body{border-color:#3c5dcd;color:#3253c3}.message.is-success{background-color:#effded}.message.is-success .message-header{background-color:#259a12;color:#fff}.message.is-success .message-body{border-color:#259a12;color:#2ec016}.message.is-warning{background-color:#fffbeb}.message.is-warning .message-header{background-color:#a98800;color:#fff}.message.is-warning .message-body{border-color:#a98800;color:#cca400}.message.is-danger{background-color:#fbefef}.message.is-danger .message-header{background-color:#cb3c33;color:#fff}.message.is-danger .message-body{border-color:#cb3c33;color:#c03930}.message-header{align-items:center;background-color:#222;border-radius:4px 4px 0 0;color:#fff;display:flex;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.75em 1em;position:relative}.message-header .delete{flex-grow:0;flex-shrink:0;margin-left:.75em}.message-header+.message-body{border-width:0;border-top-left-radius:0;border-top-right-radius:0}.message-body{border-color:#dbdbdb;border-radius:4px;border-style:solid;border-width:0 0 0 4px;color:#222;padding:1.25em 1.5em}.message-body code,.message-body pre{background-color:#fff}.message-body pre code{background-color:rgba(0,0,0,0)}.modal{align-items:center;display:none;flex-direction:column;justify-content:center;overflow:hidden;position:fixed;z-index:40}.modal.is-active{display:flex}.modal-background{background-color:rgba(10,10,10,0.86)}.modal-content,.modal-card{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width: 769px){.modal-content,.modal-card{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}.modal-close{background:none;height:40px;position:fixed;right:20px;top:20px;width:40px}.modal-card{display:flex;flex-direction:column;max-height:calc(100vh - 40px);overflow:hidden;-ms-overflow-y:visible}.modal-card-head,.modal-card-foot{align-items:center;background-color:#f5f5f5;display:flex;flex-shrink:0;justify-content:flex-start;padding:20px;position:relative}.modal-card-head{border-bottom:1px solid #dbdbdb;border-top-left-radius:6px;border-top-right-radius:6px}.modal-card-title{color:#222;flex-grow:1;flex-shrink:0;font-size:1.5rem;line-height:1}.modal-card-foot{border-bottom-left-radius:6px;border-bottom-right-radius:6px;border-top:1px solid #dbdbdb}.modal-card-foot .button:not(:last-child){margin-right:.5em}.modal-card-body{-webkit-overflow-scrolling:touch;background-color:#fff;flex-grow:1;flex-shrink:1;overflow:auto;padding:20px}.navbar{background-color:#fff;min-height:3.25rem;position:relative;z-index:30}.navbar.is-white{background-color:#fff;color:#0a0a0a}.navbar.is-white .navbar-brand>.navbar-item,.navbar.is-white .navbar-brand .navbar-link{color:#0a0a0a}.navbar.is-white .navbar-brand>a.navbar-item:focus,.navbar.is-white .navbar-brand>a.navbar-item:hover,.navbar.is-white .navbar-brand>a.navbar-item.is-active,.navbar.is-white .navbar-brand .navbar-link:focus,.navbar.is-white .navbar-brand .navbar-link:hover,.navbar.is-white .navbar-brand .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-brand .navbar-link::after{border-color:#0a0a0a}.navbar.is-white .navbar-burger{color:#0a0a0a}@media screen and (min-width: 1056px){.navbar.is-white .navbar-start>.navbar-item,.navbar.is-white .navbar-start .navbar-link,.navbar.is-white .navbar-end>.navbar-item,.navbar.is-white .navbar-end .navbar-link{color:#0a0a0a}.navbar.is-white .navbar-start>a.navbar-item:focus,.navbar.is-white .navbar-start>a.navbar-item:hover,.navbar.is-white .navbar-start>a.navbar-item.is-active,.navbar.is-white .navbar-start .navbar-link:focus,.navbar.is-white .navbar-start .navbar-link:hover,.navbar.is-white .navbar-start .navbar-link.is-active,.navbar.is-white .navbar-end>a.navbar-item:focus,.navbar.is-white .navbar-end>a.navbar-item:hover,.navbar.is-white .navbar-end>a.navbar-item.is-active,.navbar.is-white .navbar-end .navbar-link:focus,.navbar.is-white .navbar-end .navbar-link:hover,.navbar.is-white .navbar-end .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-start .navbar-link::after,.navbar.is-white .navbar-end .navbar-link::after{border-color:#0a0a0a}.navbar.is-white .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-white .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-dropdown a.navbar-item.is-active{background-color:#fff;color:#0a0a0a}}.navbar.is-black{background-color:#0a0a0a;color:#fff}.navbar.is-black .navbar-brand>.navbar-item,.navbar.is-black .navbar-brand .navbar-link{color:#fff}.navbar.is-black .navbar-brand>a.navbar-item:focus,.navbar.is-black .navbar-brand>a.navbar-item:hover,.navbar.is-black .navbar-brand>a.navbar-item.is-active,.navbar.is-black .navbar-brand .navbar-link:focus,.navbar.is-black .navbar-brand .navbar-link:hover,.navbar.is-black .navbar-brand .navbar-link.is-active{background-color:#000;color:#fff}.navbar.is-black .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-black .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-black .navbar-start>.navbar-item,.navbar.is-black .navbar-start .navbar-link,.navbar.is-black .navbar-end>.navbar-item,.navbar.is-black .navbar-end .navbar-link{color:#fff}.navbar.is-black .navbar-start>a.navbar-item:focus,.navbar.is-black .navbar-start>a.navbar-item:hover,.navbar.is-black .navbar-start>a.navbar-item.is-active,.navbar.is-black .navbar-start .navbar-link:focus,.navbar.is-black .navbar-start .navbar-link:hover,.navbar.is-black .navbar-start .navbar-link.is-active,.navbar.is-black .navbar-end>a.navbar-item:focus,.navbar.is-black .navbar-end>a.navbar-item:hover,.navbar.is-black .navbar-end>a.navbar-item.is-active,.navbar.is-black .navbar-end .navbar-link:focus,.navbar.is-black .navbar-end .navbar-link:hover,.navbar.is-black .navbar-end .navbar-link.is-active{background-color:#000;color:#fff}.navbar.is-black .navbar-start .navbar-link::after,.navbar.is-black .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-black .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-black .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link{background-color:#000;color:#fff}.navbar.is-black .navbar-dropdown a.navbar-item.is-active{background-color:#0a0a0a;color:#fff}}.navbar.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-brand>.navbar-item,.navbar.is-light .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-brand>a.navbar-item:focus,.navbar.is-light .navbar-brand>a.navbar-item:hover,.navbar.is-light .navbar-brand>a.navbar-item.is-active,.navbar.is-light .navbar-brand .navbar-link:focus,.navbar.is-light .navbar-brand .navbar-link:hover,.navbar.is-light .navbar-brand .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){.navbar.is-light .navbar-start>.navbar-item,.navbar.is-light .navbar-start .navbar-link,.navbar.is-light .navbar-end>.navbar-item,.navbar.is-light .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-start>a.navbar-item:focus,.navbar.is-light .navbar-start>a.navbar-item:hover,.navbar.is-light .navbar-start>a.navbar-item.is-active,.navbar.is-light .navbar-start .navbar-link:focus,.navbar.is-light .navbar-start .navbar-link:hover,.navbar.is-light .navbar-start .navbar-link.is-active,.navbar.is-light .navbar-end>a.navbar-item:focus,.navbar.is-light .navbar-end>a.navbar-item:hover,.navbar.is-light .navbar-end>a.navbar-item.is-active,.navbar.is-light .navbar-end .navbar-link:focus,.navbar.is-light .navbar-end .navbar-link:hover,.navbar.is-light .navbar-end .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-start .navbar-link::after,.navbar.is-light .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-light .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}}.navbar.is-dark,.content kbd.navbar{background-color:#363636;color:#fff}.navbar.is-dark .navbar-brand>.navbar-item,.content kbd.navbar .navbar-brand>.navbar-item,.navbar.is-dark .navbar-brand .navbar-link,.content kbd.navbar .navbar-brand .navbar-link{color:#fff}.navbar.is-dark .navbar-brand>a.navbar-item:focus,.content kbd.navbar .navbar-brand>a.navbar-item:focus,.navbar.is-dark .navbar-brand>a.navbar-item:hover,.content kbd.navbar .navbar-brand>a.navbar-item:hover,.navbar.is-dark .navbar-brand>a.navbar-item.is-active,.content kbd.navbar .navbar-brand>a.navbar-item.is-active,.navbar.is-dark .navbar-brand .navbar-link:focus,.content kbd.navbar .navbar-brand .navbar-link:focus,.navbar.is-dark .navbar-brand .navbar-link:hover,.content kbd.navbar .navbar-brand .navbar-link:hover,.navbar.is-dark .navbar-brand .navbar-link.is-active,.content kbd.navbar .navbar-brand .navbar-link.is-active{background-color:#292929;color:#fff}.navbar.is-dark .navbar-brand .navbar-link::after,.content kbd.navbar .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-dark .navbar-burger,.content kbd.navbar .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-dark .navbar-start>.navbar-item,.content kbd.navbar .navbar-start>.navbar-item,.navbar.is-dark .navbar-start .navbar-link,.content kbd.navbar .navbar-start .navbar-link,.navbar.is-dark .navbar-end>.navbar-item,.content kbd.navbar .navbar-end>.navbar-item,.navbar.is-dark .navbar-end .navbar-link,.content kbd.navbar .navbar-end .navbar-link{color:#fff}.navbar.is-dark .navbar-start>a.navbar-item:focus,.content kbd.navbar .navbar-start>a.navbar-item:focus,.navbar.is-dark .navbar-start>a.navbar-item:hover,.content kbd.navbar .navbar-start>a.navbar-item:hover,.navbar.is-dark .navbar-start>a.navbar-item.is-active,.content kbd.navbar .navbar-start>a.navbar-item.is-active,.navbar.is-dark .navbar-start .navbar-link:focus,.content kbd.navbar .navbar-start .navbar-link:focus,.navbar.is-dark .navbar-start .navbar-link:hover,.content kbd.navbar .navbar-start .navbar-link:hover,.navbar.is-dark .navbar-start .navbar-link.is-active,.content kbd.navbar .navbar-start .navbar-link.is-active,.navbar.is-dark .navbar-end>a.navbar-item:focus,.content kbd.navbar .navbar-end>a.navbar-item:focus,.navbar.is-dark .navbar-end>a.navbar-item:hover,.content kbd.navbar .navbar-end>a.navbar-item:hover,.navbar.is-dark .navbar-end>a.navbar-item.is-active,.content kbd.navbar .navbar-end>a.navbar-item.is-active,.navbar.is-dark .navbar-end .navbar-link:focus,.content kbd.navbar .navbar-end .navbar-link:focus,.navbar.is-dark .navbar-end .navbar-link:hover,.content kbd.navbar .navbar-end .navbar-link:hover,.navbar.is-dark .navbar-end .navbar-link.is-active,.content kbd.navbar .navbar-end .navbar-link.is-active{background-color:#292929;color:#fff}.navbar.is-dark .navbar-start .navbar-link::after,.content kbd.navbar .navbar-start .navbar-link::after,.navbar.is-dark .navbar-end .navbar-link::after,.content kbd.navbar .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link,.content kbd.navbar .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link,.content kbd.navbar .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link,.content kbd.navbar .navbar-item.has-dropdown.is-active .navbar-link{background-color:#292929;color:#fff}.navbar.is-dark .navbar-dropdown a.navbar-item.is-active,.content kbd.navbar .navbar-dropdown a.navbar-item.is-active{background-color:#363636;color:#fff}}.navbar.is-primary,.docstring>section>a.navbar.docs-sourcelink{background-color:#4eb5de;color:#fff}.navbar.is-primary .navbar-brand>.navbar-item,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>.navbar-item,.navbar.is-primary .navbar-brand .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link{color:#fff}.navbar.is-primary .navbar-brand>a.navbar-item:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:focus,.navbar.is-primary .navbar-brand>a.navbar-item:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:hover,.navbar.is-primary .navbar-brand>a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item.is-active,.navbar.is-primary .navbar-brand .navbar-link:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:focus,.navbar.is-primary .navbar-brand .navbar-link:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:hover,.navbar.is-primary .navbar-brand .navbar-link.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link.is-active{background-color:#39acda;color:#fff}.navbar.is-primary .navbar-brand .navbar-link::after,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-primary .navbar-burger,.docstring>section>a.navbar.docs-sourcelink .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-primary .navbar-start>.navbar-item,.docstring>section>a.navbar.docs-sourcelink .navbar-start>.navbar-item,.navbar.is-primary .navbar-start .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link,.navbar.is-primary .navbar-end>.navbar-item,.docstring>section>a.navbar.docs-sourcelink .navbar-end>.navbar-item,.navbar.is-primary .navbar-end .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link{color:#fff}.navbar.is-primary .navbar-start>a.navbar-item:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:focus,.navbar.is-primary .navbar-start>a.navbar-item:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:hover,.navbar.is-primary .navbar-start>a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item.is-active,.navbar.is-primary .navbar-start .navbar-link:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:focus,.navbar.is-primary .navbar-start .navbar-link:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:hover,.navbar.is-primary .navbar-start .navbar-link.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link.is-active,.navbar.is-primary .navbar-end>a.navbar-item:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:focus,.navbar.is-primary .navbar-end>a.navbar-item:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:hover,.navbar.is-primary .navbar-end>a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item.is-active,.navbar.is-primary .navbar-end .navbar-link:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:focus,.navbar.is-primary .navbar-end .navbar-link:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:hover,.navbar.is-primary .navbar-end .navbar-link.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link.is-active{background-color:#39acda;color:#fff}.navbar.is-primary .navbar-start .navbar-link::after,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link::after,.navbar.is-primary .navbar-end .navbar-link::after,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown.is-active .navbar-link{background-color:#39acda;color:#fff}.navbar.is-primary .navbar-dropdown a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#4eb5de;color:#fff}}.navbar.is-link{background-color:#2e63b8;color:#fff}.navbar.is-link .navbar-brand>.navbar-item,.navbar.is-link .navbar-brand .navbar-link{color:#fff}.navbar.is-link .navbar-brand>a.navbar-item:focus,.navbar.is-link .navbar-brand>a.navbar-item:hover,.navbar.is-link .navbar-brand>a.navbar-item.is-active,.navbar.is-link .navbar-brand .navbar-link:focus,.navbar.is-link .navbar-brand .navbar-link:hover,.navbar.is-link .navbar-brand .navbar-link.is-active{background-color:#2958a4;color:#fff}.navbar.is-link .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-link .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-link .navbar-start>.navbar-item,.navbar.is-link .navbar-start .navbar-link,.navbar.is-link .navbar-end>.navbar-item,.navbar.is-link .navbar-end .navbar-link{color:#fff}.navbar.is-link .navbar-start>a.navbar-item:focus,.navbar.is-link .navbar-start>a.navbar-item:hover,.navbar.is-link .navbar-start>a.navbar-item.is-active,.navbar.is-link .navbar-start .navbar-link:focus,.navbar.is-link .navbar-start .navbar-link:hover,.navbar.is-link .navbar-start .navbar-link.is-active,.navbar.is-link .navbar-end>a.navbar-item:focus,.navbar.is-link .navbar-end>a.navbar-item:hover,.navbar.is-link .navbar-end>a.navbar-item.is-active,.navbar.is-link .navbar-end .navbar-link:focus,.navbar.is-link .navbar-end .navbar-link:hover,.navbar.is-link .navbar-end .navbar-link.is-active{background-color:#2958a4;color:#fff}.navbar.is-link .navbar-start .navbar-link::after,.navbar.is-link .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-link .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-link .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link{background-color:#2958a4;color:#fff}.navbar.is-link .navbar-dropdown a.navbar-item.is-active{background-color:#2e63b8;color:#fff}}.navbar.is-info{background-color:#3c5dcd;color:#fff}.navbar.is-info .navbar-brand>.navbar-item,.navbar.is-info .navbar-brand .navbar-link{color:#fff}.navbar.is-info .navbar-brand>a.navbar-item:focus,.navbar.is-info .navbar-brand>a.navbar-item:hover,.navbar.is-info .navbar-brand>a.navbar-item.is-active,.navbar.is-info .navbar-brand .navbar-link:focus,.navbar.is-info .navbar-brand .navbar-link:hover,.navbar.is-info .navbar-brand .navbar-link.is-active{background-color:#3151bf;color:#fff}.navbar.is-info .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-info .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-info .navbar-start>.navbar-item,.navbar.is-info .navbar-start .navbar-link,.navbar.is-info .navbar-end>.navbar-item,.navbar.is-info .navbar-end .navbar-link{color:#fff}.navbar.is-info .navbar-start>a.navbar-item:focus,.navbar.is-info .navbar-start>a.navbar-item:hover,.navbar.is-info .navbar-start>a.navbar-item.is-active,.navbar.is-info .navbar-start .navbar-link:focus,.navbar.is-info .navbar-start .navbar-link:hover,.navbar.is-info .navbar-start .navbar-link.is-active,.navbar.is-info .navbar-end>a.navbar-item:focus,.navbar.is-info .navbar-end>a.navbar-item:hover,.navbar.is-info .navbar-end>a.navbar-item.is-active,.navbar.is-info .navbar-end .navbar-link:focus,.navbar.is-info .navbar-end .navbar-link:hover,.navbar.is-info .navbar-end .navbar-link.is-active{background-color:#3151bf;color:#fff}.navbar.is-info .navbar-start .navbar-link::after,.navbar.is-info .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-info .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-info .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link{background-color:#3151bf;color:#fff}.navbar.is-info .navbar-dropdown a.navbar-item.is-active{background-color:#3c5dcd;color:#fff}}.navbar.is-success{background-color:#259a12;color:#fff}.navbar.is-success .navbar-brand>.navbar-item,.navbar.is-success .navbar-brand .navbar-link{color:#fff}.navbar.is-success .navbar-brand>a.navbar-item:focus,.navbar.is-success .navbar-brand>a.navbar-item:hover,.navbar.is-success .navbar-brand>a.navbar-item.is-active,.navbar.is-success .navbar-brand .navbar-link:focus,.navbar.is-success .navbar-brand .navbar-link:hover,.navbar.is-success .navbar-brand .navbar-link.is-active{background-color:#20830f;color:#fff}.navbar.is-success .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-success .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-success .navbar-start>.navbar-item,.navbar.is-success .navbar-start .navbar-link,.navbar.is-success .navbar-end>.navbar-item,.navbar.is-success .navbar-end .navbar-link{color:#fff}.navbar.is-success .navbar-start>a.navbar-item:focus,.navbar.is-success .navbar-start>a.navbar-item:hover,.navbar.is-success .navbar-start>a.navbar-item.is-active,.navbar.is-success .navbar-start .navbar-link:focus,.navbar.is-success .navbar-start .navbar-link:hover,.navbar.is-success .navbar-start .navbar-link.is-active,.navbar.is-success .navbar-end>a.navbar-item:focus,.navbar.is-success .navbar-end>a.navbar-item:hover,.navbar.is-success .navbar-end>a.navbar-item.is-active,.navbar.is-success .navbar-end .navbar-link:focus,.navbar.is-success .navbar-end .navbar-link:hover,.navbar.is-success .navbar-end .navbar-link.is-active{background-color:#20830f;color:#fff}.navbar.is-success .navbar-start .navbar-link::after,.navbar.is-success .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-success .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-success .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link{background-color:#20830f;color:#fff}.navbar.is-success .navbar-dropdown a.navbar-item.is-active{background-color:#259a12;color:#fff}}.navbar.is-warning{background-color:#a98800;color:#fff}.navbar.is-warning .navbar-brand>.navbar-item,.navbar.is-warning .navbar-brand .navbar-link{color:#fff}.navbar.is-warning .navbar-brand>a.navbar-item:focus,.navbar.is-warning .navbar-brand>a.navbar-item:hover,.navbar.is-warning .navbar-brand>a.navbar-item.is-active,.navbar.is-warning .navbar-brand .navbar-link:focus,.navbar.is-warning .navbar-brand .navbar-link:hover,.navbar.is-warning .navbar-brand .navbar-link.is-active{background-color:#8f7300;color:#fff}.navbar.is-warning .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-warning .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-warning .navbar-start>.navbar-item,.navbar.is-warning .navbar-start .navbar-link,.navbar.is-warning .navbar-end>.navbar-item,.navbar.is-warning .navbar-end .navbar-link{color:#fff}.navbar.is-warning .navbar-start>a.navbar-item:focus,.navbar.is-warning .navbar-start>a.navbar-item:hover,.navbar.is-warning .navbar-start>a.navbar-item.is-active,.navbar.is-warning .navbar-start .navbar-link:focus,.navbar.is-warning .navbar-start .navbar-link:hover,.navbar.is-warning .navbar-start .navbar-link.is-active,.navbar.is-warning .navbar-end>a.navbar-item:focus,.navbar.is-warning .navbar-end>a.navbar-item:hover,.navbar.is-warning .navbar-end>a.navbar-item.is-active,.navbar.is-warning .navbar-end .navbar-link:focus,.navbar.is-warning .navbar-end .navbar-link:hover,.navbar.is-warning .navbar-end .navbar-link.is-active{background-color:#8f7300;color:#fff}.navbar.is-warning .navbar-start .navbar-link::after,.navbar.is-warning .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link{background-color:#8f7300;color:#fff}.navbar.is-warning .navbar-dropdown a.navbar-item.is-active{background-color:#a98800;color:#fff}}.navbar.is-danger{background-color:#cb3c33;color:#fff}.navbar.is-danger .navbar-brand>.navbar-item,.navbar.is-danger .navbar-brand .navbar-link{color:#fff}.navbar.is-danger .navbar-brand>a.navbar-item:focus,.navbar.is-danger .navbar-brand>a.navbar-item:hover,.navbar.is-danger .navbar-brand>a.navbar-item.is-active,.navbar.is-danger .navbar-brand .navbar-link:focus,.navbar.is-danger .navbar-brand .navbar-link:hover,.navbar.is-danger .navbar-brand .navbar-link.is-active{background-color:#b7362e;color:#fff}.navbar.is-danger .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-danger .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-danger .navbar-start>.navbar-item,.navbar.is-danger .navbar-start .navbar-link,.navbar.is-danger .navbar-end>.navbar-item,.navbar.is-danger .navbar-end .navbar-link{color:#fff}.navbar.is-danger .navbar-start>a.navbar-item:focus,.navbar.is-danger .navbar-start>a.navbar-item:hover,.navbar.is-danger .navbar-start>a.navbar-item.is-active,.navbar.is-danger .navbar-start .navbar-link:focus,.navbar.is-danger .navbar-start .navbar-link:hover,.navbar.is-danger .navbar-start .navbar-link.is-active,.navbar.is-danger .navbar-end>a.navbar-item:focus,.navbar.is-danger .navbar-end>a.navbar-item:hover,.navbar.is-danger .navbar-end>a.navbar-item.is-active,.navbar.is-danger .navbar-end .navbar-link:focus,.navbar.is-danger .navbar-end .navbar-link:hover,.navbar.is-danger .navbar-end .navbar-link.is-active{background-color:#b7362e;color:#fff}.navbar.is-danger .navbar-start .navbar-link::after,.navbar.is-danger .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link{background-color:#b7362e;color:#fff}.navbar.is-danger .navbar-dropdown a.navbar-item.is-active{background-color:#cb3c33;color:#fff}}.navbar>.container{align-items:stretch;display:flex;min-height:3.25rem;width:100%}.navbar.has-shadow{box-shadow:0 2px 0 0 #f5f5f5}.navbar.is-fixed-bottom,.navbar.is-fixed-top{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom{bottom:0}.navbar.is-fixed-bottom.has-shadow{box-shadow:0 -2px 0 0 #f5f5f5}.navbar.is-fixed-top{top:0}html.has-navbar-fixed-top,body.has-navbar-fixed-top{padding-top:3.25rem}html.has-navbar-fixed-bottom,body.has-navbar-fixed-bottom{padding-bottom:3.25rem}.navbar-brand,.navbar-tabs{align-items:stretch;display:flex;flex-shrink:0;min-height:3.25rem}.navbar-brand a.navbar-item:focus,.navbar-brand a.navbar-item:hover{background-color:transparent}.navbar-tabs{-webkit-overflow-scrolling:touch;max-width:100vw;overflow-x:auto;overflow-y:hidden}.navbar-burger{color:#222;-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;cursor:pointer;display:block;height:3.25rem;position:relative;width:3.25rem;margin-left:auto}.navbar-burger span{background-color:currentColor;display:block;height:1px;left:calc(50% - 8px);position:absolute;transform-origin:center;transition-duration:86ms;transition-property:background-color, opacity, transform;transition-timing-function:ease-out;width:16px}.navbar-burger span:nth-child(1){top:calc(50% - 6px)}.navbar-burger span:nth-child(2){top:calc(50% - 1px)}.navbar-burger span:nth-child(3){top:calc(50% + 4px)}.navbar-burger:hover{background-color:rgba(0,0,0,0.05)}.navbar-burger.is-active span:nth-child(1){transform:translateY(5px) rotate(45deg)}.navbar-burger.is-active span:nth-child(2){opacity:0}.navbar-burger.is-active span:nth-child(3){transform:translateY(-5px) rotate(-45deg)}.navbar-menu{display:none}.navbar-item,.navbar-link{color:#222;display:block;line-height:1.5;padding:0.5rem 0.75rem;position:relative}.navbar-item .icon:only-child,.navbar-link .icon:only-child{margin-left:-0.25rem;margin-right:-0.25rem}a.navbar-item,.navbar-link{cursor:pointer}a.navbar-item:focus,a.navbar-item:focus-within,a.navbar-item:hover,a.navbar-item.is-active,.navbar-link:focus,.navbar-link:focus-within,.navbar-link:hover,.navbar-link.is-active{background-color:#fafafa;color:#2e63b8}.navbar-item{flex-grow:0;flex-shrink:0}.navbar-item img{max-height:1.75rem}.navbar-item.has-dropdown{padding:0}.navbar-item.is-expanded{flex-grow:1;flex-shrink:1}.navbar-item.is-tab{border-bottom:1px solid transparent;min-height:3.25rem;padding-bottom:calc(0.5rem - 1px)}.navbar-item.is-tab:focus,.navbar-item.is-tab:hover{background-color:rgba(0,0,0,0);border-bottom-color:#2e63b8}.navbar-item.is-tab.is-active{background-color:rgba(0,0,0,0);border-bottom-color:#2e63b8;border-bottom-style:solid;border-bottom-width:3px;color:#2e63b8;padding-bottom:calc(0.5rem - 3px)}.navbar-content{flex-grow:1;flex-shrink:1}.navbar-link:not(.is-arrowless){padding-right:2.5em}.navbar-link:not(.is-arrowless)::after{border-color:#2e63b8;margin-top:-0.375em;right:1.125em}.navbar-dropdown{font-size:0.875rem;padding-bottom:0.5rem;padding-top:0.5rem}.navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}.navbar-divider{background-color:#f5f5f5;border:none;display:none;height:2px;margin:0.5rem 0}@media screen and (max-width: 1055px){.navbar>.container{display:block}.navbar-brand .navbar-item,.navbar-tabs .navbar-item{align-items:center;display:flex}.navbar-link::after{display:none}.navbar-menu{background-color:#fff;box-shadow:0 8px 16px rgba(10,10,10,0.1);padding:0.5rem 0}.navbar-menu.is-active{display:block}.navbar.is-fixed-bottom-touch,.navbar.is-fixed-top-touch{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom-touch{bottom:0}.navbar.is-fixed-bottom-touch.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}.navbar.is-fixed-top-touch{top:0}.navbar.is-fixed-top .navbar-menu,.navbar.is-fixed-top-touch .navbar-menu{-webkit-overflow-scrolling:touch;max-height:calc(100vh - 3.25rem);overflow:auto}html.has-navbar-fixed-top-touch,body.has-navbar-fixed-top-touch{padding-top:3.25rem}html.has-navbar-fixed-bottom-touch,body.has-navbar-fixed-bottom-touch{padding-bottom:3.25rem}}@media screen and (min-width: 1056px){.navbar,.navbar-menu,.navbar-start,.navbar-end{align-items:stretch;display:flex}.navbar{min-height:3.25rem}.navbar.is-spaced{padding:1rem 2rem}.navbar.is-spaced .navbar-start,.navbar.is-spaced .navbar-end{align-items:center}.navbar.is-spaced a.navbar-item,.navbar.is-spaced .navbar-link{border-radius:4px}.navbar.is-transparent a.navbar-item:focus,.navbar.is-transparent a.navbar-item:hover,.navbar.is-transparent a.navbar-item.is-active,.navbar.is-transparent .navbar-link:focus,.navbar.is-transparent .navbar-link:hover,.navbar.is-transparent .navbar-link.is-active{background-color:transparent !important}.navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link{background-color:transparent !important}.navbar.is-transparent .navbar-dropdown a.navbar-item:focus,.navbar.is-transparent .navbar-dropdown a.navbar-item:hover{background-color:#f5f5f5;color:#0a0a0a}.navbar.is-transparent .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#2e63b8}.navbar-burger{display:none}.navbar-item,.navbar-link{align-items:center;display:flex}.navbar-item.has-dropdown{align-items:stretch}.navbar-item.has-dropdown-up .navbar-link::after{transform:rotate(135deg) translate(0.25em, -0.25em)}.navbar-item.has-dropdown-up .navbar-dropdown{border-bottom:2px solid #dbdbdb;border-radius:6px 6px 0 0;border-top:none;bottom:100%;box-shadow:0 -8px 8px rgba(10,10,10,0.1);top:auto}.navbar-item.is-active .navbar-dropdown,.navbar-item.is-hoverable:focus .navbar-dropdown,.navbar-item.is-hoverable:focus-within .navbar-dropdown,.navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar.is-spaced .navbar-item.is-active .navbar-dropdown,.navbar-item.is-active .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-hoverable:focus .navbar-dropdown,.navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-hoverable:focus-within .navbar-dropdown,.navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-hoverable:hover .navbar-dropdown,.navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed{opacity:1;pointer-events:auto;transform:translateY(0)}.navbar-menu{flex-grow:1;flex-shrink:0}.navbar-start{justify-content:flex-start;margin-right:auto}.navbar-end{justify-content:flex-end;margin-left:auto}.navbar-dropdown{background-color:#fff;border-bottom-left-radius:6px;border-bottom-right-radius:6px;border-top:2px solid #dbdbdb;box-shadow:0 8px 8px rgba(10,10,10,0.1);display:none;font-size:0.875rem;left:0;min-width:100%;position:absolute;top:100%;z-index:20}.navbar-dropdown .navbar-item{padding:0.375rem 1rem;white-space:nowrap}.navbar-dropdown a.navbar-item{padding-right:3rem}.navbar-dropdown a.navbar-item:focus,.navbar-dropdown a.navbar-item:hover{background-color:#f5f5f5;color:#0a0a0a}.navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#2e63b8}.navbar.is-spaced .navbar-dropdown,.navbar-dropdown.is-boxed{border-radius:6px;border-top:none;box-shadow:0 8px 8px rgba(10,10,10,0.1), 0 0 0 1px rgba(10,10,10,0.1);display:block;opacity:0;pointer-events:none;top:calc(100% + (-4px));transform:translateY(-5px);transition-duration:86ms;transition-property:opacity, transform}.navbar-dropdown.is-right{left:auto;right:0}.navbar-divider{display:block}.navbar>.container .navbar-brand,.container>.navbar .navbar-brand{margin-left:-.75rem}.navbar>.container .navbar-menu,.container>.navbar .navbar-menu{margin-right:-.75rem}.navbar.is-fixed-bottom-desktop,.navbar.is-fixed-top-desktop{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom-desktop{bottom:0}.navbar.is-fixed-bottom-desktop.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}.navbar.is-fixed-top-desktop{top:0}html.has-navbar-fixed-top-desktop,body.has-navbar-fixed-top-desktop{padding-top:3.25rem}html.has-navbar-fixed-bottom-desktop,body.has-navbar-fixed-bottom-desktop{padding-bottom:3.25rem}html.has-spaced-navbar-fixed-top,body.has-spaced-navbar-fixed-top{padding-top:5.25rem}html.has-spaced-navbar-fixed-bottom,body.has-spaced-navbar-fixed-bottom{padding-bottom:5.25rem}a.navbar-item.is-active,.navbar-link.is-active{color:#0a0a0a}a.navbar-item.is-active:not(:focus):not(:hover),.navbar-link.is-active:not(:focus):not(:hover){background-color:rgba(0,0,0,0)}.navbar-item.has-dropdown:focus .navbar-link,.navbar-item.has-dropdown:hover .navbar-link,.navbar-item.has-dropdown.is-active .navbar-link{background-color:#fafafa}}.hero.is-fullheight-with-navbar{min-height:calc(100vh - 3.25rem)}.pagination{font-size:1rem;margin:-.25rem}.pagination.is-small,#documenter .docs-sidebar form.docs-search>input.pagination{font-size:.75rem}.pagination.is-medium{font-size:1.25rem}.pagination.is-large{font-size:1.5rem}.pagination.is-rounded .pagination-previous,#documenter .docs-sidebar form.docs-search>input.pagination .pagination-previous,.pagination.is-rounded .pagination-next,#documenter .docs-sidebar form.docs-search>input.pagination .pagination-next{padding-left:1em;padding-right:1em;border-radius:9999px}.pagination.is-rounded .pagination-link,#documenter .docs-sidebar form.docs-search>input.pagination .pagination-link{border-radius:9999px}.pagination,.pagination-list{align-items:center;display:flex;justify-content:center;text-align:center}.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis{font-size:1em;justify-content:center;margin:.25rem;padding-left:.5em;padding-right:.5em;text-align:center}.pagination-previous,.pagination-next,.pagination-link{border-color:#dbdbdb;color:#222;min-width:2.5em}.pagination-previous:hover,.pagination-next:hover,.pagination-link:hover{border-color:#b5b5b5;color:#363636}.pagination-previous:focus,.pagination-next:focus,.pagination-link:focus{border-color:#3c5dcd}.pagination-previous:active,.pagination-next:active,.pagination-link:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2)}.pagination-previous[disabled],.pagination-previous.is-disabled,.pagination-next[disabled],.pagination-next.is-disabled,.pagination-link[disabled],.pagination-link.is-disabled{background-color:#dbdbdb;border-color:#dbdbdb;box-shadow:none;color:#6b6b6b;opacity:0.5}.pagination-previous,.pagination-next{padding-left:.75em;padding-right:.75em;white-space:nowrap}.pagination-link.is-current{background-color:#2e63b8;border-color:#2e63b8;color:#fff}.pagination-ellipsis{color:#b5b5b5;pointer-events:none}.pagination-list{flex-wrap:wrap}.pagination-list li{list-style:none}@media screen and (max-width: 768px){.pagination{flex-wrap:wrap}.pagination-previous,.pagination-next{flex-grow:1;flex-shrink:1}.pagination-list li{flex-grow:1;flex-shrink:1}}@media screen and (min-width: 769px),print{.pagination-list{flex-grow:1;flex-shrink:1;justify-content:flex-start;order:1}.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis{margin-bottom:0;margin-top:0}.pagination-previous{order:2}.pagination-next{order:3}.pagination{justify-content:space-between;margin-bottom:0;margin-top:0}.pagination.is-centered .pagination-previous{order:1}.pagination.is-centered .pagination-list{justify-content:center;order:2}.pagination.is-centered .pagination-next{order:3}.pagination.is-right .pagination-previous{order:1}.pagination.is-right .pagination-next{order:2}.pagination.is-right .pagination-list{justify-content:flex-end;order:3}}.panel{border-radius:6px;box-shadow:#bbb;font-size:1rem}.panel:not(:last-child){margin-bottom:1.5rem}.panel.is-white .panel-heading{background-color:#fff;color:#0a0a0a}.panel.is-white .panel-tabs a.is-active{border-bottom-color:#fff}.panel.is-white .panel-block.is-active .panel-icon{color:#fff}.panel.is-black .panel-heading{background-color:#0a0a0a;color:#fff}.panel.is-black .panel-tabs a.is-active{border-bottom-color:#0a0a0a}.panel.is-black .panel-block.is-active .panel-icon{color:#0a0a0a}.panel.is-light .panel-heading{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.panel.is-light .panel-tabs a.is-active{border-bottom-color:#f5f5f5}.panel.is-light .panel-block.is-active .panel-icon{color:#f5f5f5}.panel.is-dark .panel-heading,.content kbd.panel .panel-heading{background-color:#363636;color:#fff}.panel.is-dark .panel-tabs a.is-active,.content kbd.panel .panel-tabs a.is-active{border-bottom-color:#363636}.panel.is-dark .panel-block.is-active .panel-icon,.content kbd.panel .panel-block.is-active .panel-icon{color:#363636}.panel.is-primary .panel-heading,.docstring>section>a.panel.docs-sourcelink .panel-heading{background-color:#4eb5de;color:#fff}.panel.is-primary .panel-tabs a.is-active,.docstring>section>a.panel.docs-sourcelink .panel-tabs a.is-active{border-bottom-color:#4eb5de}.panel.is-primary .panel-block.is-active .panel-icon,.docstring>section>a.panel.docs-sourcelink .panel-block.is-active .panel-icon{color:#4eb5de}.panel.is-link .panel-heading{background-color:#2e63b8;color:#fff}.panel.is-link .panel-tabs a.is-active{border-bottom-color:#2e63b8}.panel.is-link .panel-block.is-active .panel-icon{color:#2e63b8}.panel.is-info .panel-heading{background-color:#3c5dcd;color:#fff}.panel.is-info .panel-tabs a.is-active{border-bottom-color:#3c5dcd}.panel.is-info .panel-block.is-active .panel-icon{color:#3c5dcd}.panel.is-success .panel-heading{background-color:#259a12;color:#fff}.panel.is-success .panel-tabs a.is-active{border-bottom-color:#259a12}.panel.is-success .panel-block.is-active .panel-icon{color:#259a12}.panel.is-warning .panel-heading{background-color:#a98800;color:#fff}.panel.is-warning .panel-tabs a.is-active{border-bottom-color:#a98800}.panel.is-warning .panel-block.is-active .panel-icon{color:#a98800}.panel.is-danger .panel-heading{background-color:#cb3c33;color:#fff}.panel.is-danger .panel-tabs a.is-active{border-bottom-color:#cb3c33}.panel.is-danger .panel-block.is-active .panel-icon{color:#cb3c33}.panel-tabs:not(:last-child),.panel-block:not(:last-child){border-bottom:1px solid #ededed}.panel-heading{background-color:#ededed;border-radius:6px 6px 0 0;color:#222;font-size:1.25em;font-weight:700;line-height:1.25;padding:0.75em 1em}.panel-tabs{align-items:flex-end;display:flex;font-size:.875em;justify-content:center}.panel-tabs a{border-bottom:1px solid #dbdbdb;margin-bottom:-1px;padding:0.5em}.panel-tabs a.is-active{border-bottom-color:#4a4a4a;color:#363636}.panel-list a{color:#222}.panel-list a:hover{color:#2e63b8}.panel-block{align-items:center;color:#222;display:flex;justify-content:flex-start;padding:0.5em 0.75em}.panel-block input[type="checkbox"]{margin-right:.75em}.panel-block>.control{flex-grow:1;flex-shrink:1;width:100%}.panel-block.is-wrapped{flex-wrap:wrap}.panel-block.is-active{border-left-color:#2e63b8;color:#363636}.panel-block.is-active .panel-icon{color:#2e63b8}.panel-block:last-child{border-bottom-left-radius:6px;border-bottom-right-radius:6px}a.panel-block,label.panel-block{cursor:pointer}a.panel-block:hover,label.panel-block:hover{background-color:#f5f5f5}.panel-icon{display:inline-block;font-size:14px;height:1em;line-height:1em;text-align:center;vertical-align:top;width:1em;color:#6b6b6b;margin-right:.75em}.panel-icon .fa{font-size:inherit;line-height:inherit}.tabs{-webkit-overflow-scrolling:touch;align-items:stretch;display:flex;font-size:1rem;justify-content:space-between;overflow:hidden;overflow-x:auto;white-space:nowrap}.tabs a{align-items:center;border-bottom-color:#dbdbdb;border-bottom-style:solid;border-bottom-width:1px;color:#222;display:flex;justify-content:center;margin-bottom:-1px;padding:0.5em 1em;vertical-align:top}.tabs a:hover{border-bottom-color:#222;color:#222}.tabs li{display:block}.tabs li.is-active a{border-bottom-color:#2e63b8;color:#2e63b8}.tabs ul{align-items:center;border-bottom-color:#dbdbdb;border-bottom-style:solid;border-bottom-width:1px;display:flex;flex-grow:1;flex-shrink:0;justify-content:flex-start}.tabs ul.is-left{padding-right:0.75em}.tabs ul.is-center{flex:none;justify-content:center;padding-left:0.75em;padding-right:0.75em}.tabs ul.is-right{justify-content:flex-end;padding-left:0.75em}.tabs .icon:first-child{margin-right:.5em}.tabs .icon:last-child{margin-left:.5em}.tabs.is-centered ul{justify-content:center}.tabs.is-right ul{justify-content:flex-end}.tabs.is-boxed a{border:1px solid transparent;border-radius:4px 4px 0 0}.tabs.is-boxed a:hover{background-color:#f5f5f5;border-bottom-color:#dbdbdb}.tabs.is-boxed li.is-active a{background-color:#fff;border-color:#dbdbdb;border-bottom-color:rgba(0,0,0,0) !important}.tabs.is-fullwidth li{flex-grow:1;flex-shrink:0}.tabs.is-toggle a{border-color:#dbdbdb;border-style:solid;border-width:1px;margin-bottom:0;position:relative}.tabs.is-toggle a:hover{background-color:#f5f5f5;border-color:#b5b5b5;z-index:2}.tabs.is-toggle li+li{margin-left:-1px}.tabs.is-toggle li:first-child a{border-top-left-radius:4px;border-bottom-left-radius:4px}.tabs.is-toggle li:last-child a{border-top-right-radius:4px;border-bottom-right-radius:4px}.tabs.is-toggle li.is-active a{background-color:#2e63b8;border-color:#2e63b8;color:#fff;z-index:1}.tabs.is-toggle ul{border-bottom:none}.tabs.is-toggle.is-toggle-rounded li:first-child a{border-bottom-left-radius:9999px;border-top-left-radius:9999px;padding-left:1.25em}.tabs.is-toggle.is-toggle-rounded li:last-child a{border-bottom-right-radius:9999px;border-top-right-radius:9999px;padding-right:1.25em}.tabs.is-small,#documenter .docs-sidebar form.docs-search>input.tabs{font-size:.75rem}.tabs.is-medium{font-size:1.25rem}.tabs.is-large{font-size:1.5rem}.column{display:block;flex-basis:0;flex-grow:1;flex-shrink:1;padding:.75rem}.columns.is-mobile>.column.is-narrow{flex:none;width:unset}.columns.is-mobile>.column.is-full{flex:none;width:100%}.columns.is-mobile>.column.is-three-quarters{flex:none;width:75%}.columns.is-mobile>.column.is-two-thirds{flex:none;width:66.6666%}.columns.is-mobile>.column.is-half{flex:none;width:50%}.columns.is-mobile>.column.is-one-third{flex:none;width:33.3333%}.columns.is-mobile>.column.is-one-quarter{flex:none;width:25%}.columns.is-mobile>.column.is-one-fifth{flex:none;width:20%}.columns.is-mobile>.column.is-two-fifths{flex:none;width:40%}.columns.is-mobile>.column.is-three-fifths{flex:none;width:60%}.columns.is-mobile>.column.is-four-fifths{flex:none;width:80%}.columns.is-mobile>.column.is-offset-three-quarters{margin-left:75%}.columns.is-mobile>.column.is-offset-two-thirds{margin-left:66.6666%}.columns.is-mobile>.column.is-offset-half{margin-left:50%}.columns.is-mobile>.column.is-offset-one-third{margin-left:33.3333%}.columns.is-mobile>.column.is-offset-one-quarter{margin-left:25%}.columns.is-mobile>.column.is-offset-one-fifth{margin-left:20%}.columns.is-mobile>.column.is-offset-two-fifths{margin-left:40%}.columns.is-mobile>.column.is-offset-three-fifths{margin-left:60%}.columns.is-mobile>.column.is-offset-four-fifths{margin-left:80%}.columns.is-mobile>.column.is-0{flex:none;width:0%}.columns.is-mobile>.column.is-offset-0{margin-left:0%}.columns.is-mobile>.column.is-1{flex:none;width:8.33333337%}.columns.is-mobile>.column.is-offset-1{margin-left:8.33333337%}.columns.is-mobile>.column.is-2{flex:none;width:16.66666674%}.columns.is-mobile>.column.is-offset-2{margin-left:16.66666674%}.columns.is-mobile>.column.is-3{flex:none;width:25%}.columns.is-mobile>.column.is-offset-3{margin-left:25%}.columns.is-mobile>.column.is-4{flex:none;width:33.33333337%}.columns.is-mobile>.column.is-offset-4{margin-left:33.33333337%}.columns.is-mobile>.column.is-5{flex:none;width:41.66666674%}.columns.is-mobile>.column.is-offset-5{margin-left:41.66666674%}.columns.is-mobile>.column.is-6{flex:none;width:50%}.columns.is-mobile>.column.is-offset-6{margin-left:50%}.columns.is-mobile>.column.is-7{flex:none;width:58.33333337%}.columns.is-mobile>.column.is-offset-7{margin-left:58.33333337%}.columns.is-mobile>.column.is-8{flex:none;width:66.66666674%}.columns.is-mobile>.column.is-offset-8{margin-left:66.66666674%}.columns.is-mobile>.column.is-9{flex:none;width:75%}.columns.is-mobile>.column.is-offset-9{margin-left:75%}.columns.is-mobile>.column.is-10{flex:none;width:83.33333337%}.columns.is-mobile>.column.is-offset-10{margin-left:83.33333337%}.columns.is-mobile>.column.is-11{flex:none;width:91.66666674%}.columns.is-mobile>.column.is-offset-11{margin-left:91.66666674%}.columns.is-mobile>.column.is-12{flex:none;width:100%}.columns.is-mobile>.column.is-offset-12{margin-left:100%}@media screen and (max-width: 768px){.column.is-narrow-mobile{flex:none;width:unset}.column.is-full-mobile{flex:none;width:100%}.column.is-three-quarters-mobile{flex:none;width:75%}.column.is-two-thirds-mobile{flex:none;width:66.6666%}.column.is-half-mobile{flex:none;width:50%}.column.is-one-third-mobile{flex:none;width:33.3333%}.column.is-one-quarter-mobile{flex:none;width:25%}.column.is-one-fifth-mobile{flex:none;width:20%}.column.is-two-fifths-mobile{flex:none;width:40%}.column.is-three-fifths-mobile{flex:none;width:60%}.column.is-four-fifths-mobile{flex:none;width:80%}.column.is-offset-three-quarters-mobile{margin-left:75%}.column.is-offset-two-thirds-mobile{margin-left:66.6666%}.column.is-offset-half-mobile{margin-left:50%}.column.is-offset-one-third-mobile{margin-left:33.3333%}.column.is-offset-one-quarter-mobile{margin-left:25%}.column.is-offset-one-fifth-mobile{margin-left:20%}.column.is-offset-two-fifths-mobile{margin-left:40%}.column.is-offset-three-fifths-mobile{margin-left:60%}.column.is-offset-four-fifths-mobile{margin-left:80%}.column.is-0-mobile{flex:none;width:0%}.column.is-offset-0-mobile{margin-left:0%}.column.is-1-mobile{flex:none;width:8.33333337%}.column.is-offset-1-mobile{margin-left:8.33333337%}.column.is-2-mobile{flex:none;width:16.66666674%}.column.is-offset-2-mobile{margin-left:16.66666674%}.column.is-3-mobile{flex:none;width:25%}.column.is-offset-3-mobile{margin-left:25%}.column.is-4-mobile{flex:none;width:33.33333337%}.column.is-offset-4-mobile{margin-left:33.33333337%}.column.is-5-mobile{flex:none;width:41.66666674%}.column.is-offset-5-mobile{margin-left:41.66666674%}.column.is-6-mobile{flex:none;width:50%}.column.is-offset-6-mobile{margin-left:50%}.column.is-7-mobile{flex:none;width:58.33333337%}.column.is-offset-7-mobile{margin-left:58.33333337%}.column.is-8-mobile{flex:none;width:66.66666674%}.column.is-offset-8-mobile{margin-left:66.66666674%}.column.is-9-mobile{flex:none;width:75%}.column.is-offset-9-mobile{margin-left:75%}.column.is-10-mobile{flex:none;width:83.33333337%}.column.is-offset-10-mobile{margin-left:83.33333337%}.column.is-11-mobile{flex:none;width:91.66666674%}.column.is-offset-11-mobile{margin-left:91.66666674%}.column.is-12-mobile{flex:none;width:100%}.column.is-offset-12-mobile{margin-left:100%}}@media screen and (min-width: 769px),print{.column.is-narrow,.column.is-narrow-tablet{flex:none;width:unset}.column.is-full,.column.is-full-tablet{flex:none;width:100%}.column.is-three-quarters,.column.is-three-quarters-tablet{flex:none;width:75%}.column.is-two-thirds,.column.is-two-thirds-tablet{flex:none;width:66.6666%}.column.is-half,.column.is-half-tablet{flex:none;width:50%}.column.is-one-third,.column.is-one-third-tablet{flex:none;width:33.3333%}.column.is-one-quarter,.column.is-one-quarter-tablet{flex:none;width:25%}.column.is-one-fifth,.column.is-one-fifth-tablet{flex:none;width:20%}.column.is-two-fifths,.column.is-two-fifths-tablet{flex:none;width:40%}.column.is-three-fifths,.column.is-three-fifths-tablet{flex:none;width:60%}.column.is-four-fifths,.column.is-four-fifths-tablet{flex:none;width:80%}.column.is-offset-three-quarters,.column.is-offset-three-quarters-tablet{margin-left:75%}.column.is-offset-two-thirds,.column.is-offset-two-thirds-tablet{margin-left:66.6666%}.column.is-offset-half,.column.is-offset-half-tablet{margin-left:50%}.column.is-offset-one-third,.column.is-offset-one-third-tablet{margin-left:33.3333%}.column.is-offset-one-quarter,.column.is-offset-one-quarter-tablet{margin-left:25%}.column.is-offset-one-fifth,.column.is-offset-one-fifth-tablet{margin-left:20%}.column.is-offset-two-fifths,.column.is-offset-two-fifths-tablet{margin-left:40%}.column.is-offset-three-fifths,.column.is-offset-three-fifths-tablet{margin-left:60%}.column.is-offset-four-fifths,.column.is-offset-four-fifths-tablet{margin-left:80%}.column.is-0,.column.is-0-tablet{flex:none;width:0%}.column.is-offset-0,.column.is-offset-0-tablet{margin-left:0%}.column.is-1,.column.is-1-tablet{flex:none;width:8.33333337%}.column.is-offset-1,.column.is-offset-1-tablet{margin-left:8.33333337%}.column.is-2,.column.is-2-tablet{flex:none;width:16.66666674%}.column.is-offset-2,.column.is-offset-2-tablet{margin-left:16.66666674%}.column.is-3,.column.is-3-tablet{flex:none;width:25%}.column.is-offset-3,.column.is-offset-3-tablet{margin-left:25%}.column.is-4,.column.is-4-tablet{flex:none;width:33.33333337%}.column.is-offset-4,.column.is-offset-4-tablet{margin-left:33.33333337%}.column.is-5,.column.is-5-tablet{flex:none;width:41.66666674%}.column.is-offset-5,.column.is-offset-5-tablet{margin-left:41.66666674%}.column.is-6,.column.is-6-tablet{flex:none;width:50%}.column.is-offset-6,.column.is-offset-6-tablet{margin-left:50%}.column.is-7,.column.is-7-tablet{flex:none;width:58.33333337%}.column.is-offset-7,.column.is-offset-7-tablet{margin-left:58.33333337%}.column.is-8,.column.is-8-tablet{flex:none;width:66.66666674%}.column.is-offset-8,.column.is-offset-8-tablet{margin-left:66.66666674%}.column.is-9,.column.is-9-tablet{flex:none;width:75%}.column.is-offset-9,.column.is-offset-9-tablet{margin-left:75%}.column.is-10,.column.is-10-tablet{flex:none;width:83.33333337%}.column.is-offset-10,.column.is-offset-10-tablet{margin-left:83.33333337%}.column.is-11,.column.is-11-tablet{flex:none;width:91.66666674%}.column.is-offset-11,.column.is-offset-11-tablet{margin-left:91.66666674%}.column.is-12,.column.is-12-tablet{flex:none;width:100%}.column.is-offset-12,.column.is-offset-12-tablet{margin-left:100%}}@media screen and (max-width: 1055px){.column.is-narrow-touch{flex:none;width:unset}.column.is-full-touch{flex:none;width:100%}.column.is-three-quarters-touch{flex:none;width:75%}.column.is-two-thirds-touch{flex:none;width:66.6666%}.column.is-half-touch{flex:none;width:50%}.column.is-one-third-touch{flex:none;width:33.3333%}.column.is-one-quarter-touch{flex:none;width:25%}.column.is-one-fifth-touch{flex:none;width:20%}.column.is-two-fifths-touch{flex:none;width:40%}.column.is-three-fifths-touch{flex:none;width:60%}.column.is-four-fifths-touch{flex:none;width:80%}.column.is-offset-three-quarters-touch{margin-left:75%}.column.is-offset-two-thirds-touch{margin-left:66.6666%}.column.is-offset-half-touch{margin-left:50%}.column.is-offset-one-third-touch{margin-left:33.3333%}.column.is-offset-one-quarter-touch{margin-left:25%}.column.is-offset-one-fifth-touch{margin-left:20%}.column.is-offset-two-fifths-touch{margin-left:40%}.column.is-offset-three-fifths-touch{margin-left:60%}.column.is-offset-four-fifths-touch{margin-left:80%}.column.is-0-touch{flex:none;width:0%}.column.is-offset-0-touch{margin-left:0%}.column.is-1-touch{flex:none;width:8.33333337%}.column.is-offset-1-touch{margin-left:8.33333337%}.column.is-2-touch{flex:none;width:16.66666674%}.column.is-offset-2-touch{margin-left:16.66666674%}.column.is-3-touch{flex:none;width:25%}.column.is-offset-3-touch{margin-left:25%}.column.is-4-touch{flex:none;width:33.33333337%}.column.is-offset-4-touch{margin-left:33.33333337%}.column.is-5-touch{flex:none;width:41.66666674%}.column.is-offset-5-touch{margin-left:41.66666674%}.column.is-6-touch{flex:none;width:50%}.column.is-offset-6-touch{margin-left:50%}.column.is-7-touch{flex:none;width:58.33333337%}.column.is-offset-7-touch{margin-left:58.33333337%}.column.is-8-touch{flex:none;width:66.66666674%}.column.is-offset-8-touch{margin-left:66.66666674%}.column.is-9-touch{flex:none;width:75%}.column.is-offset-9-touch{margin-left:75%}.column.is-10-touch{flex:none;width:83.33333337%}.column.is-offset-10-touch{margin-left:83.33333337%}.column.is-11-touch{flex:none;width:91.66666674%}.column.is-offset-11-touch{margin-left:91.66666674%}.column.is-12-touch{flex:none;width:100%}.column.is-offset-12-touch{margin-left:100%}}@media screen and (min-width: 1056px){.column.is-narrow-desktop{flex:none;width:unset}.column.is-full-desktop{flex:none;width:100%}.column.is-three-quarters-desktop{flex:none;width:75%}.column.is-two-thirds-desktop{flex:none;width:66.6666%}.column.is-half-desktop{flex:none;width:50%}.column.is-one-third-desktop{flex:none;width:33.3333%}.column.is-one-quarter-desktop{flex:none;width:25%}.column.is-one-fifth-desktop{flex:none;width:20%}.column.is-two-fifths-desktop{flex:none;width:40%}.column.is-three-fifths-desktop{flex:none;width:60%}.column.is-four-fifths-desktop{flex:none;width:80%}.column.is-offset-three-quarters-desktop{margin-left:75%}.column.is-offset-two-thirds-desktop{margin-left:66.6666%}.column.is-offset-half-desktop{margin-left:50%}.column.is-offset-one-third-desktop{margin-left:33.3333%}.column.is-offset-one-quarter-desktop{margin-left:25%}.column.is-offset-one-fifth-desktop{margin-left:20%}.column.is-offset-two-fifths-desktop{margin-left:40%}.column.is-offset-three-fifths-desktop{margin-left:60%}.column.is-offset-four-fifths-desktop{margin-left:80%}.column.is-0-desktop{flex:none;width:0%}.column.is-offset-0-desktop{margin-left:0%}.column.is-1-desktop{flex:none;width:8.33333337%}.column.is-offset-1-desktop{margin-left:8.33333337%}.column.is-2-desktop{flex:none;width:16.66666674%}.column.is-offset-2-desktop{margin-left:16.66666674%}.column.is-3-desktop{flex:none;width:25%}.column.is-offset-3-desktop{margin-left:25%}.column.is-4-desktop{flex:none;width:33.33333337%}.column.is-offset-4-desktop{margin-left:33.33333337%}.column.is-5-desktop{flex:none;width:41.66666674%}.column.is-offset-5-desktop{margin-left:41.66666674%}.column.is-6-desktop{flex:none;width:50%}.column.is-offset-6-desktop{margin-left:50%}.column.is-7-desktop{flex:none;width:58.33333337%}.column.is-offset-7-desktop{margin-left:58.33333337%}.column.is-8-desktop{flex:none;width:66.66666674%}.column.is-offset-8-desktop{margin-left:66.66666674%}.column.is-9-desktop{flex:none;width:75%}.column.is-offset-9-desktop{margin-left:75%}.column.is-10-desktop{flex:none;width:83.33333337%}.column.is-offset-10-desktop{margin-left:83.33333337%}.column.is-11-desktop{flex:none;width:91.66666674%}.column.is-offset-11-desktop{margin-left:91.66666674%}.column.is-12-desktop{flex:none;width:100%}.column.is-offset-12-desktop{margin-left:100%}}@media screen and (min-width: 1216px){.column.is-narrow-widescreen{flex:none;width:unset}.column.is-full-widescreen{flex:none;width:100%}.column.is-three-quarters-widescreen{flex:none;width:75%}.column.is-two-thirds-widescreen{flex:none;width:66.6666%}.column.is-half-widescreen{flex:none;width:50%}.column.is-one-third-widescreen{flex:none;width:33.3333%}.column.is-one-quarter-widescreen{flex:none;width:25%}.column.is-one-fifth-widescreen{flex:none;width:20%}.column.is-two-fifths-widescreen{flex:none;width:40%}.column.is-three-fifths-widescreen{flex:none;width:60%}.column.is-four-fifths-widescreen{flex:none;width:80%}.column.is-offset-three-quarters-widescreen{margin-left:75%}.column.is-offset-two-thirds-widescreen{margin-left:66.6666%}.column.is-offset-half-widescreen{margin-left:50%}.column.is-offset-one-third-widescreen{margin-left:33.3333%}.column.is-offset-one-quarter-widescreen{margin-left:25%}.column.is-offset-one-fifth-widescreen{margin-left:20%}.column.is-offset-two-fifths-widescreen{margin-left:40%}.column.is-offset-three-fifths-widescreen{margin-left:60%}.column.is-offset-four-fifths-widescreen{margin-left:80%}.column.is-0-widescreen{flex:none;width:0%}.column.is-offset-0-widescreen{margin-left:0%}.column.is-1-widescreen{flex:none;width:8.33333337%}.column.is-offset-1-widescreen{margin-left:8.33333337%}.column.is-2-widescreen{flex:none;width:16.66666674%}.column.is-offset-2-widescreen{margin-left:16.66666674%}.column.is-3-widescreen{flex:none;width:25%}.column.is-offset-3-widescreen{margin-left:25%}.column.is-4-widescreen{flex:none;width:33.33333337%}.column.is-offset-4-widescreen{margin-left:33.33333337%}.column.is-5-widescreen{flex:none;width:41.66666674%}.column.is-offset-5-widescreen{margin-left:41.66666674%}.column.is-6-widescreen{flex:none;width:50%}.column.is-offset-6-widescreen{margin-left:50%}.column.is-7-widescreen{flex:none;width:58.33333337%}.column.is-offset-7-widescreen{margin-left:58.33333337%}.column.is-8-widescreen{flex:none;width:66.66666674%}.column.is-offset-8-widescreen{margin-left:66.66666674%}.column.is-9-widescreen{flex:none;width:75%}.column.is-offset-9-widescreen{margin-left:75%}.column.is-10-widescreen{flex:none;width:83.33333337%}.column.is-offset-10-widescreen{margin-left:83.33333337%}.column.is-11-widescreen{flex:none;width:91.66666674%}.column.is-offset-11-widescreen{margin-left:91.66666674%}.column.is-12-widescreen{flex:none;width:100%}.column.is-offset-12-widescreen{margin-left:100%}}@media screen and (min-width: 1408px){.column.is-narrow-fullhd{flex:none;width:unset}.column.is-full-fullhd{flex:none;width:100%}.column.is-three-quarters-fullhd{flex:none;width:75%}.column.is-two-thirds-fullhd{flex:none;width:66.6666%}.column.is-half-fullhd{flex:none;width:50%}.column.is-one-third-fullhd{flex:none;width:33.3333%}.column.is-one-quarter-fullhd{flex:none;width:25%}.column.is-one-fifth-fullhd{flex:none;width:20%}.column.is-two-fifths-fullhd{flex:none;width:40%}.column.is-three-fifths-fullhd{flex:none;width:60%}.column.is-four-fifths-fullhd{flex:none;width:80%}.column.is-offset-three-quarters-fullhd{margin-left:75%}.column.is-offset-two-thirds-fullhd{margin-left:66.6666%}.column.is-offset-half-fullhd{margin-left:50%}.column.is-offset-one-third-fullhd{margin-left:33.3333%}.column.is-offset-one-quarter-fullhd{margin-left:25%}.column.is-offset-one-fifth-fullhd{margin-left:20%}.column.is-offset-two-fifths-fullhd{margin-left:40%}.column.is-offset-three-fifths-fullhd{margin-left:60%}.column.is-offset-four-fifths-fullhd{margin-left:80%}.column.is-0-fullhd{flex:none;width:0%}.column.is-offset-0-fullhd{margin-left:0%}.column.is-1-fullhd{flex:none;width:8.33333337%}.column.is-offset-1-fullhd{margin-left:8.33333337%}.column.is-2-fullhd{flex:none;width:16.66666674%}.column.is-offset-2-fullhd{margin-left:16.66666674%}.column.is-3-fullhd{flex:none;width:25%}.column.is-offset-3-fullhd{margin-left:25%}.column.is-4-fullhd{flex:none;width:33.33333337%}.column.is-offset-4-fullhd{margin-left:33.33333337%}.column.is-5-fullhd{flex:none;width:41.66666674%}.column.is-offset-5-fullhd{margin-left:41.66666674%}.column.is-6-fullhd{flex:none;width:50%}.column.is-offset-6-fullhd{margin-left:50%}.column.is-7-fullhd{flex:none;width:58.33333337%}.column.is-offset-7-fullhd{margin-left:58.33333337%}.column.is-8-fullhd{flex:none;width:66.66666674%}.column.is-offset-8-fullhd{margin-left:66.66666674%}.column.is-9-fullhd{flex:none;width:75%}.column.is-offset-9-fullhd{margin-left:75%}.column.is-10-fullhd{flex:none;width:83.33333337%}.column.is-offset-10-fullhd{margin-left:83.33333337%}.column.is-11-fullhd{flex:none;width:91.66666674%}.column.is-offset-11-fullhd{margin-left:91.66666674%}.column.is-12-fullhd{flex:none;width:100%}.column.is-offset-12-fullhd{margin-left:100%}}.columns{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}.columns:last-child{margin-bottom:-.75rem}.columns:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}.columns.is-centered{justify-content:center}.columns.is-gapless{margin-left:0;margin-right:0;margin-top:0}.columns.is-gapless>.column{margin:0;padding:0 !important}.columns.is-gapless:not(:last-child){margin-bottom:1.5rem}.columns.is-gapless:last-child{margin-bottom:0}.columns.is-mobile{display:flex}.columns.is-multiline{flex-wrap:wrap}.columns.is-vcentered{align-items:center}@media screen and (min-width: 769px),print{.columns:not(.is-desktop){display:flex}}@media screen and (min-width: 1056px){.columns.is-desktop{display:flex}}.columns.is-variable{--columnGap: 0.75rem;margin-left:calc(-1 * var(--columnGap));margin-right:calc(-1 * var(--columnGap))}.columns.is-variable>.column{padding-left:var(--columnGap);padding-right:var(--columnGap)}.columns.is-variable.is-0{--columnGap: 0rem}@media screen and (max-width: 768px){.columns.is-variable.is-0-mobile{--columnGap: 0rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-0-tablet{--columnGap: 0rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-0-tablet-only{--columnGap: 0rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-0-touch{--columnGap: 0rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-0-desktop{--columnGap: 0rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-0-desktop-only{--columnGap: 0rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-0-widescreen{--columnGap: 0rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-0-widescreen-only{--columnGap: 0rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-0-fullhd{--columnGap: 0rem}}.columns.is-variable.is-1{--columnGap: .25rem}@media screen and (max-width: 768px){.columns.is-variable.is-1-mobile{--columnGap: .25rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-1-tablet{--columnGap: .25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-1-tablet-only{--columnGap: .25rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-1-touch{--columnGap: .25rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-1-desktop{--columnGap: .25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-1-desktop-only{--columnGap: .25rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-1-widescreen{--columnGap: .25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-1-widescreen-only{--columnGap: .25rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-1-fullhd{--columnGap: .25rem}}.columns.is-variable.is-2{--columnGap: .5rem}@media screen and (max-width: 768px){.columns.is-variable.is-2-mobile{--columnGap: .5rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-2-tablet{--columnGap: .5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-2-tablet-only{--columnGap: .5rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-2-touch{--columnGap: .5rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-2-desktop{--columnGap: .5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-2-desktop-only{--columnGap: .5rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-2-widescreen{--columnGap: .5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-2-widescreen-only{--columnGap: .5rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-2-fullhd{--columnGap: .5rem}}.columns.is-variable.is-3{--columnGap: .75rem}@media screen and (max-width: 768px){.columns.is-variable.is-3-mobile{--columnGap: .75rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-3-tablet{--columnGap: .75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-3-tablet-only{--columnGap: .75rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-3-touch{--columnGap: .75rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-3-desktop{--columnGap: .75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-3-desktop-only{--columnGap: .75rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-3-widescreen{--columnGap: .75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-3-widescreen-only{--columnGap: .75rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-3-fullhd{--columnGap: .75rem}}.columns.is-variable.is-4{--columnGap: 1rem}@media screen and (max-width: 768px){.columns.is-variable.is-4-mobile{--columnGap: 1rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-4-tablet{--columnGap: 1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-4-tablet-only{--columnGap: 1rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-4-touch{--columnGap: 1rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-4-desktop{--columnGap: 1rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-4-desktop-only{--columnGap: 1rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-4-widescreen{--columnGap: 1rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-4-widescreen-only{--columnGap: 1rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-4-fullhd{--columnGap: 1rem}}.columns.is-variable.is-5{--columnGap: 1.25rem}@media screen and (max-width: 768px){.columns.is-variable.is-5-mobile{--columnGap: 1.25rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-5-tablet{--columnGap: 1.25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-5-tablet-only{--columnGap: 1.25rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-5-touch{--columnGap: 1.25rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-5-desktop{--columnGap: 1.25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-5-desktop-only{--columnGap: 1.25rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-5-widescreen{--columnGap: 1.25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-5-widescreen-only{--columnGap: 1.25rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-5-fullhd{--columnGap: 1.25rem}}.columns.is-variable.is-6{--columnGap: 1.5rem}@media screen and (max-width: 768px){.columns.is-variable.is-6-mobile{--columnGap: 1.5rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-6-tablet{--columnGap: 1.5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-6-tablet-only{--columnGap: 1.5rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-6-touch{--columnGap: 1.5rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-6-desktop{--columnGap: 1.5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-6-desktop-only{--columnGap: 1.5rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-6-widescreen{--columnGap: 1.5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-6-widescreen-only{--columnGap: 1.5rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-6-fullhd{--columnGap: 1.5rem}}.columns.is-variable.is-7{--columnGap: 1.75rem}@media screen and (max-width: 768px){.columns.is-variable.is-7-mobile{--columnGap: 1.75rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-7-tablet{--columnGap: 1.75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-7-tablet-only{--columnGap: 1.75rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-7-touch{--columnGap: 1.75rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-7-desktop{--columnGap: 1.75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-7-desktop-only{--columnGap: 1.75rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-7-widescreen{--columnGap: 1.75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-7-widescreen-only{--columnGap: 1.75rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-7-fullhd{--columnGap: 1.75rem}}.columns.is-variable.is-8{--columnGap: 2rem}@media screen and (max-width: 768px){.columns.is-variable.is-8-mobile{--columnGap: 2rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-8-tablet{--columnGap: 2rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-8-tablet-only{--columnGap: 2rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-8-touch{--columnGap: 2rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-8-desktop{--columnGap: 2rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-8-desktop-only{--columnGap: 2rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-8-widescreen{--columnGap: 2rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-8-widescreen-only{--columnGap: 2rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-8-fullhd{--columnGap: 2rem}}.tile{align-items:stretch;display:block;flex-basis:0;flex-grow:1;flex-shrink:1;min-height:min-content}.tile.is-ancestor{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}.tile.is-ancestor:last-child{margin-bottom:-.75rem}.tile.is-ancestor:not(:last-child){margin-bottom:.75rem}.tile.is-child{margin:0 !important}.tile.is-parent{padding:.75rem}.tile.is-vertical{flex-direction:column}.tile.is-vertical>.tile.is-child:not(:last-child){margin-bottom:1.5rem !important}@media screen and (min-width: 769px),print{.tile:not(.is-child){display:flex}.tile.is-1{flex:none;width:8.33333337%}.tile.is-2{flex:none;width:16.66666674%}.tile.is-3{flex:none;width:25%}.tile.is-4{flex:none;width:33.33333337%}.tile.is-5{flex:none;width:41.66666674%}.tile.is-6{flex:none;width:50%}.tile.is-7{flex:none;width:58.33333337%}.tile.is-8{flex:none;width:66.66666674%}.tile.is-9{flex:none;width:75%}.tile.is-10{flex:none;width:83.33333337%}.tile.is-11{flex:none;width:91.66666674%}.tile.is-12{flex:none;width:100%}}.hero{align-items:stretch;display:flex;flex-direction:column;justify-content:space-between}.hero .navbar{background:none}.hero .tabs ul{border-bottom:none}.hero.is-white{background-color:#fff;color:#0a0a0a}.hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-white strong{color:inherit}.hero.is-white .title{color:#0a0a0a}.hero.is-white .subtitle{color:rgba(10,10,10,0.9)}.hero.is-white .subtitle a:not(.button),.hero.is-white .subtitle strong{color:#0a0a0a}@media screen and (max-width: 1055px){.hero.is-white .navbar-menu{background-color:#fff}}.hero.is-white .navbar-item,.hero.is-white .navbar-link{color:rgba(10,10,10,0.7)}.hero.is-white a.navbar-item:hover,.hero.is-white a.navbar-item.is-active,.hero.is-white .navbar-link:hover,.hero.is-white .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}.hero.is-white .tabs a{color:#0a0a0a;opacity:0.9}.hero.is-white .tabs a:hover{opacity:1}.hero.is-white .tabs li.is-active a{color:#fff !important;opacity:1}.hero.is-white .tabs.is-boxed a,.hero.is-white .tabs.is-toggle a{color:#0a0a0a}.hero.is-white .tabs.is-boxed a:hover,.hero.is-white .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-white .tabs.is-boxed li.is-active a,.hero.is-white .tabs.is-boxed li.is-active a:hover,.hero.is-white .tabs.is-toggle li.is-active a,.hero.is-white .tabs.is-toggle li.is-active a:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.hero.is-white.is-bold{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}@media screen and (max-width: 768px){.hero.is-white.is-bold .navbar-menu{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}}.hero.is-black{background-color:#0a0a0a;color:#fff}.hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-black strong{color:inherit}.hero.is-black .title{color:#fff}.hero.is-black .subtitle{color:rgba(255,255,255,0.9)}.hero.is-black .subtitle a:not(.button),.hero.is-black .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-black .navbar-menu{background-color:#0a0a0a}}.hero.is-black .navbar-item,.hero.is-black .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-black a.navbar-item:hover,.hero.is-black a.navbar-item.is-active,.hero.is-black .navbar-link:hover,.hero.is-black .navbar-link.is-active{background-color:#000;color:#fff}.hero.is-black .tabs a{color:#fff;opacity:0.9}.hero.is-black .tabs a:hover{opacity:1}.hero.is-black .tabs li.is-active a{color:#0a0a0a !important;opacity:1}.hero.is-black .tabs.is-boxed a,.hero.is-black .tabs.is-toggle a{color:#fff}.hero.is-black .tabs.is-boxed a:hover,.hero.is-black .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-black .tabs.is-boxed li.is-active a,.hero.is-black .tabs.is-boxed li.is-active a:hover,.hero.is-black .tabs.is-toggle li.is-active a,.hero.is-black .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}.hero.is-black.is-bold{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}@media screen and (max-width: 768px){.hero.is-black.is-bold .navbar-menu{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}}.hero.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-light strong{color:inherit}.hero.is-light .title{color:rgba(0,0,0,0.7)}.hero.is-light .subtitle{color:rgba(0,0,0,0.9)}.hero.is-light .subtitle a:not(.button),.hero.is-light .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){.hero.is-light .navbar-menu{background-color:#f5f5f5}}.hero.is-light .navbar-item,.hero.is-light .navbar-link{color:rgba(0,0,0,0.7)}.hero.is-light a.navbar-item:hover,.hero.is-light a.navbar-item.is-active,.hero.is-light .navbar-link:hover,.hero.is-light .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.hero.is-light .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}.hero.is-light .tabs a:hover{opacity:1}.hero.is-light .tabs li.is-active a{color:#f5f5f5 !important;opacity:1}.hero.is-light .tabs.is-boxed a,.hero.is-light .tabs.is-toggle a{color:rgba(0,0,0,0.7)}.hero.is-light .tabs.is-boxed a:hover,.hero.is-light .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-light .tabs.is-boxed li.is-active a,.hero.is-light .tabs.is-boxed li.is-active a:hover,.hero.is-light .tabs.is-toggle li.is-active a,.hero.is-light .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#f5f5f5}.hero.is-light.is-bold{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}@media screen and (max-width: 768px){.hero.is-light.is-bold .navbar-menu{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}}.hero.is-dark,.content kbd.hero{background-color:#363636;color:#fff}.hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.content kbd.hero a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-dark strong,.content kbd.hero strong{color:inherit}.hero.is-dark .title,.content kbd.hero .title{color:#fff}.hero.is-dark .subtitle,.content kbd.hero .subtitle{color:rgba(255,255,255,0.9)}.hero.is-dark .subtitle a:not(.button),.content kbd.hero .subtitle a:not(.button),.hero.is-dark .subtitle strong,.content kbd.hero .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-dark .navbar-menu,.content kbd.hero .navbar-menu{background-color:#363636}}.hero.is-dark .navbar-item,.content kbd.hero .navbar-item,.hero.is-dark .navbar-link,.content kbd.hero .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-dark a.navbar-item:hover,.content kbd.hero a.navbar-item:hover,.hero.is-dark a.navbar-item.is-active,.content kbd.hero a.navbar-item.is-active,.hero.is-dark .navbar-link:hover,.content kbd.hero .navbar-link:hover,.hero.is-dark .navbar-link.is-active,.content kbd.hero .navbar-link.is-active{background-color:#292929;color:#fff}.hero.is-dark .tabs a,.content kbd.hero .tabs a{color:#fff;opacity:0.9}.hero.is-dark .tabs a:hover,.content kbd.hero .tabs a:hover{opacity:1}.hero.is-dark .tabs li.is-active a,.content kbd.hero .tabs li.is-active a{color:#363636 !important;opacity:1}.hero.is-dark .tabs.is-boxed a,.content kbd.hero .tabs.is-boxed a,.hero.is-dark .tabs.is-toggle a,.content kbd.hero .tabs.is-toggle a{color:#fff}.hero.is-dark .tabs.is-boxed a:hover,.content kbd.hero .tabs.is-boxed a:hover,.hero.is-dark .tabs.is-toggle a:hover,.content kbd.hero .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-dark .tabs.is-boxed li.is-active a,.content kbd.hero .tabs.is-boxed li.is-active a,.hero.is-dark .tabs.is-boxed li.is-active a:hover,.hero.is-dark .tabs.is-toggle li.is-active a,.content kbd.hero .tabs.is-toggle li.is-active a,.hero.is-dark .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#363636}.hero.is-dark.is-bold,.content kbd.hero.is-bold{background-image:linear-gradient(141deg, #1f191a 0%, #363636 71%, #46403f 100%)}@media screen and (max-width: 768px){.hero.is-dark.is-bold .navbar-menu,.content kbd.hero.is-bold .navbar-menu{background-image:linear-gradient(141deg, #1f191a 0%, #363636 71%, #46403f 100%)}}.hero.is-primary,.docstring>section>a.hero.docs-sourcelink{background-color:#4eb5de;color:#fff}.hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.docstring>section>a.hero.docs-sourcelink a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-primary strong,.docstring>section>a.hero.docs-sourcelink strong{color:inherit}.hero.is-primary .title,.docstring>section>a.hero.docs-sourcelink .title{color:#fff}.hero.is-primary .subtitle,.docstring>section>a.hero.docs-sourcelink .subtitle{color:rgba(255,255,255,0.9)}.hero.is-primary .subtitle a:not(.button),.docstring>section>a.hero.docs-sourcelink .subtitle a:not(.button),.hero.is-primary .subtitle strong,.docstring>section>a.hero.docs-sourcelink .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-primary .navbar-menu,.docstring>section>a.hero.docs-sourcelink .navbar-menu{background-color:#4eb5de}}.hero.is-primary .navbar-item,.docstring>section>a.hero.docs-sourcelink .navbar-item,.hero.is-primary .navbar-link,.docstring>section>a.hero.docs-sourcelink .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-primary a.navbar-item:hover,.docstring>section>a.hero.docs-sourcelink a.navbar-item:hover,.hero.is-primary a.navbar-item.is-active,.docstring>section>a.hero.docs-sourcelink a.navbar-item.is-active,.hero.is-primary .navbar-link:hover,.docstring>section>a.hero.docs-sourcelink .navbar-link:hover,.hero.is-primary .navbar-link.is-active,.docstring>section>a.hero.docs-sourcelink .navbar-link.is-active{background-color:#39acda;color:#fff}.hero.is-primary .tabs a,.docstring>section>a.hero.docs-sourcelink .tabs a{color:#fff;opacity:0.9}.hero.is-primary .tabs a:hover,.docstring>section>a.hero.docs-sourcelink .tabs a:hover{opacity:1}.hero.is-primary .tabs li.is-active a,.docstring>section>a.hero.docs-sourcelink .tabs li.is-active a{color:#4eb5de !important;opacity:1}.hero.is-primary .tabs.is-boxed a,.docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a,.hero.is-primary .tabs.is-toggle a,.docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a{color:#fff}.hero.is-primary .tabs.is-boxed a:hover,.docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a:hover,.hero.is-primary .tabs.is-toggle a:hover,.docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-primary .tabs.is-boxed li.is-active a,.docstring>section>a.hero.docs-sourcelink .tabs.is-boxed li.is-active a,.hero.is-primary .tabs.is-boxed li.is-active a:hover,.hero.is-primary .tabs.is-toggle li.is-active a,.docstring>section>a.hero.docs-sourcelink .tabs.is-toggle li.is-active a,.hero.is-primary .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#4eb5de}.hero.is-primary.is-bold,.docstring>section>a.hero.is-bold.docs-sourcelink{background-image:linear-gradient(141deg, #1bc7de 0%, #4eb5de 71%, #5fa9e7 100%)}@media screen and (max-width: 768px){.hero.is-primary.is-bold .navbar-menu,.docstring>section>a.hero.is-bold.docs-sourcelink .navbar-menu{background-image:linear-gradient(141deg, #1bc7de 0%, #4eb5de 71%, #5fa9e7 100%)}}.hero.is-link{background-color:#2e63b8;color:#fff}.hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-link strong{color:inherit}.hero.is-link .title{color:#fff}.hero.is-link .subtitle{color:rgba(255,255,255,0.9)}.hero.is-link .subtitle a:not(.button),.hero.is-link .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-link .navbar-menu{background-color:#2e63b8}}.hero.is-link .navbar-item,.hero.is-link .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-link a.navbar-item:hover,.hero.is-link a.navbar-item.is-active,.hero.is-link .navbar-link:hover,.hero.is-link .navbar-link.is-active{background-color:#2958a4;color:#fff}.hero.is-link .tabs a{color:#fff;opacity:0.9}.hero.is-link .tabs a:hover{opacity:1}.hero.is-link .tabs li.is-active a{color:#2e63b8 !important;opacity:1}.hero.is-link .tabs.is-boxed a,.hero.is-link .tabs.is-toggle a{color:#fff}.hero.is-link .tabs.is-boxed a:hover,.hero.is-link .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-link .tabs.is-boxed li.is-active a,.hero.is-link .tabs.is-boxed li.is-active a:hover,.hero.is-link .tabs.is-toggle li.is-active a,.hero.is-link .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#2e63b8}.hero.is-link.is-bold{background-image:linear-gradient(141deg, #1b6098 0%, #2e63b8 71%, #2d51d2 100%)}@media screen and (max-width: 768px){.hero.is-link.is-bold .navbar-menu{background-image:linear-gradient(141deg, #1b6098 0%, #2e63b8 71%, #2d51d2 100%)}}.hero.is-info{background-color:#3c5dcd;color:#fff}.hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-info strong{color:inherit}.hero.is-info .title{color:#fff}.hero.is-info .subtitle{color:rgba(255,255,255,0.9)}.hero.is-info .subtitle a:not(.button),.hero.is-info .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-info .navbar-menu{background-color:#3c5dcd}}.hero.is-info .navbar-item,.hero.is-info .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-info a.navbar-item:hover,.hero.is-info a.navbar-item.is-active,.hero.is-info .navbar-link:hover,.hero.is-info .navbar-link.is-active{background-color:#3151bf;color:#fff}.hero.is-info .tabs a{color:#fff;opacity:0.9}.hero.is-info .tabs a:hover{opacity:1}.hero.is-info .tabs li.is-active a{color:#3c5dcd !important;opacity:1}.hero.is-info .tabs.is-boxed a,.hero.is-info .tabs.is-toggle a{color:#fff}.hero.is-info .tabs.is-boxed a:hover,.hero.is-info .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-info .tabs.is-boxed li.is-active a,.hero.is-info .tabs.is-boxed li.is-active a:hover,.hero.is-info .tabs.is-toggle li.is-active a,.hero.is-info .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#3c5dcd}.hero.is-info.is-bold{background-image:linear-gradient(141deg, #215bb5 0%, #3c5dcd 71%, #4b53d8 100%)}@media screen and (max-width: 768px){.hero.is-info.is-bold .navbar-menu{background-image:linear-gradient(141deg, #215bb5 0%, #3c5dcd 71%, #4b53d8 100%)}}.hero.is-success{background-color:#259a12;color:#fff}.hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-success strong{color:inherit}.hero.is-success .title{color:#fff}.hero.is-success .subtitle{color:rgba(255,255,255,0.9)}.hero.is-success .subtitle a:not(.button),.hero.is-success .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-success .navbar-menu{background-color:#259a12}}.hero.is-success .navbar-item,.hero.is-success .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-success a.navbar-item:hover,.hero.is-success a.navbar-item.is-active,.hero.is-success .navbar-link:hover,.hero.is-success .navbar-link.is-active{background-color:#20830f;color:#fff}.hero.is-success .tabs a{color:#fff;opacity:0.9}.hero.is-success .tabs a:hover{opacity:1}.hero.is-success .tabs li.is-active a{color:#259a12 !important;opacity:1}.hero.is-success .tabs.is-boxed a,.hero.is-success .tabs.is-toggle a{color:#fff}.hero.is-success .tabs.is-boxed a:hover,.hero.is-success .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-success .tabs.is-boxed li.is-active a,.hero.is-success .tabs.is-boxed li.is-active a:hover,.hero.is-success .tabs.is-toggle li.is-active a,.hero.is-success .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#259a12}.hero.is-success.is-bold{background-image:linear-gradient(141deg, #287207 0%, #259a12 71%, #10b614 100%)}@media screen and (max-width: 768px){.hero.is-success.is-bold .navbar-menu{background-image:linear-gradient(141deg, #287207 0%, #259a12 71%, #10b614 100%)}}.hero.is-warning{background-color:#a98800;color:#fff}.hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-warning strong{color:inherit}.hero.is-warning .title{color:#fff}.hero.is-warning .subtitle{color:rgba(255,255,255,0.9)}.hero.is-warning .subtitle a:not(.button),.hero.is-warning .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-warning .navbar-menu{background-color:#a98800}}.hero.is-warning .navbar-item,.hero.is-warning .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-warning a.navbar-item:hover,.hero.is-warning a.navbar-item.is-active,.hero.is-warning .navbar-link:hover,.hero.is-warning .navbar-link.is-active{background-color:#8f7300;color:#fff}.hero.is-warning .tabs a{color:#fff;opacity:0.9}.hero.is-warning .tabs a:hover{opacity:1}.hero.is-warning .tabs li.is-active a{color:#a98800 !important;opacity:1}.hero.is-warning .tabs.is-boxed a,.hero.is-warning .tabs.is-toggle a{color:#fff}.hero.is-warning .tabs.is-boxed a:hover,.hero.is-warning .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-warning .tabs.is-boxed li.is-active a,.hero.is-warning .tabs.is-boxed li.is-active a:hover,.hero.is-warning .tabs.is-toggle li.is-active a,.hero.is-warning .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#a98800}.hero.is-warning.is-bold{background-image:linear-gradient(141deg, #764b00 0%, #a98800 71%, #c2bd00 100%)}@media screen and (max-width: 768px){.hero.is-warning.is-bold .navbar-menu{background-image:linear-gradient(141deg, #764b00 0%, #a98800 71%, #c2bd00 100%)}}.hero.is-danger{background-color:#cb3c33;color:#fff}.hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-danger strong{color:inherit}.hero.is-danger .title{color:#fff}.hero.is-danger .subtitle{color:rgba(255,255,255,0.9)}.hero.is-danger .subtitle a:not(.button),.hero.is-danger .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-danger .navbar-menu{background-color:#cb3c33}}.hero.is-danger .navbar-item,.hero.is-danger .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-danger a.navbar-item:hover,.hero.is-danger a.navbar-item.is-active,.hero.is-danger .navbar-link:hover,.hero.is-danger .navbar-link.is-active{background-color:#b7362e;color:#fff}.hero.is-danger .tabs a{color:#fff;opacity:0.9}.hero.is-danger .tabs a:hover{opacity:1}.hero.is-danger .tabs li.is-active a{color:#cb3c33 !important;opacity:1}.hero.is-danger .tabs.is-boxed a,.hero.is-danger .tabs.is-toggle a{color:#fff}.hero.is-danger .tabs.is-boxed a:hover,.hero.is-danger .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-danger .tabs.is-boxed li.is-active a,.hero.is-danger .tabs.is-boxed li.is-active a:hover,.hero.is-danger .tabs.is-toggle li.is-active a,.hero.is-danger .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#cb3c33}.hero.is-danger.is-bold{background-image:linear-gradient(141deg, #ac1f2e 0%, #cb3c33 71%, #d66341 100%)}@media screen and (max-width: 768px){.hero.is-danger.is-bold .navbar-menu{background-image:linear-gradient(141deg, #ac1f2e 0%, #cb3c33 71%, #d66341 100%)}}.hero.is-small .hero-body,#documenter .docs-sidebar form.docs-search>input.hero .hero-body{padding:1.5rem}@media screen and (min-width: 769px),print{.hero.is-medium .hero-body{padding:9rem 4.5rem}}@media screen and (min-width: 769px),print{.hero.is-large .hero-body{padding:18rem 6rem}}.hero.is-halfheight .hero-body,.hero.is-fullheight .hero-body,.hero.is-fullheight-with-navbar .hero-body{align-items:center;display:flex}.hero.is-halfheight .hero-body>.container,.hero.is-fullheight .hero-body>.container,.hero.is-fullheight-with-navbar .hero-body>.container{flex-grow:1;flex-shrink:1}.hero.is-halfheight{min-height:50vh}.hero.is-fullheight{min-height:100vh}.hero-video{overflow:hidden}.hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;transform:translate3d(-50%, -50%, 0)}.hero-video.is-transparent{opacity:0.3}@media screen and (max-width: 768px){.hero-video{display:none}}.hero-buttons{margin-top:1.5rem}@media screen and (max-width: 768px){.hero-buttons .button{display:flex}.hero-buttons .button:not(:last-child){margin-bottom:0.75rem}}@media screen and (min-width: 769px),print{.hero-buttons{display:flex;justify-content:center}.hero-buttons .button:not(:last-child){margin-right:1.5rem}}.hero-head,.hero-foot{flex-grow:0;flex-shrink:0}.hero-body{flex-grow:1;flex-shrink:0;padding:3rem 1.5rem}@media screen and (min-width: 769px),print{.hero-body{padding:3rem 3rem}}.section{padding:3rem 1.5rem}@media screen and (min-width: 1056px){.section{padding:3rem 3rem}.section.is-medium{padding:9rem 4.5rem}.section.is-large{padding:18rem 6rem}}.footer{background-color:#fafafa;padding:3rem 1.5rem 6rem}h1 .docs-heading-anchor,h1 .docs-heading-anchor:hover,h1 .docs-heading-anchor:visited,h2 .docs-heading-anchor,h2 .docs-heading-anchor:hover,h2 .docs-heading-anchor:visited,h3 .docs-heading-anchor,h3 .docs-heading-anchor:hover,h3 .docs-heading-anchor:visited,h4 .docs-heading-anchor,h4 .docs-heading-anchor:hover,h4 .docs-heading-anchor:visited,h5 .docs-heading-anchor,h5 .docs-heading-anchor:hover,h5 .docs-heading-anchor:visited,h6 .docs-heading-anchor,h6 .docs-heading-anchor:hover,h6 .docs-heading-anchor:visited{color:#222}h1 .docs-heading-anchor-permalink,h2 .docs-heading-anchor-permalink,h3 .docs-heading-anchor-permalink,h4 .docs-heading-anchor-permalink,h5 .docs-heading-anchor-permalink,h6 .docs-heading-anchor-permalink{visibility:hidden;vertical-align:middle;margin-left:0.5em;font-size:0.7rem}h1 .docs-heading-anchor-permalink::before,h2 .docs-heading-anchor-permalink::before,h3 .docs-heading-anchor-permalink::before,h4 .docs-heading-anchor-permalink::before,h5 .docs-heading-anchor-permalink::before,h6 .docs-heading-anchor-permalink::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f0c1"}h1:hover .docs-heading-anchor-permalink,h2:hover .docs-heading-anchor-permalink,h3:hover .docs-heading-anchor-permalink,h4:hover .docs-heading-anchor-permalink,h5:hover .docs-heading-anchor-permalink,h6:hover .docs-heading-anchor-permalink{visibility:visible}.docs-dark-only{display:none !important}pre{position:relative;overflow:hidden}pre code,pre code.hljs{padding:0 .75rem !important;overflow:auto;display:block}pre code:first-of-type,pre code.hljs:first-of-type{padding-top:0.5rem !important}pre code:last-of-type,pre code.hljs:last-of-type{padding-bottom:0.5rem !important}pre .copy-button{opacity:0.2;transition:opacity 0.2s;position:absolute;right:0em;top:0em;padding:0.5em;width:2.5em;height:2.5em;background:transparent;border:none;font-family:"Font Awesome 6 Free";color:#222;cursor:pointer;text-align:center}pre .copy-button:focus,pre .copy-button:hover{opacity:1;background:rgba(34,34,34,0.1);color:#2e63b8}pre .copy-button.success{color:#259a12;opacity:1}pre .copy-button.error{color:#cb3c33;opacity:1}pre:hover .copy-button{opacity:1}.admonition{background-color:#f5f5f5;border-style:solid;border-width:2px;border-color:#4a4a4a;border-radius:4px;font-size:1rem}.admonition strong{color:currentColor}.admonition.is-small,#documenter .docs-sidebar form.docs-search>input.admonition{font-size:.75rem}.admonition.is-medium{font-size:1.25rem}.admonition.is-large{font-size:1.5rem}.admonition.is-default{background-color:#f5f5f5;border-color:#4a4a4a}.admonition.is-default>.admonition-header{background-color:rgba(0,0,0,0);color:#4a4a4a}.admonition.is-default>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-info{background-color:#f5f5f5;border-color:#3c5dcd}.admonition.is-info>.admonition-header{background-color:rgba(0,0,0,0);color:#3c5dcd}.admonition.is-info>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-success{background-color:#f5f5f5;border-color:#259a12}.admonition.is-success>.admonition-header{background-color:rgba(0,0,0,0);color:#259a12}.admonition.is-success>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-warning{background-color:#f5f5f5;border-color:#a98800}.admonition.is-warning>.admonition-header{background-color:rgba(0,0,0,0);color:#a98800}.admonition.is-warning>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-danger{background-color:#f5f5f5;border-color:#cb3c33}.admonition.is-danger>.admonition-header{background-color:rgba(0,0,0,0);color:#cb3c33}.admonition.is-danger>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-compat{background-color:#f5f5f5;border-color:#3489da}.admonition.is-compat>.admonition-header{background-color:rgba(0,0,0,0);color:#3489da}.admonition.is-compat>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-todo{background-color:#f5f5f5;border-color:#9558b2}.admonition.is-todo>.admonition-header{background-color:rgba(0,0,0,0);color:#9558b2}.admonition.is-todo>.admonition-body{color:rgba(0,0,0,0.7)}.admonition-header{color:#4a4a4a;background-color:rgba(0,0,0,0);align-items:center;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.5rem .75rem;position:relative}.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;margin-right:.75rem;content:"\f06a"}details.admonition.is-details>.admonition-header{list-style:none}details.admonition.is-details>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f055"}details.admonition.is-details[open]>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f056"}.admonition-body{color:#222;padding:0.5rem .75rem}.admonition-body pre{background-color:#f5f5f5}.admonition-body code{background-color:rgba(0,0,0,0.05)}.docstring{margin-bottom:1em;background-color:rgba(0,0,0,0);border:2px solid #dbdbdb;border-radius:4px;box-shadow:2px 2px 3px rgba(10,10,10,0.1);max-width:100%}.docstring>header{cursor:pointer;display:flex;flex-grow:1;align-items:stretch;padding:0.5rem .75rem;background-color:#f5f5f5;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);box-shadow:none;border-bottom:1px solid #dbdbdb;overflow:auto}.docstring>header code{background-color:transparent}.docstring>header .docstring-article-toggle-button{min-width:1.1rem;padding:0.2rem 0.2rem 0.2rem 0}.docstring>header .docstring-binding{margin-right:0.3em}.docstring>header .docstring-category{margin-left:0.3em}.docstring>section{position:relative;padding:.75rem .75rem;border-bottom:1px solid #dbdbdb}.docstring>section:last-child{border-bottom:none}.docstring>section>a.docs-sourcelink{transition:opacity 0.3s;opacity:0;position:absolute;right:.375rem;bottom:.375rem}.docstring>section>a.docs-sourcelink:focus{opacity:1 !important}.docstring:hover>section>a.docs-sourcelink{opacity:0.2}.docstring:focus-within>section>a.docs-sourcelink{opacity:0.2}.docstring>section:hover a.docs-sourcelink{opacity:1}.documenter-example-output{background-color:#fff}.outdated-warning-overlay{position:fixed;top:0;left:0;right:0;box-shadow:0 0 10px rgba(0,0,0,0.3);z-index:999;background-color:#f5f5f5;color:rgba(0,0,0,0.7);border-bottom:3px solid rgba(0,0,0,0);padding:10px 35px;text-align:center;font-size:15px}.outdated-warning-overlay .outdated-warning-closer{position:absolute;top:calc(50% - 10px);right:18px;cursor:pointer;width:12px}.outdated-warning-overlay a{color:#2e63b8}.outdated-warning-overlay a:hover{color:#363636}.content pre{border:2px solid #dbdbdb;border-radius:4px}.content code{font-weight:inherit}.content a code{color:#2e63b8}.content a:hover code{color:#363636}.content h1 code,.content h2 code,.content h3 code,.content h4 code,.content h5 code,.content h6 code{color:#222}.content table{display:block;width:initial;max-width:100%;overflow-x:auto}.content blockquote>ul:first-child,.content blockquote>ol:first-child,.content .admonition-body>ul:first-child,.content .admonition-body>ol:first-child{margin-top:0}pre,code{font-variant-ligatures:no-contextual}.breadcrumb a.is-disabled{cursor:default;pointer-events:none}.breadcrumb a.is-disabled,.breadcrumb a.is-disabled:hover{color:#222}.hljs{background:initial !important}.katex .katex-mathml{top:0;right:0}.katex-display,mjx-container,.MathJax_Display{margin:0.5em 0 !important}html{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto}li.no-marker{list-style:none}#documenter .docs-main>article{overflow-wrap:break-word}#documenter .docs-main>article .math-container{overflow-x:auto;overflow-y:hidden}@media screen and (min-width: 1056px){#documenter .docs-main{max-width:52rem;margin-left:20rem;padding-right:1rem}}@media screen and (max-width: 1055px){#documenter .docs-main{width:100%}#documenter .docs-main>article{max-width:52rem;margin-left:auto;margin-right:auto;margin-bottom:1rem;padding:0 1rem}#documenter .docs-main>header,#documenter .docs-main>nav{max-width:100%;width:100%;margin:0}}#documenter .docs-main header.docs-navbar{background-color:#fff;border-bottom:1px solid #dbdbdb;z-index:2;min-height:4rem;margin-bottom:1rem;display:flex}#documenter .docs-main header.docs-navbar .breadcrumb{flex-grow:1;overflow-x:hidden}#documenter .docs-main header.docs-navbar .docs-sidebar-button{display:block;font-size:1.5rem;padding-bottom:0.1rem;margin-right:1rem}#documenter .docs-main header.docs-navbar .docs-right{display:flex;white-space:nowrap;gap:1rem;align-items:center}#documenter .docs-main header.docs-navbar .docs-right .docs-icon,#documenter .docs-main header.docs-navbar .docs-right .docs-label{display:inline-block}#documenter .docs-main header.docs-navbar .docs-right .docs-label{padding:0;margin-left:0.3em}@media screen and (max-width: 1055px){#documenter .docs-main header.docs-navbar .docs-right .docs-navbar-link{margin-left:0.4rem;margin-right:0.4rem}}#documenter .docs-main header.docs-navbar>*{margin:auto 0}@media screen and (max-width: 1055px){#documenter .docs-main header.docs-navbar{position:sticky;top:0;padding:0 1rem;transition-property:top, box-shadow;-webkit-transition-property:top, box-shadow;transition-duration:0.3s;-webkit-transition-duration:0.3s}#documenter .docs-main header.docs-navbar.headroom--not-top{box-shadow:.2rem 0rem .4rem #bbb;transition-duration:0.7s;-webkit-transition-duration:0.7s}#documenter .docs-main header.docs-navbar.headroom--unpinned.headroom--not-top.headroom--not-bottom{top:-4.5rem;transition-duration:0.7s;-webkit-transition-duration:0.7s}}#documenter .docs-main section.footnotes{border-top:1px solid #dbdbdb}#documenter .docs-main section.footnotes li .tag:first-child,#documenter .docs-main section.footnotes li .docstring>section>a.docs-sourcelink:first-child,#documenter .docs-main section.footnotes li .content kbd:first-child,.content #documenter .docs-main section.footnotes li kbd:first-child{margin-right:1em;margin-bottom:0.4em}#documenter .docs-main .docs-footer{display:flex;flex-wrap:wrap;margin-left:0;margin-right:0;border-top:1px solid #dbdbdb;padding-top:1rem;padding-bottom:1rem}@media screen and (max-width: 1055px){#documenter .docs-main .docs-footer{padding-left:1rem;padding-right:1rem}}#documenter .docs-main .docs-footer .docs-footer-nextpage,#documenter .docs-main .docs-footer .docs-footer-prevpage{flex-grow:1}#documenter .docs-main .docs-footer .docs-footer-nextpage{text-align:right}#documenter .docs-main .docs-footer .flexbox-break{flex-basis:100%;height:0}#documenter .docs-main .docs-footer .footer-message{font-size:0.8em;margin:0.5em auto 0 auto;text-align:center}#documenter .docs-sidebar{display:flex;flex-direction:column;color:#0a0a0a;background-color:#f5f5f5;border-right:1px solid #dbdbdb;padding:0;flex:0 0 18rem;z-index:5;font-size:1rem;position:fixed;left:-18rem;width:18rem;height:100%;transition:left 0.3s}#documenter .docs-sidebar.visible{left:0;box-shadow:.4rem 0rem .8rem #bbb}@media screen and (min-width: 1056px){#documenter .docs-sidebar.visible{box-shadow:none}}@media screen and (min-width: 1056px){#documenter .docs-sidebar{left:0;top:0}}#documenter .docs-sidebar .docs-logo{margin-top:1rem;padding:0 1rem}#documenter .docs-sidebar .docs-logo>img{max-height:6rem;margin:auto}#documenter .docs-sidebar .docs-package-name{flex-shrink:0;font-size:1.5rem;font-weight:700;text-align:center;white-space:nowrap;overflow:hidden;padding:0.5rem 0}#documenter .docs-sidebar .docs-package-name .docs-autofit{max-width:16.2rem}#documenter .docs-sidebar .docs-package-name a,#documenter .docs-sidebar .docs-package-name a:hover{color:#0a0a0a}#documenter .docs-sidebar .docs-version-selector{border-top:1px solid #dbdbdb;display:none;padding:0.5rem}#documenter .docs-sidebar .docs-version-selector.visible{display:flex}#documenter .docs-sidebar ul.docs-menu{flex-grow:1;user-select:none;border-top:1px solid #dbdbdb;padding-bottom:1.5rem}#documenter .docs-sidebar ul.docs-menu>li>.tocitem{font-weight:bold}#documenter .docs-sidebar ul.docs-menu>li li{font-size:.95rem;margin-left:1em;border-left:1px solid #dbdbdb}#documenter .docs-sidebar ul.docs-menu input.collapse-toggle{display:none}#documenter .docs-sidebar ul.docs-menu ul.collapsed{display:none}#documenter .docs-sidebar ul.docs-menu input:checked~ul.collapsed{display:block}#documenter .docs-sidebar ul.docs-menu label.tocitem{display:flex}#documenter .docs-sidebar ul.docs-menu label.tocitem .docs-label{flex-grow:2}#documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-size:.75rem;margin-left:1rem;margin-top:auto;margin-bottom:auto}#documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f054"}#documenter .docs-sidebar ul.docs-menu input:checked~label.tocitem .docs-chevron::before{content:"\f078"}#documenter .docs-sidebar ul.docs-menu .tocitem{display:block;padding:0.5rem 0.5rem}#documenter .docs-sidebar ul.docs-menu .tocitem,#documenter .docs-sidebar ul.docs-menu .tocitem:hover{color:#0a0a0a;background:#f5f5f5}#documenter .docs-sidebar ul.docs-menu a.tocitem:hover,#documenter .docs-sidebar ul.docs-menu label.tocitem:hover{color:#0a0a0a;background-color:#ebebeb}#documenter .docs-sidebar ul.docs-menu li.is-active{border-top:1px solid #dbdbdb;border-bottom:1px solid #dbdbdb;background-color:#fff}#documenter .docs-sidebar ul.docs-menu li.is-active .tocitem,#documenter .docs-sidebar ul.docs-menu li.is-active .tocitem:hover{background-color:#fff;color:#0a0a0a}#documenter .docs-sidebar ul.docs-menu li.is-active ul.internal .tocitem:hover{background-color:#ebebeb;color:#0a0a0a}#documenter .docs-sidebar ul.docs-menu>li.is-active:first-child{border-top:none}#documenter .docs-sidebar ul.docs-menu ul.internal{margin:0 0.5rem 0.5rem;border-top:1px solid #dbdbdb}#documenter .docs-sidebar ul.docs-menu ul.internal li{font-size:.85rem;border-left:none;margin-left:0;margin-top:0.5rem}#documenter .docs-sidebar ul.docs-menu ul.internal .tocitem{width:100%;padding:0}#documenter .docs-sidebar ul.docs-menu ul.internal .tocitem::before{content:"⚬";margin-right:0.4em}#documenter .docs-sidebar form.docs-search{margin:auto;margin-top:0.5rem;margin-bottom:0.5rem}#documenter .docs-sidebar form.docs-search>input{width:14.4rem}#documenter .docs-sidebar #documenter-search-query{color:#707070;width:14.4rem;box-shadow:inset 0 1px 2px rgba(10,10,10,0.1)}@media screen and (min-width: 1056px){#documenter .docs-sidebar ul.docs-menu{overflow-y:auto;-webkit-overflow-scroll:touch}#documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar{width:.3rem;background:none}#documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#e0e0e0}#documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb:hover{background:#ccc}}@media screen and (max-width: 1055px){#documenter .docs-sidebar{overflow-y:auto;-webkit-overflow-scroll:touch}#documenter .docs-sidebar::-webkit-scrollbar{width:.3rem;background:none}#documenter .docs-sidebar::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#e0e0e0}#documenter .docs-sidebar::-webkit-scrollbar-thumb:hover{background:#ccc}}kbd.search-modal-key-hints{border-radius:0.25rem;border:1px solid rgba(0,0,0,0.6);box-shadow:0 2px 0 1px rgba(0,0,0,0.6);cursor:default;font-size:0.9rem;line-height:1.5;min-width:0.75rem;text-align:center;padding:0.1rem 0.3rem;position:relative;top:-1px}.search-min-width-50{min-width:50%}.search-min-height-100{min-height:100%}.search-modal-card-body{max-height:calc(100vh - 15rem)}.search-result-link{border-radius:0.7em;transition:all 300ms}.search-result-link:hover,.search-result-link:focus{background-color:rgba(0,128,128,0.1)}.search-result-link .property-search-result-badge,.search-result-link .search-filter{transition:all 300ms}.property-search-result-badge,.search-filter{padding:0.15em 0.5em;font-size:0.8em;font-style:italic;text-transform:none !important;line-height:1.5;color:#f5f5f5;background-color:rgba(51,65,85,0.501961);border-radius:0.6rem}.search-result-link:hover .property-search-result-badge,.search-result-link:hover .search-filter,.search-result-link:focus .property-search-result-badge,.search-result-link:focus .search-filter{color:#f1f5f9;background-color:#333}.search-filter{color:#333;background-color:#f5f5f5;transition:all 300ms}.search-filter:hover,.search-filter:focus{color:#333}.search-filter-selected{color:#f5f5f5;background-color:rgba(139,0,139,0.5)}.search-filter-selected:hover,.search-filter-selected:focus{color:#f5f5f5}.search-result-highlight{background-color:#ffdd57;color:black}.search-divider{border-bottom:1px solid #dbdbdb}.search-result-title{width:85%;color:#333}.search-result-code-title{font-size:0.875rem;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}#search-modal .modal-card-body::-webkit-scrollbar,#search-modal .filter-tabs::-webkit-scrollbar{height:10px;width:10px;background-color:transparent}#search-modal .modal-card-body::-webkit-scrollbar-thumb,#search-modal .filter-tabs::-webkit-scrollbar-thumb{background-color:gray;border-radius:1rem}#search-modal .modal-card-body::-webkit-scrollbar-track,#search-modal .filter-tabs::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,0.6);background-color:transparent}.w-100{width:100%}.gap-2{gap:0.5rem}.gap-4{gap:1rem}.gap-8{gap:2rem}.ansi span.sgr1{font-weight:bolder}.ansi span.sgr2{font-weight:lighter}.ansi span.sgr3{font-style:italic}.ansi span.sgr4{text-decoration:underline}.ansi span.sgr7{color:#fff;background-color:#222}.ansi span.sgr8{color:transparent}.ansi span.sgr8 span{color:transparent}.ansi span.sgr9{text-decoration:line-through}.ansi span.sgr30{color:#242424}.ansi span.sgr31{color:#a7201f}.ansi span.sgr32{color:#066f00}.ansi span.sgr33{color:#856b00}.ansi span.sgr34{color:#2149b0}.ansi span.sgr35{color:#7d4498}.ansi span.sgr36{color:#007989}.ansi span.sgr37{color:gray}.ansi span.sgr40{background-color:#242424}.ansi span.sgr41{background-color:#a7201f}.ansi span.sgr42{background-color:#066f00}.ansi span.sgr43{background-color:#856b00}.ansi span.sgr44{background-color:#2149b0}.ansi span.sgr45{background-color:#7d4498}.ansi span.sgr46{background-color:#007989}.ansi span.sgr47{background-color:gray}.ansi span.sgr90{color:#616161}.ansi span.sgr91{color:#cb3c33}.ansi span.sgr92{color:#0e8300}.ansi span.sgr93{color:#a98800}.ansi span.sgr94{color:#3c5dcd}.ansi span.sgr95{color:#9256af}.ansi span.sgr96{color:#008fa3}.ansi span.sgr97{color:#f5f5f5}.ansi span.sgr100{background-color:#616161}.ansi span.sgr101{background-color:#cb3c33}.ansi span.sgr102{background-color:#0e8300}.ansi span.sgr103{background-color:#a98800}.ansi span.sgr104{background-color:#3c5dcd}.ansi span.sgr105{background-color:#9256af}.ansi span.sgr106{background-color:#008fa3}.ansi span.sgr107{background-color:#f5f5f5}code.language-julia-repl>span.hljs-meta{color:#066f00;font-weight:bolder}/*! + Theme: Default + Description: Original highlight.js style + Author: (c) Ivan Sagalaev + Maintainer: @highlightjs/core-team + Website: https://highlightjs.org/ + License: see project LICENSE + Touched: 2021 +*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#F3F3F3;color:#444}.hljs-comment{color:#697070}.hljs-tag,.hljs-punctuation{color:#444a}.hljs-tag .hljs-name,.hljs-tag .hljs-attr{color:#444}.hljs-keyword,.hljs-attribute,.hljs-selector-tag,.hljs-meta .hljs-keyword,.hljs-doctag,.hljs-name{font-weight:bold}.hljs-type,.hljs-string,.hljs-number,.hljs-selector-id,.hljs-selector-class,.hljs-quote,.hljs-template-tag,.hljs-deletion{color:#880000}.hljs-title,.hljs-section{color:#880000;font-weight:bold}.hljs-regexp,.hljs-symbol,.hljs-variable,.hljs-template-variable,.hljs-link,.hljs-selector-attr,.hljs-operator,.hljs-selector-pseudo{color:#ab5656}.hljs-literal{color:#695}.hljs-built_in,.hljs-bullet,.hljs-code,.hljs-addition{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta .hljs-string{color:#38a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold}.gap-4{gap:1rem} diff --git a/v0.2.0/assets/themeswap.js b/v0.2.0/assets/themeswap.js new file mode 100644 index 000000000..9f5eebe6a --- /dev/null +++ b/v0.2.0/assets/themeswap.js @@ -0,0 +1,84 @@ +// Small function to quickly swap out themes. Gets put into the tag.. +function set_theme_from_local_storage() { + // Initialize the theme to null, which means default + var theme = null; + // If the browser supports the localstorage and is not disabled then try to get the + // documenter theme + if (window.localStorage != null) { + // Get the user-picked theme from localStorage. May be `null`, which means the default + // theme. + theme = window.localStorage.getItem("documenter-theme"); + } + // Check if the users preference is for dark color scheme + var darkPreference = + window.matchMedia("(prefers-color-scheme: dark)").matches === true; + // Initialize a few variables for the loop: + // + // - active: will contain the index of the theme that should be active. Note that there + // is no guarantee that localStorage contains sane values. If `active` stays `null` + // we either could not find the theme or it is the default (primary) theme anyway. + // Either way, we then need to stick to the primary theme. + // + // - disabled: style sheets that should be disabled (i.e. all the theme style sheets + // that are not the currently active theme) + var active = null; + var disabled = []; + var primaryLightTheme = null; + var primaryDarkTheme = null; + for (var i = 0; i < document.styleSheets.length; i++) { + var ss = document.styleSheets[i]; + // The tag of each style sheet is expected to have a data-theme-name attribute + // which must contain the name of the theme. The names in localStorage much match this. + var themename = ss.ownerNode.getAttribute("data-theme-name"); + // attribute not set => non-theme stylesheet => ignore + if (themename === null) continue; + // To distinguish the default (primary) theme, it needs to have the data-theme-primary + // attribute set. + if (ss.ownerNode.getAttribute("data-theme-primary") !== null) { + primaryLightTheme = themename; + } + // Check if the theme is primary dark theme so that we could store its name in darkTheme + if (ss.ownerNode.getAttribute("data-theme-primary-dark") !== null) { + primaryDarkTheme = themename; + } + // If we find a matching theme (and it's not the default), we'll set active to non-null + if (themename === theme) active = i; + // Store the style sheets of inactive themes so that we could disable them + if (themename !== theme) disabled.push(ss); + } + var activeTheme = null; + if (active !== null) { + // If we did find an active theme, we'll (1) add the theme--$(theme) class to + document.getElementsByTagName("html")[0].className = "theme--" + theme; + activeTheme = theme; + } else { + // If we did _not_ find an active theme, then we need to fall back to the primary theme + // which can either be dark or light, depending on the user's OS preference. + var activeTheme = darkPreference ? primaryDarkTheme : primaryLightTheme; + // In case it somehow happens that the relevant primary theme was not found in the + // preceding loop, we abort without doing anything. + if (activeTheme === null) { + console.error("Unable to determine primary theme."); + return; + } + // When switching to the primary light theme, then we must not have a class name + // for the tag. That's only for non-primary or the primary dark theme. + if (darkPreference) { + document.getElementsByTagName("html")[0].className = + "theme--" + activeTheme; + } else { + document.getElementsByTagName("html")[0].className = ""; + } + } + for (var i = 0; i < document.styleSheets.length; i++) { + var ss = document.styleSheets[i]; + // The tag of each style sheet is expected to have a data-theme-name attribute + // which must contain the name of the theme. The names in localStorage much match this. + var themename = ss.ownerNode.getAttribute("data-theme-name"); + // attribute not set => non-theme stylesheet => ignore + if (themename === null) continue; + // we'll disable all the stylesheets, except for the active one + ss.disabled = !(themename == activeTheme); + } +} +set_theme_from_local_storage(); diff --git a/v0.2.0/assets/warner.js b/v0.2.0/assets/warner.js new file mode 100644 index 000000000..3f6f5d008 --- /dev/null +++ b/v0.2.0/assets/warner.js @@ -0,0 +1,52 @@ +function maybeAddWarning() { + // DOCUMENTER_NEWEST is defined in versions.js, DOCUMENTER_CURRENT_VERSION and DOCUMENTER_STABLE + // in siteinfo.js. + // If either of these are undefined something went horribly wrong, so we abort. + if ( + window.DOCUMENTER_NEWEST === undefined || + window.DOCUMENTER_CURRENT_VERSION === undefined || + window.DOCUMENTER_STABLE === undefined + ) { + return; + } + + // Current version is not a version number, so we can't tell if it's the newest version. Abort. + if (!/v(\d+\.)*\d+/.test(window.DOCUMENTER_CURRENT_VERSION)) { + return; + } + + // Current version is newest version, so no need to add a warning. + if (window.DOCUMENTER_NEWEST === window.DOCUMENTER_CURRENT_VERSION) { + return; + } + + // Add a noindex meta tag (unless one exists) so that search engines don't index this version of the docs. + if (document.body.querySelector('meta[name="robots"]') === null) { + const meta = document.createElement("meta"); + meta.name = "robots"; + meta.content = "noindex"; + + document.getElementsByTagName("head")[0].appendChild(meta); + } + + const div = document.createElement("div"); + div.classList.add("outdated-warning-overlay"); + const closer = document.createElement("button"); + closer.classList.add("outdated-warning-closer", "delete"); + closer.addEventListener("click", function () { + document.body.removeChild(div); + }); + const href = window.documenterBaseURL + "/../" + window.DOCUMENTER_STABLE; + div.innerHTML = + 'This documentation is not for the latest stable release, but for either the development version or an older release.
Click here to go to the documentation for the latest stable release.'; + div.appendChild(closer); + document.body.appendChild(div); +} + +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", maybeAddWarning); +} else { + maybeAddWarning(); +} diff --git a/v0.2.0/background/bibliography/index.html b/v0.2.0/background/bibliography/index.html new file mode 100644 index 000000000..de87b3d5e --- /dev/null +++ b/v0.2.0/background/bibliography/index.html @@ -0,0 +1,2 @@ + +Bibliography · JuliaGrid

Bibliography

[1]
A. Gomez-Exposito, A. Abur, P. Rousseaux, A. de la Villa Jaen and C. Gomez-Quiles. On the use of PMUs in power system state estimation. In: 17th power system computation conference (2011).
[2]
G. N. Korres. Observability analysis based on Echelon form of a reduced dimensional Jacobian matrix. IEEE Transactions on Power Systems 26, 2572–2573 (2011).
[3]
M. Zhou, V. A. Centeno, J. S. Thorp and A. G. Phadke. An alternative for including phasor measurements in state estimators. IEEE transactions on power systems 21, 1930–1937 (2006).
[4]
G. Korres and N. Manousakis. State estimation and observability analysis for phasor measurement unit measured systems. IET generation, transmission & distribution 6, 902–913 (2012).
[5]
A. Abur and A. G. Exposito. Power system state estimation: theory and implementation (CRC press, 2004).
[6]
G. Andersson. Power system analysis. EEH-Power Systems Laboratory, ETH Zurich, Lecture Notes, 227–0526 (2012).
[7]
J. J. Grainger and W. D. Stevenson. Power system analysis (McGraw-Hill, 1994).
[8]
R. D. Zimmerman and C. E. Murillo-Sánchez. Matpower 6.0 users manual. Power Systems Engineering Research Center 9 (2016).
[9]
A. J. Wood, B. F. Wollenberg and G. B. Sheblé. Power generation, operation, and control (John Wiley & Sons, 2013).
[10]
R. A. Van Amerongen. A general-purpose version of the fast decoupled load flow. IEEE Transactions on Power Systems 4, 760–770 (1989).
[11]
D. P. Chassin, P. R. Armstrong, D. G. Chavarrı́a-Miranda and R. T. Guttromson. Gauss-Seidel accelerated: implementing flow solvers on field programmable gate arrays. In: 2006 IEEE Power Engineering Society General Meeting (IEEE, 2006); p. 5–pp.
[12]
F. C. Schweppe and D. B. Rom. Power system static-state estimation, Part II: Approximate model. IEEE Transactions on Power Apparatus and Systems, 125–130 (1970).
[13]
A. Monticelli. State estimation in electric power systems: a generalized approach (Springer Science & Business Media, 2012).
[14]
A. G. Phadke and J. S. Thorp. Synchronized phasor measurements and their applications. Vol. 1 no. 2017 (Springer, 2008).
[15]
D. Barber. Bayesian reasoning and machine learning (Cambridge University Press, 2012).
[16]
I. ISO. and B. OIML. Guide to the Expression of Uncertainty in Measurement (Aenor, 1993).
[17]
Y. Weng, Q. Li, R. Negi and M. Ilić. Semidefinite programming for power system state estimation. In: 2012 IEEE Power and Energy Society General Meeting (IEEE, 2012); pp. 1–8.
[18]
P. C. Hansen, V. Pereyra and G. Scherer. Least squares data fitting with applications (JHU Press, 2013).
[19]
G. N. Korres. A distributed multiarea state estimation. IEEE Transactions on Power Systems 26, 73–84 (2010).
[20]
M. Cosovic, M. Delalic, D. Raca and D. Vukobratovic. Observability analysis for large-scale power systems using factor graphs. IEEE Transactions on Power Systems 36, 4791–4799 (2021).
[21]
H. Horisberger. Observability analysis for power systems with measurement deficiencies. IFAC Proceedings Volumes 18, 51–58 (1985).
[22]
N. M. Manousakis and G. N. Korres. Observability analysis for power systems including conventional and phasor measurements. IET Conference Proceedings, 158-158(1) (2010).
[23]
B. Gou. Optimal placement of PMUs by integer linear programming. IEEE Transactions on power systems 23, 1525–1526 (2008).
[24]
B. Xu and A. Abur. Observability analysis and measurement placement for systems with PMUs. In: IEEE PES Power Systems Conference and Exposition, 2004. (IEEE, 2004); pp. 943–946.
diff --git a/v0.2.0/background/installation/index.html b/v0.2.0/background/installation/index.html new file mode 100644 index 000000000..4bf7fe1fa --- /dev/null +++ b/v0.2.0/background/installation/index.html @@ -0,0 +1,4 @@ + +Installation Guide · JuliaGrid

Installation Guide

JuliaGrid is compatible with Julia version 1.9 and later. To get started with JuliaGrid, users should first install Julia and consider using a code editor for a smoother coding experience.


Install Julia

Begin by downloading and installing Julia. We can choose either the Current Stable Release or the Long-term Support Release.

The Current Stable Release is the most recent version of Julia, providing access to the latest features and typically offering better performance. For most users, we recommend installing the Current Stable Release. The Long-term Support Release is an older version of Julia that has continued to receive bug and security fixes. However, it may not have the latest features or performance improvements.


Install Code Editor

For a smoother development experience, we recommend using a code editor. While you can write Julia code in any text editor, using an integrated development environment (IDE) makes coding easier and more efficient. We suggest installing Visual Studio Code, which provides excellent support for Julia through its dedicated Julia extension. Visual Studio Code offers features like syntax highlighting, debugging, and autocompletion, making it an ideal choice for both beginners and experienced users.

The Julia extension for Visual Studio Code includes built-in dynamic autocompletion, inline results, plot pane, integrated REPL, variable view, code navigation, and many other advanced language features. For a step-by-step guide on how to use Julia in Visual Studio Code, you can follow the tutorial available here.


Install JuliaGrid

To get the JuliaGrid package installed, execute the following Julia command:

import Pkg
+Pkg.add("JuliaGrid")

When a new version of JuliaGrid is released, you can update it with the following command:

import Pkg
+Pkg.update("JuliaGrid")
diff --git a/v0.2.0/background/references.bib b/v0.2.0/background/references.bib new file mode 100644 index 000000000..cf6d90f25 --- /dev/null +++ b/v0.2.0/background/references.bib @@ -0,0 +1,214 @@ +@inproceedings{gomez2011use, + title = {On the use of PMUs in power system state estimation}, + author = {Gomez-Exposito, Antonio and Abur, Ali and Rousseaux, Patricia and de la Villa Jaen, Antonio and Gomez-Quiles, Catalina}, + booktitle = {17th power system computation conference}, + year = {2011} +} + +@article{korres2011observability, + title = {Observability analysis based on Echelon form of a reduced dimensional Jacobian matrix}, + author = {Korres, George N}, + journal = {IEEE Transactions on Power Systems}, + volume = {26}, + number = {4}, + pages = {2572--2573}, + year = {2011}, + publisher = {IEEE} +} + +@article{korres2012state, + title = {State estimation and observability analysis for phasor measurement unit measured systems}, + author = {Korres, GN and Manousakis, NM}, + journal = {IET generation, transmission \& distribution}, + volume = {6}, + number = {9}, + pages = {902--913}, + year = {2012}, + publisher = {IET} +} + +@article{zhou2006alternative, + title = {An alternative for including phasor measurements in state estimators}, + author = {Zhou, Ming and Centeno, Virgilio A and Thorp, James S and Phadke, Arun G}, + journal = {IEEE transactions on power systems}, + volume = {21}, + number = {4}, + pages = {1930--1937}, + year = {2006}, + publisher = {IEEE} +} + +@book{aburbook, + title = {Power system state estimation: theory and implementation}, + author = {Abur, Ali and Exposito, Antonio Gomez}, + year = {2004}, + publisher = {CRC press} +} + +@article{andersson2012power, + title = {Power system analysis}, + author = {Andersson, G{\"o}ran}, + journal = {EEH-Power Systems Laboratory, ETH Zurich, Lecture Notes}, + pages = {227--0526}, + year = {2012} +} + +@book{john1994power, + title = {Power system analysis}, + author = {John J.. Grainger and Stevenson, William D}, + year = {1994}, + publisher = {McGraw-Hill} +} + +@article{zimmerman2016matpower, + title = {Matpower 6.0 users manual}, + author = {Zimmerman, Ray D and Murillo-S{\'a}nchez, Carlos E}, + journal = {Power Systems Engineering Research Center}, + volume = {9}, + year = {2016} +} + +@book{wood2013power, + title = {Power generation, operation, and control}, + author = {Wood, Allen J and Wollenberg, Bruce F and Shebl{\'e}, Gerald B}, + year = {2013}, + publisher = {John Wiley \& Sons} +} + +@article{van1989general, + title = {A general-purpose version of the fast decoupled load flow}, + author = {Van Amerongen, Robert AM}, + journal = {IEEE Transactions on Power Systems}, + volume = {4}, + number = {2}, + pages = {760--770}, + year = {1989}, + publisher = {IEEE} +} + +@inproceedings{chassin2006gauss, + title = {Gauss-Seidel accelerated: implementing flow solvers on field programmable gate arrays}, + author = {Chassin, David P and Armstrong, Peter R and Chavarr{\'\i}a-Miranda, Daniel G and Guttromson, Ross T}, + booktitle = {2006 IEEE Power Engineering Society General Meeting}, + pages = {5--pp}, + year = {2006}, + organization = {IEEE} +} + +@article{schweppe1970power, + title = {Power system static-state estimation, Part II: Approximate model}, + author = {Schweppe, Fred C and Rom, Douglas B}, + journal = {IEEE Transactions on Power Apparatus and Systems}, + number = {1}, + pages = {125--130}, + year = {1970}, + publisher = {IEEE} +} + +@book{monticellibook, + title = {State estimation in electric power systems: a generalized approach}, + author = {Monticelli, Alcir}, + year = {2012}, + publisher = {Springer Science \& Business Media} +} + +@book{phadkebook, + title = {Synchronized phasor measurements and their applications}, + author = {Phadke, Arun G and Thorp, James S}, + volume = {1}, + number = {2017}, + year = {2008}, + publisher = {Springer} +} + +@book{barberbook, + title = {Bayesian reasoning and machine learning}, + author = {Barber, David}, + year = {2012}, + publisher = {Cambridge University Press} +} + +@book{iso1993guide, + title={Guide to the Expression of Uncertainty in Measurement}, + author={ISO., I and OIML, BIPM}, + year={1993}, + publisher={Aenor} +} + +@inproceedings{weng2012semidefinite, + title={Semidefinite programming for power system state estimation}, + author={Weng, Yang and Li, Qiao and Negi, Rohit and Ili{\'c}, Marija}, + booktitle={2012 IEEE Power and Energy Society General Meeting}, + pages={1--8}, + year={2012}, + organization={IEEE} +} + +@book{hansen2013least, + title={Least squares data fitting with applications}, + author={Hansen, Per Christian and Pereyra, Victor and Scherer, Godela}, + year={2013}, + publisher={JHU Press} +} + +@article{korres2010distributed, + title={A distributed multiarea state estimation}, + author={Korres, George N}, + journal={IEEE Transactions on Power Systems}, + volume={26}, + number={1}, + pages={73--84}, + year={2010}, + publisher={IEEE} +} + +@article{cosovic2021observability, + title={Observability analysis for large-scale power systems using factor graphs}, + author={Cosovic, Mirsad and Delalic, Muhamed and Raca, Darijo and Vukobratovic, Dejan}, + journal={IEEE Transactions on Power Systems}, + volume={36}, + number={5}, + pages={4791--4799}, + year={2021}, + publisher={IEEE} +} + +@article{horisberger1985observability, + title={Observability analysis for power systems with measurement deficiencies}, + author={Horisberger, HP}, + journal={IFAC Proceedings Volumes}, + volume={18}, + number={7}, + pages={51--58}, + year={1985}, + publisher={Elsevier} +} + +@article{manousakis2010observability, + title={Observability analysis for power systems including conventional and phasor measurements}, + author={Manousakis, Nikolaos M and Korres, George N}, + journal = {IET Conference Proceedings}, + pages = {158-158(1)}, + year={2010}, + publisher = {Institution of Engineering and Technology} +} + +@article{gou2008optimal, + title={Optimal placement of PMUs by integer linear programming}, + author={Gou, Bei}, + journal={IEEE Transactions on power systems}, + volume={23}, + number={3}, + pages={1525--1526}, + year={2008}, + publisher={IEEE} +} + +@inproceedings{xu2004observability, + title={Observability analysis and measurement placement for systems with PMUs}, + author={Xu, Bei and Abur, Ali}, + booktitle={IEEE PES Power Systems Conference and Exposition, 2004.}, + pages={943--946}, + year={2004}, + organization={IEEE} +} \ No newline at end of file diff --git a/v0.2.0/index.html b/v0.2.0/index.html new file mode 100644 index 000000000..0c05c8119 --- /dev/null +++ b/v0.2.0/index.html @@ -0,0 +1,91 @@ + +Introduction · JuliaGrid

JuliaGrid

JuliaGrid is a fast, flexible, and easy-to-use open-source tool for analyzing and modifying power system configurations and measurement data. It represents a comprehensive framework for steady-state power system analysis written in the Julia programming language. The framework is available as a Julia package under MIT License. JuliaGrid is primarily designed for researchers and academics, providing various state-of-the-art algorithms.

The framework's architecture centres around code-reusability paradigm, allowing users a high level of customization for their experiments. To simplify, the overall logic for setting the experiments and its analysis can be as follows:

  • Users define a power system with/without measurement data.
  • Users select between the AC or DC model.
  • Users define the specific type of required analysis.
  • Finally, they solve the generated power system model.

Installation Guide

JuliaGrid is compatible with Julia version 1.9 and later. To get started with JuliaGrid, users should first install Julia and consider using a code editor for a smoother coding experience. For detailed instructions, please consult the Installation Guide.

To get the JuliaGrid package installed, execute the following Julia command:

import Pkg
+Pkg.add("JuliaGrid")

Documentation Structure

JuliaGrid documentation consists of three main parts:

  • The manual provides users with guidance on how to use available functions, its return values, and offers instructions for modifying power system configurations, measurement data, and other user specific analysis.
  • The tutorials delve deeper into the theoretical underpinnings of state-of-the-art algorithms, allowing users to gain an in-depth understanding of the equations used in various functions.
  • API references offer a comprehensive list of objects, functions and methods within the package, categorised according to specific use-cases.

Getting Started

Below, we have provided a list of exhaustive examples in order to ease users in getting started with the JuliaGrid package. These examples highlight some of the functionalities that the framework offers.


AC Power Flow

using JuliaGrid
+
+system = powerSystem("case14.h5")          # Build the power system model
+acModel!(system)                           # Create matrices and vectors for the AC model
+
+analysis = newtonRaphson(system)           # Build the power flow model
+for iteration = 1:10                       # Begin the iteration loop
+    stopping = mismatch!(system, analysis) # Compute power mismatches
+    if all(stopping .< 1e-8)               # Check if the stopping criterion is met
+        println("Solution Found.")         # Output message indicating convergence
+        break                              # Stop iterations if the criterion is met
+    end
+    solve!(system, analysis)               # Compute voltage magnitudes and angles
+end
+power!(system, analysis)                   # Compute powers within the power system
+current!(system, analysis)                 # Compute currents within the power system
+
+printBusData(system, analysis)             # Print data related to buses

DC Power Flow

using JuliaGrid
+
+@power(MW, MVAr, MVA)                    # Specify the power units for input data
+system = powerSystem("case14.h5")        # Build the power system model
+dcModel!(system)                         # Create matrices and vectors for the DC model
+
+analysis = dcPowerFlow(system)           # Build the power flow analysis
+solve!(system, analysis)                 # Compute voltage angles
+
+@generator(active = 20)                  # Define the template for generators
+addGenerator!(system, analysis; bus = 1) # Add the new generator to the power system
+solve!(system, analysis)                 # Recompute voltage angles with the updated model
+
+printBusSummary(system, analysis)        # Print a summary of data related to buses

AC Optimal Power Flow

using JuliaGrid, Ipopt
+
+system = powerSystem("case14.h5")              # Build the power system model
+acModel!(system)                               # Create matrices and vectors for the AC model
+
+analysis = acOptimalPowerFlow(system, Ipopt.Optimizer) # Build the optimal power flow model
+solve!(system, analysis)                       # Compute generator powers and bus voltages
+current!(system, analysis)                     # Compute currents within the power system
+
+@branch(resistance = 0.01, reactance = 0.2)    # Define the new template for branches
+addBranch!(system, analysis; from = 1, to = 5) # Add the new branch to the power system
+solve!(system, analysis)                       # Recompute solutions with the updated model

DC Optimal Power Flow

using JuliaGrid, HiGHS
+
+system = powerSystem("case14.h5") # Build the power system model
+dcModel!(system)                  # Create matrices and vectors for the DC model
+
+analysis = dcOptimalPowerFlow(system, HiGHS.Optimizer) # Build the optimal power flow model
+solve!(system, analysis)          # Compute generator powers and bus voltages
+power!(system, analysis)          # Compute active powers within the power system
+
+printBranchData(system, analysis) # Print data related to branches

AC State Estimation

using JuliaGrid
+
+system = powerSystem("case14.h5")            # Build the power system model
+device = measurement("measurement14.h5")     # Build the measurement model
+acModel!(system)                             # Create matrices and vectors for the AC model
+
+analysis = gaussNewton(system, device)       # Build the state estimation model
+for iteration = 1:20                         # Begin the iteration loop
+    stopping = solve!(system, analysis)      # Compute estimate of voltages
+    if stopping < 1e-8                       # Check if the stopping criterion is met
+        println("Solution Found.")           # Output message indicating convergence
+        break                                # Stop iterations if the criterion is met
+    end
+end
+power!(system, analysis)                     # Compute active powers within the power system
+
+printWattmeterData(system, device, analysis) # Print data related to wattmeters

PMU State Estimation

using JuliaGrid
+
+system = powerSystem("case14.h5")        # Build the power system model
+device = measurement("measurement14.h5") # Build the measurement model
+acModel!(system)                         # Create matrices and vectors for the AC model
+
+analysis = pmuStateEstimation(system, device) # Build the state estimation model
+solve!(system, analysis)                 # Compute estimate of voltages
+
+updatePmu!(system, device, analysis; label = "To 1", angle = 0.0) # Update phasor measurement
+solve!(system, analysis)                 # Recompute the solution with the updated model
+
+printPmuData(system, device, analysis)   # Print data related to PMUs

DC State Estimation

using JuliaGrid
+
+system = powerSystem("case14.h5")        # Build the power system model
+device = measurement("measurement14.h5") # Build the measurement model
+dcModel!(system)                         # Create matrices and vectors for the DC model
+
+analysis = dcStateEstimation(system, device) # Build the state estimation model
+solve!(system, analysis)                 # Compute estimate of voltage angles
+
+residualTest!(system, device, analysis)  # Perform bad data analysis and remove outlier
+solve!(system, analysis)                 # Recompute voltage angles with the updated model

Contributors

diff --git a/v0.2.0/manual/acOptimalPowerFlow/index.html b/v0.2.0/manual/acOptimalPowerFlow/index.html new file mode 100644 index 000000000..8514876e1 --- /dev/null +++ b/v0.2.0/manual/acOptimalPowerFlow/index.html @@ -0,0 +1,141 @@ + +AC Optimal Power Flow · JuliaGrid

AC Optimal Power Flow

JuliaGrid utilizes the JuMP package to construct optimal power flow models, allowing users to manipulate these models using the standard functions provided by JuMP. As a result, JuliaGrid supports popular solvers mentioned in the JuMP documentation to solve the optimization problem.

To perform the AC optimal power flow, we first need to have the PowerSystem type that has been created with the AC model. After that, create the ACOptimalPowerFlow type to establish the AC optimal power flow framework using the function:

To solve the AC optimal power flow problem and acquire bus voltage magnitudes and angles, and generator active and reactive power outputs, make use of the following function:


After obtaining the AC optimal power flow solution, JuliaGrid offers post-processing analysis functions to calculate powers and currents associated with buses and branches:

Additionally, specialized functions are available for calculating specific types of powers or currents for individual buses, branches, or generators.


Optimal Power Flow Model

To set up the AC optimal power flow, we begin by creating the model. To illustrate this, consider the following:

using JuMP, Ipopt
+
+system = powerSystem()
+
+@bus(minMagnitude = 0.95, maxMagnitude = 1.05)
+addBus!(system; label = "Bus 1", type = 3, active = 0.1, angle = -0.1)
+addBus!(system; label = "Bus 2", reactive = 0.01, magnitude = 1.1)
+
+@branch(minDiffAngle = -pi, maxDiffAngle = pi, reactance = 0.5, type = 2)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", maxFromBus = 0.15)
+
+@generator(maxActive = 0.5, minReactive = -0.1, maxReactive = 0.1, status = 0)
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 0.4, reactive = 0.2)
+addGenerator!(system; label = "Generator 2", bus = "Bus 2", active = 0.2, reactive = 0.1)
+
+cost!(system; label = "Generator 1", active = 2, polynomial = [800.0; 200.0; 80.0])
+cost!(system; label = "Generator 2", active = 1, piecewise = [10.8 12.3; 14.7 16.8; 18 18.1])
+
+cost!(system; label = "Generator 1", reactive = 2, polynomial = [2.0])
+cost!(system; label = "Generator 2", reactive = 1, piecewise = [2.0 4.0; 6.0 8.0])
+
+acModel!(system)

Next, the acOptimalPowerFlow function is utilized to formulate the AC optimal power flow problem:

analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)

Optimization Variables

In the AC optimal power flow model, the active and reactive power outputs of the generators are expressed as nonlinear functions of the bus voltage magnitudes and angles. As a result, the variables in this model include the active and reactive power outputs of the generators, as well as the bus voltage magnitudes and angles:

julia> JuMP.all_variables(analysis.method.jump)8-element Vector{VariableRef}:
+ active[1]
+ active[2]
+ reactive[1]
+ reactive[2]
+ magnitude[1]
+ magnitude[2]
+ angle[1]
+ angle[2]

It is important to note that this is not a comprehensive set of optimization variables. When the cost function is defined as a linear piecewise function comprising multiple segments, as illustrated in the case of the active power output cost for Generator 2, JuliaGrid automatically generates helper optimization variables named actwise and reactwise, and formulates a set of linear constraints to effectively address these cost functions. For the sake of simplicity, we initially assume that Generator 2 is out-of-service. Consequently, the helper variable is not included in the set of optimization variables. However, as we progress through this manual, we will activate the generator, introducing the helper variable and additional constraints to the optimization model.

It is worth emphasizing that in instances where a linear piecewise cost function consists of only a single segment, as demonstrated by the reactive power output cost of Generator 2, the function is modeled as a standard linear function, obviating the need for additional helper optimization variables.

Please be aware that JuliaGrid maintains references to all variables, which are categorized into six fields:

julia> fieldnames(typeof(analysis.method.variable))(:active, :reactive, :magnitude, :angle, :actwise, :reactwise)

Variable Names

Users have the option to define custom variable names for printing and writing equations, which can help present them in a more compact form. For example:

analysis = acOptimalPowerFlow(system, Ipopt.Optimizer; magnitude = "V", angle = "θ")

Add Variables

The user has the ability to easily add new variables to the defined AC optimal power flow model by using the @variable macro from the JuMP package:

JuMP.@variable(analysis.method.jump, newVariable)

We can verify that the new variable is included in the defined model by using the function:

julia> JuMP.is_valid(analysis.method.jump, newVariable)true

Delete Variables

The variable can be deleted, but this operation is only applicable if the objective function is either affine or quadratic. To achieve this, we can utilize the delete function provided by the JuMP, as demonstrated below:

JuMP.delete(analysis.method.jump, newVariable)

After deletion, the variable is no longer part of the model:

julia> JuMP.is_valid(analysis.method.jump, newVariable)false

Constraint Functions

JuliaGrid keeps track of all the references to internally formed constraints in the constraint field of the ACOptimalPowerFlow type. These constraints are divided into six fields:

julia> fieldnames(typeof(analysis.method.constraint))(:slack, :balance, :voltage, :flow, :capability, :piecewise)
Info

We suggest that readers refer to the tutorial on AC Optimal Power Flow for insights into the implementation.


Slack Bus Constraint

The slack field contains a reference to the equality constraint associated with the fixed bus voltage angle value of the slack bus. This constraint is set within the addBus! function using the angle keyword:

julia> print(system.bus.label, analysis.method.constraint.slack.angle)Bus 1: θ[1] = -0.1

Users have the flexibility to modify this constraint by changing which bus serves as the slack bus and by adjusting the value of the bus angle. This can be achieved using the updateBus! function, for example:

updateBus!(system, analysis; label = "Bus 1", type = 1)
+updateBus!(system, analysis; label = "Bus 2", type = 3, angle = -0.2)

Subsequently, the updated slack constraint can be inspected as follows:

julia> print(system.bus.label, analysis.method.constraint.slack.angle)Bus 2: θ[2] = -0.2

Bus Power Balance Constraints

The balance field contains references to the equality constraints associated with the active and reactive power balance equations defined for each bus. These constraints ensure that the total active and reactive power injected by the generators matches the total active and reactive power demanded at each bus.

The constant term in the active power balance equations is determined by the active keyword within the addBus! function, which defines the active power demanded at the bus. We can access the references to the active power balance constraints using the following code snippet:

julia> print(system.bus.label, analysis.method.constraint.balance.active)Bus 1: (-V[1]) * ((V[2] * ((2.0 * sin(θ[1] - θ[2]))))) - 0.1 = 0
+Bus 2: (-V[2]) * ((V[1] * ((2.0 * sin(-θ[1] + θ[2]))))) - 0.0 = 0

Similarly, the constant term in the reactive power balance equations is determined by the reactive keyword within the addBus! function, which defines the reactive power demanded at the bus. We can access the references to the reactive power balance constraints using the following code snippet:

julia> print(system.bus.label, analysis.method.constraint.balance.reactive)Bus 1: (-V[1]) * ((2 V[1]) + (V[2] * ( - (2.0 * cos(θ[1] - θ[2]))))) - 0.0 = 0
+Bus 2: (-V[2]) * ((2 V[2]) + (V[1] * ( - (2.0 * cos(-θ[1] + θ[2]))))) - 0.01 = 0

During the execution of functions that add or update power system components, these constraints are automatically adjusted to reflect the current configuration of the power system, for example:

updateBus!(system, analysis; label = "Bus 2", active = 0.5)
+updateBranch!(system, analysis; label = "Branch 1", reactance = 0.25)

The updated set of active power balance constraints can be examined as follows:

julia> print(system.bus.label, analysis.method.constraint.balance.active)Bus 1: (-V[1]) * ((V[2] * ((4.0 * sin(θ[1] - θ[2]))))) - 0.1 = 0
+Bus 2: (-V[2]) * ((V[1] * ((4.0 * sin(-θ[1] + θ[2]))))) - 0.5 = 0

Bus Voltage Constraints

The voltage field contains references to the inequality constraints associated with the voltage magnitude and voltage angle difference limits. These constraints ensure that the bus voltage magnitudes and the angle differences between the from-bus and to-bus ends of each branch are within specified limits.

The minimum and maximum bus voltage magnitude limits are set using the minMagnitude and maxMagnitude keywords within the addBus! function. The constraints associated with these limits can be accessed using:

julia> print(system.bus.label, analysis.method.constraint.voltage.magnitude)Bus 1: V[1] ∈ [0.95, 1.05]
+Bus 2: V[2] ∈ [0.95, 1.05]

The minimum and maximum voltage angle difference limits between the from-bus and to-bus ends of each branch are set using the minDiffAngle and maxDiffAngle keywords within the addBranch! function. The constraints associated with these limits can be accessed using the following code snippet:

julia> print(system.branch.label, analysis.method.constraint.voltage.angle)Branch 1: θ[1] - θ[2] ∈ [-3.141592653589793, 3.141592653589793]
Info

Please note that if the limit constraints are set to minDiffAngle = -2π and maxDiffAngle = 2π for the corresponding branch, JuliGrid will omit the corresponding inequality constraint.

Additionally, by employing the updateBus! and updateBranch! functions, the user has the ability to modify these specific constraints:

updateBus!(system, analysis; label = "Bus 1", minMagnitude = 1.0, maxMagnitude = 1.0)
+updateBranch!(system, analysis; label = "Branch 1", minDiffAngle = -1.7, maxDiffAngle = 1.7)

Subsequently, the updated set of constraints can be examined as follows:

julia> print(system.bus.label, analysis.method.constraint.voltage.magnitude)Bus 1: V[1] = 1
+Bus 2: V[2] ∈ [0.95, 1.05]
julia> print(system.branch.label, analysis.method.constraint.voltage.angle)Branch 1: θ[1] - θ[2] ∈ [-1.7, 1.7]

Branch Flow Constraints

The flow field contains references to the inequality constraints associated with the apparent power flow, active power flow, or current flow magnitude limits at the from-bus and to-bus ends of each branch. The type to which one of the constraints will be applied is defined according to the type keyword within the addBranch! function:

  • type = 1 for the apparent power flow,
  • type = 2 for the active power flow,
  • type = 3 for the current flow magnitude.

These limits are specified using the minFromBus, maxFromBus, minToBus and maxToBus keywords within the addBranch! function. By default, these limit keywords are associated with apparent power (type = 1).

However, in the example, we configured it to use active power flow by setting type = 2. To access the flow constraints of branches at the from-bus end, we can utilize the following code snippet:

julia> print(system.branch.label, analysis.method.constraint.flow.from)Branch 1:  - ((V[1]*V[2]) * ((-4.0 * sin(θ[1] - θ[2])))) ∈ [0, 0.15]
Info

If the branch flow limits are set to minFromBus = 0.0 and maxFromBus = 0.0 for the corresponding branch, JuliGrid will omit the corresponding inequality constraint at the from-bus end of the branch. The same applies to the to-bus end if minToBus = 0.0 and maxToBus = 0.0 are set.

Additionally, by employing the updateBranch! function, we have the ability to modify these specific constraints:

updateBranch!(system, analysis; label = "Branch 1", minFromBus = -0.15, maxToBus = 0.15)

The updated set of flow constraints can be examined as follows:

julia> print(system.branch.label, analysis.method.constraint.flow.from)Branch 1:  - ((V[1]*V[2]) * ((-4.0 * sin(θ[1] - θ[2])))) ∈ [-0.15, 0.15]
julia> print(system.branch.label, analysis.method.constraint.flow.to)Branch 1: - ((V[1]*V[2]) * ( - (-4.0 * sin(θ[1] - θ[2])))) ∈ [0, 0.15]
Tip

In typical scenarios, minFromBus is equal to minToBus, and maxFromBus is equal to maxToBus. However, we allow these values to be defined separately for greater flexibility, enabling, among other things, the option to apply constraints on only one side of the branch.


Generator Power Capability Constraints

The capability field contains references to the inequality constraints associated with the minimum and maximum active and reactive power outputs of the generators.

The constraints associated with the minimum and maximum active power output limits of the generators are defined using the minActive and maxActive keywords within the addGenerator! function. To access the constraints associated with these limits, we can use the following code snippet:

julia> print(system.generator.label, analysis.method.constraint.capability.active)Generator 1: active[1] = 0
+Generator 2: active[2] = 0

Similarly, the constraints associated with the minimum and maximum reactive power output limits of the generators are specified using the minReactive and maxReactive keywords within the addGenerator! function. To access these constraints, we can use the following code snippet:

julia> print(system.generator.label, analysis.method.constraint.capability.reactive)Generator 1: reactive[1] = 0
+Generator 2: reactive[2] = 0

As demonstrated, the active and reactive power outputs of Generator 1 and Generator 2 are currently fixed at zero due to previous actions that set these generators out-of-service. However, we can modify these specific constraints by utilizing the updateGenerator! function, as shown below:

updateGenerator!(system, analysis; label = "Generator 1", status = 1)
+updateGenerator!(system, analysis; label = "Generator 2", status = 1, minActive = 0.1)

Subsequently, the updated set of constraints can be examined as follows:

julia> print(system.generator.label, analysis.method.constraint.capability.active)Generator 1: active[1] ∈ [0, 0.5]
+Generator 2: active[2] ∈ [0.1, 0.5]
julia> print(system.generator.label, analysis.method.constraint.capability.reactive)Generator 1: reactive[1] ∈ [-0.1, 0.1] +Generator 2: reactive[2] ∈ [-0.1, 0.1]
Info

This representation may not fully capture the generator's power output behavior due to the tradeoff between active and reactive power outputs. JuliaGrid can incorporate this tradeoff in its optimization model. For more information, see the tutorial on Power Capability Constraints.


Power Piecewise Constraints

In the context of cost modeling, the piecewise field acts as a reference to the inequality constraints associated with linear piecewise cost functions. These constraints are established using the cost! function, with active = 1 or reactive = 1 specified when working with linear piecewise cost functions that consist of multiple segments.

In our example, only the active power cost of Generator 2 is modeled as a linear piecewise function with two segments, and JuliaGrid takes care of setting up the appropriate inequality constraints for each segment:

julia> print(system.generator.label, analysis.method.constraint.piecewise.active)Generator 2: 1.1538461538461542 active[2] - actwise[2] ≤ 0.16153846153846452
+Generator 2: 0.3939393939393941 active[2] - actwise[2] ≤ -11.009090909090908

It is worth noting that these constraints can also be automatically updated using the cost! function. Readers can find more details in the section discussing the objective function.

As mentioned at the beginning, linear piecewise cost functions with multiple segments will also introduce helper variables that are added to the objective function. In this specific example, the helper variable is:

julia> analysis.method.variable.actwise[2]actwise[2]

Add Constraints

Users can effortlessly introduce additional constraints into the defined AC optimal power flow model by utilizing the addBranch! or addGenerator! functions. Specifically, if a user wishes to include a new branch or generator in an already defined PowerSystem and ACOptimalPowerFlow type:

addBranch!(system, analysis; label = "Branch 2", from = "Bus 1", to = "Bus 2", reactance = 1)
+addGenerator!(system, analysis; label = "Generator 3", bus = "Bus 2", active = 2, status = 1)

This will affect all constraints related to branches and generators, but it will also update balance constraints to configure the optimization model to match the current state of the power system. For example, we can observe the following updated constraints:

julia> print(system.branch.label, analysis.method.constraint.voltage.angle)Branch 1: θ[1] - θ[2] ∈ [-1.7, 1.7]
+Branch 2: θ[1] - θ[2] ∈ [-3.141592653589793, 3.141592653589793]
julia> print(system.generator.label, analysis.method.constraint.capability.active)Generator 1: active[1] ∈ [0, 0.5] +Generator 2: active[2] ∈ [0.1, 0.5] +Generator 3: active[3] ∈ [0, 0.5]

Add User-Defined Constraints

Users also have the option to include their custom constraints within the established AC optimal power flow model by employing the @constraint macro. For example, the addition of a new constraint can be achieved as follows:

JuMP.@constraint(analysis.method.jump, 0.0 <= analysis.method.variable.active[3] <= 0.3)

Delete Constraints

To delete a constraint, users can make use of the delete function from the JuMP package. When handling constraints that have been internally created, users can refer to the constraint references stored in the constraint field of the ACOptimalPowerFlow type.

For example, if the intention is to eliminate constraints related to the capability of Generator 3, we can use:

JuMP.delete(analysis.method.jump, analysis.method.constraint.capability.active[3])
Info

In the event that a user deletes a constraint and subsequently executes a function that updates bus, branch, or generator parameters, and if the deleted constraint is affected by these functions, JuliaGrid will automatically reinstate that constraint. Users should exercise caution when deleting constraints, as this action is considered potentially harmful since it operates independently of power system data.


Objective Function

The objective function of the AC optimal power flow is formulated using polynomial and linear piecewise cost functions associated with the generators, defined using the cost! functions.

In the provided example, the objective function to be minimized in order to obtain optimal values for the active and reactive power outputs of the generators, as well as the bus voltage magnitudes and angles, is as follows:

julia> JuMP.objective_function(analysis.method.jump)800 active[1]² + 200 active[1] + actwise[2] + reactive[2] + 84

JuliaGrid also stores the objective function in a separate variable, which can be accessed by referring to the variable analysis.objective. In this variable, the objective function is organized in a way that separates the quadratic and nonlinear components of the objective function.


Update Objective Function

By utilizing the cost! functions, users have the flexibility to modify the objective function by adjusting polynomial or linear piecewise coefficients or by changing the type of polynomial or linear piecewise function employed. For example, consider Generator 1, which employs a quadratic polynomial cost function for active power. We can redefine the cost function for this generator as a cubic polynomial and thereby define a nonlinear objective function:

cost!(system, analysis; label = "Generator 1", active = 2, polynomial = [631; 257; 40; 5.0])

This leads to an updated objective function, which can be examined as follows:

julia> JuMP.objective_function(analysis.method.jump)(257 active[1]² + 40 active[1] + actwise[2] + reactive[2] + 9) + (631.0 * (active[1] ^ 3.0))

User-Defined Objective Function

Users can modify the objective function using the set_objective_function function from the JuMP package. This operation is considered destructive because it is independent of power system data; however, in certain scenarios, it may be more straightforward than using the cost! function for updates. Moreover, using this methodology, users can combine a defined function with a newly defined expression.

In this context, we can utilize the saved objective function within the objective field of the ACOptimalPowerFlow type. For example, we can easily eliminate nonlinear parts and alter the quadratic component of the objective:

expr = 5.0 * analysis.method.variable.active[1] * analysis.method.variable.active[1]
+JuMP.set_objective_function(analysis.method.jump, analysis.method.objective.quadratic - expr)

We can now observe the updated objective function as follows:

julia> JuMP.objective_function(analysis.method.jump)252 active[1]² + 40 active[1] + actwise[2] + reactive[2] + 9

Setup Starting Values

In JuliaGrid, the assignment of starting primal and dual values for optimization variables and constraints takes place when the solve! function is executed.


Starting Primal Values

Starting primal values are determined based on the generator and voltage fields within the ACOptimalPowerFlow type. By default, these values are initially established using the active and reactive power outputs of the generators and the initial bus voltage magnitudes and angles:

julia> generator = analysis.power.generator;
julia> print(system.generator.label, generator.active, generator.reactive)Generator 1: 0.4, 0.2 +Generator 2: 0.2, 0.1 +Generator 3: 2.0, 0.0
julia> print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)Bus 1: 1.0, -0.1 +Bus 2: 1.1, -0.2

Users have the flexibility to adjust these values according to their specifications, which will then be used as the starting primal values when executing the solve! function.


Using AC Power Flow

In this perspective, users have the capability to conduct the AC power flow analysis and leverage the resulting solution to configure starting primal values. Here is an illustration of how this can be achieved:

flow = newtonRaphson(system)
+for iteration = 1:100
+    stopping = mismatch!(system, flow)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, flow)
+end

After obtaining the solution, we can calculate the active and reactive power outputs of the generators and utilize the bus voltage magnitudes and angles to set the starting values. In this case, the generator and voltage fields of the ACOptimalPowerFlow type can be employed to store the new starting values:

for (key, idx) in system.generator.label
+    active, reactive = generatorPower(system, flow; label = key)
+    analysis.power.generator.active[idx] = active
+    analysis.power.generator.reactive[idx] = reactive
+end
+
+for i = 1:system.bus.number
+    analysis.voltage.magnitude[i] = flow.voltage.magnitude[i]
+    analysis.voltage.angle[i] = flow.voltage.angle[i]
+end

Starting Dual Values

Dual variables, often referred to as Lagrange multipliers or Kuhn-Tucker multipliers, represent the shadow prices or marginal costs associated with constraints. The assignment of initial dual values occurs when the solve! function is executed. Initially, the starting dual values are unknown, but users can access and manually set them. For example:

analysis.method.dual.balance.active[1] = 0.4

Optimal Power Flow Solution

To establish the AC optimal power flow problem, we can utilize the acOptimalPowerFlow function. After setting up the problem, we can use the solve! function to compute the optimal values for the active and reactive power outputs of the generators and the bus voltage magnitudes angles. Also, to turn off the solver output within the REPL, we use the set_silent function before calling solve! function. Here is an example:

JuMP.set_silent(analysis.method.jump)
+solve!(system, analysis)

By executing this function, we will obtain the solution with the optimal values for the active and reactive power outputs of the generators, as well as the bus voltage magnitudes and angles.

julia> generator = analysis.power.generator;
julia> print(system.generator.label, generator.active, generator.reactive)Generator 1: -9.847040444910615e-9, 0.053699893519534185 +Generator 2: 0.30000001503710166, -0.10000000422506586 +Generator 3: 0.2999999948099388, 0.05887684681121572
julia> print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)Bus 1: 1.0, -0.2202143797620762 +Bus 2: 0.9894621719972532, -0.2

Objective Value

To obtain the objective value of the optimal power flow solution, we can use the objective_value function:

julia> JuMP.objective_value(analysis.method.jump)20.02727223105133

Dual Variables

The values of the dual variables are stored in the dual field of the ACOptimalPowerFlow type. For example:

julia> analysis.method.dual.balance.active[1]0.39393945244763234

Users can utilize the functions printBusData and printGeneratorData to display results. Additionally, the functions listed in the Print Constraint Data section allow users to print constraint data related to buses, branches, or generators in the desired units. For example:

@power(MW, MVAr, pu)
+show = Dict("Active Power Balance" => false)
+printBusConstraint(system, analysis; show)
|---------------------------------------------------------------------------|
+| Bus Constraint Data                                                       |
+|---------------------------------------------------------------------------|
+| Label |            Voltage Magnitude             | Reactive Power Balance |
+|       |                                          |                        |
+|       | Minimum | Solution | Maximum |      Dual | Solution |        Dual |
+|       |    [pu] |     [pu] |    [pu] | [$/pu-hr] |   [MVAr] | [$/MVAr-hr] |
+|-------|---------|----------|---------|-----------|----------|-------------|
+| Bus 1 |  1.0000 |   1.0000 |  1.0000 |   -0.0000 |  -0.0000 |      0.0000 |
+| Bus 2 |  0.9500 |   0.9895 |  1.0500 |    0.0000 |  -0.0000 |      0.0000 |
+|---------------------------------------------------------------------------|

Next, users can easily customize the print results for specific constraint, for example:

printBusConstraint(system, analysis; label = "Bus 1", header = true)
+printBusConstraint(system, analysis; label = "Bus 2", footer = true)

Save Results to a File

Users can also redirect print output to a file. For example, data can be saved in a text file as follows:

open("bus.txt", "w") do file
+    printBusConstraint(system, analysis, file)
+end

Save Results to a CSV File

For CSV output, users should first generate a simple table with style = false, and then save it to a CSV file:

using CSV
+
+io = IOBuffer()
+printBusConstraint(system, analysis, io; style = false)
+CSV.write("constraint.csv", CSV.File(take!(io); delim = "|"))

Primal and Dual Warm Start

Utilizing the ACOptimalPowerFlow type and proceeding directly to the solver offers the advantage of a "warm start". In this scenario, the starting primal and dual values for the subsequent solving step correspond to the solution obtained from the previous step.


Primal Variables

In the previous example, the following solution was obtained, representing the values of the primal variables:

julia> print(system.generator.label, generator.active, generator.reactive)Generator 1: -9.847040444910615e-9, 0.053699893519534185
+Generator 2: 0.30000001503710166, -0.10000000422506586
+Generator 3: 0.2999999948099388, 0.05887684681121572
julia> print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)Bus 1: 1.0, -0.2202143797620762 +Bus 2: 0.9894621719972532, -0.2

Dual Variables

We also obtained all dual values. Here, we list only the dual variables for one type of constraint as an example:

julia> print(system.generator.label, analysis.method.dual.capability.reactive)Generator 1: -9.800017812106651e-8
+Generator 2: 0.999999888440207
+Generator 3: -1.1155979297348172e-7

Modify Optimal Power Flow

Now, let us introduce changes to the power system from the previous example:

updateGenerator!(system, analysis; label = "Generator 2", maxActive = 0.08)

Next, we want to solve this modified optimal power flow problem. If we use solve! at this point, the primal and dual starting values will be set to the previously obtained values:

solve!(system, analysis)

As a result, we obtain a new solution:

julia> print(system.generator.label, generator.active, generator.reactive)Generator 1: -9.847040444910615e-9, 0.053699893519534185
+Generator 2: 0.30000001503710166, -0.10000000422506586
+Generator 3: 0.2999999948099388, 0.05887684681121572
julia> print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)Bus 1: 1.0, -0.2202143797620762 +Bus 2: 0.9894621719972532, -0.2

Reset Primal and Dual Values

Users retain the flexibility to reset initial primal values to their default configurations at any juncture. This can be accomplished by utilizing the active and reactive power outputs of the generators and the initial bus voltage magnitudes and angles extracted from the PowerSystem type, employing the startingPrimal! function:

startingPrimal!(system, analysis)

The primal starting values will now be identical to those that would be obtained if the acOptimalPowerFlow function were executed after all the updates have been applied.

Using the startingDual! function, users can clear all dual variable values, resetting them to their default state:

startingDual!(system, analysis)

Power and Current Analysis

After obtaining the solution from the AC optimal power flow, we can calculate various electrical quantities related to buses and branches using the power! and current! functions. For instance, let us consider the power system for which we obtained the AC optimal power flow solution:

using Ipopt
+
+system = powerSystem()
+
+@bus(minMagnitude = 0.9, maxMagnitude = 1.1)
+addBus!(system; label = "Bus 1", type = 3, magnitude = 1.05, angle = 0.17)
+addBus!(system; label = "Bus 2", active = 0.1, reactive = 0.01, conductance = 0.04)
+addBus!(system; label = "Bus 3", active = 0.05, reactive = 0.02)
+
+@branch(resistance = 0.5, reactance = 1.0, conductance = 1e-4, susceptance = 0.01)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", maxFromBus = 0.15)
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 3", maxFromBus = 0.10)
+addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", maxFromBus = 0.25)
+
+@generator(maxActive = 0.5, minReactive = -0.1, maxReactive = 0.1)
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 3.2, reactive = 0.5)
+addGenerator!(system; label = "Generator 2", bus = "Bus 2", active = 0.2, reactive = 0.1)
+
+cost!(system; label = "Generator 1", active = 2, polynomial = [1100.2; 500; 80])
+cost!(system; label = "Generator 2", active = 1, piecewise = [10.8 12.3; 14.7 16.8; 18 18.1])
+
+analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)
+solve!(system, analysis)

We can now utilize the following functions to calculate powers and currents:

power!(system, analysis)
+current!(system, analysis)

For instance, if we want to show the active power injections and the from-bus current magnitudes, we can employ:

julia> print(system.bus.label, analysis.power.injection.active)Bus 1: -9.546423295966888e-9
+Bus 2: 0.08516606773169498
+Bus 3: -0.049999999946000594
julia> print(system.branch.label, analysis.current.from.magnitude)Branch 1: 0.026580443847061253 +Branch 2: 0.023278980454995702 +Branch 3: 0.03814033058634639
Info

To better understand the powers and current associated with buses and branches that are calculated by the power! and current! functions, we suggest referring to the tutorials on AC Optimal Power Flow.


Users can utilize any of the print functions outlined in the Print Power System Data or Print Power System Summary. For example, to create a bus data with the desired units, users can use the following function:

@voltage(pu, deg, V)
+@power(MW, MVAr, pu)
+show = Dict("Power Generation" => false, "Current Injection" => false)
+printBusData(system, analysis; show)
|-------------------------------------------------------------------------------------------|
+| Bus Data                                                                                  |
+|-------------------------------------------------------------------------------------------|
+| Label |       Voltage       |    Power Demand    |  Power Injection   |    Shunt Power    |
+|       |                     |                    |                    |                   |
+|   Bus | Magnitude |   Angle |  Active | Reactive |  Active | Reactive | Active | Reactive |
+|       |      [pu] |   [deg] |    [MW] |   [MVAr] |    [MW] |   [MVAr] |   [MW] |   [MVAr] |
+|-------|-----------|---------|---------|----------|---------|----------|--------|----------|
+| Bus 1 |    0.9279 |  9.7403 |  0.0000 |   0.0000 | -0.0000 |   3.0784 | 0.0000 |  -0.0000 |
+| Bus 2 |    0.9140 | 11.6474 | 10.0000 |   1.0000 |  8.5166 |  -3.2853 | 3.3418 |  -0.0000 |
+| Bus 3 |    0.9000 |  9.1610 |  5.0000 |   2.0000 | -5.0000 |  -2.0000 | 0.0000 |  -0.0000 |
+|-------------------------------------------------------------------------------------------|

Active and Reactive Power Injection

To calculate the active and reactive power injection associated with a specific bus, the function can be used:

julia> active, reactive = injectionPower(system, analysis; label = "Bus 1")(-9.546423295966888e-9, 0.030783736488970356)

Active and Reactive Power Injection from Generators

To calculate the active and reactive power injection from the generators at a specific bus, the function can be used:

julia> active, reactive = supplyPower(system, analysis; label = "Bus 2")(0.1851660676852624, -0.022853372793443977)

Active and Reactive Power at Shunt Element

To calculate the active and reactive power associated with shunt element at a specific bus, the function can be used:

julia> active, reactive = shuntPower(system, analysis; label = "Bus 2")(0.033417573991519366, -0.0)

Active and Reactive Power Flow

Similarly, we can compute the active and reactive power flow at both the from-bus and to-bus ends of the specific branch by utilizing the provided functions below:

julia> active, reactive = fromPower(system, analysis; label = "Branch 2")(0.01718395201242816, 0.01308966404839291)
julia> active, reactive = toPower(system, analysis; label = "Branch 2")(-0.016754088348856475, -0.020752498338831162)

Active and Reactive Power at Charging Admittances

To calculate the total active and reactive power linked with branch charging admittances of the particular branch, the function can be used:

julia> active, reactive = chargingPower(system, analysis; label = "Branch 1")(8.482586112312036e-5, -0.008482586112312037)

Active powers indicate active losses within the branch's charging admittances. Moreover, charging admittances injected reactive powers into the power system due to their capacitive nature, as denoted by a negative sign.


Active and Reactive Power at Series Impedance

To calculate the active and reactive power across the series impedance of the branch, the function can be used:

julia> active, reactive = seriesPower(system, analysis; label = "Branch 2")(0.0003463091379091515, 0.000692618275818303)

The active power also considers active losses originating from the series resistance of the branch, while the reactive power represents reactive losses resulting from the impedance's inductive characteristics.


Current Injection

To calculate the current injection associated with a specific bus, the function can be used:

julia> magnitude, angle = injectionCurrent(system, analysis; label = "Bus 1")(0.03317417399671275, -1.4007966369074556)

Current Flow

We can compute the current flow at both the from-bus and to-bus ends of the specific branch by using:

julia> magnitude, angle = fromCurrent(system, analysis; label = "Branch 2")(0.023278980454995702, -0.48097100965369877)
julia> magnitude, angle = toCurrent(system, analysis; label = "Branch 2")(0.02963470110066419, 2.409879948091975)

Current Through Series Impedance

To calculate the current passing through the series impedance of the branch in the direction from the from-bus end to the to-bus end, we can use the following function:

julia> magnitude, angle = seriesCurrent(system, analysis; label = "Branch 2")(0.026317641912190822, -0.6227571818622949)
diff --git a/v0.2.0/manual/acPowerFlow/index.html b/v0.2.0/manual/acPowerFlow/index.html new file mode 100644 index 000000000..d71487f18 --- /dev/null +++ b/v0.2.0/manual/acPowerFlow/index.html @@ -0,0 +1,337 @@ + +AC Power Flow · JuliaGrid

AC Power Flow

To perform the AC power flow analysis, we will first need the PowerSystem type that has been created with the AC model. Following that, we can construct the power flow model encapsulated within the ACPowerFlow type by employing one of the following functions:

These functions will set up the AC power flow framework. To obtain bus voltages and solve the power flow problem, we can use the following functions:

Additionally, the package provides two functions for reactive power limit validation of generators and adjusting the voltage angles to match an arbitrary bus angle:


After obtaining the AC power flow solution, JuliaGrid offers post-processing analysis functions for calculating powers and currents associated with buses, branches, or generators:

Additionally, specialized functions are available for calculating specific types of powers or currents for individual buses, branches, or generators.


Bus Type Modification

Depending on how the system is constructed, the types of buses that are initially set are checked and can be changed during the construction of the ACPowerFlow type.

Assuming the Newton-Raphson method has been chosen, to explain the details, we can observe a power system:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3)
+addBus!(system; label = "Bus 2", type = 2)
+addBus!(system; label = "Bus 3", type = 2)
+
+addGenerator!(system; bus = "Bus 2")
+
+analysis = newtonRaphson(system)

Initially, Bus 1 is set as the slack bus (type = 3), and Bus 2 and Bus 3 are generator buses (type = 2). However, Bus 3 does not have a generator, and JuliaGrid considers this a mistake and changes the corresponding bus to a demand bus (type = 1).

After this step, JuliaGrid verifies the slack bus. Initially, the slack bus (type = 3) corresponds to Bus 1, but since it does not have an in-service generator connected to it, JuliaGrid recognizes it as another mistake. Therefore, JuliaGrid assigns a new slack bus from the available generator buses (type = 2) that have connected in-service generators. In this specific example, Bus 2 becomes the new slack bus.

As a result, we can observe the updated array of bus types:

julia> print(system.bus.label, system.bus.layout.type)Bus 1: 1
+Bus 2: 3
+Bus 3: 1

Note that, if a bus is initially defined as the demand bus (type = 1) and later a generator is added to it, the bus type will not be changed to the generator bus (type = 2). Instead, it will remain as a demand bus.

Info

Only the type of these buses that are defined as generator buses (type = 2) but do not have a connected in-service generator will be changed to demand buses (type = 1).

The bus that is defined as the slack bus (type = 3) but lacks a connected in-service generator will have its type changed to the demand bus (type = 1). Meanwhile, the first generator bus (type = 2) with an in-service generator connected to it will be assigned as the new slack bus (type = 3).


Setup Starting Voltages

To begin analyzing the AC power flow in JuliaGrid, we must first establish the PowerSystem type. Once the power system is set up, we can select one of the available methods for solving the AC power flow problem, such as newtonRaphson, fastNewtonRaphsonBX, fastNewtonRaphsonXB, or gaussSeidel.

Assuming we have selected the Newton-Raphson method, we can use the following code snippet:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, magnitude = 1.0, angle = 0.0)
+addBus!(system; label = "Bus 2", type = 1, magnitude = 0.9, angle = -0.1)
+addBus!(system; label = "Bus 3", type = 2, magnitude = 0.8, angle = -0.2)
+
+addGenerator!(system; bus = "Bus 1", magnitude = 1.3)
+addGenerator!(system; bus = "Bus 2", magnitude = 1.1)
+addGenerator!(system; bus = "Bus 3", magnitude = 1.2)
+
+acModel!(system)
+analysis = newtonRaphson(system)

Here, the function newtonRaphson generates starting voltage vectors in polar coordinates.

The starting voltage magnitudes are set to:

julia> print(system.bus.label, analysis.voltage.magnitude)Bus 1: 1.3
+Bus 2: 0.9
+Bus 3: 1.2

This vector is created based on the bus types by selecting voltage magnitude values from the PowerSystem type, using the vectors:

julia> [system.bus.voltage.magnitude system.generator.voltage.magnitude]3×2 Matrix{Float64}:
+ 1.0  1.3
+ 0.9  1.1
+ 0.8  1.2

The starting voltage angles are set to:

julia> print(system.bus.label, analysis.voltage.angle)Bus 1: 0.0
+Bus 2: -0.1
+Bus 3: -0.2

This vector is derived from the voltage angle values in the PowerSystem type:

julia> system.bus.voltage.angle3-element Vector{Float64}:
+  0.0
+ -0.1
+ -0.2
Info

The rule governing the specification of starting voltage magnitudes is simple. If a bus has an in-service generator and is declared the generator bus (type = 2), then the starting voltage magnitudes are specified using the setpoint provided within the generator. This is because the generator bus has known values of voltage magnitude that are specified within the generator.

On the other hand, the slack bus (type = 3) always requires an in-service generator. The starting value of the voltage magnitude at the slack bus is determined exclusively by the setpoints provided within the generators connected to it. This is a result of the slack bus having a known voltage magnitude that must be maintained.

If there are multiple generators connected to the generator or slack bus, the initial voltage magnitude will align with the magnitude setpoint specified for the first in-service generator in the list.


Custom Starting Voltages

This method of specifying starting values has a significant advantage in that it allows the user to easily change the starting voltage magnitudes and angles, which play a crucial role in iterative methods. For instance, suppose we define our power system as follows:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, magnitude = 1.0, angle = 0.0)
+addBus!(system; label = "Bus 2", type = 1, magnitude = 0.9, angle = -0.1)
+addBus!(system; label = "Bus 3", type = 2, magnitude = 0.8, angle = -0.2)
+
+addGenerator!(system; bus = "Bus 1", magnitude = 1.1)
+addGenerator!(system; bus = "Bus 3", magnitude = 1.2)
+
+acModel!(system)

Now, the user can initiate a "flat start", this can be easily done as follows:

for i = 1:system.bus.number
+    system.bus.voltage.magnitude[i] = 1.0
+    system.bus.voltage.angle[i] = 0.0
+end
+
+analysis = newtonRaphson(system)

The starting voltage values are:

julia> print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)Bus 1: 1.1, 0.0
+Bus 2: 1.0, 0.0
+Bus 3: 1.2, 0.0

Consequently, the iteration begins with a fixed set of voltage magnitude values that remain constant throughout the iteration process. The remaining values are initialized as part of the "flat start" approach.


Power Flow Solution

To start, we will create a power system and define the AC model by invoking the acModel! function:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.5, magnitude = 0.9, angle = 0.0)
+addBus!(system; label = "Bus 2", type = 1, reactive = 0.05, magnitude = 1.1, angle = -0.1)
+addBus!(system; label = "Bus 3", type = 1, active = 0.5, magnitude = 1.0, angle = -0.2)
+
+@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 2", reactance = 0.01)
+addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", reactance = 0.04)
+
+@generator(active = 3.2)
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", magnitude = 1.1)
+addGenerator!(system; label = "Generator 2", bus = "Bus 2", magnitude = 1.2)
+
+acModel!(system)

Once the AC model is defined, we can choose the method to solve the power flow problem. JuliaGrid provides four methods: newtonRaphson, fastNewtonRaphsonBX, fastNewtonRaphsonXB, and gaussSeidel.

For example, to use the Newton-Raphson method to solve the power flow problem, we can use:

analysis = newtonRaphson(system)
Tip

By default, the user activates LU factorization to solve the system of linear equations within each iteration of the Newton-Raphson method. However, users can specifically opt for the QR factorization method:

analysis = newtonRaphson(system, QR)

The capability to change the factorization method is exclusively available for the Newton-Raphson and fast Newton-Raphson methods.

This function sets up the desired method for an iterative process based on two functions: mismatch! and solve!. The mismatch! function calculates the active and reactive power injection mismatches using the given voltage magnitudes and angles, while solve! computes the voltage magnitudes and angles.

To perform an iterative process with the Newton-Raphson or fast Newton-Raphson methods in JuliaGrid, the mismatch! function must be included inside the iteration loop. For instance:

for iteration = 1:100
+    mismatch!(system, analysis)
+    solve!(system, analysis)
+end

Upon completion of the AC power flow analysis, the solution is conveyed through the bus voltage magnitudes and angles. Here are the values corresponding to the buses:

julia> print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)Bus 1: 1.1, 0.0
+Bus 2: 1.1312984943545519, 0.022034582385283743
+Bus 3: 1.123144964293639, 0.005894335154140862

In contrast, the iterative loop of the Gauss-Seidel method does not require the mismatch! function:

analysis = gaussSeidel(system)
+for iteration = 1:100
+    solve!(system, analysis)
+end

In these examples, the algorithms run until the specified number of iterations is reached.

Info

We recommend that the reader refer to the tutorial on AC Power Flow Analysis, where we explain the implementation of the methods and algorithm structures in detail.


Breaking the Iterative Process

We can terminate the iterative process using the mismatch! function. The following code shows an example of how to use the function to break out of the iteration loop:

analysis = newtonRaphson(system)
+for iteration = 1:100
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        println("Solution Found.")
+        break
+    end
+    solve!(system, analysis)
+end
Solution Found.

The mismatch! function returns the maximum absolute values of active and reactive power injection mismatches, which are commonly used as a convergence criterion in iterative AC power flow algorithms. Note that the function can also be used to terminate the loop when using the Gauss-Seidel method, even though it is not required.

Tip

To ensure an accurate count of iterations, the user should place the iteration counter after the condition expressions within the if construct.


Combining Methods

The PowerSystem type, once created, can be shared among different methods, offering several advantages.

For instance, while the Gauss-Seidel method is commonly used to swiftly derive an approximate solution, the Newton-Raphson method is favored for obtaining precise final solutions. Hence, a strategy involves employing the Gauss-Seidel method for a limited number of iterations, followed by initializing the Newton-Raphson method with the voltages obtained from the Gauss-Seidel method, leveraging it as a starting point for further refinement:

gs = gaussSeidel(system)
+for iteration = 1:5
+    solve!(system, gs)
+end

Next, we can initialize the Newton-Raphson method with the voltages obtained from the Gauss-Seidel method and start the algorithm from that point:

analysis = newtonRaphson(system)
+
+for i = 1:system.bus.number
+    analysis.voltage.magnitude[i] = gs.voltage.magnitude[i]
+    analysis.voltage.angle[i] = gs.voltage.angle[i]
+end
+
+for iteration = 1:100
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
Info

The functions newtonRaphson, fastNewtonRaphsonBX, fastNewtonRaphsonXB, or gaussSeidel only modify the PowerSystem type to eliminate mistakes in the bus types as explained in the section Bus Type Modification. Further, the functions mismatch! and solve! do not modify the PowerSystem type at all. Therefore, it is safe to use the same PowerSystem type for multiple analyses once it has been created.


Users have the option to print the results in the REPL using any units that have been configured, such as:

@voltage(pu, deg, V)
+printBusData(system, analysis)
|----------------------------|
+| Bus Data                   |
+|----------------------------|
+| Label |      Voltage       |
+|       |                    |
+|   Bus | Magnitude |  Angle |
+|       |      [pu] |  [deg] |
+|-------|-----------|--------|
+| Bus 1 |    1.1000 | 0.0000 |
+| Bus 2 |    1.1313 | 1.2625 |
+| Bus 3 |    1.1231 | 0.3377 |
+|----------------------------|

Next, users can easily customize the print results for specific buses, for example:

printBusData(system, analysis; label = "Bus 1", header = true)
+printBusData(system, analysis; label = "Bus 2")
+printBusData(system, analysis; label = "Bus 3", footer = true)

Save Results to a File

Users can also redirect print output to a file. For example, data can be saved in a text file as follows:

open("bus.txt", "w") do file
+    printBusData(system, analysis, file)
+end

Save Results to a CSV File

For CSV output, users should first generate a simple table with style = false, and then save it to a CSV file:

using CSV
+
+io = IOBuffer()
+printBusData(system, analysis, io; style = false)
+CSV.write("bus.csv", CSV.File(take!(io); delim = "|"))

Power System Update

After establishing the PowerSystem type using the powerSystem function and configuring the AC model with acModel!, users gain the capability to incorporate new branches and generators. Furthermore, they can adjust buses, branches, and generators.

Once updates are done, users can progress towards generating the ACPowerFlow type using the newtonRaphson, fastNewtonRaphsonBX, fastNewtonRaphsonXB, or gaussSeidel function. Ultimately, resolving the AC power flow is achieved through the utilization of the mismatch! and solve! functions:

system = powerSystem() # <- Initialize the PowerSystem instance
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.5, magnitude = 0.9, angle = 0.0)
+addBus!(system; label = "Bus 2", type = 1, reactive = 0.05, magnitude = 1.1, angle = -0.1)
+
+@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", magnitude = 1.1, active = 3.2)
+
+acModel!(system)
+analysis = newtonRaphson(system) # <- Build ACPowerFlow for the defined power system
+for iteration = 1:100
+    mismatch!(system, analysis)
+    solve!(system, analysis)
+end
+
+updateBus!(system; label = "Bus 2", active = 0.2)
+
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 2", reactance = 1)
+updateBranch!(system; label = "Branch 1", status = 0)
+
+addGenerator!(system; label = "Generator 2", bus = "Bus 1", active = 0.2)
+updateGenerator!(system; label = "Generator 1", active = 0.3)
+
+analysis = newtonRaphson(system) # <- Build ACPowerFlow for the updated power system
+for iteration = 1:100
+    mismatch!(system, analysis)
+    solve!(system, analysis)
+end
Info

This concept removes the need to restart and recreate the PowerSystem within the ac field from the beginning when implementing changes to the existing power system.


Power Flow Update

An advanced methodology involves users establishing the ACPowerFlow type using newtonRaphson, fastNewtonRaphsonBX, fastNewtonRaphsonXB, or gaussSeidel just once. After this initial setup, users can integrate new branches and generators, and also have the capability to modify buses, branches, and generators, all without the need to recreate the ACPowerFlow type.

This advancement extends beyond the previous scenario where recreating the PowerSystem and AC model was unnecessary, to now include the scenario where ACPowerFlow also does not need to be recreated. Such efficiency proves particularly beneficial in cases where JuliaGrid can reuse established Jacobian matrices or even factorizations, especially when users choose the fast Newton-Raphson method.

By modifying the previous example, we observe that we now create the ACPowerFlow type only once using the newtonRaphson function. This approach allows us to circumvent the need for reinitializing the Jacobian matrix, enabling us to proceed directly with iterations:

system = powerSystem() # <- Initialize the PowerSystem instance
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.5, magnitude = 0.9, angle = 0.0)
+addBus!(system; label = "Bus 2", type = 1, reactive = 0.05, magnitude = 1.1, angle = -0.1)
+
+@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", magnitude = 1.1, active = 3.2)
+
+acModel!(system)
+analysis = newtonRaphson(system) # <- Build ACPowerFlow for the defined power system
+for iteration = 1:100
+    mismatch!(system, analysis)
+    solve!(system, analysis)
+end
+
+updateBus!(system, analysis; label = "Bus 2", active = 0.2)
+
+addBranch!(system, analysis; label = "Branch 2", from = "Bus 1", to = "Bus 2", reactance = 1)
+updateBranch!(system, analysis; label = "Branch 1", status = 0)
+
+addGenerator!(system, analysis; label = "Generator 2", bus = "Bus 1", active = 0.2)
+updateGenerator!(system, analysis; label = "Generator 1", active = 0.3)
+
+# <- No need for re-build; we have already updated the existing ACPowerFlow instance
+for iteration = 1:100
+    mismatch!(system, analysis)
+    solve!(system, analysis)
+end
Info

This concept removes the need to restart and recreate both the PowerSystem within the ac field and the ACPowerFlow from the beginning when implementing changes to the existing power system.


Fast Newton-Raphson: Reusing Jacobian Matrices Factorizations

An intriguing scenario unfolds when employing the fast Newton-Raphson method. Continuing from the previous example, let us now initialize the fast Newton-Raphson method and proceed with iterations as outlined below:

analysis = fastNewtonRaphsonBX(system)
+for iteration = 1:100
+    mismatch!(system, analysis)
+    solve!(system, analysis)
+end

Throughout this process, JuliaGrid will factorize the constant Jacobian matrices that govern the fast Newton-Raphson method.

Now, let us make changes to the power system and proceed directly to the iteration step:

updateBus!(system, analysis; label = "Bus 2", reactive = 0.02)
+updateGenerator!(system, analysis; label = "Generator 1", reactive = 0.1)
+
+for iteration = 1:100
+    mismatch!(system, analysis)
+    solve!(system, analysis)
+end
Info

In this scenario, JuliaGrid identifies cases where the user has not altered parameters that impact the Jacobian matrices. Consequently, JuliaGrid efficiently utilizes the previously performed factorizations, leading to a notably faster solution compared to recomputing the factorization process.


Warm Start

In these scenarios, users leverage the previously created PowerSystem type with the AC model and also reuse the ACPowerFlow type, proceeding directly to the iterations. This approach offers the advantage of a "warm start", wherein the initial voltages for the subsequent iteration step align with the solution from the previous iteration step. This alignment facilitates an efficient continuation of the power flow analysis.

Let us now make another alteration to the power system:

updateBus!(system, analysis; label = "Bus 1", active = 0.1, magnitude = 0.95, angle = -0.07)
+updateGenerator!(system, analysis; label = "Generator 2", reactive = 0.2, magnitude = 1.1)

With these modifications we are not only altering the power system, but also starting voltages. For the next uses of one of the methods, these values now are:

julia> print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)Bus 1: 1.1, -0.07
+Bus 2: 1.0839300986879146, -0.16864600045398928

Therefore, users possess the flexibility to adjust these initial values as needed by employing the magnitude and angle keywords within the updateBus! and updateGenerator! functions.

If users prefer to set starting voltages according to the typical scenario, they can accomplish this through the startingVoltage! function:

startingVoltage!(system, analysis)

Now, we have starting voltages defined exclusively according to the PowerSystem. These values are exactly the same as if we executed the newtonRaphson, fastNewtonRaphsonBX, fastNewtonRaphsonXB, or gaussSeidel function after all the updates we performed:

julia> print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)Bus 1: 1.1, -0.07
+Bus 2: 1.1, -0.1

Limitations

The newtonRaphson, fastNewtonRaphsonBX, fastNewtonRaphsonXB, or gaussSeidel function oversees bus type validations, as outlined in the Bus Type Modification section. Consequently, attempting to change bus types or leaving generator buses without a generator and then proceeding directly to the iteration process is not viable.

In such scenarios, JuliaGrid will raise an error:

julia> updateBus!(system, analysis; label = "Bus 2", type = 2)ERROR: The power flow model cannot be reused due to required bus type conversion.

In this scenario, the user must execute the newtonRaphson, fastNewtonRaphsonBX, fastNewtonRaphsonXB, or gaussSeidel function instead of trying to reuse them, for example:

updateBus!(system; label = "Bus 2", type = 2)
+
+analysis = fastNewtonRaphsonBX(system)
+for iteration = 1:100
+    mismatch!(system, analysis)
+    solve!(system, analysis)
+end
Info

After creating the PowerSystem and ACPowerFlow types, users can add or modify buses, branches, and generators before directly proceeding to iterations. JuliaGrid automatically executes the necessary functions when adjustments lead to a valid solution. However, if modifications are incompatible, like altering bus types, JuliaGrid raises an error to prevent misleading outcomes, ensuring accuracy.


Power and Current Analysis

After obtaining the solution from the AC power flow, we can calculate various electrical quantities related to buses, branches, and generators using the power! and current! functions. For instance, let us consider the power system for which we obtained the AC power flow solution:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.6)
+addBus!(system; label = "Bus 2", type = 1, reactive = 0.1, susceptance = 0.03)
+addBus!(system; label = "Bus 3", type = 1, conductance = 0.02)
+
+@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.5)
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 2", reactance = 0.1)
+addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", reactance = 0.4)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 0.2)
+addGenerator!(system; label = "Generator 2", bus = "Bus 2", active = 1.0, reactive = 0.2)
+
+analysis = newtonRaphson(system)
+for iteration = 1:100
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end

We can now utilize the provided functions to compute powers and currents:

power!(system, analysis)
+current!(system, analysis)

For instance, if we want to show the active power injections and the to-bus current angles, we can employ the following code:

julia> print(system.bus.label, analysis.power.injection.active)Bus 1: -0.9645033643807599
+Bus 2: 1.0000000022772795
+Bus 3: -4.359533802980213e-10
julia> print(system.branch.label, analysis.current.to.angle)Branch 1: -0.15017765586673948 +Branch 2: -0.08939059735692804 +Branch 3: -3.073480808526896
Info

To better understand the powers and currents associated with buses, branches, and generators that are obtained by the power! and current! functions, we suggest referring to the tutorials on AC Power Flow Analysis.


Users can utilize any of the print functions outlined in the Print Power System Data or Print Power System Summary. For example, to create a bus summary with the desired units, users can use the following function:

@voltage(pu, deg, V)
+@power(MW, MVAr, pu)
+printBusSummary(system, analysis)
|----------------------------------------------------------------------------|
+| Bus Summary                                                                |
+|----------------------------------------------------------------------------|
+|       Type        |     Minimum      |     Maximum      | In-Use |  Total  |
+|                   |                  |                  |        |         |
+|                   | Label |    Value | Label |    Value |        |         |
+|-------------------|-------|----------|-------|----------|--------|---------|
+| Voltage           |       |          |       |          |      3 |         |
+|  Magnitude [pu]   | Bus 1 |   1.0000 | Bus 3 |   1.0362 |        |         |
+|  Angle [deg]      | Bus 1 |   0.0000 | Bus 2 |   4.3886 |        |         |
+|-------------------|-------|----------|-------|----------|--------|---------|
+| Power Generation  |       |          |       |          |      1 |         |
+|  Active [MW]      | Bus 3 |   0.0000 | Bus 3 |   0.0000 |        |  0.0000 |
+|  Reactive [MVAr]  | Bus 3 |   0.0000 | Bus 3 |   0.0000 |        |  0.0000 |
+|-------------------|-------|----------|-------|----------|--------|---------|
+| Power Demand      |       |          |       |          |      2 |         |
+|  Active [MW]      | Bus 2 |   0.0000 | Bus 1 |  60.0000 |        | 60.0000 |
+|  Reactive [MVAr]  | Bus 1 |   0.0000 | Bus 2 |  10.0000 |        | 10.0000 |
+|-------------------|-------|----------|-------|----------|--------|---------|
+| Power Injection   |       |          |       |          |      3 |         |
+|  Active [MW]      | Bus 1 | -96.4503 | Bus 2 | 100.0000 |        |  3.5497 |
+|  Reactive [MVAr]  | Bus 1 | -17.6931 | Bus 2 |  10.0000 |        | -7.6931 |
+|-------------------|-------|----------|-------|----------|--------|---------|
+| Shunt Power       |       |          |       |          |      2 |         |
+|  Active [MW]      | Bus 2 |   0.0000 | Bus 3 |   2.1475 |        |  2.1475 |
+|  Reactive [MVAr]  | Bus 2 |  -3.1727 | Bus 3 |  -0.0000 |        | -3.1727 |
+|-------------------|-------|----------|-------|----------|--------|---------|
+| Current Injection |       |          |       |          |      3 |         |
+|  Magnitude [pu]   | Bus 3 |   0.0000 | Bus 1 |   0.9806 |        |         |
+|  Angle [rad]      | Bus 3 |  -2.7799 | Bus 1 |   2.9602 |        |         |
+|----------------------------------------------------------------------------|

Active and Reactive Power Injection

To calculate the active and reactive power injection associated with a specific bus, the function can be used:

julia> active, reactive = injectionPower(system, analysis; label = "Bus 1")(-0.9645033643807599, -0.17693071258892878)

Active and Reactive Power Injection from Generators

To calculate the active and reactive power injection from the generators at a specific bus, the function can be used:

julia> active, reactive = supplyPower(system, analysis; label = "Bus 1")(-0.3645033643807599, -0.17693071258892878)

Active and Reactive Power at Shunt Element

To calculate the active and reactive power associated with shunt element at a specific bus, the function can be used:

julia> active, reactive = shuntPower(system, analysis; label = "Bus 3")(0.021474952575336232, -0.0)

Active and Reactive Power Flow

Similarly, we can compute the active and reactive power flow at both the from-bus and to-bus ends of the specific branch by utilizing the functions provided below:

julia> active, reactive = fromPower(system, analysis; label = "Branch 2")(-0.8053928587014492, -0.11256618205670144)
julia> active, reactive = toPower(system, analysis; label = "Branch 2")(0.8186418709823436, 0.13714551291797428)

Active and Reactive Power at Charging Admittances

To calculate the active and reactive power linked with branch charging admittances of the particular branch, the function can be used:

julia> active, reactive = chargingPower(system, analysis; label = "Branch 1")(0.00010287834702025066, -0.04115133880810026)

Active powers indicate active losses within the branch's charging admittances. Moreover, charging admittances injected reactive powers into the power system due to their capacitive nature.


Active and Reactive Power at Series Impedance

To calculate the active and reactive power across the series impedance of the branch, the function can be used:

julia> active, reactive = seriesPower(system, analysis; label = "Branch 2")(0.013146133933874347, 0.06573066966937174)

The active power also considers active losses originating from the series resistance of the branch, while the reactive power represents reactive losses resulting from the impedance's inductive characteristics.


Generator Active and Reactive Power Output

We can compute the active and reactive power output of a particular generator using the function:

julia> active, reactive = generatorPower(system, analysis; label = "Generator 1")(-0.3645033643807599, -0.17693071258892878)

Current Injection

To calculate the current injection associated with a specific bus, the function can be used:

julia> magnitude, angle = injectionCurrent(system, analysis; label = "Bus 1")(0.9805973776015471, 2.9601674608926722)

Current Flow

We can compute the current flow at both the from-bus and to-bus ends of the specific branch by utilizing the provided functions below:

julia> magnitude, angle = fromCurrent(system, analysis; label = "Branch 2")(0.8132212504540907, 3.0027266550776193)
julia> magnitude, angle = toCurrent(system, analysis; label = "Branch 2")(0.807142930926126, -0.08939059735692804)

Current Through Series Impedance

To calculate the current passing through the series impedance of the branch in the direction from the from-bus end to the to-bus end, we can use the following function:

julia> magnitude, angle = seriesCurrent(system, analysis; label = "Branch 2")(0.8107445323242811, 3.027168837917323)

Generator Reactive Power Limits

The function reactiveLimit! can be used to check if the generators' output of reactive power is within the defined limits after obtaining the solution from the AC power flow analysis:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3)
+addBus!(system; label = "Bus 2", type = 1, active = 0.5)
+addBus!(system; label = "Bus 3", type = 2, reactive = 0.05)
+addBus!(system; label = "Bus 4", type = 2, reactive = 0.05)
+
+@branch(resistance = 0.015)
+addBranch!(system; from = "Bus 1", to = "Bus 2", reactance = 0.05)
+addBranch!(system; from = "Bus 1", to = "Bus 3", reactance = 0.01)
+addBranch!(system; from = "Bus 2", to = "Bus 3", reactance = 0.04)
+addBranch!(system; from = "Bus 2", to = "Bus 4", reactance = 0.004)
+
+@generator(minReactive = -0.4, maxReactive = 0.1)
+addGenerator!(system; label = "Generator 1", bus = "Bus 1")
+addGenerator!(system; label = "Generator 2", bus = "Bus 3", reactive = 0.8)
+addGenerator!(system; label = "Generator 3", bus = "Bus 4", reactive = 0.9)
+
+analysis = newtonRaphson(system)
+for iteration = 1:100
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+
+violate = reactiveLimit!(system, analysis)

The output reactive power of the observed generators is subject to limits which are defined as follows:

julia> [system.generator.capability.minReactive system.generator.capability.maxReactive]3×2 Matrix{Float64}:
+ -0.4  0.1
+ -0.4  0.1
+ -0.4  0.1

After obtaining the solution of the AC power flow analysis, the reactiveLimit! function is used to internally calculate the output powers of the generators and verify if these values exceed the defined limits. Consequently, the variable violate indicates whether there is a violation of limits.

In the provided example, it can be observed that the Generator 2 and Generator 3 violate the maximum limit:

julia> print(system.generator.label, violate)Generator 1: 0
+Generator 2: 1
+Generator 3: 1

Due to these violations of limits, the PowerSystem type undergoes modifications, and the output reactive power at the limit-violating generators is adjusted as follows:

julia> print(system.generator.label, system.generator.output.reactive)Generator 1: 0.0
+Generator 2: 0.1
+Generator 3: 0.1

To ensure that these values stay within the limits, the bus type must be changed from the generator bus (type = 2) to the demand bus (type = 1), as shown below:

julia> print(system.bus.label, system.bus.layout.type)Bus 1: 3
+Bus 2: 1
+Bus 3: 1
+Bus 4: 1

After modifying the PowerSystem type as described earlier, we can run the simulation again with the following code:

analysis = newtonRaphson(system)
+for iteration = 1:100
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end

Once the simulation is complete, we can verify that all generator reactive power outputs now satisfy the limits by checking the violate variable again:

julia> violate = reactiveLimit!(system, analysis)3-element Vector{Int64}:
+ 0
+ 0
+ 0
Info

The reactiveLimit! function changes the PowerSystem type deliberately because it is intended to help users create the power system where all reactive power outputs of the generators are within limits.


New Slack Bus

Looking at the following code example, we can see that the output limits of the generator are set only for Generator 1 that is connected to the slack bus:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.5, reactive = 0.05)
+addBus!(system; label = "Bus 2", type = 1, active = 0.5)
+addBus!(system; label = "Bus 3", type = 2)
+addBus!(system; label = "Bus 4", type = 2)
+
+@branch(resistance = 0.01)
+addBranch!(system; from = "Bus 1", to = "Bus 2", reactance = 0.05)
+addBranch!(system; from = "Bus 1", to = "Bus 3", reactance = 0.01)
+addBranch!(system; from = "Bus 2", to = "Bus 3", reactance = 0.04)
+addBranch!(system; from = "Bus 2", to = "Bus 4", reactance = 0.004)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", maxReactive = 0.2)
+addGenerator!(system; label = "Generator 2", bus = "Bus 4", reactive = 0.3)
+
+analysis = newtonRaphson(system)
+for iteration = 1:100
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end

Upon checking the limits, we can observe that the slack bus has been transformed by executing the following code:

julia> violate = reactiveLimit!(system, analysis)[ Info: The slack bus labeled Bus 1 is converted to generator bus. The bus labeled Bus 4 is the new slack bus.
+2-element Vector{Int64}:
+ -1
+  0

Here, the generator connected to the slack bus is violating the minimum reactive power limit, which indicates the need to convert the slack bus. It is important to note that the new slack bus can be created only from the generator bus (type = 2). We will now perform another AC power flow analysis on the modified system using the following:

analysis = newtonRaphson(system)
+for iteration = 1:100
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end

After examining the bus voltages, we will focus on the angles:

julia> print(system.bus.label, analysis.voltage.angle)Bus 1: 0.013581064245677444
+Bus 2: 0.0005651921742472857
+Bus 3: 0.01069570666159161
+Bus 4: 0.0

We can observe that the angles have been calculated based on the new slack bus. JuliaGrid offers the function to adjust these angles to match the original slack bus as follows:

adjustAngle!(system, analysis; slack = "Bus 1")

After executing the above code, the updated results can be viewed:

julia> print(system.bus.label, analysis.voltage.angle)Bus 1: 0.0
+Bus 2: -0.013015872071430158
+Bus 3: -0.0028853575840858334
+Bus 4: -0.013581064245677444
diff --git a/v0.2.0/manual/acStateEstimation/index.html b/v0.2.0/manual/acStateEstimation/index.html new file mode 100644 index 000000000..7f13e4c58 --- /dev/null +++ b/v0.2.0/manual/acStateEstimation/index.html @@ -0,0 +1,333 @@ + +AC State Estimation · JuliaGrid

AC State Estimation

To perform nonlinear or AC state estimation, the initial requirement is to have the PowerSystem type configured with the AC model, along with the Measurement type storing measurement data. Next, we can develop either the weighted least-squares (WLS) model, utilizing the Gauss-Newton method, or the least absolute value (LAV) model. These models are encapsulated within the ACStateEstimation type:

For resolving the AC state estimation problem and obtaining bus voltage magnitudes and angles, utilize the following function:

After executing the function solve!, where the user employs the Gauss-Newton method, the user has the ability to check if the measurement set contains outliers throughout bad data analysis and remove those measurements using:

Moreover, before the creating ACStateEstimation type, users can initiate observability analysis to identify observable islands and restore observability by employing:


After obtaining the AC state estimation solution, JuliaGrid offers post-processing analysis functions for calculating powers and currents associated with buses and branches:

Additionally, specialized functions are available for calculating specific types of powers or currents for individual buses or branches.


Bus Type Modification

In AC state estimation, it is necessary to designate a slack bus, where the bus voltage angle is known. Therefore, when establishing the ACStateEstimation type, the initially assigned slack bus is evaluated and may be altered. If the designated slack bus (type = 3) lacks a connected in-service generator, it will be changed to a demand bus (type = 1). Conversely, the first generator bus (type = 2) with an active in-service generator linked to it will be reassigned as the new slack bus (type = 3).


Observability Analysis

To initiate the power system with measurements at specific locations, follow the provided example:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", type = 3)
+addBus!(system; label = "Bus 2", type = 1, active = 0.1, reactive = 0.01)
+addBus!(system; label = "Bus 3", type = 2, active = 0.5, reactive = 0.01)
+addBus!(system; label = "Bus 4", type = 1, active = 0.2, reactive = 0.02)
+addBus!(system; label = "Bus 5", type = 1, active = 0.3, reactive = 0.03)
+addBus!(system; label = "Bus 6", type = 1, active = 0.1, reactive = 0.01)
+addBus!(system; label = "Bus 7", type = 1, active = 0.1, reactive = 0.01)
+
+@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.002)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+addBranch!(system; label = "Branch 2", from = "Bus 2", to = "Bus 3", reactance = 0.01)
+addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 5", reactance = 0.02)
+addBranch!(system; label = "Branch 4", from = "Bus 3", to = "Bus 4", reactance = 0.03)
+addBranch!(system; label = "Branch 5", from = "Bus 5", to = "Bus 6", reactance = 0.05)
+addBranch!(system; label = "Branch 6", from = "Bus 3", to = "Bus 5", reactance = 0.05)
+addBranch!(system; label = "Branch 7", from = "Bus 6", to = "Bus 7", reactance = 0.05)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 4.2, reactive = 0.2)
+addGenerator!(system; label = "Generator 2", bus = "Bus 3", active = 0.2, reactive = 0.1)
+
+addWattmeter!(system, device; label = "Wattmeter 1", from = "Branch 1", active = 1.15)
+addVarmeter!(system, device; label = "Varmeter 1", from = "Branch 1", reactive = -0.50)
+
+addWattmeter!(system, device; label = "Wattmeter 2", from = "Branch 4", active = 0.20)
+addVarmeter!(system, device; label = "Varmeter 2", from = "Branch 4", reactive = -0.02)
+
+addWattmeter!(system, device; label = "Wattmeter 3", from = "Branch 5", active = -0.20)
+addVarmeter!(system, device; label = "Varmeter 3", from = "Branch 5", reactive = 0.02)
+
+addWattmeter!(system, device; label = "Wattmeter 4", bus = "Bus 2", active = -0.1)
+addVarmeter!(system, device; label = "Varmeter 4", bus = "Bus 2", reactive = -0.01)
+
+addWattmeter!(system, device; label = "Wattmeter 5", bus = "Bus 3", active = -0.30)
+addVarmeter!(system, device; label = "Varmeter 5", bus = "Bus 3", reactive = 0.66)

Attempting to solve this system immediately may not be possible because the gain matrix will be singular. To avoid this situation, users can perform observability analysis.

JuliaGrid employs standard observability analysis performed on the linear decoupled measurement model. Active power measurements from wattmeters are utilized to estimate bus voltage angles, while reactive power measurements from varmeters are used to estimate bus voltage magnitudes. This necessitates that measurements of active and reactive power come in pairs.

Info

We suggest that readers refer to the tutorial on Observability Analysis for insights into the implementation.

However, the initial step involves defining observable islands. JuliaGrid offers users two options for obtaining observable islands: flow observable islands or maximal observable islands. The selection depends on the power system's structure and available measurements. Identifying only flow observable islands reduces complexity in the island detection function, but increases complexity in the restoration function.


Flow Observable Islands

Now, let us identify flow observable islands:

islands = islandTopologicalFlow(system, device)

As a result, four flow observable islands are identified: Bus 1 and Bus 2 form the first island, Bus 3 and Bus 4 form the second island, Bus 5 and Bus 6 constitute the third island, while Bus 7 forms the fourth island:

julia> islands.island4-element Vector{Vector{Int64}}:
+ [1, 2]
+ [3, 4]
+ [5, 6]
+ [7]

Maximal Observable Islands

Following that, we will instruct the user on obtaining maximal observable islands:

islands = islandTopological(system, device)

The outcome reveals the identification of two maximal observable islands:

julia> islands.island2-element Vector{Vector{Int64}}:
+ [1, 2, 3, 4, 5, 6]
+ [7]

It is evident that upon comparing this result with the flow islands, the merging of the two injection measurements at Bus 2 and Bus 3 consolidated the first, second, and third flow observable islands into a single island.


Restore Observability

Before commencing the restoration of observability in the context of the linear decoupled measurement model and observability analysis, it is imperative to ensure that the system possesses one bus voltage magnitude measurement. This necessity arises from the fact that observable islands are identified based on wattmeters, where wattmeters are tasked with estimating voltage angles. Since one voltage angle is already known from the slack bus, the same principle should be applied to bus voltage magnitudes. Therefore, to address this requirement, we add:

addVoltmeter!(system, device; bus = "Bus 1", magnitude = 1.0)

Subsequently, the user needs to establish a set of pseudo-measurements, where measurements must come in pairs as well. Let us create that set:

pseudo = measurement()
+
+addWattmeter!(system, pseudo; label = "Pseudo-Wattmeter 1", bus = "Bus 1", active = 0.31)
+addVarmeter!(system, pseudo; label = "Pseudo-Varmeter 1", bus = "Bus 1", reactive = -0.19)
+
+addWattmeter!(system, pseudo; label = "Pseudo-Wattmeter 2", from = "Branch 7", active = 0.10)
+addVarmeter!(system, pseudo; label = "Pseudo-Varmeter 2", from = "Branch 7", reactive = 0.01)
Info

The labels for specific pseudo-measurements must differ from those defined in the measurements stored in the device set. This is necessary because the next step involves adding pseudo-measurements to the device set.

Subsequently, the user can execute the restorationGram! function:

restorationGram!(system, device, pseudo, islands)

This function attempts to restore observability using pseudo-measurements. As a result, the inclusion of measurements from Pseudo-Wattmeter 2 and Pseudo-Varmeter 2 facilitates observability restoration, and these measurements are subsequently added to the device variable:

julia> device.wattmeter.labelOrderedCollections.OrderedDict{String, Int64} with 6 entries:
+  "Wattmeter 1"        => 1
+  "Wattmeter 2"        => 2
+  "Wattmeter 3"        => 3
+  "Wattmeter 4"        => 4
+  "Wattmeter 5"        => 5
+  "Pseudo-Wattmeter 2" => 6
julia> device.varmeter.labelOrderedCollections.OrderedDict{String, Int64} with 6 entries: + "Varmeter 1" => 1 + "Varmeter 2" => 2 + "Varmeter 3" => 3 + "Varmeter 4" => 4 + "Varmeter 5" => 5 + "Pseudo-Varmeter 2" => 6

Consequently, the power system becomes observable, allowing the user to proceed with forming the AC state estimation model and solving it. Ensuring the observability of the system does not guarantee obtaining accurate estimates of the state variables. Numerical ill-conditioning may adversely impact the state estimation algorithm. However, in most cases, efficient estimation becomes feasible when the system is observable [2].

Additionally, it is worth mentioning that restoration might encounter difficulties due to the default zero pivot threshold set at 1e-5. This threshold can be modified using the restorationGram! function.

Info

During the restoration step, if users define bus phasor measurements, these measurements will be considered. Consequently, the system may achieve observability even if multiple islands persist.


Weighted Least-Squares Estimator

To begin, we will define the PowerSystem and Measurement types:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", type = 3)
+addBus!(system; label = "Bus 2", type = 1, active = 0.1, reactive = 0.01)
+addBus!(system; label = "Bus 3", type = 1, active = 2.5, reactive = 0.2)
+
+@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 3", reactance = 0.05)
+addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", reactance = 0.03)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 3.2, reactive = 0.3)
+
+@voltmeter(label = "Voltmeter ? (!)")
+addVoltmeter!(system, device; bus = "Bus 1", magnitude = 1.0, variance = 1e-2)
+
+@ammeter(label = "Ammeter ? (!)")
+addAmmeter!(system, device; from = "Branch 3", magnitude = 0.947, variance = 1e-1)
+addAmmeter!(system, device; to = "Branch 2", magnitude = 1.674, variance = 1e-1)
+
+@wattmeter(label = "Wattmeter ? (!)")
+addWattmeter!(system, device; from = "Branch 1", active = 1.046, variance = 1e-3)
+addWattmeter!(system, device; bus = "Bus 2", active = -0.1, variance = 2e-3)
+
+@varmeter(label = "Varmeter ? (!)")
+addVarmeter!(system, device; from = "Branch 1", reactive = 0.059, variance = 1e-4)
+addVarmeter!(system, device; bus = "Bus 2", reactive = -0.01, variance = 1e-3)

Next, to establish the AC state estimation model, we will utilize the gaussNewton function:

analysis = gaussNewton(system, device)
Tip

Here, the user triggers LU factorization as the default method for solving the system of linear equations within each iteration of the Gauss-Newton method. However, the user also has the option to select alternative factorization methods such as LDLt or QR:

analysis = gaussNewton(system, device, LDLt)

Setup Starting Voltages

The initial voltages for the Gauss-Newton method are determined based on the specified initial voltage magnitudes and angles within the buses of the PowerSystem type. These values are then forwarded to the ACStateEstimation during the execution of the gaussNewton function. Therefore, the starting voltages in this example are as follows:

julia> print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)Bus 1: 1.0, 0.0
+Bus 2: 1.0, 0.0
+Bus 3: 1.0, 0.0

Users have the flexibility to modify these vectors according to their own requirements in order to adjust the starting voltages. For instance, users can conduct an initial AC power flow analysis and utilize the obtained solution as the starting voltages for AC state estimation:

powerFlow = newtonRaphson(system)
+for iteration = 1:10
+    mismatch!(system, powerFlow)
+    solve!(system, powerFlow)
+end
+
+for i = 1:system.bus.number
+    analysis.voltage.magnitude[i] = powerFlow.voltage.magnitude[i]
+    analysis.voltage.angle[i] = powerFlow.voltage.angle[i]
+end

State Estimator

To conduct an iterative process using the Gauss-Newton method, it is essential to include the solve! function inside the iteration loop. For example:

for iteration = 1:20
+    solve!(system, analysis)
+end

Once the state estimator is obtained, users can access the bus voltage magnitudes and angles using:

julia> print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)Bus 1: 0.9999492012048251, 0.0
+Bus 2: 0.9763971958413055, -0.05196984653510681
+Bus 3: 0.9562624707681646, -0.08054149367597971

Breaking the Iterative Process

The iterative process can be terminated using the solve! function. The following code demonstrates how to utilize this function to break out of the iteration loop:

analysis = gaussNewton(system, device)
+for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        println("Solution Found.")
+        break
+    end
+end
Solution Found.

The solve! function returns the maximum absolute values of the state variable increment, which are commonly used as a convergence criterion in the iterative Gauss-Newton algorithm.

Info

We suggest that readers refer to the tutorial on AC State Estimation for insights into the implementation.


Inclusion of PMUs in Rectangular Coordinates

In the example above, our focus is solely on solving the AC state estimation using SCADA measurements. However, users have the option to also integrate PMUs into the AC state estimation, either in the rectangular or polar coordinate system.

The default approach is to include PMUs in the rectangular coordinate system:

@pmu(label = "PMU ? (!)")
+addPmu!(system, device; to = "Branch 1", magnitude = 1.05, angle = 3.047)

In the case of the rectangular system, inclusion resolves ill-conditioned problems arising in polar coordinates due to small values of current magnitudes. However, this approach's main disadvantage is related to measurement errors, as measurement errors correspond to polar coordinates. Therefore, the covariance matrix must be transformed from polar to rectangular coordinates [3]. As a result, measurement errors of a single PMU are correlated, and the covariance matrix does not have a diagonal form. Despite that, the measurement error covariance matrix is usually considered as a diagonal matrix, affecting the accuracy of the state estimation.

In the example above, we specifically include PMUs where measurement error correlations are disregarded. This is evident through the precision matrix, which maintains a diagonal form:

julia> analysis = gaussNewton(system, device);
julia> analysis.method.precision9×9 SparseArrays.SparseMatrixCSC{Float64, Int64} with 9 stored entries: + 100.0 ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ + ⋅ 10.0 ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ 10.0 ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ 1000.0 ⋅ ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ 500.0 ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ ⋅ 10000.0 ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1000.0 ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 99908.6 ⋅ + ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 90778.2

Lastly, we incorporate correlation into our model by adding a new PMU with the desired error correlation:

addPmu!(system, device; bus = "Bus 3", magnitude = 0.95, angle = -0.08, correlated = true)

Now, we can observe the precision matrix that does not hold a diagonal form:

julia> analysis = gaussNewton(system, device);
julia> analysis.method.precision11×11 SparseArrays.SparseMatrixCSC{Float64, Int64} with 13 stored entries: + 100.0 ⋅ ⋅ ⋅ ⋅ … ⋅ ⋅ ⋅ + ⋅ 10.0 ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ 10.0 ⋅ ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ 1000.0 ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ 500.0 ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ ⋅ … ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ ⋅ 90778.2 ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 100069.0 860.583 + ⋅ ⋅ ⋅ ⋅ ⋅ … ⋅ 860.583 1.10734e5

Inclusion of PMUs in Polar Coordinates

The second approach involves incorporating these measurements into the polar coordinate system. For instance:

addPmu!(system, device; from = "Branch 1", magnitude = 1.048, angle = -0.057, polar = true)

This inclusion of PMUs provides more accurate state estimates compared to rectangular inclusion, but demands longer computing time. PMUs are handled in the same manner as SCADA measurements. However, this approach is susceptible to ill-conditioned problems arising in polar coordinates due to small values of current magnitudes [3, 4].

Tip

It is important to note that with each individual phasor measurement, we can set the coordinate system, providing flexibility to include some in polar and some in rectangular systems. This flexibility is particularly valuable because bus voltage phasor measurements are preferably included in a polar coordinate system, while current phasor measurements are best suited to a rectangular coordinate system.


Alternative Formulation

The resolution of the WLS state estimation problem using the conventional method typically progresses smoothly. However, it is widely acknowledged that in certain situations common to real-world systems, this method can be vulnerable to numerical instabilities. Such conditions might impede the algorithm from finding a satisfactory solution. In such cases, users may opt for an alternative formulation of the WLS state estimation, namely, employing an approach called orthogonal factorization [5, Sec. 3.2].

This approach is suitable when measurement errors are uncorrelated, and the precision matrix remains diagonal. Therefore, as a preliminary step, we need to eliminate the correlation, as we did previously:

updatePmu!(system, device; label = "PMU 2 (Bus 3)", correlated = false)

Subsequently, by specifying the Orthogonal argument in the gaussNewton function, JuliaGrid implements a more robust approach to obtain the WLS estimator, which proves particularly beneficial when substantial differences exist among measurement variances:

analysis = gaussNewton(system, device, Orthogonal)
+for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        break
+    end
+end

Users have the option to print the results in the REPL using any units that have been configured, such as:

@voltage(pu, deg, V)
+printBusData(system, analysis)
|-----------------------------|
+| Bus Data                    |
+|-----------------------------|
+| Label |       Voltage       |
+|       |                     |
+|   Bus | Magnitude |   Angle |
+|       |      [pu] |   [deg] |
+|-------|-----------|---------|
+| Bus 1 |    0.9938 |  0.0000 |
+| Bus 2 |    0.9702 | -2.9966 |
+| Bus 3 |    0.9501 | -4.6319 |
+|-----------------------------|

Next, users can easily customize the print results for specific buses, for example:

printBusData(system, analysis; label = "Bus 1", header = true)
+printBusData(system, analysis; label = "Bus 2")
+printBusData(system, analysis; label = "Bus 3", footer = true)

Save Results to a File

Users can also redirect print output to a file. For example, data can be saved in a text file as follows:

open("bus.txt", "w") do file
+    printBusData(system, analysis, file)
+end
Tip

We also provide functions to print or save state estimation results, such as estimated values and residuals. For more details, users can consult the Power and Current Analysis section of this manual.


Bad Data Processing

After acquiring the WLS solution using the Gauss-Newton method, users can conduct bad data analysis employing the largest normalized residual test. Continuing with our defined power system and measurement set, let us introduce a new measurement. Upon proceeding to find the solution for this updated state:

addWattmeter!(system, device; from = "Branch 2", active = 31.1)
+
+analysis = gaussNewton(system, device)
+for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        break
+    end
+end

Here, we can observe the impact of the outlier on the solution:

julia> print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)Bus 1: 1.1056340315956998, 0.0
+Bus 2: 1.0813928031976308, -0.04784530109433746
+Bus 3: 1.0117796176799676, -0.1652821329710149

Following the solution acquisition, we can verify the presence of erroneous data. Detection of such data is determined by the threshold keyword. If the largest normalized residual's value exceeds the threshold, the measurement will be identified as bad data and consequently removed from the AC state estimation model:

outlier = residualTest!(system, device, analysis; threshold = 4.0)

Users can examine the data obtained from the bad data analysis:

julia> outlier.detecttrue
julia> outlier.maxNormalizedResidual282.71971026036334
julia> outlier.label"Wattmeter 3 (From Branch 2)"

Hence, upon detecting bad data, the detect variable will hold true. The maxNormalizedResidual variable retains the value of the largest normalized residual, while the label contains the label of the measurement identified as bad data. JuliaGrid will mark the respective measurement as out-of-service within the Measurement type.

After removing bad data, a new estimate can be computed without considering this specific measurement. The user has the option to either restart the gaussNewton function or proceed directly to the iteration loop. However, if the latter option is chosen, using voltages obtained with outlier presence as the starting point could significantly impede algorithm convergence. To avoid this undesirable outcome, the user should first establish a new starting point and commence the iteration procedure. For instance:

for i = 1:system.bus.number
+    analysis.voltage.magnitude[i] = system.bus.voltage.magnitude[i]
+    analysis.voltage.angle[i] = system.bus.voltage.angle[i]
+end
+
+for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        break
+    end
+end

Consequently, we obtain a new solution devoid of the impact of the outlier measurement:

julia> print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)Bus 1: 0.9938191289507476, 0.0
+Bus 2: 0.9702353516839952, -0.05230134628742846
+Bus 3: 0.9501354580385983, -0.08084132445043372
Info

We suggest that readers refer to the tutorial on Bad Data Processing for insights into the implementation.


Least Absolute Value Estimator

The LAV method presents an alternative estimation technique known for its increased robustness compared to WLS. While the WLS method relies on specific assumptions regarding measurement errors, robust estimators like LAV are designed to maintain unbiasedness even in the presence of various types of measurement errors and outliers. This characteristic often eliminates the need for extensive bad data processing procedures [5, Ch. 6]. However, it is important to note that achieving robustness typically involves increased computational complexity.

To obtain an LAV estimator, users need to employ one of the solvers listed in the JuMP documentation. In many common scenarios, the Ipopt solver proves sufficient to obtain a solution:

using Ipopt
+
+analysis = acLavStateEstimation(system, device, Ipopt.Optimizer)

Setup Starting Primal Values

In JuliaGrid, the assignment of starting primal values for optimization variables takes place when the solve! function is executed. Starting primal values are determined based on the voltage fields within the ACStateEstimation type. By default, these values are initially established using the initial bus voltage magnitudes and angles from PowerSystem type:

julia> print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)Bus 1: 1.0, 0.0
+Bus 2: 1.0, 0.0
+Bus 3: 1.0, 0.0

Users have the flexibility to customize these values according to their requirements, and they will be utilized as the starting primal values when executing the solve! function.


Solution

To solve the formulated LAV state estimation model, simply execute the following function:

solve!(system, analysis)

Upon obtaining the solution, access the bus voltage magnitudes and angles using:

julia> print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)Bus 1: 0.9997143022794717, 0.0
+Bus 2: 0.9761238416137985, -0.05198283338938836
+Bus 3: 0.9559672151603991, -0.08055409251983292
Info

We suggest that readers refer to the tutorial on Least Absolute Value Estimation for insights into the implementation.


Measurement Set Update

After establishing the Measurement type using the measurement function, users gain the capability to incorporate new measurement devices or update existing ones.

Once updates are completed, users can seamlessly progress towards generating the ACStateEstimation type using the gaussNewton or acLavStateEstimation function. Ultimately, resolving the AC state estimation is achieved through the utilization of the solve! function:

system = powerSystem()
+device = measurement() # <- Initialize the Measurement instance
+
+addBus!(system; label = "Bus 1", type = 3)
+addBus!(system; label = "Bus 2", type = 1, active = 0.1, reactive = 0.01)
+addBus!(system; label = "Bus 3", type = 1, active = 2.5, reactive = 0.2)
+
+@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 3", reactance = 0.05)
+addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", reactance = 0.03)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 3.2, reactive = 0.3)
+
+@voltmeter(label = "Voltmeter ? (!)", variance = 1e-3)
+addVoltmeter!(system, device; bus = "Bus 1", magnitude = 1.0)
+
+@wattmeter(label = "Wattmeter ? (!)", varianceBus = 1e-2)
+addWattmeter!(system, device; from = "Branch 1", active = 1.046)
+addWattmeter!(system, device; bus = "Bus 2", active = -0.1)
+
+@varmeter(label = "Varmeter ? (!)", varianceFrom = 1e-3)
+addVarmeter!(system, device; from = "Branch 1", reactive = 0.059)
+addVarmeter!(system, device; bus = "Bus 2", reactive = -0.01)
+
+@pmu(label = "PMU ? (!)")
+addPmu!(system, device; bus = "Bus 2", magnitude = 0.976, angle = -0.052)
+
+analysis = gaussNewton(system, device) # <- Build ACStateEstimation for the defined model
+for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        break
+    end
+end
+
+addWattmeter!(system, device; from = "Branch 3", active = 0.924)
+updateWattmeter!(system, device; label = "Wattmeter 2 (Bus 2)", variance = 1e-4)
+
+addVarmeter!(system, device; to = "Branch 3", reactive = -0.044, variance = 1e-5)
+updateVarmeter!(system, device; label = "Varmeter 2 (Bus 2)", reactive = -0.011)
+
+updatePmu!(system, device; label = "PMU 1 (Bus 2)", polar = false)
+
+analysis = gaussNewton(system, device) # <- Build ACStateEstimation for the updated model
+for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        break
+    end
+end
Info

This concept removes the need to restart and recreate the Measurement type from the beginning when implementing changes to the existing measurement set.


State Estimation Update

An advanced methodology involves users establishing the ACStateEstimation type using gaussNewton or acLavStateEstimation just once. After this initial setup, users can seamlessly modify existing measurement devices without the need to recreate the ACStateEstimation type.

This advancement extends beyond the previous scenario where recreating the Measurement type was unnecessary, to now include the scenario where ACStateEstimation also does not need to be recreated.

Tip

The addition of new measurements after the creation of ACStateEstimation is not practical in terms of reusing this type. Instead, we recommend that users create a final set of measurements and then utilize update functions to manage devices, either putting them in-service or out-of-service throughout the process.

We can modify the prior example to achieve the same model without establishing ACStateEstimation twice:

system = powerSystem()
+device = measurement() # <- Initialize the Measurement instance
+
+addBus!(system; label = "Bus 1", type = 3)
+addBus!(system; label = "Bus 2", type = 1, active = 0.1, reactive = 0.01)
+addBus!(system; label = "Bus 3", type = 1, active = 2.5, reactive = 0.2)
+
+@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 3", reactance = 0.05)
+addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", reactance = 0.03)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 3.2, reactive = 0.3)
+
+@voltmeter(label = "Voltmeter ? (!)", variance = 1e-3)
+addVoltmeter!(system, device; bus = "Bus 1", magnitude = 1.0)
+
+@wattmeter(label = "Wattmeter ? (!)", varianceBus = 1e-2)
+addWattmeter!(system, device; from = "Branch 1", active = 1.046)
+addWattmeter!(system, device; bus = "Bus 2", active = -0.1)
+addWattmeter!(system, device; from = "Branch 3", active = 0.924, status = 0)
+
+@varmeter(label = "Varmeter ? (!)", varianceFrom = 1e-3)
+addVarmeter!(system, device; from = "Branch 1", reactive = 0.059)
+addVarmeter!(system, device; bus = "Bus 2", reactive = -0.01)
+addVarmeter!(system, device; to = "Branch 3", reactive = -0.044, variance = 1e-5, status = 0)
+
+@pmu(label = "PMU ? (!)")
+addPmu!(system, device; bus = "Bus 2", magnitude = 0.976, angle = -0.052)
+
+analysis = gaussNewton(system, device) # <- Build ACStateEstimation for the defined model
+for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        break
+    end
+end
+
+updateWattmeter!(system, device, analysis; label = "Wattmeter 3 (From Branch 3)", status = 1)
+updateWattmeter!(system, device, analysis; label = "Wattmeter 2 (Bus 2)", variance = 1e-4)
+
+updateVarmeter!(system, device, analysis; label = "Varmeter 3 (To Branch 3)", status = 1)
+updateVarmeter!(system, device, analysis; label = "Varmeter 2 (Bus 2)", reactive = -0.011)
+
+updatePmu!(system, device, analysis; label = "PMU 1 (Bus 2)", polar = false)
+
+# <- No need for re-build; we have already updated the existing ACStateEstimation instance
+for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        break
+    end
+end
Info

This concept removes the need to rebuild both the Measurement and the ACStateEstimation from the beginning when implementing changes to the existing measurement set. In the scenario of employing the WLS model, JuliaGrid can reuse the symbolic factorizations of LU or LDLt, provided that the nonzero pattern of the gain matrix remains unchanged.


Power and Current Analysis

After obtaining the solution from the AC state estimation, we can calculate various electrical quantities related to buses and branches using the power! and current! functions. For instance, let us consider the model for which we obtained the AC state estimation solution:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", type = 3, susceptance = 0.002)
+addBus!(system; label = "Bus 2", type = 1, active = 0.1, reactive = 0.01)
+addBus!(system; label = "Bus 3", type = 1, active = 2.5, reactive = 0.2)
+
+@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 3", reactance = 0.05)
+addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", reactance = 0.03)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 3.2, reactive = 0.3)
+
+addWattmeter!(system, device; from = "Branch 1", active = 1.046, variance = 1e-2)
+addWattmeter!(system, device; bus = "Bus 2", active = -0.1, variance = 1e-3)
+addWattmeter!(system, device; from = "Branch 3", active = 0.924, variance = 1e-3)
+
+addVarmeter!(system, device; from = "Branch 1", reactive = 0.059, variance = 1e-3)
+addVarmeter!(system, device; bus = "Bus 2", reactive = -0.01, variance = 1e-2)
+addVarmeter!(system, device; to = "Branch 3", reactive = -0.044, variance = 1e-3)
+
+analysis = gaussNewton(system, device)
+for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        break
+    end
+end

We can now utilize the provided functions to compute powers and currents:

power!(system, analysis)
+current!(system, analysis)

For instance, if we want to show the active power injections and the from-bus current angles, we can employ the following code:

julia> print(system.bus.label, analysis.power.injection.active)Bus 1: 2.6951392445386304
+Bus 2: -0.09999730749216829
+Bus 3: -2.499287793840309
julia> print(system.branch.label, analysis.current.from.angle)Branch 1: -0.056343895480383585 +Branch 2: -0.1541309681169004 +Branch 3: -0.08788060713202979
Info

To better understand the powers and currents associated with buses and branches that are calculated by the power! and current! functions, we suggest referring to the tutorials on AC State Estimation.


Users can utilize any of the print functions outlined in the Print API. For example, to print state estimation data related to wattmeters, we can use:

@power(MW, pu, pu)
+printWattmeterData(system, device, analysis)
|---------------------------------------------------------------|
+| Wattmeter Data                                                |
+|---------------------------------------------------------------|
+| Label |                     Active Power                      |
+|       |                                                       |
+|       | Measurement | Variance | Estimate | Residual | Status |
+|       |        [MW] |     [MW] |     [MW] |     [MW] |        |
+|-------|-------------|----------|----------|----------|--------|
+| 1     |    104.6000 | 1.00e+00 | 104.6026 |  -0.0026 |      1 |
+| 2     |    -10.0000 | 1.00e-01 |  -9.9997 |  -0.0003 |      1 |
+| 3     |     92.4000 | 1.00e-01 |  92.3997 |   0.0003 |      1 |
+|---------------------------------------------------------------|

Save Results to a CSV File

For CSV output, users should first generate a simple table with style = false, and then save it to a CSV file:

using CSV
+
+io = IOBuffer()
+printWattmeterData(system, device, analysis, io; style = false)
+CSV.write("bus.csv", CSV.File(take!(io); delim = "|"))

Active and Reactive Power Injection

To calculate the active and reactive power injection associated with a specific bus, the function can be used:

julia> active, reactive = injectionPower(system, analysis; label = "Bus 1")(2.6951392445386304, 0.3132044957940553)

Active and Reactive Power Injection from Generators

To calculate the active and reactive power injection from the generators at a specific bus, the function can be used:

julia> active, reactive = supplyPower(system, analysis; label = "Bus 1")(2.6951392445386304, 0.3132044957940553)

Active and Reactive Power at Shunt Element

To calculate the active and reactive power associated with shunt element at a specific bus, the function can be used:

julia> active, reactive = shuntPower(system, analysis; label = "Bus 1")(0.0, -0.0020066379525219783)

Active and Reactive Power Flow

Similarly, we can compute the active and reactive power flow at both the from-bus and to-bus ends of the specific branch by utilizing the provided functions below:

julia> active, reactive = fromPower(system, analysis; label = "Branch 2")(1.6491130561317449, 0.2562114962034585)
julia> active, reactive = toPower(system, analysis; label = "Branch 2")(-1.5932872079562321, -0.15530958620622967)

Active and Reactive Power at Charging Admittances

To calculate the active and reactive power linked with branch charging admittances of the particular branch, the function can be used:

julia> active, reactive = chargingPower(system, analysis; label = "Branch 1")(9.800363372293906e-5, -0.03920145348917562)

Active powers indicate active losses within the branch's charging admittances. Moreover, charging admittances injected reactive powers into the power system due to their capacitive nature, as denoted by a negative sign.


Active and Reactive Power at Series Impedance

To calculate the active and reactive power across the series impedance of the branch, the function can be used:

julia> active, reactive = seriesPower(system, analysis; label = "Branch 2")(0.05572979175205785, 0.13932447938014464)

The active power also considers active losses originating from the series resistance of the branch, while the reactive power represents reactive losses resulting from the impedance's inductive characteristics.


Current Injection

To calculate the current injection associated with a specific bus, the function can be used:

julia> magnitude, angle = injectionCurrent(system, analysis; label = "Bus 1")(2.708785622827216, -0.11569193435017798)

Current Flow

We can compute the current flow at both the from-bus and to-bus ends of the specific branch by utilizing the provided functions below:

julia> magnitude, angle = fromCurrent(system, analysis; label = "Branch 2")(1.6661346611128287, -0.1541309681169004)
julia> magnitude, angle = toCurrent(system, analysis; label = "Branch 2")(1.6709804057015962, 2.9641707920912417)

Current Through Series Impedance

To calculate the current passing through the series impedance of the branch in the direction from the from-bus end to the to-bus end, we can use the following function:

julia> magnitude, angle = seriesCurrent(system, analysis; label = "Branch 2")(1.6692781636392697, -0.16599467621735334)
diff --git a/v0.2.0/manual/dcOptimalPowerFlow/index.html b/v0.2.0/manual/dcOptimalPowerFlow/index.html new file mode 100644 index 000000000..28b28c689 --- /dev/null +++ b/v0.2.0/manual/dcOptimalPowerFlow/index.html @@ -0,0 +1,143 @@ + +DC Optimal Power Flow · JuliaGrid

DC Optimal Power Flow

Similar to AC Optimal Power Flow, JuliaGrid utilizes the JuMP package to construct optimal power flow models, enabling users to manipulate these models using the standard functions provided by JuMP. JuliaGrid supports popular solvers mentioned in the JuMP documentation to solve the optimization problem.

To perform the DC optimal power flow, we first need to have the PowerSystem type that has been created with the DC model. After that, create the DCOptimalPowerFlow type to establish the DC optimal power flow framework using the function:

To solve the DC optimal power flow problem and acquire generator active power outputs and bus voltage angles, make use of the following function:


After obtaining the solution for DC optimal power flow, JuliaGrid offers a post-processing analysis function to compute powers associated with buses and branches:

Additionally, specialized functions are available for calculating specific types of powers for individual buses, branches, or generators.


Optimal Power Flow Model

To set up the DC optimal power flow, we begin by creating the model. To illustrate this, consider the following:

using JuMP, HiGHS
+
+system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, angle = 0.17)
+addBus!(system; label = "Bus 2", active = 0.1, conductance = 0.04)
+addBus!(system; label = "Bus 3", active = 0.05)
+
+@branch(minDiffAngle = -3.1, maxDiffAngle = 3.1, minFromBus = -0.12, maxFromBus = 0.12)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 3", reactance = 0.01)
+addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", reactance = 0.01)
+
+@generator(minActive = 0.0)
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 0.6, maxActive = 0.8)
+addGenerator!(system; label = "Generator 2", bus = "Bus 2", active = 0.1, maxActive = 0.3)
+addGenerator!(system; label = "Generator 3", bus = "Bus 2", active = 0.2, maxActive = 0.4)
+
+cost!(system; label = "Generator 1", active = 2, polynomial = [1100.2; 500; 80])
+cost!(system; label = "Generator 2", active = 1, piecewise = [8.0 11.0; 14.0 17.0])
+cost!(system; label = "Generator 3", active = 1, piecewise = [6.8 12.3; 8.7 16.8; 11.2 19.8])
+
+dcModel!(system)

Next, the dcOptimalPowerFlow function is utilized to formulate the DC optimal power flow problem:

analysis = dcOptimalPowerFlow(system, HiGHS.Optimizer)

Optimization Variables

In DC optimal power flow, generator active power outputs are linear functions of bus voltage angles. Thus, the model's variables include generator active power outputs and bus voltage angles:

julia> JuMP.all_variables(analysis.method.jump)7-element Vector{VariableRef}:
+ active[1]
+ active[2]
+ active[3]
+ angle[1]
+ angle[2]
+ angle[3]
+ actwise[3]

It is important to highlight that when dealing with linear piecewise cost functions comprising multiple segments, as exemplified in the case of Generator 3, JuliaGrid automatically generates helper optimization variables, such as actwise[3], and formulates a set of linear constraints to appropriately handle these cost functions.

However, in instances where a linear piecewise cost function consists of only a single segment, as demonstrated by Generator 2, the function is modelled as a standard linear function, eliminating the necessity for additional helper optimization variables.

Please note that JuliaGrid keeps references to all variables categorized into three fields:

julia> fieldnames(typeof(analysis.method.variable))(:active, :angle, :actwise)

Variable Names

Users have the option to define custom variable names for printing and writing equations, which can help present them in a more compact form. For example:

analysis = dcOptimalPowerFlow(system, HiGHS.Optimizer; active = "P", angle = "θ")

Add Variables

The user has the ability to easily add new variables to the defined DC optimal power flow model by using the @variable macro from the JuMP package:

JuMP.@variable(analysis.method.jump, newVariable)

We can verify that the new variable is included in the defined model by using the function:

julia> JuMP.is_valid(analysis.method.jump, newVariable)true

Delete Variables

To delete a variable, the delete function from the JuMP package can be used:

JuMP.delete(analysis.method.jump, newVariable)

After deletion, the variable is no longer part of the model:

julia> JuMP.is_valid(analysis.method.jump, newVariable)false

Constraint Functions

JuliGrid keeps track of all the references to internally formed constraints in the constraint field of the DCOptimalPowerFlow type. These constraints are divided into six fields:

julia> fieldnames(typeof(analysis.method.constraint))(:slack, :balance, :voltage, :flow, :capability, :piecewise)
Info

We suggest that readers refer to the tutorial on DC Optimal Power Flow for insights into the implementation.


Slack Bus Constraint

The slack field contains a reference to the equality constraint associated with the fixed bus voltage angle value of the slack bus. This constraint is set within the addBus! function using the angle keyword:

julia> print(system.bus.label, analysis.method.constraint.slack.angle)Bus 1: θ[1] = 0.17

Users have the flexibility to modify this constraint by changing which bus serves as the slack bus and by adjusting the value of the bus angle. This can be achieved using the updateBus! function, for example:

updateBus!(system, analysis; label = "Bus 1", angle = -0.1)

Subsequently, the updated slack constraint can be inspected as follows:

julia> print(system.bus.label, analysis.method.constraint.slack.angle)Bus 1: θ[1] = -0.1

Bus Active Power Balance Constraints

The balance field contains references to the equality constraints associated with the active power balance equations defined for each bus. The constant terms in these equations are determined by the active and conductance keywords within the addBus! function. Additionally, if there are phase shift transformers in the system, the constant terms can also be affected by the shiftAngle keyword within the addBranch! function:

julia> print(system.bus.label, analysis.method.constraint.balance.active)Bus 1: P[1] - 120 θ[1] + 20 θ[2] + 100 θ[3] = 0
+Bus 2: P[2] + P[3] + 20 θ[1] - 120 θ[2] + 100 θ[3] = 0.14
+Bus 3: 100 θ[1] + 100 θ[2] - 200 θ[3] = 0.05

During the execution of functions that add or update power system components, these constraints are automatically adjusted to reflect the current configuration of the power system, for example:

updateBus!(system, analysis; label = "Bus 3", active = 0.1)
+updateGenerator!(system, analysis; label = "Generator 2", status = 0)

Subsequently, the updated set of active power balance constraints can be examined as follows:

julia> print(system.bus.label, analysis.method.constraint.balance.active)Bus 1: P[1] - 120 θ[1] + 20 θ[2] + 100 θ[3] = 0
+Bus 2: P[3] + 20 θ[1] - 120 θ[2] + 100 θ[3] = 0.14
+Bus 3: 100 θ[1] + 100 θ[2] - 200 θ[3] = 0.1

Bus Voltage Angle Difference Constraints

The voltage field contains references to the inequality constraints associated with the minimum and maximum bus voltage angle difference between the from-bus and to-bus ends of each branch. These values are specified using the minDiffAngle and maxDiffAngle keywords within the addBranch! function:

julia> print(system.branch.label, analysis.method.constraint.voltage.angle)Branch 1: θ[1] - θ[2] ∈ [-3.1, 3.1]
+Branch 2: θ[1] - θ[3] ∈ [-3.1, 3.1]
+Branch 3: θ[2] - θ[3] ∈ [-3.1, 3.1]
Info

Please note that if the limit constraints are set to minDiffAngle = -2π and maxDiffAngle = 2π for the corresponding branch, JuliGrid will omit the corresponding inequality constraint.

Additionally, by employing the updateBranch! function, we have the ability to modify these constraints as follows:

updateBranch!(system, analysis; label = "Branch 1", minDiffAngle = -1.7, maxDiffAngle = 1.7)

Subsequently, the updated set of voltage angle difference constraints can be examined as follows:

julia> print(system.branch.label, analysis.method.constraint.voltage.angle)Branch 1: θ[1] - θ[2] ∈ [-1.7, 1.7]
+Branch 2: θ[1] - θ[3] ∈ [-3.1, 3.1]
+Branch 3: θ[2] - θ[3] ∈ [-3.1, 3.1]

Branch Active Power Flow Constraints

The flow field refers to the inequality constraints associated with active power flow limits at the from-bus end of each branch. These limits are set using the minFromBus and maxFromBus keywords in the addBranch! function:

julia> print(system.branch.label, analysis.method.constraint.flow.active)Branch 1: 20 θ[1] - 20 θ[2] ∈ [-0.12, 0.12]
+Branch 2: 100 θ[1] - 100 θ[3] ∈ [-0.12, 0.12]
+Branch 3: 100 θ[2] - 100 θ[3] ∈ [-0.12, 0.12]
Info

If the branch flow limits are set to minFromBus = 0.0 and maxFromBus = 0.0 for the corresponding branch, JuliGrid will omit the corresponding inequality constraint.

By employing the updateBranch! function, we have the ability to modify these specific constraints, for example:

updateBranch!(system, analysis; label = "Branch 1", status = 0)
+updateBranch!(system, analysis; label = "Branch 2", reactance = 0.03, maxFromBus = 0.14)

Subsequently, the updated set of active power flow constraints can be examined as follows:

julia> print(system.branch.label, analysis.method.constraint.flow.active)Branch 2: 33.333333333333336 θ[1] - 33.333333333333336 θ[3] ∈ [-0.12, 0.14]
+Branch 3: 100 θ[2] - 100 θ[3] ∈ [-0.12, 0.12]

Generator Active Power Capability Constraints

The capability field contains references to the inequality constraints associated with the minimum and maximum active power outputs of the generators. These limits are specified using the minActive and maxActive keywords within the addGenerator! function:

julia> print(system.generator.label, analysis.method.constraint.capability.active)Generator 1: P[1] ∈ [0, 0.8]
+Generator 2: P[2] = 0
+Generator 3: P[3] ∈ [0, 0.4]

As demonstrated, the active power output of Generator 2 is currently fixed at zero due to the earlier action of setting this generator out-of-service. Let us adjust this specific constraint using the updateGenerator! function:

updateGenerator!(system, analysis; label = "Generator 2", status = 1, maxActive = 0.5)

Subsequently, the updated set of active power capability constraints can be examined as follows:

julia> print(system.generator.label, analysis.method.constraint.capability.active)Generator 1: P[1] ∈ [0, 0.8]
+Generator 2: P[2] ∈ [0, 0.5]
+Generator 3: P[3] ∈ [0, 0.4]

It is important to note that bringing back Generator 2 into service will also have an impact on the balance constraint, which will once again be influenced by the generator's output.


Active Power Piecewise Constraints

In the context of active power modelling, the piecewise field serves as a reference to the inequality constraints related to linear piecewise cost functions. These constraints are created using the cost! function with active = 1 specified when dealing with linear piecewise cost functions comprising multiple segments. JuliaGrid takes care of establishing the appropriate inequality constraints for each segment of the linear piecewise cost:

julia> print(system.generator.label, analysis.method.constraint.piecewise.active)Generator 3: 2.3684210526315796 P[3] - actwise[3] ≤ 3.805263157894739
+Generator 3: 1.2 P[3] - actwise[3] ≤ -6.360000000000001

It is worth noting that these constraints can also be automatically updated using the cost! function, and readers can find more details in the section about the objective function.


Add Constraints

Users can effortlessly introduce additional constraints into the defined DC optimal power flow model by utilizing the addBranch! or addGenerator! functions. Specifically, if a user wishes to include a new branch or generator in an already defined PowerSystem and DCOptimalPowerFlow type:

addBranch!(system, analysis; label = "Branch 4", from = "Bus 1", to = "Bus 2", reactance = 1)
+addGenerator!(system, analysis; label = "Generator 4", bus = "Bus 1", maxActive = 0.2)

As a result, the flow and capability constraints will be adjusted as follows:

julia> print(system.branch.label, analysis.method.constraint.flow.active)Branch 2: 33.333333333333336 θ[1] - 33.333333333333336 θ[3] ∈ [-0.12, 0.14]
+Branch 3: 100 θ[2] - 100 θ[3] ∈ [-0.12, 0.12]
+Branch 4: θ[1] - θ[2] ∈ [-0.12, 0.12]
julia> print(system.generator.label, analysis.method.constraint.capability.active)Generator 1: P[1] ∈ [0, 0.8] +Generator 2: P[2] ∈ [0, 0.5] +Generator 3: P[3] ∈ [0, 0.4] +Generator 4: active[4] ∈ [0, 0.2]

Add User-Defined Constraints

Users also have the option to include their custom constraints within the established DC optimal power flow model by employing the @constraint macro. For example, the addition of a new constraint can be achieved as follows:

JuMP.@constraint(analysis.method.jump, 0.0 <= analysis.method.variable.active[4] <= 0.3)

Delete Constraints

To delete a constraint, users can make use of the delete function from the JuMP package. When handling constraints that have been internally created, users can refer to the constraint references stored in the constraint field of the DCOptimalPowerFlow type.

For example, if the intention is to eliminate constraints related to the capability of Generator 4, the following code snippet can be employed:

JuMP.delete(analysis.method.jump, analysis.method.constraint.capability.active[4])
Info

In the event that a user deletes a constraint and subsequently executes a function that updates bus, branch, or generator parameters, and if the deleted constraint is affected by these functions, JuliaGrid will automatically reinstate that constraint. Users should exercise caution when deleting constraints, as this action is considered potentially harmful since it operates independently of power system data.


Objective Function

The objective function of the DC optimal power flow is constructed using polynomial and linear piecewise cost functions of the generators, which are defined using the cost! functions. It is important to note that only polynomial cost functions up to the second degree are included in the objective. If there are polynomials of higher degrees, JuliaGrid will exclude them from the objective function.

In the provided example, the objective function that needs to be minimized to obtain the optimal values of the active power outputs of the generators and the bus voltage angles is as follows:

julia> JuMP.objective_function(analysis.method.jump)1100.2 P[1]² + 500 P[1] + actwise[3] + P[2] + 83

Additionally, JuliaGrid stores the objective function in a separate variable, allowing users to access it by referencing the variable analysis.objective.


Update Objective Function

By utilizing the cost! functions, users have the flexibility to modify the objective function by adjusting polynomial or linear piecewise cost coefficients or by changing the type of polynomial or linear piecewise function employed. For instance, consider Generator 3, which incorporates a piecewise cost structure with two segments. Now, we can define a polynomial function for this generator and activate it by specifying the keyword active = 2 as shown:

cost!(system, analysis; label = "Generator 3", active = 2, polynomial = [853.4; 257; 40])

This results in the updated objective function, which can be observed as follows:

julia> analysis.method.objective1100.2 P[1]² + 853.4 P[3]² + 500 P[1] + P[2] + 257 P[3] + 123

User-Defined Objective Function

Users can modify the objective function using the set_objective_function function from the JuMP package. This operation is considered destructive because it is independent of power system data; however, in certain scenarios, it may be more straightforward than using the cost! function for updates. Moreover, using this methodology, users can combine a defined function with a newly defined expression. Here is an example of how it can be achieved:

expr = 100.2 * analysis.method.variable.active[1] * analysis.method.variable.active[1] + 123
+JuMP.set_objective_function(analysis.method.jump, analysis.method.objective - expr)

We can now observe the updated objective function as follows:

julia> JuMP.objective_function(analysis.method.jump)1000 P[1]² + 853.4 P[3]² + 500 P[1] + P[2] + 257 P[3]

Setup Starting Values

In JuliaGrid, the assignment of starting primal and dual values for optimization variables takes place when the solve! function is executed.


Starting Primal Values

Starting primal values are determined based on the generator and voltage fields within the DCOptimalPowerFlow type. By default, these values are initially established using the active power outputs of the generators and the initial bus voltage angles:

julia> print(system.generator.label, analysis.power.generator.active)Generator 1: 0.6
+Generator 2: 0.1
+Generator 3: 0.2
+Generator 4: 0.0
julia> print(system.bus.label, analysis.voltage.angle)Bus 1: -0.1 +Bus 2: 0.0 +Bus 3: 0.0

Users have the flexibility to adjust these values according to their specifications, which will then be used as the starting primal values when executing the solve! function.


Using DC Power Flow

In this perspective, users have the capability to conduct the DC power flow analysis and leverage the resulting solution to configure starting primal values. Here is an illustration of how this can be achieved:

flow = dcPowerFlow(system)
+solve!(system, flow)

After obtaining the solution, we can calculate the active power outputs of the generators and utilize the bus voltage angles to set the starting values. In this case, the generator and voltage fields of the DCOptimalPowerFlow type can be employed to store the new starting values:

for (key, idx) in system.generator.label
+    analysis.power.generator.active[idx] = generatorPower(system, flow; label = key)
+end
+
+for i = 1:system.bus.number
+    analysis.voltage.angle[i] = flow.voltage.angle[i]
+end

Starting Dual Values

Dual variables, often referred to as Lagrange multipliers or Kuhn-Tucker multipliers, represent the shadow prices or marginal costs associated with constraints. The assignment of initial dual values occurs when the solve! function is executed. Initially, the starting dual values are unknown, but users can access and manually set them. For example:

analysis.method.dual.balance.active[1] = 0.4

Optimal Power Flow Solution

To establish the DC optimal power flow problem, we can utilize the dcOptimalPowerFlow function. After setting up the problem, we can use the solve! function to compute the optimal values for the active power outputs of the generators and the bus voltage angles. Also, to turn off the solver output within the REPL, we use the set_silent function before calling solve! function. Here is an example:

JuMP.set_silent(analysis.method.jump)
+solve!(system, analysis)

By executing this function, we will obtain the solution with the optimal values for the active power outputs of the generators and the bus voltage angles:

julia> print(system.generator.label, analysis.power.generator.active)Generator 1: 0.0
+Generator 2: 0.09539999999999843
+Generator 3: 0.0
+Generator 4: 0.14460000000000084
julia> print(system.bus.label, analysis.voltage.angle)Bus 1: -0.1 +Bus 2: -0.10460000000000004 +Bus 3: -0.10420000000000001

Objective Value

To obtain the objective value of the optimal power flow solution, we can use the objective_value function:

julia> JuMP.objective_value(analysis.method.jump)0.09539999999999843

Dual Variables

The values of the dual variables are stored in the dual field of the DCOptimalPowerFlow type. For example:

julia> analysis.method.dual.balance.active[1]1.4459979675179438e-8

Users can utilize the functions printBusData and printGeneratorData to display results. Additionally, the functions listed in the Print Constraint Data section allow users to print constraint data related to buses, branches, or generators in the desired units. For example:

@power(MW, MVAr, pu)
+printBusConstraint(system, analysis)
|------------------------------|
+| Bus Constraint Data          |
+|------------------------------|
+| Label | Active Power Balance |
+|       |                      |
+|       | Solution |      Dual |
+|       |     [MW] | [$/MW-hr] |
+|-------|----------|-----------|
+| Bus 1 |   0.0000 |    0.0000 |
+| Bus 2 |  14.0000 |    0.0100 |
+| Bus 3 |  10.0000 |    0.0101 |
+|------------------------------|

Next, users can easily customize the print results for specific constraint, for example:

printBusConstraint(system, analysis; label = "Bus 1", header = true)
+printBusConstraint(system, analysis; label = "Bus 2", footer = true)

Save Results to a File

Users can also redirect print output to a file. For example, data can be saved in a text file as follows:

open("bus.txt", "w") do file
+    printBusConstraint(system, analysis, file)
+end

Save Results to a CSV File

For CSV output, users should first generate a simple table with style = false, and then save it to a CSV file:

using CSV
+
+io = IOBuffer()
+printBusConstraint(system, analysis, io; style = false)
+CSV.write("constraint.csv", CSV.File(take!(io); delim = "|"))

Primal and Dual Warm Start

Utilizing the DCOptimalPowerFlow type and proceeding directly to the solver offers the advantage of a "warm start". In this scenario, the starting primal and dual values for the subsequent solving step correspond to the solution obtained from the previous step.


Primal Variables

In the previous example, the following solution was obtained, representing the values of the primal variables:

julia> print(system.generator.label, analysis.power.generator.active)Generator 1: 0.0
+Generator 2: 0.09539999999999843
+Generator 3: 0.0
+Generator 4: 0.14460000000000084
julia> print(system.bus.label, analysis.voltage.angle)Bus 1: -0.1 +Bus 2: -0.10460000000000004 +Bus 3: -0.10420000000000001

Dual Variables

We also obtained all dual values. Here, we list only the dual variables for one type of constraint as an example:

julia> print(system.branch.label, analysis.method.dual.flow.active)Branch 2: -1.039999994152338
+Branch 3: 0.0
+Branch 4: 0.0

Modify Optimal Power Flow

Now, let us introduce changes to the power system from the previous example:

updateGenerator!(system, analysis; label = "Generator 2", maxActive = 0.08)

Next, we want to solve this modified optimal power flow problem. If we use solve! at this point, the primal and dual starting values will be set to the previously obtained values:

solve!(system, analysis)

As a result, we obtain a new solution:

julia> print(system.generator.label, analysis.power.generator.active)Generator 1: 0.0
+Generator 2: 0.0008
+Generator 3: 0.09459999999999802
+Generator 4: 0.1446000000000005
julia> print(system.bus.label, analysis.voltage.angle)Bus 1: -0.1 +Bus 2: -0.10460000000000004 +Bus 3: -0.10420000000000001

Reset Primal and Dual Values

Users retain the flexibility to reset these initial primal values to their default configurations at any juncture. This can be accomplished by utilizing the active power outputs of the generators and the initial bus voltage angles extracted from the PowerSystem type, employing the startingPrimal! function:

startingPrimal!(system, analysis)

The primal starting values will now be identical to those that would be obtained if the dcOptimalPowerFlow function were executed after all the updates have been applied.

Using the startingDual! function, users can clear all dual variable values, resetting them to their default state:

startingDual!(system, analysis)

Power Analysis

After obtaining the solution from the DC optimal power flow, we can calculate powers related to buses and branches using the power! function. For instance, let us consider the power system for which we obtained the DC optimal power flow solution:

using HiGHS
+
+system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, angle = 0.17)
+addBus!(system; label = "Bus 2", active = 0.1, conductance = 0.04)
+addBus!(system; label = "Bus 3", active = 0.05)
+
+@branch(minDiffAngle = -pi, maxDiffAngle = pi, minFromBus = -0.12, maxFromBus = 0.12)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 3", reactance = 0.01)
+addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", reactance = 0.01)
+
+@generator(minActive = 0.0)
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 3.2, maxActive = 0.5)
+addGenerator!(system; label = "Generator 2", bus = "Bus 2", active = 0.2, maxActive = 0.2)
+
+cost!(system; label = "Generator 1", active = 2, polynomial = [1100.2; 500; 80])
+cost!(system; label = "Generator 2", active = 1, piecewise = [10.8 12.3; 14.7 16.8])
+
+analysis = dcOptimalPowerFlow(system, HiGHS.Optimizer)
+solve!(system, analysis)

Now we can calculate the active powers using the following function:

power!(system, analysis)

Finally, to display the active power injections and from-bus active power flows, we can use the following code:

julia> print(system.bus.label, analysis.power.injection.active)Bus 1: 0.0
+Bus 2: 0.0008999999999991246
+Bus 3: -0.0005
julia> print(system.branch.label, analysis.power.from.active)Branch 1: -7.142857142816705e-5 +Branch 2: 7.142857142983239e-5 +Branch 3: 0.00042857142857066766
Info

To better understand the powers associated with buses and branches that are calculated by the power! function, we suggest referring to the tutorials on DC Optimal Power Flow.


Users can utilize any of the print functions outlined in the Print Power System Data or Print Power System Summary. For example, to create a bus data with the desired units, users can use the following function:

@voltage(pu, deg, V)
+@power(MW, MVAr, pu)
+printBusData(system, analysis)
|---------------------------------------------------------------------|
+| Bus Data                                                            |
+|---------------------------------------------------------------------|
+| Label | Voltage | Power Generation | Power Demand | Power Injection |
+|       |         |                  |              |                 |
+|   Bus |   Angle |           Active |       Active |          Active |
+|       |   [deg] |             [MW] |         [MW] |            [MW] |
+|-------|---------|------------------|--------------|-----------------|
+| Bus 1 |  9.7403 |           0.0000 |       0.0000 |          0.0000 |
+| Bus 2 |  9.7405 |           0.1900 |       0.1000 |          0.0900 |
+| Bus 3 |  9.7402 |           0.0000 |       0.0500 |         -0.0500 |
+|---------------------------------------------------------------------|

Active Power Injection

To calculate active power injection associated with a specific bus, the function can be used:

julia> active = injectionPower(system, analysis; label = "Bus 2")0.0008999999999991246

Active Power Injection from Generators

To calculate active power injection from the generators at a specific bus, the function can be used:

julia> active = supplyPower(system, analysis; label = "Bus 2")0.0018999999999991246

Active Power Flow

Similarly, we can compute the active power flow at both the from-bus and to-bus ends of the specific branch by utilizing the provided functions below:

julia> active = fromPower(system, analysis; label = "Branch 2")7.142857142983239e-5
julia> active = toPower(system, analysis; label = "Branch 2")-7.142857142983239e-5
diff --git a/v0.2.0/manual/dcPowerFlow/index.html b/v0.2.0/manual/dcPowerFlow/index.html new file mode 100644 index 000000000..a4d92de16 --- /dev/null +++ b/v0.2.0/manual/dcPowerFlow/index.html @@ -0,0 +1,130 @@ + +DC Power Flow · JuliaGrid

DC Power Flow

To perform the DC power flow, we first need to have the PowerSystem type that has been created with the DC model. Following that, we can construct the power flow model encapsulated within the DCPowerFlow type by employing the following function:

To solve the DC power flow problem and acquire bus voltage angles, make use of the following function:


After obtaining the solution for DC power flow, JuliaGrid offers a post-processing analysis function to compute active powers associated with buses, branches, and generators:

Additionally, specialized functions are available for calculating specific types of powers for individual buses, branches, or generators.


Bus Type Modification

During the initialization process, the designated slack bus, which is initially set, undergoes examination and can be altered using the dcPowerFlow function. Here is an example:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3)
+addBus!(system; label = "Bus 2", type = 2)
+addBus!(system; label = "Bus 3", type = 2)
+
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+addBranch!(system; label = "Branch 2", from = "Bus 2", to = "Bus 3", reactance = 0.01)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 3")
+
+dcModel!(system)
+analysis = dcPowerFlow(system)

In this example, the slack bus (type = 3) corresponds to the Bus 1. However, this bus does not have an in-service generator connected to it. JuliaGrid considers this a mistake and attempts to assign a new slack bus from the available generator buses (type = 2) that have connected in-service generators. In this particular example, the Bus 3 will become the new slack bus. As a result, we can observe the updated array of bus types:

julia> print(system.bus.label, system.bus.layout.type)Bus 1: 1
+Bus 2: 2
+Bus 3: 3
Info

The bus that is defined as the slack bus (type = 3) but lacks a connected in-service generator will have its type changed to the demand bus (type = 1). Meanwhile, the first generator bus (type = 2) with an in-service generator connected to it will be assigned as the new slack bus (type = 3).


Power Flow Solution

To solve the DC power flow problem using JuliaGrid, we start by creating the PowerSystem type and defining the DC model with the dcModel! function. Here is an example:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3)
+addBus!(system; label = "Bus 2", type = 1, active = 0.1)
+addBus!(system; label = "Bus 3", type = 1, active = 0.05)
+
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 3", reactance = 0.01)
+addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", reactance = 0.01)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 3.2)
+
+dcModel!(system)

The dcPowerFlow function can be used to establish the DC power flow problem:

analysis = dcPowerFlow(system)
Tip

Here, the user triggers LU factorization as the default method for solving the DC power flow problem. However, the user also has the option to select alternative factorization methods such as LDLt or QR, for instance:

analysis = dcPowerFlow(system, LDLt)

To obtain the bus voltage angles, we can call the solve! function as follows:

solve!(system, analysis)

Once the solution is obtained, the bus voltage angles can be accessed using:

julia> print(system.bus.label, analysis.voltage.angle)Bus 1: 0.0
+Bus 2: -0.0017857142857142859
+Bus 3: -0.001142857142857143
Info

For implementation insights, we suggest referring to the tutorial on DC Power Flow Analysis.


Users have the option to print the results in the REPL using any units that have been configured, such as:

@voltage(pu, deg, V)
+printBusData(system, analysis)
|-----------------|
+| Bus Data        |
+|-----------------|
+| Label | Voltage |
+|       |         |
+|   Bus |   Angle |
+|       |   [deg] |
+|-------|---------|
+| Bus 1 |  0.0000 |
+| Bus 2 | -0.1023 |
+| Bus 3 | -0.0655 |
+|-----------------|

Next, users can easily customize the print results for specific buses, for example:

printBusData(system, analysis; label = "Bus 1", header = true)
+printBusData(system, analysis; label = "Bus 2")
+printBusData(system, analysis; label = "Bus 3", footer = true)

Save Results to a File

Users can also redirect print output to a file. For example, data can be saved in a text file as follows:

open("bus.txt", "w") do file
+    printBusData(system, analysis, file)
+end

Save Results to a CSV File

For CSV output, users should first generate a simple table with style = false, and then save it to a CSV file:

using CSV
+
+io = IOBuffer()
+printBusData(system, analysis, io; style = false)
+CSV.write("bus.csv", CSV.File(take!(io); delim = "|"))

Power System Update

After establishing the PowerSystem type using the powerSystem function and configuring the DC model with dcModel!, users gain the capability to incorporate new branches and generators. Furthermore, they can adjust buses, branches, and generators.

Once updates are completed, users can progress towards generating the DCPowerFlow type using the dcPowerFlow function. Ultimately, resolving the DC power flow is achieved through the utilization of the solve! function:

system = powerSystem() # <- Initialize the PowerSystem instance
+
+addBus!(system; label = "Bus 1", type = 3)
+addBus!(system; label = "Bus 2", type = 2, active = 2.1)
+
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 3.2)
+
+dcModel!(system)
+analysis = dcPowerFlow(system) # <- Build DCPowerFlow for the defined power system
+solve!(system, analysis)
+
+updateBus!(system; label = "Bus 2", active = 0.4)
+
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 2", reactance = 1)
+updateBranch!(system; label = "Branch 1", status = 0)
+
+addGenerator!(system; label = "Generator 2", bus = "Bus 2", active = 1.5)
+updateGenerator!(system; label = "Generator 1", active = 1.9)
+
+analysis = dcPowerFlow(system) # <- Build DCPowerFlow for the updated power system
+solve!(system, analysis)
Info

This concept removes the need to restart and recreate the PowerSystem within the dc field from the beginning when implementing changes to the existing power system.


Power Flow Update

An advanced methodology involves users establishing the DCPowerFlow type using dcPowerFlow just once. After this initial setup, users can integrate new branches and generators, and also have the capability to modify buses, branches, and generators, all without the need to recreate the DCPowerFlow type.

This advancement extends beyond the previous scenario where recreating the PowerSystem and DC model was unnecessary, to now include the scenario where DCPowerFlow also does not need to be recreated. Such efficiency can be particularly advantageous in cases where JuliaGrid can reuse nodal matrix factorization.

By modifying the previous example, we observe that we now create the DCPowerFlow type only once:

system = powerSystem() # <- Initialize the PowerSystem instance
+
+addBus!(system; label = "Bus 1", type = 3)
+addBus!(system; label = "Bus 2", type = 2, active = 2.1)
+
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 3.2)
+
+dcModel!(system)
+analysis = dcPowerFlow(system) # <- Build DCPowerFlow for the defined power system
+solve!(system, analysis)
+
+updateBus!(system, analysis; label = "Bus 2", active = 0.4)
+
+addBranch!(system, analysis; label = "Branch 2", from = "Bus 1", to = "Bus 2", reactance = 1)
+updateBranch!(system, analysis; label = "Branch 1", status = 0)
+
+addGenerator!(system, analysis; label = "Generator 2", bus = "Bus 2", active = 1.5)
+updateGenerator!(system, analysis; label = "Generator 1", active = 1.9)
+
+# <- No need for re-build; we have already updated the existing DCPowerFlow instance
+solve!(system, analysis)
Info

This concept removes the need to restart and recreate both the PowerSystem within the dc field and the DCPowerFlow from the beginning when implementing changes to the existing power system. Additionally, JuliaGrid can reuse symbolic factorizations of LU or LDLt, as long as the nonzero pattern of the nodal matrix remains consistent between power system configurations.


Reusing Matrix Factorization

Drawing from the preceding example, our focus now shifts to finding a solution involving modifications that entail adjusting the active power demand at Bus 2, introducing a new generator at Bus 2, and fine-tuning the output power of Generator 1. It is important to note that these adjustments do not impact the branches, leaving the nodal matrix unchanged. To resolve this updated system, users can simply execute the solve! function:

updateBus!(system, analysis; label = "Bus 2", active = 0.2)
+addGenerator!(system, analysis; label = "Generator 3", bus = "Bus 2", active = 0.3)
+updateGenerator!(system, analysis; label = "Generator 1", active = 2.1)
+
+solve!(system, analysis)
Info

In this scenario, JuliaGrid will recognize instances where the user has not modified branch parameters affecting the nodal matrix. Consequently, JuliaGrid will leverage the previously performed nodal matrix factorization, resulting in a significantly faster solution compared to recomputing the factorization.


Limitations

The dcPowerFlow function oversees bus type validations, as detailed in the Bus Type Modification section. Consequently, if a user intends to change the slack bus or leaves an existing slack bus without a generator, proceeding directly to the solve! function is not feasible.

In these instances, JuliaGrid will raise an error:

julia> updateGenerator!(system, analysis; label = "Generator 1", status = 0)ERROR: The power flow model cannot be reused due to required bus type conversion.

Now, the user must execute the dcPowerFlow function instead of attempting to reuse the DCPowerFlow type:

updateGenerator!(system; label = "Generator 1", status = 0)
+
+analysis = dcPowerFlow(system)
+solve!(system, analysis)
Info

After creating the PowerSystem and DCPowerFlow types, users can add or modify buses, branches, and generators before directly using the solve! function. JuliaGrid automatically executes the necessary functions when adjustments lead to a valid solution. However, if modifications are incompatible, like changing the slack bus, JuliaGrid raises an error to prevent misleading outcomes, ensuring accuracy.


Power Analysis

After obtaining the solution, we can calculate powers related to buses, branches, and generators using the power! function. For example, let us consider the power system for which we obtained the DC power flow solution:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3)
+addBus!(system; label = "Bus 2", type = 1, active = 0.1)
+addBus!(system; label = "Bus 3", type = 1, active = 0.05)
+
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 3", reactance = 0.01)
+addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", reactance = 0.01)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 3.2)
+
+analysis = dcPowerFlow(system)
+solve!(system, analysis)

Now we can calculate the active powers using the following function:

power!(system, analysis)

Next, let us convert the base power unit to megavolt-amperes (MVA):

@base(system, MVA, V)

Finally, here are the calculated active power values in megawatts (MW) corresponding to buses and branches:

julia> print(system.bus.label, system.base.power.value * analysis.power.injection.active)Bus 1: 15.000000000000002
+Bus 2: -10.0
+Bus 3: -5.0
julia> print(system.branch.label, system.base.power.value * analysis.power.from.active)Branch 1: 3.571428571428572 +Branch 2: 11.428571428571429 +Branch 3: -6.42857142857143
Info

To better understand the powers associated with buses, branches, and generators that are calculated by the power! function, we suggest referring to the tutorials on DC Power Flow Analysis.


Users can utilize any of the print functions outlined in the Print Power System Data or Print Power System Summary. For example, users have the option to print the results in the REPL using any units that have been configured:

@power(MW, pu, pu)
+printBranchData(system, analysis)
|-----------------------------------------------------------------------|
+| Branch Data                                                           |
+|-----------------------------------------------------------------------|
+|            Label             | From-Bus Power | To-Bus Power | Status |
+|                              |                |              |        |
+|   Branch | From-Bus | To-Bus |         Active |       Active |        |
+|          |          |        |           [MW] |         [MW] |        |
+|----------|----------|--------|----------------|--------------|--------|
+| Branch 1 | Bus 1    | Bus 2  |         3.5714 |      -3.5714 |      1 |
+| Branch 2 | Bus 1    | Bus 3  |        11.4286 |     -11.4286 |      1 |
+| Branch 3 | Bus 2    | Bus 3  |        -6.4286 |       6.4286 |      1 |
+|-----------------------------------------------------------------------|

Active Power Injection

To calculate active power injection associated with a specific bus, the function can be used:

julia> active = injectionPower(system, analysis; label = "Bus 1")0.15000000000000002

Active Power Injection from Generators

To calculate active power injection from the generators at a specific bus, the function can be used:

julia> active = supplyPower(system, analysis; label = "Bus 1")0.15000000000000002

Active Power Flow

Similarly, we can compute the active power flow at both the from-bus and to-bus ends of the specific branch by utilizing the provided functions below:

julia> active = fromPower(system, analysis; label = "Branch 2")0.1142857142857143
julia> active = toPower(system, analysis; label = "Branch 2")-0.1142857142857143

Generator Active Power Output

Finally, we can compute the active power output of a particular generator using the function:

julia> active = generatorPower(system, analysis; label = "Generator 1")0.15000000000000002
diff --git a/v0.2.0/manual/dcStateEstimation/index.html b/v0.2.0/manual/dcStateEstimation/index.html new file mode 100644 index 000000000..8ee552bdf --- /dev/null +++ b/v0.2.0/manual/dcStateEstimation/index.html @@ -0,0 +1,142 @@ + +DC State Estimation · JuliaGrid

DC State Estimation

To perform the DC state estimation, we first need to have the PowerSystem type that has been created with the DC model, alongside the Measurement type that retains measurement data. Subsequently, we can formulate either the weighted least-squares (WLS) or the least absolute value (LAV) DC state estimation model encapsulated within the type DCStateEstimation using:

For resolving the DC state estimation problem and obtaining bus voltage angles, utilize the following function:

After executing the function solve!, where the user employs the WLS method, the user has the ability to check if the measurement set contains outliers throughout bad data analysis and remove those measurements using:

Moreover, before creating the DCStateEstimation type, users can initiate observability analysis to identify observable islands and restore observability by employing:

For more detailed information, users can refer to the Observability Analysis section within AC state estimation documentation. It is worth noting that when the system becomes observable within the AC model, it will also be observable within the DC state estimation model.


After obtaining the solution for DC state estimation, JuliaGrid offers a post-processing analysis function to compute active powers associated with buses and branches:

Additionally, specialized functions are available for calculating specific types of powers for individual buses or branches.


Bus Type Modification

Just like in the Bus Type Modification section, when establishing the DCStateEstimation type, the initially assigned slack bus is evaluated and may be altered. If the designated slack bus (type = 3) lacks a connected in-service generator, it will be changed to a demand bus (type = 1). Conversely, the first generator bus (type = 2) with an active in-service generator linked to it will be reassigned as the new slack bus (type = 3).


Weighted Least-Squares Estimator

To solve the DC state estimation and derive WLS estimates using JuliaGrid, the process initiates by defining PowerSystem and Measurement types. Here is an illustrative example:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", type = 3)
+addBus!(system; label = "Bus 2", type = 1, active = 0.2)
+addBus!(system; label = "Bus 3", type = 1, active = 0.4)
+
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.5)
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 3", reactance = 0.2)
+addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", reactance = 0.3)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 3.2)
+
+@wattmeter(label = "Wattmeter ?")
+addWattmeter!(system, device; bus = "Bus 1", active = 0.6, variance = 1e-3)
+addWattmeter!(system, device; bus = "Bus 3", active = -0.4, variance = 1e-2)
+addWattmeter!(system, device; from = "Branch 1", active = 0.18, variance = 1e-4)
+addWattmeter!(system, device; to = "Branch 2", active = -0.42, variance = 1e-4)

The dcStateEstimation function serves to establish the DC state estimation problem:

analysis = dcStateEstimation(system, device)
Tip

Here, the user triggers LU factorization as the default method for solving the DC state estimation problem. However, the user also has the option to select alternative factorization methods such as LDLt or QR:

analysis = dcStateEstimation(system, device, LDLt)

To obtain the bus voltage angles, the solve! function can be invoked as shown:

solve!(system, analysis)

Upon obtaining the solution, access the bus voltage angles using:

julia> print(system.bus.label, analysis.voltage.angle)Bus 1: 0.0
+Bus 2: -0.09000000000000001
+Bus 3: -0.08399999999999999
Info

We recommend that readers refer to the tutorial on DC State Estimation for insights into the implementation.


Alternative Formulation

The resolution of the WLS state estimation problem using the conventional method typically progresses smoothly. However, it is widely acknowledged that in certain situations common to real-world systems, this method can be vulnerable to numerical instabilities. Such conditions might impede the algorithm from finding a satisfactory solution. In such cases, users may opt for an alternative formulation of the WLS state estimation, namely, employing an approach called orthogonal factorization [5, Sec. 3.2].

Specifically, by specifying the Orthogonal argument in the dcStateEstimation function, JuliaGrid implements a more robust approach to obtain the WLS estimator, which proves particularly beneficial when substantial differences exist among measurement variances:

analysis = dcStateEstimation(system, device, Orthogonal)
+solve!(system, analysis)

Users have the option to print the results in the REPL using any units that have been configured, such as:

@voltage(pu, deg, V)
+printBusData(system, analysis)
|-----------------|
+| Bus Data        |
+|-----------------|
+| Label | Voltage |
+|       |         |
+|   Bus |   Angle |
+|       |   [deg] |
+|-------|---------|
+| Bus 1 |  0.0000 |
+| Bus 2 | -5.1566 |
+| Bus 3 | -4.8128 |
+|-----------------|

Next, users can easily customize the print results for specific buses, for example:

printBusData(system, analysis; label = "Bus 1", header = true)
+printBusData(system, analysis; label = "Bus 2")
+printBusData(system, analysis; label = "Bus 3", footer = true)

Save Results to a File

Users can also redirect print output to a file. For example, data can be saved in a text file as follows:

open("bus.txt", "w") do file
+    printBusData(system, analysis, file)
+end
Tip

We also provide functions to print state estimation results, such as estimated values and residuals. For more details, users can consult the Power Analysis section of this manual.


Bad Data Processing

After acquiring the WLS solution using the solve! function, users can conduct bad data analysis employing the largest normalized residual test. Continuing with our defined power system and measurement set, let us introduce a new wattmeter. Upon proceeding to find the solution for this updated state:

addWattmeter!(system, device; from = "Branch 2", active = 4.1, variance = 1e-4)
+
+analysis = dcStateEstimation(system, device)
+solve!(system, analysis)

Following the solution acquisition, we can verify the presence of erroneous data. Detection of such data is determined by the threshold keyword. If the largest normalized residual's value exceeds the threshold, the measurement will be identified as bad data and consequently removed from the DC state estimation model:

outlier = residualTest!(system, device, analysis; threshold = 4.0)

Users can examine the data obtained from the bad data analysis:

julia> outlier.detecttrue
julia> outlier.maxNormalizedResidual267.65576812169894
julia> outlier.label"Wattmeter 5"

Hence, upon detecting bad data, the detect variable will hold true. The maxNormalizedResidual variable retains the value of the largest normalized residual, while the label contains the label of the measurement identified as bad data. JuliaGrid will mark the respective measurements as out-of-service within the Measurement type.

Moreover, JuliaGrid will adjust the coefficient matrix and mean vector within the DCStateEstimation type based on measurements now designated as out-of-service. To optimize the algorithm's efficiency, JuliaGrid resets non-zero elements to zero in the coefficient matrix and mean vector, effectively removing the impact of the corresponding measurement on the solution:

julia> analysis.method.mean5-element Vector{Float64}:
+  0.6
+ -0.4
+  0.18
+ -0.42
+  0.0
julia> analysis.method.coefficient5×3 SparseArrays.SparseMatrixCSC{Float64, Int64} with 12 stored entries: + 7.0 -2.0 -5.0 + -5.0 -3.33333 8.33333 + 2.0 -2.0 ⋅ + -5.0 ⋅ 5.0 + 0.0 ⋅ 0.0

Hence, after removing bad data, a new estimate can be computed without considering this specific measurement:

solve!(system, analysis)
Info

We suggest that readers refer to the tutorial on Bad Data Processing for insights into the implementation.


Least Absolute Value Estimator

The LAV method presents an alternative estimation technique known for its increased robustness compared to WLS. While the WLS method relies on specific assumptions regarding measurement errors, robust estimators like LAV are designed to maintain unbiasedness even in the presence of various types of measurement errors and outliers. This characteristic often eliminates the need for extensive bad data processing procedures [5, Ch. 6]. However, it is important to note that achieving robustness typically involves increased computational complexity.

To obtain an LAV estimator, users need to employ one of the solvers listed in the JuMP documentation. In many common scenarios, the Ipopt solver proves sufficient to obtain a solution:

using Ipopt
+
+analysis = dcLavStateEstimation(system, device, Ipopt.Optimizer)

Setup Starting Primal Values

In JuliaGrid, the assignment of starting primal values for optimization variables takes place when the solve! function is executed. Starting primal values are determined based on the voltage fields within the DCStateEstimation type. By default, these values are initially established using the initial bus voltage angles from PowerSystem type:

julia> print(system.bus.label, analysis.voltage.angle)Bus 1: 0.0
+Bus 2: 0.0
+Bus 3: 0.0

Users have the flexibility to customize these values according to their requirements, and they will be utilized as the starting primal values when executing the solve! function.


Solution

To solve the formulated LAV state estimation model, simply execute the following function:

solve!(system, analysis)

Upon obtaining the solution, access the bus voltage angles using:

julia> print(system.bus.label, analysis.voltage.angle)Bus 1: 0.0
+Bus 2: -0.08999999999956487
+Bus 3: -0.08399999999987212
Info

We suggest that readers refer to the tutorial on Least Absolute Value Estimation for insights into the implementation.


Measurement Set Update

After establishing the Measurement type using the measurement function, users gain the capability to incorporate new measurement devices or update existing ones.

Once updates are completed, users can seamlessly progress towards generating the DCStateEstimation type using the dcStateEstimation or dcLavStateEstimation function. Ultimately, resolving the DC state estimation is achieved through the utilization of the solve! function:

system = powerSystem()
+device = measurement() # <- Initialize the Measurement instance
+
+addBus!(system; label = "Bus 1", type = 3)
+addBus!(system; label = "Bus 2", type = 1, active = 0.1)
+
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.5)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 0.1)
+
+@wattmeter(label = "Wattmeter ?")
+addWattmeter!(system, device; bus = "Bus 2", active = -0.11, variance = 1e-3)
+addWattmeter!(system, device; from = "Branch 1", active = 0.09, variance = 1e-4)
+
+analysis = dcStateEstimation(system, device) # <- Build DCStateEstimation for the model
+solve!(system, analysis)
+
+addWattmeter!(system, device; to = "Branch 1", active = -0.12, variance = 1e-4)
+updateWattmeter!(system, device; label = "Wattmeter 1", status = 0)
+updateWattmeter!(system, device; label = "Wattmeter 2", active = 0.1, noise = false)
+
+analysis = dcStateEstimation(system, device) # <- Build DCStateEstimation for new model
+solve!(system, analysis)
Info

This concept removes the need to restart and recreate the Measurement type from the beginning when implementing changes to the existing measurement set.


State Estimation Update

An advanced methodology involves users establishing the DCStateEstimation type using dcStateEstimation or dcLavStateEstimation just once. After this initial setup, users can seamlessly modify existing measurement devices without the need to recreate the DCStateEstimation type.

This advancement extends beyond the previous scenario where recreating the Measurement type was unnecessary, to now include the scenario where DCStateEstimation also does not need to be recreated. Such efficiency can be particularly advantageous in cases where JuliaGrid can reuse gain matrix factorization.

Tip

The addition of new measurements after the creation of DCStateEstimation is not practical in terms of reusing this type. Instead, we recommend that users create a final set of measurements and then utilize update functions to manage devices, either putting them in-service or out-of-service throughout the process.

We can modify the prior example to achieve the same model without establishing DCStateEstimation twice:

system = powerSystem()
+device = measurement() # <- Initialize the Measurement instance
+
+addBus!(system; label = "Bus 1", type = 3)
+addBus!(system; label = "Bus 2", type = 1, active = 0.1)
+
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.5)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 0.1)
+
+@wattmeter(label = "Wattmeter ?")
+addWattmeter!(system, device; bus = "Bus 2", active = -0.11, variance = 1e-3)
+addWattmeter!(system, device; from = "Branch 1", active = 0.09, variance = 1e-4)
+addWattmeter!(system, device; to = "Branch 1", active = -0.12, variance = 1e-4, status = 0)
+
+analysis = dcStateEstimation(system, device) # <- Build DCStateEstimation for the model
+solve!(system, analysis)
+
+updateWattmeter!(system, device; label = "Wattmeter 1", status = 0)
+updateWattmeter!(system, device; label = "Wattmeter 2", active = 0.1, noise = false)
+updateWattmeter!(system, device; label = "Wattmeter 3", status = 1)
+
+# <- No need for re-build; we have already updated the existing DCStateEstimation instance
+solve!(system, analysis)
Info

This concept removes the need to rebuild both the Measurement and the DCStateEstimation from the beginning when implementing changes to the existing measurement set. In the scenario of employing the WLS model, JuliaGrid can reuse the symbolic factorizations of LU or LDLt, provided that the nonzero pattern of the gain matrix remains unchanged.


Reusing Weighted Least-Squares Matrix Factorization

Drawing from the preceding example, our focus now shifts to finding a solution involving modifications that entail adjusting the measurement value of the Wattmeter 2. It is important to note that these adjustments do not impact the variance or status of the measurement device, which can affect the gain matrix. To resolve this updated system, users can simply execute the solve! function:

updateWattmeter!(system, device, analysis; label = "Wattmeter 2", active = 0.091)
+
+solve!(system, analysis)
Info

In this scenario, JuliaGrid will recognize instances where the user has not modified parameters that impact the gain matrix. Consequently, JuliaGrid will leverage the previously performed gain matrix factorization, resulting in a significantly faster solution compared to recomputing the factorization.


Power Analysis

After obtaining the solution from the DC state estimation, calculating powers related to buses and branches is facilitated by using the power! function. For instance, let us consider the model for which we obtained the DC state estimation solution:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", type = 3, conductance = 1e-3)
+addBus!(system; label = "Bus 2", type = 1, active = 0.2)
+addBus!(system; label = "Bus 3", type = 1, active = 0.4)
+
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.5)
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 3", reactance = 0.2)
+addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", reactance = 0.3)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 3.2)
+
+addWattmeter!(system, device; bus = "Bus 1", active = 0.6, variance = 1e-3)
+addWattmeter!(system, device; bus = "Bus 3", active = -0.4, variance = 1e-2)
+addWattmeter!(system, device; from = "Branch 1", active = 0.18, variance = 1e-4)
+addWattmeter!(system, device; to = "Branch 2", active = -0.42, variance = 1e-4)
+
+analysis = dcStateEstimation(system, device)
+solve!(system, analysis)

We can compute active powers using the following function:

power!(system, analysis)

For example, active power injections corresponding to buses are:

julia> print(system.bus.label, analysis.power.injection.active)Bus 1: 0.6008333333333332
+Bus 2: -0.19983333333333342
+Bus 3: -0.4
Info

To better understand the powers associated with buses, and branches that are calculated by the power! function, we suggest referring to the tutorials on.


Users can utilize any of the print functions outlined in the Print API related to the DC analysis. For example, to print state estimation data related to wattmeters, we can use:

@power(MW, pu, pu)
+printWattmeterData(system, device, analysis)
|---------------------------------------------------------------|
+| Wattmeter Data                                                |
+|---------------------------------------------------------------|
+| Label |                     Active Power                      |
+|       |                                                       |
+|       | Measurement | Variance | Estimate | Residual | Status |
+|       |        [MW] |     [MW] |     [MW] |     [MW] |        |
+|-------|-------------|----------|----------|----------|--------|
+| 1     |     60.0000 | 1.00e-01 |  60.0833 |  -0.0833 |      1 |
+| 2     |    -40.0000 | 1.00e+00 | -40.0000 |   0.0000 |      1 |
+| 3     |     18.0000 | 1.00e-02 |  17.9917 |   0.0083 |      1 |
+| 4     |    -42.0000 | 1.00e-02 | -41.9917 |  -0.0083 |      1 |
+|---------------------------------------------------------------|

Save Results to a CSV File

For CSV output, users should first generate a simple table with style = false, and then save it to a CSV file:

using CSV
+
+io = IOBuffer()
+printWattmeterData(system, device, analysis, io; style = false)
+CSV.write("bus.csv", CSV.File(take!(io); delim = "|"))

Active Power Injection

To calculate active power injection associated with a specific bus, the function can be used:

julia> active = injectionPower(system, analysis; label = "Bus 1")0.6008333333333332

Active Power Injection from Generators

To calculate active power injection from the generators at a specific bus, the function can be used:

julia> active = supplyPower(system, analysis; label = "Bus 1")0.6008333333333332

Active Power Flow

Similarly, we can compute the active power flow at both the from-bus and to-bus ends of the specific branch by utilizing the provided functions below:

julia> active = fromPower(system, analysis; label = "Branch 1")0.17991666666666667
julia> active = toPower(system, analysis; label = "Branch 1")-0.17991666666666667
diff --git a/v0.2.0/manual/measurementModel/index.html b/v0.2.0/manual/measurementModel/index.html new file mode 100644 index 000000000..47b852aa8 --- /dev/null +++ b/v0.2.0/manual/measurementModel/index.html @@ -0,0 +1,383 @@ + +Measurement Model · JuliaGrid

Measurement Model

The JuliaGrid supports the type Measurement to preserve measurement data, with the following fields: voltmeter, ammeter, wattmeter, varmeter, and pmu. These fields contain information pertaining to measurements such as bus voltage magnitude, branch current magnitude, active power flow and injection, reactive power flow and injection measurements, and measurements of bus voltage and branch current phasors.

The type Measurement can be created using a function:

JuliaGrid supports two modes for populating the Measurement type: using built-in functions or using HDF5 files.

To work with HDF5 files, JuliaGrid provides the function:


Once the Measurement type has been established, we can incorporate voltmeters, ammeters, wattmeters, varmeters, and phasor measurement units (PMUs) using the following functions:

Also, JuliaGrid provides macros @voltmeter, @ambmeter, @wattmeter, @varmeter, and @pmu to define templates that aid in creating measurement devices. These templates help avoid entering the same parameters repeatedly.

Info

It is important to note that measurement devices associated with branches can only be incorporated if the branch is in-service. This reflects JuliaGrid's approach to mimic a network topology processor, where logical data analysis configures the energized components of the power system.

Moreover, it is feasible to modify the parameters of measurement devices. When these functions are executed, all relevant fields within the Measurement type will be automatically updated. These functions include:

Tip

The functions for updating measurement devices serve a dual purpose. While their primary function is to modify the Measurement type, they are also designed to accept various analysis models like AC or DC state estimation models. When feasible, these functions not only modify the Measurement type but also adapt the analysis model, often resulting in improved computational efficiency. Detailed instructions on utilizing this feature can be found in dedicated manuals for specific analyses.


Finally, the user has the capability to randomly alter the measurement set by activating or deactivating devices through the following function:

Furthermore, we provide users with the ability to modify each specific measurement set by utilizing the functions:


Build Model

The measurement function generates the Measurement type and requires a string-formatted path to HDF5 files as input. Alternatively, the Measurement can be created without any initial data by initializing it as empty, allowing the user to construct the measurements from scratch.


HDF5 File

In order to use the HDF5 file as input to create the Measurement type, it is necessary to have saved the data using the saveMeasurement function beforehand. Let us say we saved the measurements as measurements14.h5 in the directory C:\hdf5. Then, the following code can be used to construct the Measurement type:

device = measurement("C:/hdf5/measurements14.h5")

Model from Scratch

To start building a model from the ground up, the initial step involves constructing a power system, which facilitates the addition of measurement devices to buses or branches. As an illustration:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.12)
+
+addVoltmeter!(system, device; bus = "Bus 1", magnitude = 1.0, variance = 1e-3)
+addWattmeter!(system, device; from = "Branch 1", active = 0.2, variance = 1e-4, noise = true)

In this context, we have created the voltmeter responsible for measuring the bus voltage magnitude at Bus 1, with associated mean and variance values expressed in per-units:

julia> [device.voltmeter.magnitude.mean device.voltmeter.magnitude.variance]1×2 Matrix{Float64}:
+ 1.0  0.001

Furthermore, we have established the wattmeter to measure the active power flow at the from-bus end of Branch 1, with corresponding mean and variance values also expressed in per-units:

julia> [device.wattmeter.active.mean device.wattmeter.active.variance]1×2 Matrix{Float64}:
+ 0.202707  0.0001
Tip

The measurement values (i.e., means) can be generated by adding white Gaussian noise with specified variance values to perturb the original values. This can be achieved by setting noise = true within the functions used for adding devices.


Save Model

Once the Measurement type has been created using one of the methods outlined in Build Model, the current data can be stored in the HDF5 file by using saveMeasurement function:

saveMeasurement(device; path = "C:/hdf5/measurement.h5")

All electrical quantities saved in the HDF5 file are in per-units and radians.


Add Voltmeter

We have the option to add voltmeters to a loaded measurement type or to one created from scratch. As an example, we can initiate the Measurement type and then incorporate voltmeters by utilizing the addVoltmeter! function:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1")
+
+addVoltmeter!(system, device; bus = "Bus 1", magnitude = 0.9, variance = 1e-4)
+addVoltmeter!(system, device; bus = "Bus 1", magnitude = 1.0, variance = 1e-3, noise = true)

In this example, we have established two voltmeters designed to measure the bus voltage magnitude at Bus 1. In the case of the second voltmeter, the measurement value is generated internally by introducing white Gaussian noise with the variance added to the magnitude value. As a result, we obtain the following data:

julia> [device.voltmeter.magnitude.mean device.voltmeter.magnitude.variance]2×2 Matrix{Float64}:
+ 0.9     0.0001
+ 1.0146  0.001
Info

We recommend reading the documentation for the addVoltmeter! function, where we have provided a list of the keywords that can be used.


Customizing Input Units for Keywords

By default, the magnitude and variance keywords are expected to be provided in per-units (pu). However, users have the flexibility to specify these values in volts (V) if they prefer. For instance, consider the following example:

@voltage(kV, rad, V)
+
+system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 135e3)
+
+addVoltmeter!(system, device; bus = "Bus 1", magnitude = 121.5, variance = 0.0135)
+addVoltmeter!(system, device; bus = "Bus 1", magnitude = 135, variance = 0.135, noise = true)

In this example, we have chosen to specify magnitude and variance in kilovolts (kV). It is important to note that even though we have used kilovolts as the input units, these keywords will still be stored in the per-units:

julia> [device.voltmeter.magnitude.mean device.voltmeter.magnitude.variance]2×2 Matrix{Float64}:
+ 0.9      0.0001
+ 1.00624  0.001

Users have the option to print the voltmeter data in the REPL using any units that have been configured:

printVoltmeterData(system, device)
|-----------------------------------------|
+| Voltmeter Data                          |
+|-----------------------------------------|
+| Label |        Voltage Magnitude        |
+|       |                                 |
+|       | Measurement | Variance | Status |
+|       |        [kV] |     [kV] |        |
+|-------|-------------|----------|--------|
+| 1     |    121.5000 | 1.35e-02 |      1 |
+| 2     |    135.8420 | 1.35e-01 |      1 |
+|-----------------------------------------|

Add Ammeter

Users can introduce ammeters into either an existing measurement type or one that they create from the ground up by making use of the addAmmeter! function, as demonstrated in the following example:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.12)
+
+addAmmeter!(system, device; from = "Branch 1", magnitude = 0.8, variance = 1e-3)
+addAmmeter!(system, device; to = "Branch 1", magnitude = 0.9, variance = 1e-1, noise = true)

In this scenario, we have established one ammeter to measure the branch current magnitude at the from-bus end of Branch 1, as indicated by the use of the from keyword. Similarly, we have added an ammeter to measure the branch current magnitude at the to-bus end of the branch by utilizing the to keyword.

For the first ammeter, we assume that the measurement value is already known, defined by the magnitude. In contrast, for the second ammeter, the measurement value is generated by adding white Gaussian noise with the variance to the magnitude value. These actions result in the following outcomes:

julia> [device.ammeter.magnitude.mean device.ammeter.magnitude.variance]2×2 Matrix{Float64}:
+ 0.8       0.001
+ 0.382757  0.1
Info

We recommend reading the documentation for the addAmmeter! function, where we have provided a list of the keywords that can be used.


Customizing Input Units for Keywords

By default, the magnitude and variance keywords are expected to be provided in per-unit (pu). However, users have the flexibility to express these values in amperes (A) if they prefer. Take a look at the following example:

@current(A, rad)
+
+system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 135e3)
+addBus!(system; label = "Bus 2", base = 135e3)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.12)
+
+addAmmeter!(system, device; from = "Branch 1", magnitude = 342.13, variance = 0.428)
+addAmmeter!(system, device; to = "Branch 1", magnitude = 385, variance = 42.8, noise = true)

In this example, we have opted to specify the magnitude and variance in amperes (A). It is worth noting that, despite using amperes as the input units, these keywords will still be stored in the per-unit system:

julia> [device.ammeter.magnitude.mean device.ammeter.magnitude.variance]2×2 Matrix{Float64}:
+ 0.799992  0.00100078
+ 0.928376  0.100078

Users have the option to print the ammeter data in the REPL using any units that have been configured:

printAmmeterData(system, device)
|-----------------------------------------|
+| Ammeter Data                            |
+|-----------------------------------------|
+| Label |        Current Magnitude        |
+|       |                                 |
+|       | Measurement | Variance | Status |
+|       |         [A] |      [A] |        |
+|-------|-------------|----------|--------|
+| 1     |    342.1300 | 4.28e-01 |      1 |
+| 2     |    397.0356 | 4.28e+01 |      1 |
+|-----------------------------------------|

Add Wattmeter

Users can include wattmeters in either an existing measurement type or one that they create from scratch by utilizing the addWattmeter! function, as demonstrated in the following example:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.12)
+
+addWattmeter!(system, device; bus = "Bus 1", active = 0.6, variance = 1e-3)
+addWattmeter!(system, device; from = "Branch 1", active = 0.3, variance = 1e-2)
+addWattmeter!(system, device; to = "Branch 1", active = 0.1, variance = 1e-3, noise = true)

In this scenario, one wattmeter has been added to measure the active power injection at Bus 1, as indicated by the use of the bus keyword. Additionally, two wattmeters have been introduced to measure the active power flow on both sides of Branch 1 using the from and to keywords.

For the first and second wattmeters, we assume that the measurement values are already known, defined by the active. In contrast, for the third wattmeter, the measurement value is generated by adding white Gaussian noise with the variance to the active value. As a result, the measurement data is as follows:

julia> [device.wattmeter.active.mean device.wattmeter.active.variance]3×2 Matrix{Float64}:
+ 0.6       0.001
+ 0.3       0.01
+ 0.161741  0.001
Info

We recommend reading the documentation for the addWattmeter! function, where we have provided a list of the keywords that can be used.


Customizing Input Units for Keywords

By default, the active and variance keywords are expected to be provided in per-unit (pu) values. However, users have the option to express these values in watts (W) if they prefer, as demonstrated in the following example:

@power(MW, pu, pu)
+
+system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.12)
+
+addWattmeter!(system, device; bus = "Bus 1", active = 60, variance = 1e-1)
+addWattmeter!(system, device; from = "Branch 1", active = 30, variance = 1)
+addWattmeter!(system, device; to = "Branch 1", active = 10, variance = 1e-1, noise = true)

In this example, we have chosen to specify the active and variance in megawatts (MW), but even though we have used megawatts as the input units, these keywords will still be stored in the per-unit system:

julia> [device.wattmeter.active.mean device.wattmeter.active.variance]3×2 Matrix{Float64}:
+ 0.6        0.001
+ 0.3        0.01
+ 0.0309215  0.001

Users have the option to print the wattmeter data in the REPL using any units that have been configured:

printWattmeterData(system, device)
|-----------------------------------------|
+| Wattmeter Data                          |
+|-----------------------------------------|
+| Label |          Active Power           |
+|       |                                 |
+|       | Measurement | Variance | Status |
+|       |        [MW] |     [MW] |        |
+|-------|-------------|----------|--------|
+| 1     |     60.0000 | 1.00e-01 |      1 |
+| 2     |     30.0000 | 1.00e+00 |      1 |
+| 3     |      3.0921 | 1.00e-01 |      1 |
+|-----------------------------------------|

Add Varmeter

To include varmeters, the same approach as described in the Add Wattmeter section can be applied, but here, we make use of the addVarmeter! function, as demonstrated in the following example:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.12)
+
+addVarmeter!(system, device; bus = "Bus 1", reactive = 0.2, variance = 1e-3)
+addVarmeter!(system, device; from = "Branch 1", reactive = 0.1, variance = 1e-2)
+addVarmeter!(system, device; to = "Branch 1", reactive = 0.05, variance = 1e-3, noise = true)

In this context, one varmeter has been added to measure the reactive power injection at Bus 1, as indicated by the use of the bus keyword. Additionally, two varmeters have been introduced to measure the reactive power flow on both sides of Branch 1 using the from and to keywords. As a result, the following outcomes are observed:

julia> [device.varmeter.reactive.mean device.varmeter.reactive.variance]3×2 Matrix{Float64}:
+ 0.2       0.001
+ 0.1       0.01
+ 0.022861  0.001
Info

We recommend reading the documentation for the addVarmeter! function, where we have provided a list of the keywords that can be used.


Customizing Input Units for Keywords

Just as we explained for the previous device, users have the flexibility to select units different from per-units. In this case, they can opt for megavolt-ampere reactive (MVAr), as illustrated in the following example:

@power(pu, MVAr, pu)
+
+system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.12)
+
+addVarmeter!(system, device; bus = "Bus 1", reactive = 20, variance = 1e-1)
+addVarmeter!(system, device; from = "Branch 1", reactive = 10, variance = 1)
+addVarmeter!(system, device; to = "Branch 1", reactive = 5, variance = 1e-1, noise = true)

JuliaGrid will still store the values in the per-unit system:

julia> [device.varmeter.reactive.mean device.varmeter.reactive.variance]3×2 Matrix{Float64}:
+ 0.2       0.001
+ 0.1       0.01
+ 0.039822  0.001

Users have the option to print the varmeter data in the REPL using any units that have been configured:

printVarmeterData(system, device)
|-----------------------------------------|
+| Varmeter Data                           |
+|-----------------------------------------|
+| Label |         Reactive Power          |
+|       |                                 |
+|       | Measurement | Variance | Status |
+|       |      [MVAr] |   [MVAr] |        |
+|-------|-------------|----------|--------|
+| 1     |     20.0000 | 1.00e-01 |      1 |
+| 2     |     10.0000 | 1.00e+00 |      1 |
+| 3     |      3.9822 | 1.00e-01 |      1 |
+|-----------------------------------------|

Add PMU

Users have the capability to incorporate PMUs into either an existing measurement type or create one from scratch by utilizing the addPmu! function, as demonstrated in the following example:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.12)
+
+addPmu!(system, device; bus = "Bus 1", magnitude = 1.1, angle = 0.1, varianceMagnitude = 0.1)
+addPmu!(system, device; from = "Branch 1", magnitude = 1.0, angle = -0.2, noise = true)
+addPmu!(system, device; to = "Branch 1", magnitude = 0.9, angle = 0.0, varianceAngle = 0.001)
Info

While the typical understanding of a PMU encompasses a device that measures the bus voltage phasor and all branch current phasors incident to the bus, we have chosen to deconstruct this concept to offer users increased flexibility. As a result, our approach yields PMUs that measure individual phasors, each described with magnitude and angle, along with corresponding variances, all presented in the polar coordinate system.

In this context, one PMU has been added to measure the bus voltage phasor at Bus 1, as indicated by the use of the bus keyword. Additionally, two PMUs have been introduced to measure the branch current phasors on both sides of Branch 1 using the from and to keywords.

For the first and third PMUs, we assume that the measurement values are already known, defined by the magnitude and angle keywords. However, for the second PMU, we generate the measurement value by adding white Gaussian noise with varianceMagnitude and varianceAngle to the magnitude and angle values, respectively. It is important to note that when we omit specifying variance values, we rely on their default settings, both of which are equal to 1e-5. As a result, we observe the following outcomes:

julia> [device.pmu.magnitude.mean device.pmu.magnitude.variance]3×2 Matrix{Float64}:
+ 1.1       0.1
+ 0.997086  1.0e-5
+ 0.9       1.0e-5
julia> [device.pmu.angle.mean device.pmu.angle.variance]3×2 Matrix{Float64}: + 0.1 1.0e-5 + -0.202677 1.0e-5 + 0.0 0.001
Info

We recommend reading the documentation for the addPmu! function, where we have provided a list of the keywords that can be used.


Coordinate Systems and Correlated Measurement Errors

When users add PMUs, the incorporation of these measurements into the state estimation model is always in the rectangular coordinate system. In this scenario, the real and imaginary components of the phasor measurements become correlated, although typically these correlations are disregarded [1]. However, if users want to consider these error correlations, the keyword correlated = true is provided for support.

Further, in the AC state estimation model, users have the flexibility to integrate PMU outputs in the polar coordinate system by specifying polar = true.

For example, let us add PMUs:

addPmu!(system, device; bus = "Bus 2", magnitude = 0.9, angle = 0, correlated = true)
+addPmu!(system, device; bus = "Bus 2", magnitude = 0.9, angle = 0, polar = true)

In the case of linear state estimation using PMUs only, both PMUs will be integrated into the rectangular coordinate system because the polar keyword is only related to AC state estimation. The treatment of the first PMU assumes error correlation between the real and imaginary parts. Conversely, the treatment of the second PMU assumes no correlation, as it defaults to correlated = false.

Next, in AC state estimation, the first PMU measurement will be integrated into the rectangular coordinate system where correlation between the real and imaginary parts exists. The second PMU will be integrated in the polar coordinate system.

Tip

It is noteworthy that expressing current phasor measurements in polar coordinates can lead to ill-conditioned problems due to small current magnitudes, whereas using rectangular representation can resolve this issue.


Customizing Input Units for Keywords

By default, the magnitude and varianceMagnitude keywords are expected to be provided in per-unit (pu), while the angle and varianceAngle keywords are expected to be provided in radians (rad). However, users have the flexibility to express these values in different units, such as volts (V) and degrees (deg) if the PMU is set to a bus, or amperes (A) and degrees (deg) if the PMU is set to a branch. This flexibility is demonstrated in the following:

@voltage(kV, deg, V)
+@current(A, deg)
+
+system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", base = 135e3)
+addBus!(system; label = "Bus 2", base = 135e3)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.12)
+
+addPmu!(system, device; bus = "Bus 1", magnitude = 148.5, angle = 5.73, varianceAngle = 0.06)
+addPmu!(system, device; from = "Branch 1", magnitude = 167.35, angle = -11.46, noise = true)
+addPmu!(system, device; to = "Branch 1", magnitude = 150.61, angle = 0.0)

In this example, we have opted to specify kilovolts (kV) and degrees (deg) for the PMU located at Bus 1, and amperes (A) and degrees (deg) for the PMUs located at Branch 1. It is important to note that regardless of the units used, the values will still be stored in per-units and radians:

julia> [device.pmu.magnitude.mean device.pmu.magnitude.variance]3×2 Matrix{Float64}:
+ 1.1       1.0e-5
+ 0.382328  1.0e-5
+ 0.352167  1.0e-5
julia> [device.pmu.angle.mean device.pmu.angle.variance]3×2 Matrix{Float64}: + 0.100007 0.0010472 + -0.191076 1.0e-5 + 0.0 1.0e-5

Users have the option to print the PMU data in the REPL using any units that have been configured:

printPmuData(system, device)
|---------------------------------------------------------------------------|
+| PMU Data                                                                  |
+|---------------------------------------------------------------------------|
+| Label |        Voltage Magnitude        |          Voltage Angle          |
+|       |                                 |                                 |
+|       | Measurement | Variance | Status | Measurement | Variance | Status |
+|       |        [kV] |     [kV] |        |       [deg] |    [deg] |        |
+|-------|-------------|----------|--------|-------------|----------|--------|
+| 1     |    148.5000 | 1.35e-03 |      1 |      5.7300 | 6.00e-02 |      1 |
+|---------------------------------------------------------------------------|
+|---------------------------------------------------------------------------|
+| PMU Data                                                                  |
+|---------------------------------------------------------------------------|
+| Label |        Current Magnitude        |          Current Angle          |
+|       |                                 |                                 |
+|       | Measurement | Variance | Status | Measurement | Variance | Status |
+|       |         [A] |      [A] |        |       [deg] |    [deg] |        |
+|-------|-------------|----------|--------|-------------|----------|--------|
+| 2     |    163.5091 | 4.28e-03 |      1 |    -10.9479 | 5.73e-04 |      1 |
+| 3     |    150.6100 | 4.28e-03 |      1 |      0.0000 | 5.73e-04 |      1 |
+|---------------------------------------------------------------------------|

Add Templates

The functions addVoltmeter!, addAmmeter!, addWattmeter!, addVarmeter!, and addPmu! are employed to introduce measurement devices. In cases where specific keywords are not explicitly defined, default values are automatically assigned to certain parameters.


Default Keyword Values

When utilizing the addVoltmeter! function, the default variance is set to variance = 1e-2 per-unit, and the voltmeter's operational status is automatically assumed to be in-service, as indicated by the setting of status = 1.

Similarly, for the addAmmeter! function, the default variances are established at variance = 1e-2 per-unit, and the operational statuses are configured to status = 1. This means that if a user places an ammeter at either the from-bus or to-bus end of a branch, the default settings are identical. However, as we will explain in the following subsection, users have the flexibility to fine-tune these default values, differentiating between the two locations.

In alignment with ammeters, the addWattmeter! and addVarmeter! functions feature default variances set at variance = 1e-2 per-unit, and statuses are automatically assigned as status = 1, regardless of whether the wattmeter or varmeter is placed at the bus, the from-bus end, or the to-bus end. Users have the ability to customize these default values, making distinctions between the three positions of the measurement devices.

For the addPmu! function, variances for both magnitude and angle measurements are standardized to varianceMagnitude = 1e-5 and varianceAngle = 1e-5 in per-units. Likewise, operational statuses are uniformly set to statusMagnitude = 1 and statusAngle = 1, regardless of whether the PMU is positioned on the bus, the from-bus end, or the to-bus end. Once more, users retain the option to tailor these default values to their specific needs, allowing for distinctions between these three locations of the measurement devices. Additionally, the coordinate system utilized for AC state estimation is consistently configured with polar = false, while correlation in the rectangular system is disabled with correlated = false.

Across all measurement devices, the method for generating measurement means is established as noise = false.


Change Default Keyword Values

In JuliaGrid, users have the flexibility to customize default values and assign personalized settings using the @voltmeter, @ammeter, @wattmeter, @varmeter, and @pmu macros. These macros create voltmeter, ammeter, wattmeter, varmeter, and pmu templates that are employed each time functions for adding measurement devices are called. Here is an example of creating these templates with tailored default values:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.12)
+
+@voltmeter(variance = 1e-4, noise = true)
+addVoltmeter!(system, device; label = "Voltmeter 1", bus = "Bus 1", magnitude = 1.0)
+
+@ammeter(varianceFrom = 1e-3, varianceTo = 1e-4, statusTo = 0)
+addAmmeter!(system, device; label = "Ammeter 1", from = "Branch 1", magnitude = 1.1)
+addAmmeter!(system, device; label = "Ammeter 2", to = "Branch 1", magnitude = 0.9)
+
+@wattmeter(varianceBus = 1e-3, statusFrom = 0, noise = true)
+addWattmeter!(system, device; label = "Wattmeter 1", bus = "Bus 1", active = 0.6)
+addWattmeter!(system, device; label = "Wattmeter 2", from = "Branch 1", active = 0.3)
+addWattmeter!(system, device; label = "Wattmeter 3", to = "Branch 1", active = 0.1)
+
+@varmeter(varianceFrom = 1e-3, varianceTo = 1e-3, statusBus = 0)
+addVarmeter!(system, device; label = "Varmeter 1", bus = "Bus 1", reactive = 0.2)
+addVarmeter!(system, device; label = "Varmeter 2", from = "Branch 1", reactive = 0.1)
+addVarmeter!(system, device; label = "Varmeter 3", to = "Branch 1", reactive = 0.05)
+
+@pmu(varianceMagnitudeBus = 1e-4, statusAngleBus = 0, varianceAngleFrom = 1e-3)
+addPmu!(system, device; label = "PMU 1", bus = "Bus 1", magnitude = 1.1, angle = -0.1)
+addPmu!(system, device; label = "PMU 2", from = "Branch 1", magnitude = 1.0, angle = -0.2)
+addPmu!(system, device; label = "PMU 3", to = "Branch 1", magnitude = 0.9, angle = 0.0)

For instance, when adding a wattmeter to the bus, the varianceBus = 1e-3 will be applied, or if it is added to the from-bus end of the branch, these wattmeters will be set as out-of-service according to statusFrom = 0.

Similarly, when adding a PMU to the bus, the variance of the bus voltage magnitude will be defined in accordance with varianceMagnitudeBus = 1e-4, while the bus voltage angle measurements will be configured as out-of-service based on the statusAngleBus = 0.

It is important to note that changing input units will also impact the templates accordingly.


Multiple Templates

In the case of calling the macros multiple times, the provided keywords and values will be combined into a single template for the corresponding measurement device.


Reset Templates

To reset the measurement device templates to their default settings, users can utilize the following macros:

@default(voltmeter)
+@default(ammeter)
+@default(wattmeter)
+@default(varmeter)
+@default(pmu)

Additionally, users can reset all templates using the macro:

@default(template)

Labels

JuliaGrid necessitates a unique label for each voltmeter, ammeter, wattmeter, varmeter, or pmu. These labels are stored in order dictionaries, functioning as pairs of strings and integers. The string signifies the distinct label for the particular device, while the integer tracks the internal numbering of measurement devices.

In all the previous examples, with the exception of the last one, we relied on automatic labeling by omitting the label keyword. This allowed JuliaGrid to independently assign unique labels to measurement devices. In such cases, JuliaGrid utilizes a sequential set of increasing integers for labeling the devices. The last example demonstrates the user labeling approach.

Tip

String labels improve readability, but in larger models, the overhead from using strings can become substantial. To reduce memory usage, users can configure ordered dictionaries to accept and store integers as labels:

@labels(Integers)

Integer-Based Labeling

Let us take a look at the following illustration:

@labels(Integers)
+
+system = powerSystem()
+device = measurement()
+
+addBus!(system; label = 1)
+addBus!(system; label = 2)
+addBranch!(system; label = 1, from = 1, to = 2, reactance = 0.12)
+
+addVoltmeter!(system, device; label = 1, bus = 1, magnitude = 1.0)
+
+addAmmeter!(system, device; label = 1, from = 1, magnitude = 1.1)
+addAmmeter!(system, device; label = 2, to = 1, magnitude = 0.9)

In this example, we use the macro @labels to specify that labels will be stored as integers. It is essential to run this macro; otherwise, even if integers are used in subsequent functions, they will be stored as strings.


Automated Labeling Using Templates

Furthermore, users can create labels using templates and include the symbol ? to insert an incremental set of integers at any position. In addition, users have the option to use the symbol ! to insert the location of the measurement device into the label. For example:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.12)
+
+@voltmeter(label = "Voltmeter ?")
+addVoltmeter!(system, device; bus = "Bus 1", magnitude = 1.0)
+addVoltmeter!(system, device; bus = "Bus 2", magnitude = 0.9)
+
+@ammeter(label = "!")
+addAmmeter!(system, device; from = "Branch 1", magnitude = 1.1)
+addAmmeter!(system, device; to = "Branch 1", magnitude = 0.9)
+
+@wattmeter(label = "Wattmeter ?: !")
+addWattmeter!(system, device; bus = "Bus 1", active = 0.6)
+addWattmeter!(system, device; from = "Branch 1", active = 0.3)

To illustrate, the voltmeter labels are defined with incremental integers as follows:

julia> device.voltmeter.labelOrderedCollections.OrderedDict{String, Int64} with 2 entries:
+  "Voltmeter 1" => 1
+  "Voltmeter 2" => 2

Moreover, for ammeter labels, location information is employed:

julia> device.ammeter.labelOrderedCollections.OrderedDict{String, Int64} with 2 entries:
+  "From Branch 1" => 1
+  "To Branch 1"   => 2

Lastly, for wattmeters, a combination of both approaches is used:

julia> device.wattmeter.labelOrderedCollections.OrderedDict{String, Int64} with 2 entries:
+  "Wattmeter 1: Bus 1"         => 1
+  "Wattmeter 2: From Branch 1" => 2

Retrieving Labels

Let us explore how to retrieve stored labels. Consider the following model:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.12)
+addBranch!(system; label = "Branch 2", from = "Bus 2", to = "Bus 1", reactance = 0.14)
+
+addWattmeter!(system, device; label = "Wattmeter 2", bus = "Bus 2", active = 0.6)
+addWattmeter!(system, device; label = "Wattmeter 1", bus = "Bus 1", active = 0.2)
+addWattmeter!(system, device; label = "Wattmeter 4", from = "Branch 1", active = 0.3)
+addWattmeter!(system, device; label = "Wattmeter 3", to = "Branch 1", active = 0.1)
+addWattmeter!(system, device; label = "Wattmeter 5", from = "Branch 2", active = 0.1)

To access the wattmeter labels, we can use the variable:

julia> device.wattmeter.labelOrderedCollections.OrderedDict{String, Int64} with 5 entries:
+  "Wattmeter 2" => 1
+  "Wattmeter 1" => 2
+  "Wattmeter 4" => 3
+  "Wattmeter 3" => 4
+  "Wattmeter 5" => 5

If we need to obtain only labels, we can use the following code:

julia> label = collect(keys(device.wattmeter.label))5-element Vector{String}:
+ "Wattmeter 2"
+ "Wattmeter 1"
+ "Wattmeter 4"
+ "Wattmeter 3"
+ "Wattmeter 5"

To isolate the wattmeters positioned either at the buses or at the ends of branches (from-bus or to-bus), users can achieve this using the following code:

julia> label[device.wattmeter.layout.bus]2-element Vector{String}:
+ "Wattmeter 2"
+ "Wattmeter 1"
julia> label[device.wattmeter.layout.from]2-element Vector{String}: + "Wattmeter 4" + "Wattmeter 5"
julia> label[device.wattmeter.layout.to]1-element Vector{String}: + "Wattmeter 3"

Furthermore, when using the addWattmeter! function, the labels for the keywords bus, from, and to are stored internally as numerical values. To retrieve bus labels, we can follow this procedure:

julia> label = collect(keys(system.bus.label));
julia> label[device.wattmeter.layout.index[device.wattmeter.layout.bus]]2-element Vector{String}: + "Bus 2" + "Bus 1"

Similarly, to obtain labels for branches, we can use the following code:

julia> label = collect(keys(system.branch.label));
julia> label[device.wattmeter.layout.index[device.wattmeter.layout.from]]2-element Vector{String}: + "Branch 1" + "Branch 2"
julia> label[device.wattmeter.layout.index[device.wattmeter.layout.to]]1-element Vector{String}: + "Branch 1"

This procedure is applicable to all measurement devices, including voltmeters, ammeters, varmeters, and PMUs.

Tip

JuliaGrid offers the capability to print labels alongside various types of data. For instance, users can use the following code to print labels in combination with specific data:

julia> print(device.wattmeter.label, device.wattmeter.active.mean)Wattmeter 2: 0.6
+Wattmeter 1: 0.2
+Wattmeter 4: 0.3
+Wattmeter 3: 0.1
+Wattmeter 5: 0.1

Loading and Saving Labels

When saving the measurements to an HDF5 file, the label type (strings or integers) will match the type chosen during system setup. Likewise, when loading data from an HDF5 file, the label type will be preserved as saved, regardless of what is set by the @labels macro.


Add Multiple Devices

Users have the option to add measurement devices with data generated from one of the AC analyses, specifically, using results obtained from either AC power flow or AC optimal power flow. To do this, users simply need to provide the AC type as an argument to one of the functions responsible for adding measurement devices:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.5, magnitude = 0.9, angle = 0.0)
+addBus!(system; label = "Bus 2", type = 1, reactive = 0.05, magnitude = 1.1, angle = -0.1)
+addBus!(system; label = "Bus 3", type = 1, active = 0.5, magnitude = 1.0, angle = -0.2)
+
+@branch(resistance = 0.03, susceptance = 0.02)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.5)
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 3", reactance = 0.1)
+addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", reactance = 0.2)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 0.2)
+addGenerator!(system; label = "Generator 2", bus = "Bus 2", active = 1.2)
+
+analysis = newtonRaphson(system)
+for iteration = 1:100
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+power!(system, analysis)
+current!(system, analysis)
+
+@voltmeter(label = "!", noise = true)
+addVoltmeter!(system, device, analysis; variance = 1e-3)
+
+@ammeter(label = "!")
+addAmmeter!(system, device, analysis; varianceFrom = 1e-3, statusTo = 0, noise = true)
+
+@wattmeter(label = "!")
+addWattmeter!(system, device, analysis; varianceBus = 1e-3, statusFrom = 0)
+
+@varmeter(label = "!")
+addVarmeter!(system, device, analysis; varianceFrom = 1e-3, statusBus = 0)
+
+@pmu(label = "!", polar = true)
+addPmu!(system, device, analysis; varianceMagnitudeBus = 1e-3)

In this example, we incorporate voltmeters to all buses and ammeters to all branches on both ends of each branch. We set noise = true once in the template and once directly in the function, which means that measurement values are generated by adding white Gaussian noise with specified variances to perturb the values obtained from the AC power flow analysis.

For wattmeters, varmeters, and PMUs added to all buses and branches, we rely on the default setting of noise = false to obtain measurement values that match precisely with those obtained from the AC power flow analysis. Additionally, when including PMUs in the AC state estimation model, we opt for the polar coordinate system by setting polar = true.

Info

It is important to note that JuliaGrid follows a specific order: it first adds bus measurements, then branch measurements. For branches, it adds measurement located at the from-bus end, and immediately after, measurement at the to-bus end. This process is repeated for all in-service branches.


Users have the option to employ an alternative method for adding groups of measurements, utilizing functions that add measurements individually. This approach may offer a more straightforward process. For example, to add wattmeters similarly to the procedure outlined above, we can employ the following:

Pᵢ = analysis.power.injection.active
+for (label, idx) in system.bus.label
+    addWattmeter!(system, device; bus = label, active = Pᵢ[idx], variance = 1e-3)
+end
+
+Pᵢⱼ = analysis.power.from.active
+Pⱼᵢ = analysis.power.to.active
+for (label, idx) in system.branch.label
+    addWattmeter!(system, device; from = label, active = Pᵢⱼ[idx], status = 0)
+    addWattmeter!(system, device; to = label, active = Pⱼᵢ[idx])
+end

Update Devices

After the addition of measurement devices to the Measurement type, users possess the flexibility to modify all parameters as defined in the function that added these measurement devices.


Update Voltmeter

Users have the flexibility to modify all parameters as defined within the addVoltmeter! function. For illustration, let us continue with the example from the Add Device Groups section:

updateVoltmeter!(system, device; label = "Bus 2", magnitude = 0.9, noise = false)

In this example, we update the measurement value of the voltmeter located at Bus 2, and this measurement is now generated without the inclusion of white Gaussian noise.


Update Ammeter

Similarly, users have the flexibility to modify all parameters defined within the addAmmeter! function. Using the same example from the Add Device Groups section, for example, we have:

updateAmmeter!(system, device; label = "From Branch 2", magnitude = 1.2, variance = 1e-4)
+updateAmmeter!(system, device; label = "To Branch 2", status = 0)

In this example, we make adjustments to the measurement and variance values of the ammeter located at Branch 2, specifically at the from-bus end. Next, we deactivate the ammeter at the same branch on the to-bus end.


Update Wattmeter

Following the same logic, users can modify all parameters defined within the addWattmeter! function:

updateWattmeter!(system, device; label = "Bus 1", active = 1.2, variance = 1e-4)
+updateWattmeter!(system, device; label = "To Branch 1", variance = 1e-6)

In this case, we modify the measurement and variance values for the wattmeter located at Bus 1. The wattmeter at Branch 1 on the to-bus end retains its measurement value, while only the measurement variance is adjusted.


Update Varmeter

Following the same logic, users can modify all parameters defined within the addVarmeter! function:

updateVarmeter!(system, device; label = "Bus 1", reactive = 1.2)
+updateVarmeter!(system, device; label = "Bus 2", status = 0)

In this instance, we make adjustments to the measurement value of the varmeter located at Bus 1, while utilizing a previously defined variance. Furthermore, we deactivate the varmeter at Bus 2 and designate it as out-of-service.


Update PMU

Finally, users can modify all PMU parameters defined within the addPmu! function:

updatePmu!(system, device; label = "Bus 1", magnitude = 1.05, noise = true)
+updatePmu!(system, device; label = "From Branch 1", varianceAngle = 1e-6, polar = false)

In this example, we adjust the magnitude measurement value of the PMU located at Bus 1. Now, this measurement is generated by adding white Gaussian noise with specified variance value to perturb the magnitude value, while keeping the bus angle voltage value unchanged. For the PMU placed at Branch 1 on the from-bus end, we retain the existing measurement values and only adjust the variance of the angle measurement. Additionally, we choose to include this measurement in the rectangular coordinate system for the AC state estimation.


Measurement Set

Once measurement devices are integrated into the Measurement type, we empower users to create measurement sets in a randomized manner. To be more precise, users can manipulate the status of devices, activating or deactivating them according to specific settings. To illustrate this feature, let us first create a measurement set using the following example:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.5, magnitude = 0.9, angle = 0.0)
+addBus!(system; label = "Bus 2", type = 1, reactive = 0.05, magnitude = 1.1, angle = -0.1)
+addBus!(system; label = "Bus 3", type = 1, active = 0.5, magnitude = 1.0, angle = -0.2)
+
+@branch(resistance = 0.03, susceptance = 0.02)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.5)
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 3", reactance = 0.1)
+addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", reactance = 0.2)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 0.2)
+addGenerator!(system; label = "Generator 2", bus = "Bus 2", active = 1.2)
+
+analysis = newtonRaphson(system)
+for iteration = 1:100
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end
+power!(system, analysis)
+current!(system, analysis)
+
+addVoltmeter!(system, device, analysis)
+addAmmeter!(system, device, analysis)
+addPmu!(system, device, analysis)

Activating Devices

As a starting point, we create the measurement set where all devices are set to in-service mode based on default settings. In this instance, we generate the measurement set comprising 3 voltmeters, 6 ammeters, and 9 PMUs.

Subsequently, we offer users the ability to manipulate the status of in-service devices using the status! function. For example, within this set, if we wish to have only 12 out of the total 18 devices in-service while the rest are out-of-service, we can accomplish this as follows:

status!(system, device; inservice = 12)

Upon executing this function, 12 devices will be randomly selected to be in-service, while the remaining 6 will be set to out-of-service.

Furthermore, users can fine-tune the manipulation of specific measurements. Let us say we want to activate only 2 ammeters while deactivating the remaining ammeters:

statusAmmeter!(system, device; inservice = 2)

This action will result in 2 ammeters being in-service and 4 being out-of-service.

Users also have the option to further refine these actions by specifying devices at particular locations within the power system. For instance, we can enable 3 PMUs at buses to measure bus voltage phasors while deactivating all PMUs at branches that measure current phasors:

statusPmu!(system, device; inserviceBus = 3, inserviceFrom = 0, inserviceTo = 0)

The outcome will be that 3 PMUs are set to in-service at buses for voltage phasor measurements, while all PMUs at branches measuring current phasors will be in out-of-service mode.


Deactivating Devices

Likewise, we empower users to specify the number of devices to be set as out-of-service rather than defining the number of in-service devices. For instance, if the intention is to deactivate just 2 devices from the total measurement set, it can be achieved as follows:

status!(system, device; outservice = 2)

In this scenario 2 devices will be randomly deactivated, while the rest will remain in in-service status. Similar to the previous approach, users can apply this to specific devices or employ fine-tuning as needed.


Activating Devices Using Redundancy

Furthermore, users can take advantage of redundancy, which represents the ratio between measurement devices and state variables. For example, if we wish to have the number of measurement devices be 1.2 times greater than the number of state variables, we can utilize the following command:

status!(system, device; redundancy = 1.2)

Considering that the number of state variables is 5 (excluding the voltage angle related to the slack bus), using a redundancy value of 1.2 will result in 6 devices being set to in-service, while the remainder will be deactivated. As before, users can target specific devices or adjust settings as needed.

diff --git a/v0.2.0/manual/pmuStateEstimation/index.html b/v0.2.0/manual/pmuStateEstimation/index.html new file mode 100644 index 000000000..1f6745722 --- /dev/null +++ b/v0.2.0/manual/pmuStateEstimation/index.html @@ -0,0 +1,221 @@ + +PMU State Estimation · JuliaGrid

PMU State Estimation

To perform linear state estimation solely based on PMU data, the initial requirement is to have the PowerSystem type configured with the AC model, along with the Measurement type storing measurement data. Subsequently, we can formulate either the weighted least-squares (WLS) or the least absolute value (LAV) PMU state estimation model encapsulated within the type PMUStateEstimation using:

For resolving the PMU state estimation problem and obtaining bus voltage magnitudes and angles, utilize the following function:

After executing the function solve!, where the user employs the WLS method, the user has the ability to check if the measurement set contains outliers throughout bad data analysis and remove those measurements using:

Moreover, before the creating PMUStateEstimation type, users can initiate an optimal PMU placement algorithm to determine the minimal set of PMUs required for an observable system:


After obtaining the PMU state estimation solution, JuliaGrid offers post-processing analysis functions for calculating powers and currents associated with buses and branches:

Additionally, specialized functions are available for calculating specific types of powers or currents for individual buses or branches.


Optimal PMU Placement

Let us define the PowerSystem type and perform the AC power flow analysis solely for generating data to artificially create measurement values:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.5)
+addBus!(system; label = "Bus 2", type = 1, reactive = 0.05)
+addBus!(system; label = "Bus 3", type = 1, active = 0.5)
+
+@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 2", reactance = 0.01)
+addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", reactance = 0.04)
+
+@generator(reactive = 0.1)
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 3.2)
+addGenerator!(system; label = "Generator 2", bus = "Bus 2", active = 2.1)
+
+analysis = newtonRaphson(system)
+for iteration = 1:10
+    mismatch!(system, analysis)
+    solve!(system, analysis)
+end

Optimal Solution

Upon defining the PowerSystem type, JuliaGrid provides the possibility to determine the minimal number of PMUs required for system observability using the pmuPlacement function:

using GLPK
+
+placement = pmuPlacement(system, GLPK.Optimizer)

The placement variable contains data regarding the optimal placement of measurements. In this instance, installing a PMU at Bus 2 renders the system observable:

julia> placement.busOrderedCollections.OrderedDict{String, Int64} with 1 entry:
+  "Bus 2" => 2

This PMU installed at Bus 2 will measure the bus voltage phasor at the corresponding bus and all current phasors at the branches incident to Bus 2 located at the from-bus or to-bus ends:

julia> placement.fromOrderedCollections.OrderedDict{String, Int64} with 1 entry:
+  "Branch 3" => 3
julia> placement.toOrderedCollections.OrderedDict{String, Int64} with 2 entries: + "Branch 1" => 1 + "Branch 2" => 2
Info

We suggest that readers refer to the tutorial on Optimal PMU Placement for insights into the implementation.


Measurement Data

Utilizing PMU placement and AC power flow data, which serves as the source for measurement values in this scenario, we can construct the Measurement type as follows:

device = measurement()
+
+@pmu(label = "PMU ? (!)")
+for (bus, idx) in placement.bus
+    Vᵢ, θᵢ = analysis.voltage.magnitude[idx], analysis.voltage.angle[idx]
+    addPmu!(system, device; bus = bus, magnitude = Vᵢ, angle = θᵢ)
+end
+for branch in keys(placement.from)
+    Iᵢⱼ, ψᵢⱼ = fromCurrent(system, analysis; label = branch)
+    addPmu!(system, device; from = branch, magnitude = Iᵢⱼ, angle = ψᵢⱼ)
+end
+for branch in keys(placement.to)
+    Iⱼᵢ, ψⱼᵢ = toCurrent(system, analysis; label = branch)
+    addPmu!(system, device; to = branch, magnitude = Iⱼᵢ, angle = ψⱼᵢ)
+end

For example, we can observe the obtained set of measurement values:

julia> print(device.pmu.label, device.pmu.magnitude.mean, device.pmu.angle.mean)PMU 1 (Bus 2): 1.021562852206714, 0.014634612107908078
+PMU 2 (From Branch 3): 0.4952989219070908, 0.07710792487077446
+PMU 3 (To Branch 1): 0.47443528099140664, -0.5459877069301735
+PMU 4 (To Branch 2): 1.1722759871967534, 0.16223095483453315

Weighted Least-Squares Estimator

Let us continue with the previous example, where we defined the PowerSystem and Measurement types. To establish the PMU state estimation model, we will use the pmuStateEstimation function:

analysis = pmuStateEstimation(system, device)
Tip

Here, the user triggers LU factorization as the default method for solving the PMU state estimation problem. However, the user also has the option to select alternative factorization methods such as LDLt or QR:

analysis = pmuStateEstimation(system, device, QR)

To obtain the bus voltage magnitudes and angles, the solve! function can be invoked as shown:

solve!(system, analysis)

Upon obtaining the solution, access the bus voltage magnitudes and angles using:

julia> print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)Bus 1: 0.9999999999998838, -1.8119991786077645e-13
+Bus 2: 1.0215628522065947, 0.014634612107732418
+Bus 3: 1.012294100412283, -0.005105099383711061
Info

We recommend that readers refer to the tutorial on PMU State Estimation for insights into the implementation.


Correlated Measurement Errors

In the above approach, we assume that measurement errors from a single PMU are uncorrelated. This assumption leads to the covariance matrix and its inverse matrix (i.e., precision matrix) maintaining a diagonal form:

julia> analysis.method.precision8×8 SparseArrays.SparseMatrixCSC{Float64, Int64} with 8 stored entries:
+ 99999.1       ⋅    ⋅         ⋅               ⋅    ⋅              ⋅        ⋅
+      ⋅   95823.9   ⋅         ⋅               ⋅    ⋅              ⋅        ⋅
+      ⋅        ⋅   1.0045e5   ⋅               ⋅    ⋅              ⋅        ⋅
+      ⋅        ⋅    ⋅        4.00322e5        ⋅    ⋅              ⋅        ⋅
+      ⋅        ⋅    ⋅         ⋅         126413.0   ⋅              ⋅        ⋅
+      ⋅        ⋅    ⋅         ⋅               ⋅   2.30398e5       ⋅        ⋅
+      ⋅        ⋅    ⋅         ⋅               ⋅    ⋅         99033.1       ⋅
+      ⋅        ⋅    ⋅         ⋅               ⋅    ⋅              ⋅   73288.7

While this approach is suitable for many scenarios, linear PMU state estimation relies on transforming from polar to rectangular coordinate systems. Consequently, measurement errors from a single PMU become correlated due to this transformation. This correlation results in the covariance matrix, and hence the precision matrix, no longer maintaining a diagonal form but instead becoming a block diagonal matrix.

To accommodate this, users have the option to consider correlation when adding each PMU to the Measurement type. For instance, let us add a new PMU while considering correlation:

addPmu!(system, device; bus = "Bus 3", magnitude = 1.01, angle = -0.005, correlated = true)

Following this, we recreate the WLS state estimation model:

analysis = pmuStateEstimation(system, device)

Upon inspection, it becomes evident that the precision matrix no longer maintains a diagonal structure:

julia> analysis.method.precision10×10 SparseArrays.SparseMatrixCSC{Float64, Int64} with 12 stored entries:
+ 99999.1       ⋅    ⋅         ⋅         …       ⋅         ⋅            ⋅
+      ⋅   95823.9   ⋅         ⋅                 ⋅         ⋅            ⋅
+      ⋅        ⋅   1.0045e5   ⋅                 ⋅         ⋅            ⋅
+      ⋅        ⋅    ⋅        4.00322e5          ⋅         ⋅            ⋅
+      ⋅        ⋅    ⋅         ⋅                 ⋅         ⋅            ⋅
+      ⋅        ⋅    ⋅         ⋅         …       ⋅         ⋅            ⋅
+      ⋅        ⋅    ⋅         ⋅                 ⋅         ⋅            ⋅
+      ⋅        ⋅    ⋅         ⋅            73288.7        ⋅            ⋅
+      ⋅        ⋅    ⋅         ⋅                 ⋅   100000.0         -9.85181
+      ⋅        ⋅    ⋅         ⋅                 ⋅       -9.85181  98029.7

Subsequently, we can address this new scenario and observe the solution:

julia> solve!(system, analysis)
julia> print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)Bus 1: 0.9988543535981543, 5.9920241101968545e-5 +Bus 2: 1.020417744427955, 0.01471023439287232 +Bus 3: 1.0111477069326746, -0.005052236191630569

Alternative Formulation

The resolution of the WLS state estimation problem using the conventional method typically progresses smoothly. However, it is widely acknowledged that in certain situations common to real-world systems, this method can be vulnerable to numerical instabilities. Such conditions might impede the algorithm from finding a satisfactory solution. In such cases, users may opt for an alternative formulation of the WLS state estimation, namely, employing an approach called orthogonal factorization [5, Sec. 3.2].

This approach is suitable when measurement errors are uncorrelated, and the precision matrix remains diagonal. Therefore, as a preliminary step, we need to eliminate the correlation, as we did previously:

updatePmu!(system, device; label = "PMU 5 (Bus 3)", correlated = false)

Subsequently, by specifying the Orthogonal argument in the pmuStateEstimation function, JuliaGrid implements a more robust approach to obtain the WLS estimator, which proves particularly beneficial when substantial differences exist among measurement variances:

analysis = pmuStateEstimation(system, device, Orthogonal)
+solve!(system, analysis)

Users have the option to print the results in the REPL using any units that have been configured, such as:

@voltage(pu, deg, V)
+printBusData(system, analysis)
|-----------------------------|
+| Bus Data                    |
+|-----------------------------|
+| Label |       Voltage       |
+|       |                     |
+|   Bus | Magnitude |   Angle |
+|       |      [pu] |   [deg] |
+|-------|-----------|---------|
+| Bus 1 |    0.9989 |  0.0034 |
+| Bus 2 |    1.0204 |  0.8428 |
+| Bus 3 |    1.0111 | -0.2895 |
+|-----------------------------|

Next, users can easily customize the print results for specific buses, for example:

printBusData(system, analysis; label = "Bus 1", header = true)
+printBusData(system, analysis; label = "Bus 2")
+printBusData(system, analysis; label = "Bus 3", footer = true)

Save Results to a File

Users can also redirect print output to a file. For example, data can be saved in a text file as follows:

open("bus.txt", "w") do file
+    printBusData(system, analysis, file)
+end
Tip

We also provide functions to print or save state estimation results, such as estimated values and residuals. For more details, users can consult the Power and Current Analysis section of this manual.


Bad Data Processing

After acquiring the WLS solution using the solve! function, users can conduct bad data analysis employing the largest normalized residual test. Continuing with our defined power system and measurement set, let us introduce a new phasor measurement. Upon proceeding to find the solution for this updated state:

addPmu!(system, device; bus = "Bus 3", magnitude = 3.2, angle = 0.0, noise = false)
+
+analysis = pmuStateEstimation(system, device)
+solve!(system, analysis)

Following the solution acquisition, we can verify the presence of erroneous data. Detection of such data is determined by the threshold keyword. If the largest normalized residual's value exceeds the threshold, the measurement will be identified as bad data and consequently removed from the PMU state estimation model:

outlier = residualTest!(system, device, analysis; threshold = 4.0)

Users can examine the data obtained from the bad data analysis:

julia> outlier.detecttrue
julia> outlier.maxNormalizedResidual565.2155119055411
julia> outlier.label"PMU 6 (Bus 3)"

Hence, upon detecting bad data, the detect variable will hold true. The maxNormalizedResidual variable retains the value of the largest normalized residual, while the label contains the label of the measurement identified as bad data. JuliaGrid will mark the respective phasor measurement as out-of-service within the Measurement type.

Moreover, JuliaGrid will adjust the coefficient matrix and mean vector within the PMUStateEstimation type based on measurements now designated as out-of-service. To optimize the algorithm's efficiency, JuliaGrid resets non-zero elements to zero in the coefficient matrix and mean vector, effectively removing the impact of the corresponding measurement on the solution:

julia> analysis.method.mean12-element Vector{Float64}:
+  1.0214534591451636
+  0.014949642440409396
+  0.4938272187286028
+  0.038153637901242377
+  0.40545942634957655
+ -0.24635642762807566
+  1.1568832944388845
+  0.18934633137812892
+  1.009987375026302
+ -0.005049978958359636
+  0.0
+  0.0
julia> analysis.method.coefficient12×6 SparseArrays.SparseMatrixCSC{Float64, Int64} with 30 stored entries: + ⋅ 1.0 ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ 1.0 ⋅ + ⋅ 10.0 -10.0 ⋅ 19.98 -20.0 + ⋅ -19.98 20.0 ⋅ 10.0 -10.0 + -6.89655 6.8966 ⋅ -17.2414 17.2214 ⋅ + 17.2414 -17.2214 ⋅ -6.89655 6.8966 ⋅ + -40.0 40.0001 ⋅ -20.0 19.98 ⋅ + 20.0 -19.98 ⋅ -40.0 40.0001 ⋅ + ⋅ ⋅ 1.0 ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ ⋅ 1.0 + ⋅ ⋅ 0.0 ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ ⋅ 0.0

After removing bad data, a new estimate can be computed without considering this specific phasor measurement:

solve!(system, analysis)
Info

We suggest that readers refer to the tutorial on Bad Data Processing for insights into the implementation.


Least Absolute Value Estimator

The LAV method presents an alternative estimation technique known for its increased robustness compared to WLS. While the WLS method relies on specific assumptions regarding measurement errors, robust estimators like LAV are designed to maintain unbiasedness even in the presence of various types of measurement errors and outliers. This characteristic often eliminates the need for extensive bad data processing procedures [5, Ch. 6]. However, it is important to note that achieving robustness typically involves increased computational complexity.

To obtain an LAV estimator, users need to employ one of the solvers listed in the JuMP documentation. In many common scenarios, the Ipopt solver proves sufficient to obtain a solution:

using Ipopt
+
+analysis = pmuLavStateEstimation(system, device, Ipopt.Optimizer)

Setup Starting Primal Values

In JuliaGrid, the assignment of starting primal values for optimization variables takes place when the solve! function is executed. Starting primal values are determined based on the voltage fields within the PMUStateEstimation type. By default, these values are initially established using the initial bus voltage magnitudes and angles from PowerSystem type:

julia> print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)Bus 1: 1.0, 0.0
+Bus 2: 1.0, 0.0
+Bus 3: 1.0, 0.0

Users have the flexibility to customize these values according to their requirements, and they will be utilized as the starting primal values when executing the solve! function. It is important to note that JuliaGrid utilizes the provided data to set starting primal values in the rectangular coordinate system.


Solution

To solve the formulated LAV state estimation model, simply execute the following function:

solve!(system, analysis)

Upon obtaining the solution, access the bus voltage magnitudes and angles using:

julia> print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)Bus 1: 0.9999997020404692, 2.38511418627896e-7
+Bus 2: 1.0215625577848158, 0.014634850009356088
+Bus 3: 1.0122938013823002, -0.0051048653876440584
Info

We suggest that readers refer to the tutorial on Least Absolute Value Estimation for insights into the implementation.


Measurement Set Update

After establishing the Measurement type using the measurement function, users gain the capability to incorporate new measurement devices or update existing ones.

Once updates are completed, users can seamlessly progress towards generating the PMUStateEstimation type using the pmuStateEstimation or pmuLavStateEstimation function. Ultimately, resolving the PMU state estimation is achieved through the utilization of the solve! function:

system = powerSystem()
+device = measurement() # <- Initialize the Measurement instance
+
+addBus!(system; label = "Bus 1", type = 3)
+addBus!(system; label = "Bus 2", type = 1, active = 0.1, reactive = 0.01)
+addBus!(system; label = "Bus 3", type = 1, active = 2.5, reactive = 0.2)
+
+@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+addBranch!(system; label = "Branch 2", from = "Bus 2", to = "Bus 3", reactance = 0.03)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 3.2, reactive = 0.3)
+
+@pmu(label = "PMU ?")
+addPmu!(system, device; bus = "Bus 1", magnitude = 1.0, angle = 0.0)
+addPmu!(system, device; bus = "Bus 2", magnitude = 0.98, angle = -0.023)
+addPmu!(system, device; from = "Branch 2", magnitude = 0.5, angle = -0.05)
+
+analysis = pmuStateEstimation(system, device) # <- Build PMUStateEstimation for the model
+solve!(system, analysis)
+
+addPmu!(system, device; to = "Branch 2", magnitude = 0.5, angle = 3.1)
+updatePmu!(system, device; label = "PMU 1", varianceMagnitude = 1e-8)
+updatePmu!(system, device; label = "PMU 3", statusMagnitude = 0, statusAngle = 0)
+
+analysis = pmuStateEstimation(system, device) # <- Build PMUStateEstimation for new model
+solve!(system, analysis)
Info

This concept removes the need to restart and recreate the Measurement type from the beginning when implementing changes to the existing measurement set.


State Estimation Update

An advanced methodology involves users establishing the PMUStateEstimation type using pmuStateEstimation or pmuLavStateEstimation just once. After this initial setup, users can seamlessly modify existing measurement devices without the need to recreate the PMUStateEstimation type.

This advancement extends beyond the previous scenario where recreating the Measurement type was unnecessary, to now include the scenario where PMUStateEstimation also does not need to be recreated.

Tip

The addition of new measurements after the creation of PMUStateEstimation is not practical in terms of reusing the PMUStateEstimation type. Instead, we recommend that users create a final set of measurements and then utilize update functions to manage devices, either putting them in-service or out-of-service throughout the process.

We can modify the prior example to achieve the same model without establishing PMUStateEstimation twice:

system = powerSystem()
+device = measurement() # <- Initialize the Measurement instance
+
+addBus!(system; label = "Bus 1", type = 3)
+addBus!(system; label = "Bus 2", type = 1, active = 0.1, reactive = 0.01)
+addBus!(system; label = "Bus 3", type = 1, active = 2.5, reactive = 0.2)
+
+@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+addBranch!(system; label = "Branch 2", from = "Bus 2", to = "Bus 3", reactance = 0.03)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 3.2, reactive = 0.3)
+
+@pmu(label = "PMU ?")
+addPmu!(system, device; bus = "Bus 1", magnitude = 1.0, angle = 0.0)
+addPmu!(system, device; bus = "Bus 2", magnitude = 0.98, angle = -0.023)
+addPmu!(system, device; from = "Branch 2", magnitude = 0.5, angle = -0.05)
+addPmu!(system, device; to = "Branch 2", magnitude = 0.5, angle = 3.1, statusAngle = 0)
+
+analysis = pmuStateEstimation(system, device) # <- Build PMUStateEstimation for the model
+solve!(system, analysis)
+
+updatePmu!(system, device, analysis; label = "PMU 1", varianceMagnitude = 1e-8)
+updatePmu!(system, device, analysis; label = "PMU 3", statusMagnitude = 0, statusAngle = 0)
+updatePmu!(system, device, analysis; label = "PMU 4", statusAngle = 1)
+
+# <- No need for re-build; we have already updated the existing PMUStateEstimation instance
+solve!(system, analysis)
Info

This concept removes the need to rebuild both the Measurement and the PMUStateEstimation from the beginning when implementing changes to the existing measurement set. In the scenario of employing the WLS model, JuliaGrid can reuse the symbolic factorizations of LU or LDLt, provided that the nonzero pattern of the gain matrix remains unchanged.


Power and Current Analysis

After obtaining the solution from the PMU state estimation, we can calculate various electrical quantities related to buses and branches using the power! and current! functions. For instance, let us consider the model for which we obtained the PMU state estimation solution:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", type = 3, susceptance = 0.002)
+addBus!(system; label = "Bus 2", type = 1, active = 0.1, reactive = 0.01)
+addBus!(system; label = "Bus 3", type = 1, active = 2.5, reactive = 0.2)
+
+@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 3", reactance = 0.05)
+addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 3", reactance = 0.03)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 3.2, reactive = 0.3)
+
+addPmu!(system, device; bus = "Bus 1", magnitude = 1.0, angle = 0.0)
+addPmu!(system, device; bus = "Bus 2", magnitude = 0.97, angle = -0.051)
+addPmu!(system, device; from = "Branch 2", magnitude = 1.66, angle = -0.15)
+addPmu!(system, device; to = "Branch 2", magnitude = 1.67, angle = 2.96)
+
+analysis = pmuStateEstimation(system, device)
+solve!(system, analysis)

We can now utilize the provided functions to compute powers and currents:

power!(system, analysis)
+current!(system, analysis)

For instance, if we want to show the active power injections and the from-bus current magnitudes, we can employ the following code:

julia> print(system.bus.label, analysis.power.injection.active)Bus 1: 2.7128789695754727
+Bus 2: -0.21564110130961964
+Bus 3: -2.4028824415290972
julia> print(system.branch.label, analysis.current.from.magnitude)Branch 1: 1.084804224498079 +Branch 2: 1.662466361408605 +Branch 3: 0.865833625134112
Info

To better understand the powers and currents associated with buses and branches that are calculated by the power! and current! functions, we suggest referring to the tutorials on PMU State Estimation.


Users can utilize any of the print functions outlined in the Print API. For example, to print state estimation data related to PMUs, we can use:

@voltage(pu, deg, V)
+show = Dict("Voltage Angle" => false, "Current Angle" => false)
+printPmuData(system, device, analysis; show)
|---------------------------------------------------------------|
+| PMU Data                                                      |
+|---------------------------------------------------------------|
+| Label |                   Voltage Magnitude                   |
+|       |                                                       |
+|       | Measurement | Variance | Estimate | Residual | Status |
+|       |        [pu] |     [pu] |     [pu] |     [pu] |        |
+|-------|-------------|----------|----------|----------|--------|
+| 1     |      1.0000 | 1.00e-05 |   1.0001 |  -0.0001 |      1 |
+| 2     |      0.9700 | 1.00e-05 |   0.9700 |   0.0000 |      1 |
+|---------------------------------------------------------------|
+|---------------------------------------------------------------|
+| PMU Data                                                      |
+|---------------------------------------------------------------|
+| Label |                   Current Magnitude                   |
+|       |                                                       |
+|       | Measurement | Variance | Estimate | Residual | Status |
+|       |        [pu] |     [pu] |     [pu] |     [pu] |        |
+|-------|-------------|----------|----------|----------|--------|
+| 3     |      1.6600 | 1.00e-05 |   1.6625 |  -0.0025 |      1 |
+| 4     |      1.6700 | 1.00e-05 |   1.6673 |   0.0027 |      1 |
+|---------------------------------------------------------------|

Save Results to a CSV File

For CSV output, users should first generate a simple table with style = false, and then save it to a CSV file:

using CSV
+
+io = IOBuffer()
+printPmuData(system, device, analysis, io; style = false)
+CSV.write("bus.csv", CSV.File(take!(io); delim = "|"))

Active and Reactive Power Injection

To calculate the active and reactive power injection associated with a specific bus, the function can be used:

julia> active, reactive = injectionPower(system, analysis; label = "Bus 1")(2.7128789695754727, 0.43288460463326406)

Active and Reactive Power Injection from Generators

To calculate the active and reactive power injection from the generators at a specific bus, the function can be used:

julia> active, reactive = supplyPower(system, analysis; label = "Bus 1")(2.7128789695754727, 0.43288460463326406)

Active and Reactive Power at Shunt Element

To calculate the active and reactive power associated with shunt element at a specific bus, the function can be used:

julia> active, reactive = shuntPower(system, analysis; label = "Bus 1")(0.0, -0.002000424255767445)

Active and Reactive Power Flow

Similarly, we can compute the active and reactive power flow at both the from-bus and to-bus ends of the specific branch by utilizing the provided functions below:

julia> active, reactive = fromPower(system, analysis; label = "Branch 2")(1.6429108157162793, 0.255391331637058)
julia> active, reactive = toPower(system, analysis; label = "Branch 2")(-1.5873301378903089, -0.1549833506018255)

Active and Reactive Power at Charging Admittances

To calculate the active and reactive power linked with branch charging admittances of the particular branch, the function can be used:

julia> active, reactive = chargingPower(system, analysis; label = "Branch 1")(9.705560639418611e-5, -0.03882224255767445)

Active powers indicate active losses within the branch's charging admittances. Moreover, charging admittances injected reactive powers into the power system due to their capacitive nature, as denoted by a negative sign.


Active and Reactive Power at Series Impedance

To calculate the active and reactive power across the series impedance of the branch, the function can be used:

julia> active, reactive = seriesPower(system, analysis; label = "Branch 2")(0.05548491704701527, 0.13871229261753815)

The active power also considers active losses originating from the series resistance of the branch, while the reactive power represents reactive losses resulting from the impedance's inductive characteristics.


Current Injection

To calculate the current injection associated with a specific bus, the function can be used:

julia> magnitude, angle = injectionCurrent(system, analysis; label = "Bus 1")(2.7469074926874932, -0.15817873160622747)

Current Flow

We can compute the current flow at both the from-bus and to-bus ends of the specific branch by utilizing the provided functions below:

julia> magnitude, angle = fromCurrent(system, analysis; label = "Branch 2")(1.662466361408605, -0.1541623914297243)
julia> magnitude, angle = toCurrent(system, analysis; label = "Branch 2")(1.6673093443308729, 2.964124299788863)

Current Through Series Impedance

To calculate the current passing through the series impedance of the branch in the direction from the from-bus end to the to-bus end, we can use the following function:

julia> magnitude, angle = seriesCurrent(system, analysis; label = "Branch 2")(1.6656067520128401, -0.1660336726001753)
diff --git a/v0.2.0/manual/powerSystemModel/index.html b/v0.2.0/manual/powerSystemModel/index.html new file mode 100644 index 000000000..b5f2a6fb2 --- /dev/null +++ b/v0.2.0/manual/powerSystemModel/index.html @@ -0,0 +1,199 @@ + +Power System Model · JuliaGrid

Power System Model

JuliaGrid supports the type PowerSystem to preserve power system data, with the following fields: bus, branch, generator, base, and model. The bus, branch, and generator fields hold data related to buses, branches, and generators, respectively. The base field stores base values for power and voltages, with the default being three-phase power measured in volt-amperes for the base power and line-to-line voltages measured in volts for base voltages. Within the model field, the ac and dc subfields store vectors and matrices pertinent to the power system's topology and parameters, and these are utilized in either the AC or DC framework.

The type PowerSystem can be created using a function:

JuliaGrid supports three modes for populating the PowerSystem type: using built-in functions, using HDF5 file format, and using Matpower case files.

It is recommended to use the HDF5 format for large-scale systems. To facilitate this, JuliaGrid has the function:

Upon creation of the PowerSystem type, users can generate vectors and matrices based on the power system topology and parameters using the following functions:


Once the PowerSystem type is created, users can add buses, branches, generators, or manage costs associated with the output powers of the generators, using the following functions:

JuliaGrid also provides macros @bus, @branch, and @generator to define templates that aid in creating buses, branches, and generators. These templates help avoid entering the same parameters repeatedly.

Moreover, it is feasible to modify the parameters of buses, branches, and generators. When these functions are executed, all relevant fields within the PowerSystem type will be automatically updated, encompassing the ac and dc fields as well. These functions include:

Tip

The functions addBranch!, addGenerator!, updateBus!, updateBranch!, updateGenerator!, and cost! serve a dual purpose. While their primary function is to modify the PowerSystem type, they are also designed to accept various analysis models like AC or DC power flow models. When feasible, these functions not only modify the PowerSystem type but also adapt the analysis model, often resulting in improved computational efficiency. Detailed instructions on utilizing this feature can be found in dedicated manuals for specific analyses.


Build Model

The powerSystem function generates the PowerSystem type and requires a string-formatted path to either Matpower cases or HDF5 files as input. Alternatively, the PowerSystem can be created without any initial data by initializing it as empty, allowing the user to construct the power system from scratch.


Matpower File

For example, to create the PowerSystem type using the Matpower case file for the IEEE 14-bus test case, which is named case14.m and located in the folder C:\matpower, the following Julia code can be used:

system = powerSystem("C:/matpower/case14.m")

HDF5 File

In order to use the HDF5 file as input to create the PowerSystem type, it is necessary to have saved the data using the savePowerSystem function beforehand. As an example, let us say we saved the power system as case14.h5 in the directory C:\hdf5. In this case, the following Julia code can be used to construct the PowerSystem type:

system = powerSystem("C:/hdf5/case14.h5")
Tip

It is recommended to load the power system from the HDF5 file to reduce the loading time.


Model from Scratch

Alternatively, the model can be built from scratch using built-in functions, for example:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.1, base = 345e3)
+addBus!(system; label = "Bus 2", type = 1, reactive = 0.05, base = 345e3)
+
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)

Internal Unit System

The PowerSystem type stores all electrical quantities in per-units and radians, except for the base values of power and voltages. The base power value is expressed in volt-amperes, while the base voltages are given in volts.


Change Base Unit Prefixes

The user can retrieve the base power and base voltage values along with their respective units:

julia> system.base.power.value, system.base.power.unit(1.0e8, "VA")
julia> system.base.voltage.value, system.base.voltage.unit([345000.0, 345000.0], "V")

By using the @base macro, users can change the prefixes of the base units. For instance, if users wish to convert base power and base voltage values to megavolt-amperes (MVA) and kilovolts (kV) respectively, they can execute the following macro:

@base(system, MVA, kV)

After executing the macro, the base power and voltage values and their units will be modified accordingly:

julia> system.base.power.value, system.base.power.unit(100.0, "MVA")
julia> system.base.voltage.value, system.base.voltage.unit([345.0, 345.0], "kV")

Save Model

Once the PowerSystem type has been created using one of the methods outlined in Build Model, the data can be stored in the HDF5 file by using the savePowerSystem function:

savePowerSystem(system; path = "C:/matpower/case14.h5", reference = "IEEE 14-bus test case")

All electrical quantities saved in the HDF5 file are in per-units and radians, except for base values for power and voltages, which are given in volt-amperes and volts. Note that even if the user modifies the base units using the @base macro, the units will still be saved with the default settings.


Add Bus

The buses can be added both to the loaded power system, or to the one created from scratch. As an illustration, we can initiate the PowerSystem type and then incorporate two buses by utilizing the addBus! function:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.1, base = 345e3)
+addBus!(system; label = "Bus 2", type = 1, angle = -0.034907, base = 345e3)

In this case, we have created two buses where the active power demanded by the consumer at Bus 1 is specified in per-units, which are the same units used to store electrical quantities:

julia> system.bus.demand.active2-element Vector{Float64}:
+ 0.1
+ 0.0

It is worth noting that the base keyword is used to specify the base voltages, and its default input unit is in volts (V):

julia> system.base.voltage.value, system.base.voltage.unit([345000.0, 345000.0], "V")

Also, we have defined the bus voltage angle in radians for Bus 2 as its initial value:

julia> system.bus.voltage.angle2-element Vector{Float64}:
+  0.0
+ -0.034907
Info

We recommend reading the documentation for the addBus! function, where we have provided a list of all the keywords that can be used.


Customizing Input Units for Keywords

Typically, all keywords associated with electrical quantities are expected to be provided in per-units (pu) and radians (rad) by default, with the exception of base voltages, which should be specified in volts (V). However, users can choose to use different units than the default per-units and radians or modify the prefix of the base voltage unit by using macros such as the following:

@power(MW, MVAr, pu)
+@voltage(pu, deg, kV)

This practical example showcases the customization approach. For keywords tied to active powers, the unit is set as megawatts (MW), while reactive powers employ megavolt-amperes reactive (MVAr). Apparent power, on the other hand, employs per-units (pu). As for keywords concerning voltage magnitude, per-units (pu) remain the choice, but voltage angle mandates degrees (deg). Lastly, the input unit for base voltage is elected to be kilovolts (kV).

Now we can create identical two buses as before using new system of units as follows:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, active = 10.0, base = 345.0)
+addBus!(system; label = "Bus 2", type = 1, angle = -2.0, base = 345.0)

As can be observed, electrical quantities will continue to be stored in per-units and radians format:

julia> [system.bus.demand.active system.bus.voltage.angle]2×2 Matrix{Float64}:
+ 0.1   0.0
+ 0.0  -0.0349066

The base voltage values will still be stored in volts (V) since we only changed the input unit prefix, and did not modify the internal unit prefix, as shown below:

julia> system.base.voltage.value, system.base.voltage.unit([345000.0, 345000.0], "V")

To modify the internal unit prefix, the following macro can be used:

@base(system, VA, kV)

After executing this macro, the base voltage values will be stored in kilovolts (kV):

julia> system.base.voltage.value, system.base.voltage.unit([345.0, 345.0], "kV")

Add Branch

The branch connecting two buses can be added once those buses are defined, and from and to keywords must correspond to labels of those buses. For example:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.1)
+addBus!(system; label = "Bus 2", type = 1, angle = -0.2)
+
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.12)

Here, we created the branch from Bus 1 to Bus 2 with following parameter:

julia> system.branch.parameter.reactance1-element Vector{Float64}:
+ 0.12
Info

It is recommended to consult the documentation for the addBranch! function, where we have provided a list of all the keywords that can be used.


Customizing Input Units for Keywords

To use units other than per-units (pu) and radians (rad), macros can be employed to change the input units. For example, if there is a need to use ohms (Ω), the macros below can be employed:

@parameter(Ω, pu)
+
+system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.1)
+addBus!(system; label = "Bus 2", type = 1, angle = -0.2)
+
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 22.8528)

Still, all electrical quantities are stored in per-units, and the same branch as before is created:

julia> system.branch.parameter.reactance1-element Vector{Float64}:
+ 0.11999999999999998

It is important to note that, when working with impedance and admittance values in ohms (Ω) and siemens (S) that are related to a transformer, the assignment must be based on the primary side of the transformer.


Add Generator

The generator connected to a bus can be added once the bus is defined. Each generator must have a unique label, and the bus keyword should correspond to the unique label of the bus it is connected to. For instance:

system = powerSystem()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 2", active = 0.5, reactive = 0.1)

In the above code, we add the generator to the Bus 2, with active and reactive power outputs set to:

julia> system.generator.output.active, system.generator.output.reactive([0.5], [0.1])

Similar to buses and branches, the input units can be changed to units other than per-units using different macros.

Info

It is recommended to refer to the documentation for the addGenerator! function, where we have provided a list of all the keywords that can be used.


Add Templates

The functions addBus!, addBranch!, and addGenerator! are used to add bus, branch, and generator to the power system, respectively. If certain keywords are not specified, default values are assigned to some parameters.


Default Keyword Values

Regarding the addBus! function, the bus type is automatically configured as a demand bus with type = 1. The initial bus voltage magnitude is set to magnitude = 1.0 per-unit, while the base voltage is established as base = 138e3 volts. Additionally, the minimum and maximum bus voltage magnitudes are set to minMagnitude = 0.9 per-unit and maxMagnitude = 1.1 per-unit, respectively.

Transitioning to the addBranch! function, the default operational status is status = 1, indicating that the branch is in-service. The off-nominal turns ratio for the transformer is specified as turnsRatio = 1.0, and the phase shift angle is set to shiftAngle = 0.0, collectively defining the line configuration with these standard settings. The flow rating is also configured as type = 1. Moreover, the minimum and maximum voltage angle differences between the from-bus and to-bus ends are set to minDiffAngle = -2pi and maxDiffAngle = 2pi, respectively.

Similarly, the addGenerator! function designates an operational generator by employing status = 1, and it sets magnitude = 1.0 per-unit, denoting the desired voltage magnitude setpoint.

The remaining parameters are initialized with default values of zero.


Change Default Keyword Values

In JuliaGrid, users have the flexibility to adjust default values and assign customized values using the @bus, @branch, and @generator macros. These macros create bus, branch, and generator templates that are used every time the addBus!, addBranch!, and addGenerator! functions are called. For instance, the code block shows an example of creating bus, branch, and generator templates with customized default values:

system = powerSystem()
+
+@bus(type = 2, active = 0.1)
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2", type = 1, active = 0.5)
+
+@branch(reactance = 0.12)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2")
+addBranch!(system; label = "Branch 2", from = "Bus 1", to = "Bus 2", reactance = 0.06)
+
+@generator(magnitude = 1.1)
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 0.6)
+addGenerator!(system; label = "Generator 2", bus = "Bus 1", active = 0.2)

This code example involves two uses of the addBus! and addBranch! functions. In the first use, the functions rely on the default values set by the templates created with the @bus and @branch macros. In contrast, the second use passes specific values that match the keywords used in the templates. As a result, the templates are ignored:

julia> system.bus.layout.type2-element Vector{Int8}:
+ 2
+ 1
julia> system.bus.demand.active2-element Vector{Float64}: + 0.1 + 0.5
julia> system.branch.parameter.reactance2-element Vector{Float64}: + 0.12 + 0.06

In the given example, the @generator macro is utilized instead of repeatedly specifying the magnitude keyword in the addGenerator! function. This macro creates a generator template with a default value for magnitude, which is automatically applied every time the addGenerator! function is called. Therefore, it eliminates the requirement to set the magnitude value for each individual generator:

julia> system.generator.voltage.magnitude2-element Vector{Float64}:
+ 1.1
+ 1.1

Customizing Input Units for Keywords

Templates can also be defined using a custom unit system, for example:

system = powerSystem()
+
+@power(MW, MVAr, MVA)
+@bus(active = 100, reactive = 200)
+addBus!(system; label = "Bus 1")
+
+@power(pu, pu, pu)
+addBus!(system; label = "Bus 2", active = 0.5)

In this example, we create the bus template and one bus using SI power units, and then we switch to per-units and add the second bus. It is important to note that once the template is defined in any unit system, it remains valid regardless of subsequent unit system changes. The resulting power values are:

julia> system.bus.demand.active2-element Vector{Float64}:
+ 1.0
+ 0.5
julia> system.bus.demand.reactive2-element Vector{Float64}: + 2.0 + 2.0

Thus, JuliaGrid automatically tracks the unit system used to create templates and provides the appropriate conversion to per-units and radians. Even if the user switches to a different unit system later on, the previously defined template will still be valid.


Multiple Templates

In the case of calling the @bus, @branch, or @generator macros multiple times, the provided keywords and values will be combined into a single template for the corresponding component (bus, branch, or generator), which will be used for generating the component.


Reset Templates

To reset the bus, branch, and generator templates to their default settings, users can utilize the following macros:

@default(bus)
+@default(branch)
+@default(generator)

Additionally, users can reset all templates using the macro:

@default(template)

Labels

As we have shown, JuliaGrid mandates a distinctive label for every bus, branch, or generator. These labels are stored in ordered dictionaries, functioning as pairs of strings and integers. The string signifies the exclusive label for the specific component, whereas the integer maintains an internal numbering of buses, branches, or generators.

Tip

String labels improve readability, but in larger models, the overhead from using strings can become substantial. To reduce memory usage, users can configure ordered dictionaries to accept and store integers as labels:

@labels(Integer)

Integer-Based Labeling

Let us take a look at the following illustration:

@labels(Integer)
+
+system = powerSystem()
+
+addBus!(system; label = 1, type = 3, active = 0.1)
+addBus!(system; label = 2, type = 1, angle = -0.2)
+
+addBranch!(system; label = 1, from = 1, to = 2, reactance = 0.12)
+
+addGenerator!(system; label = 1, bus = 2, active = 0.5, reactive = 0.1)

In this example, we use the macro @labels to specify that labels will be stored as integers. It is essential to run this macro; otherwise, even if integers are used in subsequent functions, they will be stored as strings.

Here, two buses are created with labels 1 and 2. A branch connects these two buses, assigned a unique label of 1. Finally, a generator is connected to bus 2, with its own label set to 1.


Automated Labeling

Users also possess the option to omit the label keyword, allowing JuliaGrid to independently allocate unique labels for buses, branches, or generators. In such instances, JuliaGrid employs an ordered set of incremental integers for labeling components. To illustrate, consider the subsequent example:

system = powerSystem()
+
+addBus!(system; type = 3, active = 0.1)
+addBus!(system; type = 1, angle = -0.2)
+
+addBranch!(system; from = 1, to = 2, reactance = 0.12)
+
+addGenerator!(system; bus = 2, active = 0.5, reactive = 0.1)

This example models the same power system as before. In the previous case, we manually assigned labels using incremental integers. Here, we rely on the automatic labeling behavior, but since the macro @labels is not used, the labels will be stored as strings.


Automated Labeling Using Templates

Additionally, users have the ability to generate labels through templates and employ the symbol ? to insert an incremental set of integers at any location. For instance:

system = powerSystem()
+
+@bus(label = "Bus ? HV")
+addBus!(system; type = 3, active = 0.1)
+addBus!(system; type = 1, angle = -0.2)
+
+@branch(label = "Branch ?")
+addBranch!(system; from = "Bus 1 HV", to = "Bus 2 HV", reactance = 0.12)
+
+@generator(label = "Generator ?")
+addGenerator!(system; bus = "Bus 2 HV", active = 0.5, reactive = 0.1)

In this example, two buses are generated and labeled as Bus 1 HV and Bus 2 HV, along with one branch and one generator labeled as Branch 1 and Generator 1, respectively.


Retrieving Labels

Finally, we will outline how users can retrieve stored labels. Let us consider the following power system creation:

system = powerSystem()
+
+addBus!(system; label = "Bus 2")
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 3")
+
+addBranch!(system; label = "Branch 2", from = "Bus 2", to = "Bus 1", reactance = 0.8)
+addBranch!(system; label = "Branch 1", from = "Bus 2", to = "Bus 3", reactance = 0.5)
+
+addGenerator!(system; label = "Generator 2", bus = "Bus 1")
+addGenerator!(system; label = "Generator 1", bus = "Bus 3")

For instance, the bus labels can be accessed using the variable:

julia> system.bus.labelOrderedCollections.OrderedDict{String, Int64} with 3 entries:
+  "Bus 2" => 1
+  "Bus 1" => 2
+  "Bus 3" => 3

If the objective is to obtain only labels, users can utilize the following:

julia> label = collect(keys(system.bus.label))3-element Vector{String}:
+ "Bus 2"
+ "Bus 1"
+ "Bus 3"

This approach can also be extended to branch and generator labels by making use of the variables present within the PowerSystem type, namely system.branch.label or system.generator.label.

Moreover, the from and to keywords associated with branches are stored based on internally assigned numerical values linked to bus labels. These values are stored in variables:

julia> [system.branch.layout.from system.branch.layout.to]2×2 Matrix{Int64}:
+ 1  2
+ 1  3

To recover the original from and to labels, we can utilize:

julia> [label[system.branch.layout.from] label[system.branch.layout.to]]2×2 Matrix{String}:
+ "Bus 2"  "Bus 1"
+ "Bus 2"  "Bus 3"

Similarly, the bus keywords related to generators are saved based on internally assigned numerical values corresponding to bus labels and can be accessed using:

julia> system.generator.layout.bus2-element Vector{Int64}:
+ 2
+ 3

To recover the original bus labels, we can utilize:

julia> label[system.generator.layout.bus]2-element Vector{String}:
+ "Bus 1"
+ "Bus 3"
Tip

JuliaGrid offers the capability to print labels alongside various types of data, such as power system parameters, voltages, powers, currents, or constraints used in optimal power flow analyses. For instance:

julia> print(system.branch.label, system.branch.parameter.reactance)Branch 2: 0.8
+Branch 1: 0.5

Loading and Saving Labels

When a user loads a power system from a Matpower file, the default behavior is to store labels as strings. However, this can be overridden by using the @labels macro to store labels as integers.

When saving the power system to an HDF5 file, the label type (strings or integers) will match the type chosen during system setup. Likewise, when loading data from an HDF5 file, the label type will be preserved as saved, regardless of what is set by the @labels macro.


AC and DC Model

When we constructed the power system, we can create an AC and/or DC model, which include vectors and matrices related to the power system's topology and parameters. The following code snippet demonstrates this:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.1)
+addBus!(system; label = "Bus 2", type = 1, reactive = 0.05)
+addBus!(system; label = "Bus 3", type = 1, susceptance = 0.05)
+
+addBranch!(system; from = "Bus 1", to = "Bus 2", reactance = 0.12, shiftAngle = 0.1745)
+addBranch!(system; from = "Bus 2", to = "Bus 3", resistance = 0.008, reactance = 0.05)
+
+acModel!(system)
+dcModel!(system)
Tip

In many instances throughout the JuliaGrid documentation, we explicitly mention these functions by their names, although it is not mandatory. If a user begins any of the various AC or DC analyses without having previously established the AC or DC model using the acModel! or dcModel! function, the respective function for setting the analysis will automatically create the AC or DC model.

The nodal matrices are one of the components of both the AC and DC models and are stored in the variables:

julia> system.model.ac.nodalMatrix3×3 SparseArrays.SparseMatrixCSC{ComplexF64, Int64} with 7 stored entries:
+    0.0-8.33333im   -1.4468+8.20678im           ⋅
+ 1.4468+8.20678im   3.12012-27.8341im  -3.12012+19.5008im
+        ⋅          -3.12012+19.5008im   3.12012-19.4508im
julia> system.model.dc.nodalMatrix3×3 SparseArrays.SparseMatrixCSC{Float64, Int64} with 7 stored entries: + 8.33333 -8.33333 ⋅ + -8.33333 28.3333 -20.0 + ⋅ -20.0 20.0
Info

The AC model is used for performing AC power flow, AC optimal power flow, AC state estimation, or state estimation with PMUs, whereas the DC model is essential for various DC or linear analyses. Consequently, once these models are developed, they can be applied to various types of simulations. We recommend that the reader refers to the tutorial on AC and DC models.


New Branch Triggers Model Update

We can execute the acModel! and dcModel! functions after defining the final number of buses, and each new branch added will trigger an update of the AC and DC matrices and vectors. Here is an example:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.1)
+addBus!(system; label = "Bus 2", type = 1, reactive = 0.05)
+addBus!(system; label = "Bus 3", type = 1, susceptance = 0.05)
+
+acModel!(system)
+dcModel!(system)
+
+addBranch!(system; from = "Bus 1", to = "Bus 2", reactance = 0.12, shiftAngle = 0.1745)
+addBranch!(system; from = "Bus 2", to = "Bus 3", resistance = 0.008, reactance = 0.05)

For example, the nodal matrix in the DC framework has the same values as before:

julia> system.model.dc.nodalMatrix3×3 SparseArrays.SparseMatrixCSC{Float64, Int64} with 7 stored entries:
+  8.33333   -8.33333     ⋅
+ -8.33333   28.3333   -20.0
+   ⋅       -20.0       20.0
Tip

It is not fully recommended to create AC and DC models before adding a large number of branches if the execution time of functions is important. Instead, triggering updates to the AC and DC models using the addBranch! function is useful for power systems that require the addition of several branches. This update avoids the need to recreate vectors and matrices from scratch.


New Bus Triggers Model Erasure

The AC and DC models must be defined once a finite number of buses has been defined, otherwise, adding a new bus will delete them. For example, if we attempt to add a new bus to the PowerSystem type that was previously created, the current AC and DC models will be completely erased:

julia> addBus!(system; label = "Bus 4", type = 2)[ Info: The AC model has been completely erased.
+[ Info: The DC model has been completely erased.
julia> system.model.ac.nodalMatrix0×0 SparseArrays.SparseMatrixCSC{ComplexF64, Int64} with 0 stored entries
julia> system.model.dc.nodalMatrix0×0 SparseArrays.SparseMatrixCSC{Float64, Int64} with 0 stored entries

Update Bus

Once a bus has been added to the PowerSystem type, users have the flexibility to modify all parameters defined within the addBus! function. This means that when the updateBus! function is used, the PowerSystem type within AC and DC models that have been created is updated. This eliminates the need to recreate the AC and DC models from scratch.

To illustrate, let us consider the following power system:

system = powerSystem()
+
+addBus!(system; label = "Bus 1", type = 3, active = 0.1, conductance = 0.01)
+addBus!(system; label = "Bus 2", type = 2, reactive = 0.05)
+addBus!(system; label = "Bus 3", type = 1, susceptance = 0.05)
+
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.12)
+addBranch!(system; label = "Branch 2", from = "Bus 2", to = "Bus 3", reactance = 0.05)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 0.5)
+addGenerator!(system; label = "Generator 2", bus = "Bus 1", active = 0.2)
+
+acModel!(system)
+dcModel!(system)

For instance, the nodal matrix in the AC framework has the following form:

julia> system.model.ac.nodalMatrix3×3 SparseArrays.SparseMatrixCSC{ComplexF64, Int64} with 7 stored entries:
+ 0.01-8.33333im  -0.0+8.33333im       ⋅
+  0.0+8.33333im   0.0-28.3333im  -0.0+20.0im
+      ⋅           0.0+20.0im      0.0-19.95im

Now, let us add a shunt element to Bus 2:

updateBus!(system; label = "Bus 2", conductance = 0.4, susceptance = 0.5)

As we can observe, executing the function triggers an update of the AC nodal matrix:

julia> system.model.ac.nodalMatrix3×3 SparseArrays.SparseMatrixCSC{ComplexF64, Int64} with 7 stored entries:
+ 0.01-8.33333im  -0.0+8.33333im       ⋅
+  0.0+8.33333im   0.4-27.8333im  -0.0+20.0im
+      ⋅           0.0+20.0im      0.0-19.95im

Update Branch

Once a branch has been added to the PowerSystem type, users have the flexibility to modify all parameters defined within the addBranch! function. This means that when the updateBranch! function is used, the PowerSystem type within AC and DC models that have been created is updated. This eliminates the need to recreate the AC and DC models from scratch.

To illustrate, let us continue with the previous example and modify the parameters of Branch 1 as follows:

updateBranch!(system; label = "Branch 1", resistance = 0.012, reactance = 0.3)

We can observe the update in the AC nodal matrix:

julia> system.model.ac.nodalMatrix3×3 SparseArrays.SparseMatrixCSC{ComplexF64, Int64} with 7 stored entries:
+  0.14312-3.32801im  -0.13312+3.32801im       ⋅
+ -0.13312+3.32801im   0.53312-22.828im   -0.0+20.0im
+          ⋅               0.0+20.0im      0.0-19.95im

Next, let us switch the status of Branch 2 from in-service to out-of-service:

updateBranch!(system; label = "Branch 2", status = 0)

As before, the updated AC nodal matrix takes the following form:

julia> system.model.ac.nodalMatrix3×3 SparseArrays.SparseMatrixCSC{ComplexF64, Int64} with 7 stored entries:
+  0.14312-3.32801im  -0.13312+3.32801im      ⋅
+ -0.13312+3.32801im   0.53312-2.82801im  0.0+0.0im
+          ⋅               0.0+0.0im      0.0+0.05im

Drop Zeros

After the last execution of the updateBranch! function, the nodal matrices will contain zeros, as demonstrated in the code example. If needed, the user can remove these zeros using the dropZeros! function, as shown below:

dropZeros!(system.model.ac)
Info

It is worth mentioning that in simulations conducted with the JuliaGrid package, the precision of the outcomes remains unaffected even if zero entries are retained. However, we recommend users utilize this function instead of dropzeros! from the SuiteSparse package to ensure seamless functioning of all JuliaGrid functionalities.


Update Generator

Finally, users can update all generator parameters defined within the addGenerator! function using the updateGenerator! function. The execution of this function will affect all variables within the PowerSystem type.

In short, in addition to the generator field, JuliaGrid also retains variables associated with generators within the bus field. As an example, let us examine one of these variables and its values derived from a previous example:

julia> system.bus.supply.active3-element Vector{Float64}:
+ 0.7
+ 0.0
+ 0.0

Next, we will change the active output power of Generator 1:

updateGenerator!(system; label = "Generator 1", active = 0.9)

As we can see, executing the function triggers an update of the observed variable:

julia> system.bus.supply.active3-element Vector{Float64}:
+ 1.1
+ 0.0
+ 0.0

Hence, this function ensures the adjustment of generator parameters and updates all fields of the PowerSystem type affected by them.


Add and Update Costs

The cost! function is responsible for adding and updating costs associated with the active or reactive power produced by the corresponding generator. These costs are added only if the corresponding generator is defined.

To start, let us create an example of a power system using the following code:

system = powerSystem()
+
+addBus!(system; label = "Bus 1")
+addBus!(system; label = "Bus 2")
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 2")

Polynomial Cost

Let us define a quadratic polynomial cost function for the active power produced by the Generator 1:

cost!(system; label = "Generator 1", active = 2, polynomial = [1100.0; 500.0; 150.0])

In essence, what we have accomplished is the establishment of a cost function depicted as $f(P_{\text{g}1}) = 1100 P_{\text{g}1}^2 + 500 P_{\text{g}1} + 150$ through the code provided. In general, when constructing a polynomial cost function, the coefficients must be ordered from the highest degree to the lowest.

The default input units are in per-units (pu), with coefficients of the cost function having units of currency/pu²-hr for 1100, currency/pu-hr for 500, and currency/hr for 150. Therefore, the coefficients are stored exactly as entered:

julia> system.generator.cost.active.polynomial[1]3-element Vector{Float64}:
+ 1100.0
+  500.0
+  150.0

By setting active = 2 within the function, we express our intent to specify the active power cost using the active key. By using a value of 2, we signify our preference for employing a polynomial cost model for the associated generator. This flexibility is neccessary when we have also previously defined a piecewise linear cost function for the same generator. In such cases, we can set active = 1 to utilize the piecewise linear cost function to represent the cost of the corresponding generators. Thus, we retain the freedom to choose between these two cost functions according to the requirements of our simulation. Additionally, users have the option to define both piecewise and polynomial costs within a single function call, further enhancing the versatility of the implementation.


Piecewise Linear Cost

We can also create a piecewise linear cost function, for example, let us create the reactive power cost function for the same generator using the following code:

cost!(system; label = "Generator 1", reactive = 1, piecewise = [0.11 12.3; 0.15 16.8])

The first column denotes the generator's output reactive powers in per-units, while the second column specifies the corresponding costs for the specified reactive power in currency/hr. Thus, the data is stored exactly as entered:

julia> system.generator.cost.reactive.piecewise[1]2×2 Matrix{Float64}:
+ 0.11  12.3
+ 0.15  16.8

Customizing Input Units for Keywords

Changing input units from per-units (pu) can be particularly useful since cost functions are usually related to SI units. Let us set active powers in megawatts (MW) and reactive powers in megavolt-amperes reactive (MVAr) :

@power(MW, MVAr, pu)

Now, we can add the quadratic polynomial function using megawatts:

cost!(system; label = "Generator 1", active = 2, polynomial = [0.11; 5.0; 150.0])

After inspecting the resulting cost data, we can see that it is the same as before:

julia> system.generator.cost.active.polynomial[1]3-element Vector{Float64}:
+ 1100.0
+  500.0
+  150.0

Similarly, we can define the linear piecewise cost using megavolt-amperes reactive:

cost!(system; label = "Generator 1", reactive = 1, piecewise = [11.0 12.3; 15.0 16.8])

Upon inspection, we can see that the stored data is the same as before:

julia> system.generator.cost.reactive.piecewise[1]2×2 Matrix{Float64}:
+ 0.11  12.3
+ 0.15  16.8
Tip

The cost! function not only adds costs but also allows users to update previously defined cost functions. This functionality is particularly valuable in optimal power flow analyses, as it allows users to modify generator power costs without the need to recreate models from scratch.

diff --git a/v0.2.0/objects.inv b/v0.2.0/objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..539a11b6204de770b65327723f9e15a05f989e3e GIT binary patch literal 5166 zcmV+}6w&J=AX9K?X>NERX>N99Zgg*Qc_4OWa&u{KZXhxWBOp+6Z)#;@bUGkPb!=&2 zM{;Ro3L_v^WpZMd?av*PJAarPHb0B7EY-J#6 zb0A}HZE$jBb8}^6Aa!$TZf78RY-wUH3V58oU0H7&xeR*dttbVMz zT~U5t6z>jW-&NCYY`Vj0PYx4lFOJ=}y1#uM#(ICb@4h>j|PtJ{c;(a&{X zlVR%XeSH{xOK&&1D6Z#U?3KSA$yi?vv^%=P=)|oyY~Jj*V*XKy#(r96={5rKxc=;A zT15=gX~P!M;W$oX*EggcfjQ}6 z9WUQAO-RK3tuQIq=NOQnKr>v{HSq|Fd#Ig9;`ODA;v6aWm3y2H${Q{E_+At&?*mq1WXuH9`xX9-Vd_~EDw9i8`*wpfOxeVk`6`QH==@8c9 z8y`hIPREhQ*w$2xo(f3{%VulXJ2_PU3>>8loN<*8@UQM+{mRdWW-Ns!K!QEJU-U_P_pTipN|!78@tlL zNUU@r8S!-~IHT331Baoxr@}TMJ1ov*xz;sjw2V3@`fYuvdjdqP*~e)-P9wSzI06Hf zii6l`!Gnq-80f&-JBCKcAyBQhAS3L@#k1&|Z>k!t?NgGcYms$3(t&3Ph;9%;3(K9e z6ym$XFE#V}^0lI+2o*5p=TNB%2UJ8Un^+O{W4=J3N-#`l;E~L%dih z(n64~-ZzJu^yN)c@9J;OP?wu-7|S=)VdolzrBlIq6^d6uc@>fusPJ7o4Rj;BhZ3Z7 zD4PRVzuiaV!1{w>k?xz|=7!LH$b@TXjtgG@pd5xP%SQ)7m|5lFfTas!eGAQ`^1+K3^c$d_y#-@1l!Vzk_FhLc!XG)r_qcs zFf0MPX90<;o{c39Nx&XiFha1A7#TFnO-pusiUH{hf@SJyD=y49f9%Jv-D3v={`31= zi!#qF{4_!st5B2!1 z>;HWPHi>>1Ql*A5DFl~7v01$(6R0V2C_!W03l|q)^I@R>UqZQybtE|ktzhTb9^ zCRCf*riHIjp0lJAD|ZQ2UwMzqLh3unGYfjK>@ZR4xx(`pYhCJe_fG02d?oNM*1D+a z{+(jR_U>F5#)DL~IFh?;5j`a=-bP@h2t5>ulh&JCVJe_6py{bx@k5jx6XYRl$wVGS zFxknGYaHhVq7ST-xR4Ug+Z$7|28~)Z%RO{PCsfdUn#H-zgIe;?vmuvOjwaGxxDn7S zbB8)E9-GIcLrGZIj^uGc#)85n7%*F1idb=5m+yua1SBy#L3O=iQ3w_*k#hriNfRa9 zt-9%6%(rK(me+mmoVzZbM4k*d(CQ?HpLk5Fngpm2?$RIm1 zK;hM@*!mp)IxU*G82pM1EIODk4>DNDj~%^O8y+9*K$3c?VuPnQ*?3P12H}(NMS}p~ zu;dx-Ttjimvk@scrr32fNau5w382L(x+%K%*`iR=KsQA9nkBj>zp{k*X=YAvK`fn0 z@(EnNAxG(yE&+3V{q3yb%+S~l8DCBaBpcnx5HcDo){Zk^heXq3_D!2ryxh9W?W}K=z8#SR0g<@;MrMvEI-68!U zs`yG%^OxhCQTIt$ZN_4CV>L|ViIn1S_CJ$xJONTDa#h)*fR?svnQ5p<5NDd>s1Uhd z>XfI%E&grYH}!B*f{G&t&PXMxgu^7DA^@|7;_Y-lL+4T`HdOw2knSxg?qh10j|$-R z)Q-)uor8U6NMYjH%hc0s`dLfocrp2c1_$)yixD>DVd};3G%jIycp4Yq%&@&vLvVWq zh&wNI5JK3zZcW1td6)qPsArB&PaIj1i0IV}8KSwuu&UB)tXS#uG^}pPQ=Ox^DV@;R zdVq1hTM-#>cW+r-Tdhv;P=!OF?7pa;WX@l-iBk4n)Jsxop@z?bu!JUdAr=<)TuieB z!knL3OhFX@sp~XxT7pqqg*?g<%Ir4#_8wIKLTt)oPpu?5X9R~a%SXycRf3CTB#&T7 z(a_BRoz&Ckk&&)F1;;3I-F8IG-ETdV)8lwVP=e zVQXVK8)M|O7}MkgATD*`Tpz9Jy=?(iF~N)&FRk8X1PpvwTay=yGEik~4hc05XuWLT z9m{{!eHVXvC`rLc>;y$t^216`==l#lJxKM9*!{ES1?k2LzNofg0P-}*reVpq^~lZu z6X@E#>nFY!;=7(QNJDjVUV!1bZF2kummt*dvj&-YUB?=-p1nwQ+5=`BaoU}lypkiy zPjv;J6d32{=$&?NGznZe^Ky+damz9Tmf8z0g{3BLF{UuvDrl5gNqzYx@s`r%7j;XC zW1O4o&zS&`-WoJ7GtR||7{}=Qj9Sg3C^bo3mGvgZ!$;N6l80}R;Mtw!QZ@=HbJs2= zE@+gEo~6(dd!btuz2*f+hxyhE|KJgZ7)!@!^_$t>vd#uJ@NGN!JiXT@KG}c0vopcGulSpwd;jk+$w{=5tc2>TFF(^3)neDI<{36e|(5q7> zo;p@1h`H(Z_sxM7N3oH|dC8JUOqW^>QS_M_Hs3G+sa1XEov7r;L(1?A7%|oM>rF1& zNjsG5s>%&}(yW9N^Gvy7U}sCGrmb@JnGw$FEGFFACbu3S*`~kt zfoe2QiPq16C%AVWbMRaiLn zkP$iqVgKr{>-Y|kYq3A7vP?-`NNTe}b5JSF4NSkhsv0K|5s}EGv<0VKZM)q>H%$|s7%|Y)8?}+3 zl(8}~sq^N_xr$Sr2Ur3ns+mySQ!BrK!u91Yk)6VK#DCvAuYSanQ9|FP;r`0`UZmmP zivAXjE#0U!ibF-p!X<}PQlkjb4}Gx<4KV>5T%eXBHVSTK`7=nB7)vN=#b@Fbi0DFJ zgQa{zLey4icmGfFzl{6;NDL^|B4g1XdmWOhosoQ8RpnORQB6OW-ErV`T3SHIV8A^W zI?#d5xWPF?5tUeJ?{K8@kGyv)IuNh%u`4y+GS($O!*>mcl|3cpKq9K%bjzg*mh}0GB z9B5VK|Ch?MEo!}nlv=g-ydJ$bSQi1dKu9ds^))#_nGb4Adm zvPVR_ng)@bNu8}hY;%5n4~Go+?a8k1BF6XXZ{JZ0oy8*!GI0keeU%>Uw}~#l_*P7c zqfXwi)WBVL?Aq=T)KFXAO~(L#or{TwvS_oB^<|@PG`5{QDM*a z#>uhZv9N!RQlSrqq)mZRIGdydIQ={?OSlV@UQEK>uJH4Iv!C)#IuQEK_;z~X`O^+g zoqg9n)#xByC+jyJN&`Ut+lQ_PuD}1DWYk$-!ST9%LMzoP{F(O)li>eFPDQI;_{~5( z$oP-wf-jDIts9g}qZ4GPL_JD#c33hixJ=0O%QTEEKI_%__UdRf&QV}D-(*(p1Z{{g zic^S_@peL{yCSF^b2fJ$WgjtXrh+D^Ce|W%ESj(%wlUBZw_yfkdkY($$seQo_1vP) zRd1GC`}s+Rw>{Y} ziG%eQUWt}uZ>$cZWd;9%4**v$DkPhyUlh4>h@T`3OT=_DouQ41xIC7vv)q68D$`e- z2Kg9u%84U+-Uz|H5s;6j0tj^na)Pl8iF^W(MzKc*4g81Gx*9f^&z*w zc5ps)hxVm?9H&?2*3A7bcsaYTq<^Ho@2R_uFpAsk!F)wE+D)+N>|;Q*tmxT=NVl+g zQWTC-u3scdx%R8o|>9AK-nL3Oqzm7U$ZoolMeA(P0`$qN_$Vku}cLkc4lPXUPpNqom}s9E*|y$N4oo8PVd;Tf2S;M-h3E z1Wt=+!L+pjeSav)RP$81fI^r^B_!`NmfYa@}=!@F=7lC=Ft0BVy!P zHZ~TFaZw&wvT=D$_Blh5RM8Rq*id*x1m6vY`^`YI-?nT90tZ(s zE=`g8#T56sidYs?+{?D)VSbkQ)I?22)Nn9gZi#YFowWuRH9N&%k)INF$okv$M+PGynhq literal 0 HcmV?d00001 diff --git a/v0.2.0/search_index.js b/v0.2.0/search_index.js new file mode 100644 index 000000000..04e45c88f --- /dev/null +++ b/v0.2.0/search_index.js @@ -0,0 +1,3 @@ +var documenterSearchIndex = {"docs": +[{"location":"#JuliaGrid","page":"Introduction","title":"JuliaGrid","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"JuliaGrid is a fast, flexible, and easy-to-use open-source tool for analyzing and modifying power system configurations and measurement data. It represents a comprehensive framework for steady-state power system analysis written in the Julia programming language. The framework is available as a Julia package under MIT License. JuliaGrid is primarily designed for researchers and academics, providing various state-of-the-art algorithms.","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"The framework's architecture centres around code-reusability paradigm, allowing users a high level of customization for their experiments. To simplify, the overall logic for setting the experiments and its analysis can be as follows:","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"Users define a power system with/without measurement data.\nUsers select between the AC or DC model.\nUsers define the specific type of required analysis.\nFinally, they solve the generated power system model.","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"","category":"page"},{"location":"#Installation-Guide","page":"Introduction","title":"Installation Guide","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"JuliaGrid is compatible with Julia version 1.9 and later. To get started with JuliaGrid, users should first install Julia and consider using a code editor for a smoother coding experience. For detailed instructions, please consult the Installation Guide.","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"To get the JuliaGrid package installed, execute the following Julia command:","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"import Pkg\nPkg.add(\"JuliaGrid\")","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"","category":"page"},{"location":"#Documentation-Structure","page":"Introduction","title":"Documentation Structure","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"JuliaGrid documentation consists of three main parts:","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"The manual provides users with guidance on how to use available functions, its return values, and offers instructions for modifying power system configurations, measurement data, and other user specific analysis.\nThe tutorials delve deeper into the theoretical underpinnings of state-of-the-art algorithms, allowing users to gain an in-depth understanding of the equations used in various functions.\nAPI references offer a comprehensive list of objects, functions and methods within the package, categorised according to specific use-cases.","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"","category":"page"},{"location":"#Getting-Started","page":"Introduction","title":"Getting Started","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"Below, we have provided a list of exhaustive examples in order to ease users in getting started with the JuliaGrid package. These examples highlight some of the functionalities that the framework offers.","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"","category":"page"},{"location":"#AC-Power-Flow","page":"Introduction","title":"AC Power Flow","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"using JuliaGrid\n\nsystem = powerSystem(\"case14.h5\") # Build the power system model\nacModel!(system) # Create matrices and vectors for the AC model\n\nanalysis = newtonRaphson(system) # Build the power flow model\nfor iteration = 1:10 # Begin the iteration loop\n stopping = mismatch!(system, analysis) # Compute power mismatches\n if all(stopping .< 1e-8) # Check if the stopping criterion is met\n println(\"Solution Found.\") # Output message indicating convergence\n break # Stop iterations if the criterion is met\n end\n solve!(system, analysis) # Compute voltage magnitudes and angles\nend\npower!(system, analysis) # Compute powers within the power system\ncurrent!(system, analysis) # Compute currents within the power system\n\nprintBusData(system, analysis) # Print data related to buses","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"","category":"page"},{"location":"#DC-Power-Flow","page":"Introduction","title":"DC Power Flow","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"using JuliaGrid\n\n@power(MW, MVAr, MVA) # Specify the power units for input data\nsystem = powerSystem(\"case14.h5\") # Build the power system model\ndcModel!(system) # Create matrices and vectors for the DC model\n\nanalysis = dcPowerFlow(system) # Build the power flow analysis\nsolve!(system, analysis) # Compute voltage angles\n\n@generator(active = 20) # Define the template for generators\naddGenerator!(system, analysis; bus = 1) # Add the new generator to the power system\nsolve!(system, analysis) # Recompute voltage angles with the updated model\n\nprintBusSummary(system, analysis) # Print a summary of data related to buses","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"","category":"page"},{"location":"#AC-Optimal-Power-Flow","page":"Introduction","title":"AC Optimal Power Flow","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"using JuliaGrid, Ipopt\n\nsystem = powerSystem(\"case14.h5\") # Build the power system model\nacModel!(system) # Create matrices and vectors for the AC model\n\nanalysis = acOptimalPowerFlow(system, Ipopt.Optimizer) # Build the optimal power flow model\nsolve!(system, analysis) # Compute generator powers and bus voltages\ncurrent!(system, analysis) # Compute currents within the power system\n\n@branch(resistance = 0.01, reactance = 0.2) # Define the new template for branches\naddBranch!(system, analysis; from = 1, to = 5) # Add the new branch to the power system\nsolve!(system, analysis) # Recompute solutions with the updated model","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"","category":"page"},{"location":"#DC-Optimal-Power-Flow","page":"Introduction","title":"DC Optimal Power Flow","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"using JuliaGrid, HiGHS\n\nsystem = powerSystem(\"case14.h5\") # Build the power system model\ndcModel!(system) # Create matrices and vectors for the DC model\n\nanalysis = dcOptimalPowerFlow(system, HiGHS.Optimizer) # Build the optimal power flow model\nsolve!(system, analysis) # Compute generator powers and bus voltages\npower!(system, analysis) # Compute active powers within the power system\n\nprintBranchData(system, analysis) # Print data related to branches","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"","category":"page"},{"location":"#AC-State-Estimation","page":"Introduction","title":"AC State Estimation","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"using JuliaGrid\n\nsystem = powerSystem(\"case14.h5\") # Build the power system model\ndevice = measurement(\"measurement14.h5\") # Build the measurement model\nacModel!(system) # Create matrices and vectors for the AC model\n\nanalysis = gaussNewton(system, device) # Build the state estimation model\nfor iteration = 1:20 # Begin the iteration loop\n stopping = solve!(system, analysis) # Compute estimate of voltages\n if stopping < 1e-8 # Check if the stopping criterion is met\n println(\"Solution Found.\") # Output message indicating convergence\n break # Stop iterations if the criterion is met\n end\nend\npower!(system, analysis) # Compute active powers within the power system\n\nprintWattmeterData(system, device, analysis) # Print data related to wattmeters","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"","category":"page"},{"location":"#PMU-State-Estimation","page":"Introduction","title":"PMU State Estimation","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"using JuliaGrid\n\nsystem = powerSystem(\"case14.h5\") # Build the power system model\ndevice = measurement(\"measurement14.h5\") # Build the measurement model\nacModel!(system) # Create matrices and vectors for the AC model\n\nanalysis = pmuStateEstimation(system, device) # Build the state estimation model\nsolve!(system, analysis) # Compute estimate of voltages\n\nupdatePmu!(system, device, analysis; label = \"To 1\", angle = 0.0) # Update phasor measurement\nsolve!(system, analysis) # Recompute the solution with the updated model\n\nprintPmuData(system, device, analysis) # Print data related to PMUs","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"","category":"page"},{"location":"#DC-State-Estimation","page":"Introduction","title":"DC State Estimation","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"using JuliaGrid\n\nsystem = powerSystem(\"case14.h5\") # Build the power system model\ndevice = measurement(\"measurement14.h5\") # Build the measurement model\ndcModel!(system) # Create matrices and vectors for the DC model\n\nanalysis = dcStateEstimation(system, device) # Build the state estimation model\nsolve!(system, analysis) # Compute estimate of voltage angles\n\nresidualTest!(system, device, analysis) # Perform bad data analysis and remove outlier\nsolve!(system, analysis) # Recompute voltage angles with the updated model","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"","category":"page"},{"location":"#Contributors","page":"Introduction","title":"Contributors","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"Ognjen Kundacina - The Institute for Artificial Intelligence Research and Development of Serbia\nMuhamed Delalic - University of Sarajevo, Bosnia and Herzegovina\nArmin Teskeredzic - RWTH Aachen University, Germany\nMirsad Cosovic - University of Sarajevo, Bosnia and Herzegovina","category":"page"},{"location":"api/optimalPowerFlow/#OptimalPowerFlowAPI","page":"Optimal Power Flow","title":"Optimal Power Flow","text":"","category":"section"},{"location":"api/optimalPowerFlow/","page":"Optimal Power Flow","title":"Optimal Power Flow","text":"For further information on this topic, please see the AC Optimal Power Flow or DC Optimal Power Flow sections of the Manual. Below, we have provided a list of functions that can be utilized for optimal power flow analysis.","category":"page"},{"location":"api/optimalPowerFlow/","page":"Optimal Power Flow","title":"Optimal Power Flow","text":"To load optimal power flow API functionalities into the current scope, one can employ the following command:","category":"page"},{"location":"api/optimalPowerFlow/","page":"Optimal Power Flow","title":"Optimal Power Flow","text":"using JuliaGrid, Ipopt, HiGHS","category":"page"},{"location":"api/optimalPowerFlow/","page":"Optimal Power Flow","title":"Optimal Power Flow","text":"","category":"page"},{"location":"api/optimalPowerFlow/#AC-Optimal-Power-Flow","page":"Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"section"},{"location":"api/optimalPowerFlow/","page":"Optimal Power Flow","title":"Optimal Power Flow","text":"acOptimalPowerFlow\nsolve!\nstartingPrimal!\nstartingDual!","category":"page"},{"location":"api/optimalPowerFlow/#DC-Optimal-Power-Flow","page":"Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"section"},{"location":"api/optimalPowerFlow/","page":"Optimal Power Flow","title":"Optimal Power Flow","text":"dcOptimalPowerFlow\nsolve!\nstartingPrimal!\nstartingDual!","category":"page"},{"location":"api/optimalPowerFlow/","page":"Optimal Power Flow","title":"Optimal Power Flow","text":"","category":"page"},{"location":"api/optimalPowerFlow/#AC-Optimal-Power-Flow-2","page":"Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"section"},{"location":"api/optimalPowerFlow/","page":"Optimal Power Flow","title":"Optimal Power Flow","text":"acOptimalPowerFlow\nsolve!(::PowerSystem, ::ACOptimalPowerFlow)\nstartingPrimal!(::PowerSystem, ::ACOptimalPowerFlow)\nstartingDual!(::PowerSystem, ::ACOptimalPowerFlow)","category":"page"},{"location":"api/optimalPowerFlow/#JuliaGrid.acOptimalPowerFlow","page":"Optimal Power Flow","title":"JuliaGrid.acOptimalPowerFlow","text":"acOptimalPowerFlow(system::PowerSystem, optimizer; bridge, name,\n magnitude, angle, active, reactive)\n\nThe function sets up the optimization model for solving the AC optimal power flow problem.\n\nArguments\n\nThe function requires the PowerSystem composite type to establish the framework. Next, the optimizer argument is also required to create and solve the optimization problem. Specifically, JuliaGrid constructs the AC optimal power flow using the JuMP package and provides support for commonly employed solvers. For more detailed information, please consult the JuMP documentation.\n\nUpdates\n\nIf the AC model has not been created, the function automatically initiates an update within the ac field of the PowerSystem type.\n\nKeywords\n\nJuliaGrid offers the ability to manipulate the jump model based on the guidelines provided in the JuMP documentation. However, certain configurations may require different method calls, such as:\n\nbridge: manage the bridging mechanism (default: false),\nname: manage the creation of string names (default: true).\n\nAdditionally, users can modify variable names used for printing and writing through the keywords magnitude, angle, active, and reactive. For instance, users can choose magnitude = \"V\" and angle = \"θ\" to display equations in a more readable format.\n\nReturns\n\nThe function returns an instance of the ACOptimalPowerFlow type, which includes the following fields:\n\nvoltage: The bus voltage magnitudes and angles.\npower: The variable allocated to store the active and reactive powers.\ncurrent: The variable allocated to store the currents.\nmethod: The JuMP model, references to the variables, constraints, and objective.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = acOptimalPowerFlow(system, Ipopt.Optimizer)\n\n\n\n\n\n","category":"function"},{"location":"api/optimalPowerFlow/#JuliaGrid.solve!-Tuple{PowerSystem, ACOptimalPowerFlow}","page":"Optimal Power Flow","title":"JuliaGrid.solve!","text":"solve!(system::PowerSystem, analysis::ACOptimalPowerFlow)\n\nThe function solves the AC optimal power flow model, computing the active and reactive power outputs of the generators, as well as the bus voltage magnitudes and angles.\n\nUpdates\n\nThe calculated active and reactive powers, as well as voltage magnitudes and angles, are stored in the power.generator and voltage fields of the ACOptimalPowerFlow type.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = acOptimalPowerFlow(system, Ipopt.Optimizer)\nsolve!(system, analysis)\n\n\n\n\n\n","category":"method"},{"location":"api/optimalPowerFlow/#JuliaGrid.startingPrimal!-Tuple{PowerSystem, ACOptimalPowerFlow}","page":"Optimal Power Flow","title":"JuliaGrid.startingPrimal!","text":"startingPrimal!(system::PowerSystem, analysis::ACOptimalPowerFlow)\n\nThe function retrieves the active and reactive power outputs of the generators, as well as the voltage magnitudes and angles from the PowerSystem composite type. It then assigns these values to the ACOptimalPowerFlow type, allowing users to initialize starting primal values as needed.\n\nUpdates\n\nThis function only updates the voltage and generator fields of the ACOptimalPowerFlow type.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = acOptimalPowerFlow(system, Ipopt.Optimizer)\nsolve!(system, analysis)\n\nupdateBus!(system, analysis; label = 14, reactive = 0.13, magnitude = 1.2, angle = -0.17)\n\nstartingPrimal!(system, analysis)\nsolve!(system, analysis)\n\n\n\n\n\n","category":"method"},{"location":"api/optimalPowerFlow/#JuliaGrid.startingDual!-Tuple{PowerSystem, ACOptimalPowerFlow}","page":"Optimal Power Flow","title":"JuliaGrid.startingDual!","text":"startingDual!(system::PowerSystem, analysis::ACOptimalPowerFlow)\n\nThe function removes all values of the dual variables.\n\nUpdates\n\nThis function only updates the dual field of the ACOptimalPowerFlow type.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = acOptimalPowerFlow(system, Ipopt.Optimizer)\nsolve!(system, analysis)\n\nupdateBus!(system, analysis; label = 14, reactive = 0.13, magnitude = 1.2, angle = -0.17)\n\nstartingDual!(system, analysis)\nsolve!(system, analysis)\n\n\n\n\n\n","category":"method"},{"location":"api/optimalPowerFlow/","page":"Optimal Power Flow","title":"Optimal Power Flow","text":"","category":"page"},{"location":"api/optimalPowerFlow/#DC-Optimal-Power-Flow-2","page":"Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"section"},{"location":"api/optimalPowerFlow/","page":"Optimal Power Flow","title":"Optimal Power Flow","text":"dcOptimalPowerFlow\nsolve!(::PowerSystem, ::DCOptimalPowerFlow)\nstartingPrimal!(::PowerSystem, ::DCOptimalPowerFlow)\nstartingDual!(::PowerSystem, ::DCOptimalPowerFlow)","category":"page"},{"location":"api/optimalPowerFlow/#JuliaGrid.dcOptimalPowerFlow","page":"Optimal Power Flow","title":"JuliaGrid.dcOptimalPowerFlow","text":"dcOptimalPowerFlow(system::PowerSystem, optimizer; bridge, name, angle, active)\n\nThe function sets up the optimization model for solving the DC optimal power flow problem.\n\nArguments\n\nThe function requires the PowerSystem composite type to establish the framework. Next, the optimizer argument is also required to create and solve the optimization problem. Specifically, JuliaGrid constructs the DC optimal power flow using the JuMP package and provides support for commonly employed solvers. For more detailed information, please consult the JuMP documentation.\n\nUpdates\n\nIf the DC model has not been created, the function automatically initiates an update within the dc field of the PowerSystem type.\n\nKeywords\n\nJuliaGrid offers the ability to manipulate the jump model based on the guidelines provided in the JuMP documentation. However, certain configurations may require different method calls, such as:\n\nbridge: manage the bridging mechanism (default: false),\nname: manage the creation of string names (default: true).\n\nAdditionally, users can modify variable names used for printing and writing through the keywords angle and active. For instance, users can choose angle = \"θ\" to display equations in a more readable format.\n\nReturns\n\nThe function returns an instance of the DCOptimalPowerFlow type, which includes the following fields:\n\nvoltage: The variable allocated to store the bus voltage angle,\npower: The variable allocated to store the active powers,\nmethod: The JuMP model, references to the variables, constraints, and objective.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndcModel!(system)\n\nanalysis = dcOptimalPowerFlow(system, HiGHS.Optimizer)\n\n\n\n\n\n","category":"function"},{"location":"api/optimalPowerFlow/#JuliaGrid.solve!-Tuple{PowerSystem, DCOptimalPowerFlow}","page":"Optimal Power Flow","title":"JuliaGrid.solve!","text":"solve!(system::PowerSystem, analysis::DCOptimalPowerFlow)\n\nThe function solves the DC optimal power flow model, computing the active power outputs of the generators, as well as the bus voltage angles.\n\nUpdates\n\nThe calculated active powers, as well as voltage angles, are stored in the power.generator and voltage fields of the DCOptimalPowerFlow type.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndcModel!(system)\n\nanalysis = dcOptimalPowerFlow(system, HiGHS.Optimizer)\nsolve!(system, analysis)\n\n\n\n\n\n","category":"method"},{"location":"api/optimalPowerFlow/#JuliaGrid.startingPrimal!-Tuple{PowerSystem, DCOptimalPowerFlow}","page":"Optimal Power Flow","title":"JuliaGrid.startingPrimal!","text":"startingPrimal!(system::PowerSystem, analysis::DCOptimalPowerFlow)\n\nThe function retrieves the active power outputs of the generators and the bus voltage angles from the PowerSystem composite type. These values are then assigned to the DCOptimalPowerFlow type, enabling users to initialize starting primal values according to their requirements.\n\nUpdates\n\nThis function only updates the voltage and generator fields of the DCOptimalPowerFlow type.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndcModel!(system)\n\nanalysis = dcOptimalPowerFlow(system, HiGHS.Optimizer)\nsolve!(system, analysis)\n\nupdateBus!(system, analysis; label = 14, active = 0.1, angle = -0.17)\n\nstartingPrimal!(system, analysis)\nsolve!(system, analysis)\n\n\n\n\n\n","category":"method"},{"location":"api/optimalPowerFlow/#JuliaGrid.startingDual!-Tuple{PowerSystem, DCOptimalPowerFlow}","page":"Optimal Power Flow","title":"JuliaGrid.startingDual!","text":"startingDual!(system::PowerSystem, analysis::DCOptimalPowerFlow)\n\nThe function removes all values of the dual variables.\n\nUpdates\n\nThis function only updates the dual field of the DCOptimalPowerFlow type.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndcModel!(system)\n\nanalysis = dcOptimalPowerFlow(system, HiGHS.Optimizer)\nsolve!(system, analysis)\n\nupdateBus!(system, analysis; label = 14, active = 0.1, angle = -0.17)\n\nstartingDual!(system, analysis)\nsolve!(system, analysis)\n\n\n\n\n\n","category":"method"},{"location":"manual/acPowerFlow/#ACPowerFlowManual","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To perform the AC power flow analysis, we will first need the PowerSystem type that has been created with the AC model. Following that, we can construct the power flow model encapsulated within the ACPowerFlow type by employing one of the following functions:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"newtonRaphson,\nfastNewtonRaphsonBX,\nfastNewtonRaphsonXB,\ngaussSeidel.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"These functions will set up the AC power flow framework. To obtain bus voltages and solve the power flow problem, we can use the following functions:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"mismatch!,\nsolve!.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Additionally, the package provides two functions for reactive power limit validation of generators and adjusting the voltage angles to match an arbitrary bus angle:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"reactiveLimit!,\nadjustAngle!.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"After obtaining the AC power flow solution, JuliaGrid offers post-processing analysis functions for calculating powers and currents associated with buses, branches, or generators:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"power!,\ncurrent!.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Additionally, specialized functions are available for calculating specific types of powers or currents for individual buses, branches, or generators.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#BusTypeModificationManual","page":"AC Power Flow","title":"Bus Type Modification","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Depending on how the system is constructed, the types of buses that are initially set are checked and can be changed during the construction of the ACPowerFlow type.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Assuming the Newton-Raphson method has been chosen, to explain the details, we can observe a power system:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"system = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3)\naddBus!(system; label = \"Bus 2\", type = 2)\naddBus!(system; label = \"Bus 3\", type = 2)\n\naddGenerator!(system; bus = \"Bus 2\")\n\nanalysis = newtonRaphson(system)","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Initially, Bus 1 is set as the slack bus (type = 3), and Bus 2 and Bus 3 are generator buses (type = 2). However, Bus 3 does not have a generator, and JuliaGrid considers this a mistake and changes the corresponding bus to a demand bus (type = 1).","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"After this step, JuliaGrid verifies the slack bus. Initially, the slack bus (type = 3) corresponds to Bus 1, but since it does not have an in-service generator connected to it, JuliaGrid recognizes it as another mistake. Therefore, JuliaGrid assigns a new slack bus from the available generator buses (type = 2) that have connected in-service generators. In this specific example, Bus 2 becomes the new slack bus.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"using JuliaGrid\n@default(unit)\n@default(template)\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3)\naddBus!(system; label = \"Bus 2\", type = 2)\naddBus!(system; label = \"Bus 3\", type = 2)\n\naddGenerator!(system; bus = \"Bus 2\")\n\nacModel!(system)\nanalysis = newtonRaphson(system)","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"As a result, we can observe the updated array of bus types:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"print(system.bus.label, system.bus.layout.type)","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Note that, if a bus is initially defined as the demand bus (type = 1) and later a generator is added to it, the bus type will not be changed to the generator bus (type = 2). Instead, it will remain as a demand bus.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"note: Info\nOnly the type of these buses that are defined as generator buses (type = 2) but do not have a connected in-service generator will be changed to demand buses (type = 1).The bus that is defined as the slack bus (type = 3) but lacks a connected in-service generator will have its type changed to the demand bus (type = 1). Meanwhile, the first generator bus (type = 2) with an in-service generator connected to it will be assigned as the new slack bus (type = 3).","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#SetupStartingVoltagesManual","page":"AC Power Flow","title":"Setup Starting Voltages","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To begin analyzing the AC power flow in JuliaGrid, we must first establish the PowerSystem type. Once the power system is set up, we can select one of the available methods for solving the AC power flow problem, such as newtonRaphson, fastNewtonRaphsonBX, fastNewtonRaphsonXB, or gaussSeidel.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Assuming we have selected the Newton-Raphson method, we can use the following code snippet:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, magnitude = 1.0, angle = 0.0)\naddBus!(system; label = \"Bus 2\", type = 1, magnitude = 0.9, angle = -0.1)\naddBus!(system; label = \"Bus 3\", type = 2, magnitude = 0.8, angle = -0.2)\n\naddGenerator!(system; bus = \"Bus 1\", magnitude = 1.3)\naddGenerator!(system; bus = \"Bus 2\", magnitude = 1.1)\naddGenerator!(system; bus = \"Bus 3\", magnitude = 1.2)\n\nacModel!(system)\nanalysis = newtonRaphson(system)\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Here, the function newtonRaphson generates starting voltage vectors in polar coordinates.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The starting voltage magnitudes are set to:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"print(system.bus.label, analysis.voltage.magnitude)","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"This vector is created based on the bus types by selecting voltage magnitude values from the PowerSystem type, using the vectors:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"[system.bus.voltage.magnitude system.generator.voltage.magnitude]","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The starting voltage angles are set to:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"print(system.bus.label, analysis.voltage.angle)","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"This vector is derived from the voltage angle values in the PowerSystem type:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"system.bus.voltage.angle","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"note: Info\nThe rule governing the specification of starting voltage magnitudes is simple. If a bus has an in-service generator and is declared the generator bus (type = 2), then the starting voltage magnitudes are specified using the setpoint provided within the generator. This is because the generator bus has known values of voltage magnitude that are specified within the generator.On the other hand, the slack bus (type = 3) always requires an in-service generator. The starting value of the voltage magnitude at the slack bus is determined exclusively by the setpoints provided within the generators connected to it. This is a result of the slack bus having a known voltage magnitude that must be maintained.If there are multiple generators connected to the generator or slack bus, the initial voltage magnitude will align with the magnitude setpoint specified for the first in-service generator in the list.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Custom-Starting-Voltages","page":"AC Power Flow","title":"Custom Starting Voltages","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"This method of specifying starting values has a significant advantage in that it allows the user to easily change the starting voltage magnitudes and angles, which play a crucial role in iterative methods. For instance, suppose we define our power system as follows:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, magnitude = 1.0, angle = 0.0)\naddBus!(system; label = \"Bus 2\", type = 1, magnitude = 0.9, angle = -0.1)\naddBus!(system; label = \"Bus 3\", type = 2, magnitude = 0.8, angle = -0.2)\n\naddGenerator!(system; bus = \"Bus 1\", magnitude = 1.1)\naddGenerator!(system; bus = \"Bus 3\", magnitude = 1.2)\n\nacModel!(system)\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Now, the user can initiate a \"flat start\", this can be easily done as follows:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"for i = 1:system.bus.number\n system.bus.voltage.magnitude[i] = 1.0\n system.bus.voltage.angle[i] = 0.0\nend\n\nanalysis = newtonRaphson(system)\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The starting voltage values are:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Consequently, the iteration begins with a fixed set of voltage magnitude values that remain constant throughout the iteration process. The remaining values are initialized as part of the \"flat start\" approach.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#ACPowerFlowSolutionManual","page":"AC Power Flow","title":"Power Flow Solution","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To start, we will create a power system and define the AC model by invoking the acModel! function:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.5, magnitude = 0.9, angle = 0.0)\naddBus!(system; label = \"Bus 2\", type = 1, reactive = 0.05, magnitude = 1.1, angle = -0.1)\naddBus!(system; label = \"Bus 3\", type = 1, active = 0.5, magnitude = 1.0, angle = -0.2)\n\n@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.01)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.04)\n\n@generator(active = 3.2)\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", magnitude = 1.1)\naddGenerator!(system; label = \"Generator 2\", bus = \"Bus 2\", magnitude = 1.2)\n\nacModel!(system)\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Once the AC model is defined, we can choose the method to solve the power flow problem. JuliaGrid provides four methods: newtonRaphson, fastNewtonRaphsonBX, fastNewtonRaphsonXB, and gaussSeidel.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"For example, to use the Newton-Raphson method to solve the power flow problem, we can use:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"analysis = newtonRaphson(system)\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"tip: Tip\nBy default, the user activates LU factorization to solve the system of linear equations within each iteration of the Newton-Raphson method. However, users can specifically opt for the QR factorization method:analysis = newtonRaphson(system, QR)The capability to change the factorization method is exclusively available for the Newton-Raphson and fast Newton-Raphson methods.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"This function sets up the desired method for an iterative process based on two functions: mismatch! and solve!. The mismatch! function calculates the active and reactive power injection mismatches using the given voltage magnitudes and angles, while solve! computes the voltage magnitudes and angles.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To perform an iterative process with the Newton-Raphson or fast Newton-Raphson methods in JuliaGrid, the mismatch! function must be included inside the iteration loop. For instance:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"for iteration = 1:100\n mismatch!(system, analysis)\n solve!(system, analysis)\nend\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Upon completion of the AC power flow analysis, the solution is conveyed through the bus voltage magnitudes and angles. Here are the values corresponding to the buses:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"In contrast, the iterative loop of the Gauss-Seidel method does not require the mismatch! function:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"analysis = gaussSeidel(system)\nfor iteration = 1:100\n solve!(system, analysis)\nend\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"In these examples, the algorithms run until the specified number of iterations is reached.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"note: Info\nWe recommend that the reader refer to the tutorial on AC Power Flow Analysis, where we explain the implementation of the methods and algorithm structures in detail.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Breaking-the-Iterative-Process","page":"AC Power Flow","title":"Breaking the Iterative Process","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"We can terminate the iterative process using the mismatch! function. The following code shows an example of how to use the function to break out of the iteration loop:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"@voltage(pu, rad, V) # hide\nanalysis = newtonRaphson(system)\nfor iteration = 1:100\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n println(\"Solution Found.\")\n break\n end\n solve!(system, analysis)\nend\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The mismatch! function returns the maximum absolute values of active and reactive power injection mismatches, which are commonly used as a convergence criterion in iterative AC power flow algorithms. Note that the function can also be used to terminate the loop when using the Gauss-Seidel method, even though it is not required.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"tip: Tip\nTo ensure an accurate count of iterations, the user should place the iteration counter after the condition expressions within the if construct.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Combining-Methods","page":"AC Power Flow","title":"Combining Methods","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The PowerSystem type, once created, can be shared among different methods, offering several advantages.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"For instance, while the Gauss-Seidel method is commonly used to swiftly derive an approximate solution, the Newton-Raphson method is favored for obtaining precise final solutions. Hence, a strategy involves employing the Gauss-Seidel method for a limited number of iterations, followed by initializing the Newton-Raphson method with the voltages obtained from the Gauss-Seidel method, leveraging it as a starting point for further refinement:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"gs = gaussSeidel(system)\nfor iteration = 1:5\n solve!(system, gs)\nend","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Next, we can initialize the Newton-Raphson method with the voltages obtained from the Gauss-Seidel method and start the algorithm from that point:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"analysis = newtonRaphson(system)\n\nfor i = 1:system.bus.number\n analysis.voltage.magnitude[i] = gs.voltage.magnitude[i]\n analysis.voltage.angle[i] = gs.voltage.angle[i]\nend\n\nfor iteration = 1:100\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"note: Info\nThe functions newtonRaphson, fastNewtonRaphsonBX, fastNewtonRaphsonXB, or gaussSeidel only modify the PowerSystem type to eliminate mistakes in the bus types as explained in the section Bus Type Modification. Further, the functions mismatch! and solve! do not modify the PowerSystem type at all. Therefore, it is safe to use the same PowerSystem type for multiple analyses once it has been created.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Print-Results-in-the-REPL","page":"AC Power Flow","title":"Print Results in the REPL","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Users have the option to print the results in the REPL using any units that have been configured, such as:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"@voltage(pu, deg, V)\nprintBusData(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Next, users can easily customize the print results for specific buses, for example:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"printBusData(system, analysis; label = \"Bus 1\", header = true)\nprintBusData(system, analysis; label = \"Bus 2\")\nprintBusData(system, analysis; label = \"Bus 3\", footer = true)","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Save-Results-to-a-File","page":"AC Power Flow","title":"Save Results to a File","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Users can also redirect print output to a file. For example, data can be saved in a text file as follows:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"open(\"bus.txt\", \"w\") do file\n printBusData(system, analysis, file)\nend","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Save-Results-to-a-CSV-File","page":"AC Power Flow","title":"Save Results to a CSV File","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"For CSV output, users should first generate a simple table with style = false, and then save it to a CSV file:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"using CSV\n\nio = IOBuffer()\nprintBusData(system, analysis, io; style = false)\nCSV.write(\"bus.csv\", CSV.File(take!(io); delim = \"|\"))","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#ACPowerSystemAlterationManual","page":"AC Power Flow","title":"Power System Update","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"After establishing the PowerSystem type using the powerSystem function and configuring the AC model with acModel!, users gain the capability to incorporate new branches and generators. Furthermore, they can adjust buses, branches, and generators.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Once updates are done, users can progress towards generating the ACPowerFlow type using the newtonRaphson, fastNewtonRaphsonBX, fastNewtonRaphsonXB, or gaussSeidel function. Ultimately, resolving the AC power flow is achieved through the utilization of the mismatch! and solve! functions:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem() # <- Initialize the PowerSystem instance\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.5, magnitude = 0.9, angle = 0.0)\naddBus!(system; label = \"Bus 2\", type = 1, reactive = 0.05, magnitude = 1.1, angle = -0.1)\n\n@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", magnitude = 1.1, active = 3.2)\n\nacModel!(system)\nanalysis = newtonRaphson(system) # <- Build ACPowerFlow for the defined power system\nfor iteration = 1:100\n mismatch!(system, analysis)\n solve!(system, analysis)\nend\n\nupdateBus!(system; label = \"Bus 2\", active = 0.2)\n\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 2\", reactance = 1)\nupdateBranch!(system; label = \"Branch 1\", status = 0)\n\naddGenerator!(system; label = \"Generator 2\", bus = \"Bus 1\", active = 0.2)\nupdateGenerator!(system; label = \"Generator 1\", active = 0.3)\n\nanalysis = newtonRaphson(system) # <- Build ACPowerFlow for the updated power system\nfor iteration = 1:100\n mismatch!(system, analysis)\n solve!(system, analysis)\nend\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"note: Info\nThis concept removes the need to restart and recreate the PowerSystem within the ac field from the beginning when implementing changes to the existing power system.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#ACPowerFlowUpdateManual","page":"AC Power Flow","title":"Power Flow Update","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"An advanced methodology involves users establishing the ACPowerFlow type using newtonRaphson, fastNewtonRaphsonBX, fastNewtonRaphsonXB, or gaussSeidel just once. After this initial setup, users can integrate new branches and generators, and also have the capability to modify buses, branches, and generators, all without the need to recreate the ACPowerFlow type.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"This advancement extends beyond the previous scenario where recreating the PowerSystem and AC model was unnecessary, to now include the scenario where ACPowerFlow also does not need to be recreated. Such efficiency proves particularly beneficial in cases where JuliaGrid can reuse established Jacobian matrices or even factorizations, especially when users choose the fast Newton-Raphson method.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"By modifying the previous example, we observe that we now create the ACPowerFlow type only once using the newtonRaphson function. This approach allows us to circumvent the need for reinitializing the Jacobian matrix, enabling us to proceed directly with iterations:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem() # <- Initialize the PowerSystem instance\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.5, magnitude = 0.9, angle = 0.0)\naddBus!(system; label = \"Bus 2\", type = 1, reactive = 0.05, magnitude = 1.1, angle = -0.1)\n\n@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", magnitude = 1.1, active = 3.2)\n\nacModel!(system)\nanalysis = newtonRaphson(system) # <- Build ACPowerFlow for the defined power system\nfor iteration = 1:100\n mismatch!(system, analysis)\n solve!(system, analysis)\nend\n\nupdateBus!(system, analysis; label = \"Bus 2\", active = 0.2)\n\naddBranch!(system, analysis; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 2\", reactance = 1)\nupdateBranch!(system, analysis; label = \"Branch 1\", status = 0)\n\naddGenerator!(system, analysis; label = \"Generator 2\", bus = \"Bus 1\", active = 0.2)\nupdateGenerator!(system, analysis; label = \"Generator 1\", active = 0.3)\n\n# <- No need for re-build; we have already updated the existing ACPowerFlow instance\nfor iteration = 1:100\n mismatch!(system, analysis)\n solve!(system, analysis)\nend\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"note: Info\nThis concept removes the need to restart and recreate both the PowerSystem within the ac field and the ACPowerFlow from the beginning when implementing changes to the existing power system.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Fast-Newton-Raphson:-Reusing-Jacobian-Matrices-Factorizations","page":"AC Power Flow","title":"Fast Newton-Raphson: Reusing Jacobian Matrices Factorizations","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"An intriguing scenario unfolds when employing the fast Newton-Raphson method. Continuing from the previous example, let us now initialize the fast Newton-Raphson method and proceed with iterations as outlined below:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"analysis = fastNewtonRaphsonBX(system)\nfor iteration = 1:100\n mismatch!(system, analysis)\n solve!(system, analysis)\nend\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Throughout this process, JuliaGrid will factorize the constant Jacobian matrices that govern the fast Newton-Raphson method.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Now, let us make changes to the power system and proceed directly to the iteration step:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"updateBus!(system, analysis; label = \"Bus 2\", reactive = 0.02)\nupdateGenerator!(system, analysis; label = \"Generator 1\", reactive = 0.1)\n\nfor iteration = 1:100\n mismatch!(system, analysis)\n solve!(system, analysis)\nend\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"note: Info\nIn this scenario, JuliaGrid identifies cases where the user has not altered parameters that impact the Jacobian matrices. Consequently, JuliaGrid efficiently utilizes the previously performed factorizations, leading to a notably faster solution compared to recomputing the factorization process.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Warm-Start","page":"AC Power Flow","title":"Warm Start","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"In these scenarios, users leverage the previously created PowerSystem type with the AC model and also reuse the ACPowerFlow type, proceeding directly to the iterations. This approach offers the advantage of a \"warm start\", wherein the initial voltages for the subsequent iteration step align with the solution from the previous iteration step. This alignment facilitates an efficient continuation of the power flow analysis.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Let us now make another alteration to the power system:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"updateBus!(system, analysis; label = \"Bus 1\", active = 0.1, magnitude = 0.95, angle = -0.07)\nupdateGenerator!(system, analysis; label = \"Generator 2\", reactive = 0.2, magnitude = 1.1)\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"With these modifications we are not only altering the power system, but also starting voltages. For the next uses of one of the methods, these values now are:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Therefore, users possess the flexibility to adjust these initial values as needed by employing the magnitude and angle keywords within the updateBus! and updateGenerator! functions.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"If users prefer to set starting voltages according to the typical scenario, they can accomplish this through the startingVoltage! function:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"startingVoltage!(system, analysis)","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Now, we have starting voltages defined exclusively according to the PowerSystem. These values are exactly the same as if we executed the newtonRaphson, fastNewtonRaphsonBX, fastNewtonRaphsonXB, or gaussSeidel function after all the updates we performed:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Limitations","page":"AC Power Flow","title":"Limitations","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The newtonRaphson, fastNewtonRaphsonBX, fastNewtonRaphsonXB, or gaussSeidel function oversees bus type validations, as outlined in the Bus Type Modification section. Consequently, attempting to change bus types or leaving generator buses without a generator and then proceeding directly to the iteration process is not viable.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"In such scenarios, JuliaGrid will raise an error:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"updateBus!(system, analysis; label = \"Bus 2\", type = 2)","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"In this scenario, the user must execute the newtonRaphson, fastNewtonRaphsonBX, fastNewtonRaphsonXB, or gaussSeidel function instead of trying to reuse them, for example:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"updateBus!(system; label = \"Bus 2\", type = 2)\n\nanalysis = fastNewtonRaphsonBX(system)\nfor iteration = 1:100\n mismatch!(system, analysis)\n solve!(system, analysis)\nend","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"note: Info\nAfter creating the PowerSystem and ACPowerFlow types, users can add or modify buses, branches, and generators before directly proceeding to iterations. JuliaGrid automatically executes the necessary functions when adjustments lead to a valid solution. However, if modifications are incompatible, like altering bus types, JuliaGrid raises an error to prevent misleading outcomes, ensuring accuracy.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#ACPowerCurrentAnalysisManual","page":"AC Power Flow","title":"Power and Current Analysis","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"After obtaining the solution from the AC power flow, we can calculate various electrical quantities related to buses, branches, and generators using the power! and current! functions. For instance, let us consider the power system for which we obtained the AC power flow solution:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.6)\naddBus!(system; label = \"Bus 2\", type = 1, reactive = 0.1, susceptance = 0.03)\naddBus!(system; label = \"Bus 3\", type = 1, conductance = 0.02)\n\n@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.5)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.1)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.4)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 0.2)\naddGenerator!(system; label = \"Generator 2\", bus = \"Bus 2\", active = 1.0, reactive = 0.2)\n\nanalysis = newtonRaphson(system)\nfor iteration = 1:100\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"We can now utilize the provided functions to compute powers and currents:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"power!(system, analysis)\ncurrent!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"For instance, if we want to show the active power injections and the to-bus current angles, we can employ the following code:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"print(system.bus.label, analysis.power.injection.active)\nprint(system.branch.label, analysis.current.to.angle)","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"note: Info\nTo better understand the powers and currents associated with buses, branches, and generators that are obtained by the power! and current! functions, we suggest referring to the tutorials on AC Power Flow Analysis.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Print-Results-in-the-REPL-2","page":"AC Power Flow","title":"Print Results in the REPL","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Users can utilize any of the print functions outlined in the Print Power System Data or Print Power System Summary. For example, to create a bus summary with the desired units, users can use the following function:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"@voltage(pu, deg, V)\n@power(MW, MVAr, pu)\nprintBusSummary(system, analysis)\n@default(unit) # hide\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Active-and-Reactive-Power-Injection","page":"AC Power Flow","title":"Active and Reactive Power Injection","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To calculate the active and reactive power injection associated with a specific bus, the function can be used:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"active, reactive = injectionPower(system, analysis; label = \"Bus 1\")","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Active-and-Reactive-Power-Injection-from-Generators","page":"AC Power Flow","title":"Active and Reactive Power Injection from Generators","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To calculate the active and reactive power injection from the generators at a specific bus, the function can be used:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"active, reactive = supplyPower(system, analysis; label = \"Bus 1\")","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Active-and-Reactive-Power-at-Shunt-Element","page":"AC Power Flow","title":"Active and Reactive Power at Shunt Element","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To calculate the active and reactive power associated with shunt element at a specific bus, the function can be used:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"active, reactive = shuntPower(system, analysis; label = \"Bus 3\")","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Active-and-Reactive-Power-Flow","page":"AC Power Flow","title":"Active and Reactive Power Flow","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Similarly, we can compute the active and reactive power flow at both the from-bus and to-bus ends of the specific branch by utilizing the functions provided below:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"active, reactive = fromPower(system, analysis; label = \"Branch 2\")\nactive, reactive = toPower(system, analysis; label = \"Branch 2\")","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Active-and-Reactive-Power-at-Charging-Admittances","page":"AC Power Flow","title":"Active and Reactive Power at Charging Admittances","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To calculate the active and reactive power linked with branch charging admittances of the particular branch, the function can be used:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"active, reactive = chargingPower(system, analysis; label = \"Branch 1\")","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Active powers indicate active losses within the branch's charging admittances. Moreover, charging admittances injected reactive powers into the power system due to their capacitive nature.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Active-and-Reactive-Power-at-Series-Impedance","page":"AC Power Flow","title":"Active and Reactive Power at Series Impedance","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To calculate the active and reactive power across the series impedance of the branch, the function can be used:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"active, reactive = seriesPower(system, analysis; label = \"Branch 2\")","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The active power also considers active losses originating from the series resistance of the branch, while the reactive power represents reactive losses resulting from the impedance's inductive characteristics.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Generator-Active-and-Reactive-Power-Output","page":"AC Power Flow","title":"Generator Active and Reactive Power Output","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"We can compute the active and reactive power output of a particular generator using the function:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"active, reactive = generatorPower(system, analysis; label = \"Generator 1\")","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Current-Injection","page":"AC Power Flow","title":"Current Injection","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To calculate the current injection associated with a specific bus, the function can be used:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"magnitude, angle = injectionCurrent(system, analysis; label = \"Bus 1\")","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Current-Flow","page":"AC Power Flow","title":"Current Flow","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"We can compute the current flow at both the from-bus and to-bus ends of the specific branch by utilizing the provided functions below:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"magnitude, angle = fromCurrent(system, analysis; label = \"Branch 2\")\nmagnitude, angle = toCurrent(system, analysis; label = \"Branch 2\")","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#Current-Through-Series-Impedance","page":"AC Power Flow","title":"Current Through Series Impedance","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To calculate the current passing through the series impedance of the branch in the direction from the from-bus end to the to-bus end, we can use the following function:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"magnitude, angle = seriesCurrent(system, analysis; label = \"Branch 2\")","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#GeneratorReactivePowerLimitsManual","page":"AC Power Flow","title":"Generator Reactive Power Limits","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The function reactiveLimit! can be used to check if the generators' output of reactive power is within the defined limits after obtaining the solution from the AC power flow analysis:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.5)\naddBus!(system; label = \"Bus 3\", type = 2, reactive = 0.05)\naddBus!(system; label = \"Bus 4\", type = 2, reactive = 0.05)\n\n@branch(resistance = 0.015)\naddBranch!(system; from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\naddBranch!(system; from = \"Bus 1\", to = \"Bus 3\", reactance = 0.01)\naddBranch!(system; from = \"Bus 2\", to = \"Bus 3\", reactance = 0.04)\naddBranch!(system; from = \"Bus 2\", to = \"Bus 4\", reactance = 0.004)\n\n@generator(minReactive = -0.4, maxReactive = 0.1)\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\")\naddGenerator!(system; label = \"Generator 2\", bus = \"Bus 3\", reactive = 0.8)\naddGenerator!(system; label = \"Generator 3\", bus = \"Bus 4\", reactive = 0.9)\n\nanalysis = newtonRaphson(system)\nfor iteration = 1:100\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\n\nviolate = reactiveLimit!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The output reactive power of the observed generators is subject to limits which are defined as follows:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"[system.generator.capability.minReactive system.generator.capability.maxReactive]","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"After obtaining the solution of the AC power flow analysis, the reactiveLimit! function is used to internally calculate the output powers of the generators and verify if these values exceed the defined limits. Consequently, the variable violate indicates whether there is a violation of limits.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"In the provided example, it can be observed that the Generator 2 and Generator 3 violate the maximum limit:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"print(system.generator.label, violate)","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Due to these violations of limits, the PowerSystem type undergoes modifications, and the output reactive power at the limit-violating generators is adjusted as follows:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"print(system.generator.label, system.generator.output.reactive)","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To ensure that these values stay within the limits, the bus type must be changed from the generator bus (type = 2) to the demand bus (type = 1), as shown below:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"print(system.bus.label, system.bus.layout.type)","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"After modifying the PowerSystem type as described earlier, we can run the simulation again with the following code:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"analysis = newtonRaphson(system)\nfor iteration = 1:100\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Once the simulation is complete, we can verify that all generator reactive power outputs now satisfy the limits by checking the violate variable again:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"violate = reactiveLimit!(system, analysis)","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"note: Info\nThe reactiveLimit! function changes the PowerSystem type deliberately because it is intended to help users create the power system where all reactive power outputs of the generators are within limits.","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"manual/acPowerFlow/#New-Slack-Bus","page":"AC Power Flow","title":"New Slack Bus","text":"","category":"section"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Looking at the following code example, we can see that the output limits of the generator are set only for Generator 1 that is connected to the slack bus:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.5, reactive = 0.05)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.5)\naddBus!(system; label = \"Bus 3\", type = 2)\naddBus!(system; label = \"Bus 4\", type = 2)\n\n@branch(resistance = 0.01)\naddBranch!(system; from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\naddBranch!(system; from = \"Bus 1\", to = \"Bus 3\", reactance = 0.01)\naddBranch!(system; from = \"Bus 2\", to = \"Bus 3\", reactance = 0.04)\naddBranch!(system; from = \"Bus 2\", to = \"Bus 4\", reactance = 0.004)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", maxReactive = 0.2)\naddGenerator!(system; label = \"Generator 2\", bus = \"Bus 4\", reactive = 0.3)\n\nanalysis = newtonRaphson(system)\nfor iteration = 1:100\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\nnothing # hide","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Upon checking the limits, we can observe that the slack bus has been transformed by executing the following code:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"violate = reactiveLimit!(system, analysis)","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Here, the generator connected to the slack bus is violating the minimum reactive power limit, which indicates the need to convert the slack bus. It is important to note that the new slack bus can be created only from the generator bus (type = 2). We will now perform another AC power flow analysis on the modified system using the following:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"analysis = newtonRaphson(system)\nfor iteration = 1:100\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"After examining the bus voltages, we will focus on the angles:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"print(system.bus.label, analysis.voltage.angle)","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"We can observe that the angles have been calculated based on the new slack bus. JuliaGrid offers the function to adjust these angles to match the original slack bus as follows:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"adjustAngle!(system, analysis; slack = \"Bus 1\")","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"After executing the above code, the updated results can be viewed:","category":"page"},{"location":"manual/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"print(system.bus.label, analysis.voltage.angle)","category":"page"},{"location":"manual/acStateEstimation/#ACStateEstimationManual","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To perform nonlinear or AC state estimation, the initial requirement is to have the PowerSystem type configured with the AC model, along with the Measurement type storing measurement data. Next, we can develop either the weighted least-squares (WLS) model, utilizing the Gauss-Newton method, or the least absolute value (LAV) model. These models are encapsulated within the ACStateEstimation type:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"gaussNewton,\nacLavStateEstimation.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"For resolving the AC state estimation problem and obtaining bus voltage magnitudes and angles, utilize the following function:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"solve!.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"After executing the function solve!, where the user employs the Gauss-Newton method, the user has the ability to check if the measurement set contains outliers throughout bad data analysis and remove those measurements using:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"residualTest!.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Moreover, before the creating ACStateEstimation type, users can initiate observability analysis to identify observable islands and restore observability by employing:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"islandTopologicalFlow,\nislandTopological,\nrestorationGram!.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"After obtaining the AC state estimation solution, JuliaGrid offers post-processing analysis functions for calculating powers and currents associated with buses and branches:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"power!,\ncurrent!.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Additionally, specialized functions are available for calculating specific types of powers or currents for individual buses or branches.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#ACSEBusTypeModificationManual","page":"AC State Estimation","title":"Bus Type Modification","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"In AC state estimation, it is necessary to designate a slack bus, where the bus voltage angle is known. Therefore, when establishing the ACStateEstimation type, the initially assigned slack bus is evaluated and may be altered. If the designated slack bus (type = 3) lacks a connected in-service generator, it will be changed to a demand bus (type = 1). Conversely, the first generator bus (type = 2) with an active in-service generator linked to it will be reassigned as the new slack bus (type = 3).","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#ACSEObservabilityAnalysisManual","page":"AC State Estimation","title":"Observability Analysis","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To initiate the power system with measurements at specific locations, follow the provided example:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", type = 3)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.1, reactive = 0.01)\naddBus!(system; label = \"Bus 3\", type = 2, active = 0.5, reactive = 0.01)\naddBus!(system; label = \"Bus 4\", type = 1, active = 0.2, reactive = 0.02)\naddBus!(system; label = \"Bus 5\", type = 1, active = 0.3, reactive = 0.03)\naddBus!(system; label = \"Bus 6\", type = 1, active = 0.1, reactive = 0.01)\naddBus!(system; label = \"Bus 7\", type = 1, active = 0.1, reactive = 0.01)\n\n@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.002)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.01)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 5\", reactance = 0.02)\naddBranch!(system; label = \"Branch 4\", from = \"Bus 3\", to = \"Bus 4\", reactance = 0.03)\naddBranch!(system; label = \"Branch 5\", from = \"Bus 5\", to = \"Bus 6\", reactance = 0.05)\naddBranch!(system; label = \"Branch 6\", from = \"Bus 3\", to = \"Bus 5\", reactance = 0.05)\naddBranch!(system; label = \"Branch 7\", from = \"Bus 6\", to = \"Bus 7\", reactance = 0.05)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 4.2, reactive = 0.2)\naddGenerator!(system; label = \"Generator 2\", bus = \"Bus 3\", active = 0.2, reactive = 0.1)\n\naddWattmeter!(system, device; label = \"Wattmeter 1\", from = \"Branch 1\", active = 1.15)\naddVarmeter!(system, device; label = \"Varmeter 1\", from = \"Branch 1\", reactive = -0.50)\n\naddWattmeter!(system, device; label = \"Wattmeter 2\", from = \"Branch 4\", active = 0.20)\naddVarmeter!(system, device; label = \"Varmeter 2\", from = \"Branch 4\", reactive = -0.02)\n\naddWattmeter!(system, device; label = \"Wattmeter 3\", from = \"Branch 5\", active = -0.20)\naddVarmeter!(system, device; label = \"Varmeter 3\", from = \"Branch 5\", reactive = 0.02)\n\naddWattmeter!(system, device; label = \"Wattmeter 4\", bus = \"Bus 2\", active = -0.1)\naddVarmeter!(system, device; label = \"Varmeter 4\", bus = \"Bus 2\", reactive = -0.01)\n\naddWattmeter!(system, device; label = \"Wattmeter 5\", bus = \"Bus 3\", active = -0.30)\naddVarmeter!(system, device; label = \"Varmeter 5\", bus = \"Bus 3\", reactive = 0.66)\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Attempting to solve this system immediately may not be possible because the gain matrix will be singular. To avoid this situation, users can perform observability analysis.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"JuliaGrid employs standard observability analysis performed on the linear decoupled measurement model. Active power measurements from wattmeters are utilized to estimate bus voltage angles, while reactive power measurements from varmeters are used to estimate bus voltage magnitudes. This necessitates that measurements of active and reactive power come in pairs.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"note: Info\nWe suggest that readers refer to the tutorial on Observability Analysis for insights into the implementation.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"However, the initial step involves defining observable islands. JuliaGrid offers users two options for obtaining observable islands: flow observable islands or maximal observable islands. The selection depends on the power system's structure and available measurements. Identifying only flow observable islands reduces complexity in the island detection function, but increases complexity in the restoration function.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Flow-Observable-Islands","page":"AC State Estimation","title":"Flow Observable Islands","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Now, let us identify flow observable islands:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"islands = islandTopologicalFlow(system, device)\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"As a result, four flow observable islands are identified: Bus 1 and Bus 2 form the first island, Bus 3 and Bus 4 form the second island, Bus 5 and Bus 6 constitute the third island, while Bus 7 forms the fourth island:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"islands.island\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Maximal-Observable-Islands","page":"AC State Estimation","title":"Maximal Observable Islands","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Following that, we will instruct the user on obtaining maximal observable islands:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"islands = islandTopological(system, device)\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The outcome reveals the identification of two maximal observable islands:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"islands.island\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"It is evident that upon comparing this result with the flow islands, the merging of the two injection measurements at Bus 2 and Bus 3 consolidated the first, second, and third flow observable islands into a single island.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Restore-Observability","page":"AC State Estimation","title":"Restore Observability","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Before commencing the restoration of observability in the context of the linear decoupled measurement model and observability analysis, it is imperative to ensure that the system possesses one bus voltage magnitude measurement. This necessity arises from the fact that observable islands are identified based on wattmeters, where wattmeters are tasked with estimating voltage angles. Since one voltage angle is already known from the slack bus, the same principle should be applied to bus voltage magnitudes. Therefore, to address this requirement, we add:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addVoltmeter!(system, device; bus = \"Bus 1\", magnitude = 1.0)\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Subsequently, the user needs to establish a set of pseudo-measurements, where measurements must come in pairs as well. Let us create that set:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"pseudo = measurement()\n\naddWattmeter!(system, pseudo; label = \"Pseudo-Wattmeter 1\", bus = \"Bus 1\", active = 0.31)\naddVarmeter!(system, pseudo; label = \"Pseudo-Varmeter 1\", bus = \"Bus 1\", reactive = -0.19)\n\naddWattmeter!(system, pseudo; label = \"Pseudo-Wattmeter 2\", from = \"Branch 7\", active = 0.10)\naddVarmeter!(system, pseudo; label = \"Pseudo-Varmeter 2\", from = \"Branch 7\", reactive = 0.01)\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"note: Info\nThe labels for specific pseudo-measurements must differ from those defined in the measurements stored in the device set. This is necessary because the next step involves adding pseudo-measurements to the device set.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Subsequently, the user can execute the restorationGram! function:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"restorationGram!(system, device, pseudo, islands)\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"This function attempts to restore observability using pseudo-measurements. As a result, the inclusion of measurements from Pseudo-Wattmeter 2 and Pseudo-Varmeter 2 facilitates observability restoration, and these measurements are subsequently added to the device variable:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"device.wattmeter.label\ndevice.varmeter.label\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Consequently, the power system becomes observable, allowing the user to proceed with forming the AC state estimation model and solving it. Ensuring the observability of the system does not guarantee obtaining accurate estimates of the state variables. Numerical ill-conditioning may adversely impact the state estimation algorithm. However, in most cases, efficient estimation becomes feasible when the system is observable [2].","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Additionally, it is worth mentioning that restoration might encounter difficulties due to the default zero pivot threshold set at 1e-5. This threshold can be modified using the restorationGram! function.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"note: Info\nDuring the restoration step, if users define bus phasor measurements, these measurements will be considered. Consequently, the system may achieve observability even if multiple islands persist.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#ACLSStateEstimationSolutionManual","page":"AC State Estimation","title":"Weighted Least-Squares Estimator","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To begin, we will define the PowerSystem and Measurement types:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", type = 3)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.1, reactive = 0.01)\naddBus!(system; label = \"Bus 3\", type = 1, active = 2.5, reactive = 0.2)\n\n@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 3\", reactance = 0.05)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.03)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 3.2, reactive = 0.3)\n\n@voltmeter(label = \"Voltmeter ? (!)\")\naddVoltmeter!(system, device; bus = \"Bus 1\", magnitude = 1.0, variance = 1e-2)\n\n@ammeter(label = \"Ammeter ? (!)\")\naddAmmeter!(system, device; from = \"Branch 3\", magnitude = 0.947, variance = 1e-1)\naddAmmeter!(system, device; to = \"Branch 2\", magnitude = 1.674, variance = 1e-1)\n\n@wattmeter(label = \"Wattmeter ? (!)\")\naddWattmeter!(system, device; from = \"Branch 1\", active = 1.046, variance = 1e-3)\naddWattmeter!(system, device; bus = \"Bus 2\", active = -0.1, variance = 2e-3)\n\n@varmeter(label = \"Varmeter ? (!)\")\naddVarmeter!(system, device; from = \"Branch 1\", reactive = 0.059, variance = 1e-4)\naddVarmeter!(system, device; bus = \"Bus 2\", reactive = -0.01, variance = 1e-3)\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Next, to establish the AC state estimation model, we will utilize the gaussNewton function:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"analysis = gaussNewton(system, device)\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"tip: Tip\nHere, the user triggers LU factorization as the default method for solving the system of linear equations within each iteration of the Gauss-Newton method. However, the user also has the option to select alternative factorization methods such as LDLt or QR:analysis = gaussNewton(system, device, LDLt)","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Setup-Starting-Voltages","page":"AC State Estimation","title":"Setup Starting Voltages","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The initial voltages for the Gauss-Newton method are determined based on the specified initial voltage magnitudes and angles within the buses of the PowerSystem type. These values are then forwarded to the ACStateEstimation during the execution of the gaussNewton function. Therefore, the starting voltages in this example are as follows:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Users have the flexibility to modify these vectors according to their own requirements in order to adjust the starting voltages. For instance, users can conduct an initial AC power flow analysis and utilize the obtained solution as the starting voltages for AC state estimation:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"powerFlow = newtonRaphson(system)\nfor iteration = 1:10\n mismatch!(system, powerFlow)\n solve!(system, powerFlow)\nend\n\nfor i = 1:system.bus.number\n analysis.voltage.magnitude[i] = powerFlow.voltage.magnitude[i]\n analysis.voltage.angle[i] = powerFlow.voltage.angle[i]\nend\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#State-Estimator","page":"AC State Estimation","title":"State Estimator","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To conduct an iterative process using the Gauss-Newton method, it is essential to include the solve! function inside the iteration loop. For example:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"for iteration = 1:20\n solve!(system, analysis)\nend\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Once the state estimator is obtained, users can access the bus voltage magnitudes and angles using:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Breaking-the-Iterative-Process","page":"AC State Estimation","title":"Breaking the Iterative Process","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The iterative process can be terminated using the solve! function. The following code demonstrates how to utilize this function to break out of the iteration loop:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"analysis = gaussNewton(system, device)\nfor iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n println(\"Solution Found.\")\n break\n end\nend\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The solve! function returns the maximum absolute values of the state variable increment, which are commonly used as a convergence criterion in the iterative Gauss-Newton algorithm.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"note: Info\nWe suggest that readers refer to the tutorial on AC State Estimation for insights into the implementation.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Inclusion-of-PMUs-in-Rectangular-Coordinates","page":"AC State Estimation","title":"Inclusion of PMUs in Rectangular Coordinates","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"In the example above, our focus is solely on solving the AC state estimation using SCADA measurements. However, users have the option to also integrate PMUs into the AC state estimation, either in the rectangular or polar coordinate system.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The default approach is to include PMUs in the rectangular coordinate system:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"@pmu(label = \"PMU ? (!)\")\naddPmu!(system, device; to = \"Branch 1\", magnitude = 1.05, angle = 3.047)\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"In the case of the rectangular system, inclusion resolves ill-conditioned problems arising in polar coordinates due to small values of current magnitudes. However, this approach's main disadvantage is related to measurement errors, as measurement errors correspond to polar coordinates. Therefore, the covariance matrix must be transformed from polar to rectangular coordinates [3]. As a result, measurement errors of a single PMU are correlated, and the covariance matrix does not have a diagonal form. Despite that, the measurement error covariance matrix is usually considered as a diagonal matrix, affecting the accuracy of the state estimation.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"In the example above, we specifically include PMUs where measurement error correlations are disregarded. This is evident through the precision matrix, which maintains a diagonal form:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"analysis = gaussNewton(system, device);\nanalysis.method.precision","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Lastly, we incorporate correlation into our model by adding a new PMU with the desired error correlation:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addPmu!(system, device; bus = \"Bus 3\", magnitude = 0.95, angle = -0.08, correlated = true)\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Now, we can observe the precision matrix that does not hold a diagonal form:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"analysis = gaussNewton(system, device);\nanalysis.method.precision","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Inclusion-of-PMUs-in-Polar-Coordinates","page":"AC State Estimation","title":"Inclusion of PMUs in Polar Coordinates","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The second approach involves incorporating these measurements into the polar coordinate system. For instance:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addPmu!(system, device; from = \"Branch 1\", magnitude = 1.048, angle = -0.057, polar = true)\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"This inclusion of PMUs provides more accurate state estimates compared to rectangular inclusion, but demands longer computing time. PMUs are handled in the same manner as SCADA measurements. However, this approach is susceptible to ill-conditioned problems arising in polar coordinates due to small values of current magnitudes [3, 4].","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"tip: Tip\nIt is important to note that with each individual phasor measurement, we can set the coordinate system, providing flexibility to include some in polar and some in rectangular systems. This flexibility is particularly valuable because bus voltage phasor measurements are preferably included in a polar coordinate system, while current phasor measurements are best suited to a rectangular coordinate system.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Alternative-Formulation","page":"AC State Estimation","title":"Alternative Formulation","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The resolution of the WLS state estimation problem using the conventional method typically progresses smoothly. However, it is widely acknowledged that in certain situations common to real-world systems, this method can be vulnerable to numerical instabilities. Such conditions might impede the algorithm from finding a satisfactory solution. In such cases, users may opt for an alternative formulation of the WLS state estimation, namely, employing an approach called orthogonal factorization [5, Sec. 3.2].","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"This approach is suitable when measurement errors are uncorrelated, and the precision matrix remains diagonal. Therefore, as a preliminary step, we need to eliminate the correlation, as we did previously:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"updatePmu!(system, device; label = \"PMU 2 (Bus 3)\", correlated = false)\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Subsequently, by specifying the Orthogonal argument in the gaussNewton function, JuliaGrid implements a more robust approach to obtain the WLS estimator, which proves particularly beneficial when substantial differences exist among measurement variances:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"analysis = gaussNewton(system, device, Orthogonal)\nfor iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n break\n end\nend\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Print-Results-in-the-REPL","page":"AC State Estimation","title":"Print Results in the REPL","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Users have the option to print the results in the REPL using any units that have been configured, such as:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"@voltage(pu, deg, V)\nprintBusData(system, analysis)\n@default(unit) # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Next, users can easily customize the print results for specific buses, for example:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"printBusData(system, analysis; label = \"Bus 1\", header = true)\nprintBusData(system, analysis; label = \"Bus 2\")\nprintBusData(system, analysis; label = \"Bus 3\", footer = true)","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Save-Results-to-a-File","page":"AC State Estimation","title":"Save Results to a File","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Users can also redirect print output to a file. For example, data can be saved in a text file as follows:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"open(\"bus.txt\", \"w\") do file\n printBusData(system, analysis, file)\nend","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"tip: Tip\nWe also provide functions to print or save state estimation results, such as estimated values and residuals. For more details, users can consult the Power and Current Analysis section of this manual.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#ACBadDataDetectionManual","page":"AC State Estimation","title":"Bad Data Processing","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"After acquiring the WLS solution using the Gauss-Newton method, users can conduct bad data analysis employing the largest normalized residual test. Continuing with our defined power system and measurement set, let us introduce a new measurement. Upon proceeding to find the solution for this updated state:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addWattmeter!(system, device; from = \"Branch 2\", active = 31.1)\n\nanalysis = gaussNewton(system, device)\nfor iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n break\n end\nend\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Here, we can observe the impact of the outlier on the solution:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Following the solution acquisition, we can verify the presence of erroneous data. Detection of such data is determined by the threshold keyword. If the largest normalized residual's value exceeds the threshold, the measurement will be identified as bad data and consequently removed from the AC state estimation model:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"outlier = residualTest!(system, device, analysis; threshold = 4.0)\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Users can examine the data obtained from the bad data analysis:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"outlier.detect\noutlier.maxNormalizedResidual\noutlier.label","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Hence, upon detecting bad data, the detect variable will hold true. The maxNormalizedResidual variable retains the value of the largest normalized residual, while the label contains the label of the measurement identified as bad data. JuliaGrid will mark the respective measurement as out-of-service within the Measurement type.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"After removing bad data, a new estimate can be computed without considering this specific measurement. The user has the option to either restart the gaussNewton function or proceed directly to the iteration loop. However, if the latter option is chosen, using voltages obtained with outlier presence as the starting point could significantly impede algorithm convergence. To avoid this undesirable outcome, the user should first establish a new starting point and commence the iteration procedure. For instance:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"for i = 1:system.bus.number\n analysis.voltage.magnitude[i] = system.bus.voltage.magnitude[i]\n analysis.voltage.angle[i] = system.bus.voltage.angle[i]\nend\n\nfor iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n break\n end\nend\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Consequently, we obtain a new solution devoid of the impact of the outlier measurement:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"note: Info\nWe suggest that readers refer to the tutorial on Bad Data Processing for insights into the implementation.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#PMULAVtateEstimationSolutionManual","page":"AC State Estimation","title":"Least Absolute Value Estimator","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The LAV method presents an alternative estimation technique known for its increased robustness compared to WLS. While the WLS method relies on specific assumptions regarding measurement errors, robust estimators like LAV are designed to maintain unbiasedness even in the presence of various types of measurement errors and outliers. This characteristic often eliminates the need for extensive bad data processing procedures [5, Ch. 6]. However, it is important to note that achieving robustness typically involves increased computational complexity.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To obtain an LAV estimator, users need to employ one of the solvers listed in the JuMP documentation. In many common scenarios, the Ipopt solver proves sufficient to obtain a solution:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"using Ipopt\nusing JuMP # hide\n\nanalysis = acLavStateEstimation(system, device, Ipopt.Optimizer)\nJuMP.set_silent(analysis.method.jump) # hide\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Setup-Starting-Primal-Values","page":"AC State Estimation","title":"Setup Starting Primal Values","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"In JuliaGrid, the assignment of starting primal values for optimization variables takes place when the solve! function is executed. Starting primal values are determined based on the voltage fields within the ACStateEstimation type. By default, these values are initially established using the initial bus voltage magnitudes and angles from PowerSystem type:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Users have the flexibility to customize these values according to their requirements, and they will be utilized as the starting primal values when executing the solve! function.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Solution","page":"AC State Estimation","title":"Solution","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To solve the formulated LAV state estimation model, simply execute the following function:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"solve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Upon obtaining the solution, access the bus voltage magnitudes and angles using:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"note: Info\nWe suggest that readers refer to the tutorial on Least Absolute Value Estimation for insights into the implementation.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#ACMeasurementsAlterationManual","page":"AC State Estimation","title":"Measurement Set Update","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"After establishing the Measurement type using the measurement function, users gain the capability to incorporate new measurement devices or update existing ones.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Once updates are completed, users can seamlessly progress towards generating the ACStateEstimation type using the gaussNewton or acLavStateEstimation function. Ultimately, resolving the AC state estimation is achieved through the utilization of the solve! function:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\ndevice = measurement() # <- Initialize the Measurement instance\n\naddBus!(system; label = \"Bus 1\", type = 3)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.1, reactive = 0.01)\naddBus!(system; label = \"Bus 3\", type = 1, active = 2.5, reactive = 0.2)\n\n@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 3\", reactance = 0.05)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.03)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 3.2, reactive = 0.3)\n\n@voltmeter(label = \"Voltmeter ? (!)\", variance = 1e-3)\naddVoltmeter!(system, device; bus = \"Bus 1\", magnitude = 1.0)\n\n@wattmeter(label = \"Wattmeter ? (!)\", varianceBus = 1e-2)\naddWattmeter!(system, device; from = \"Branch 1\", active = 1.046)\naddWattmeter!(system, device; bus = \"Bus 2\", active = -0.1)\n\n@varmeter(label = \"Varmeter ? (!)\", varianceFrom = 1e-3)\naddVarmeter!(system, device; from = \"Branch 1\", reactive = 0.059)\naddVarmeter!(system, device; bus = \"Bus 2\", reactive = -0.01)\n\n@pmu(label = \"PMU ? (!)\")\naddPmu!(system, device; bus = \"Bus 2\", magnitude = 0.976, angle = -0.052)\n\nanalysis = gaussNewton(system, device) # <- Build ACStateEstimation for the defined model\nfor iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n break\n end\nend\n\naddWattmeter!(system, device; from = \"Branch 3\", active = 0.924)\nupdateWattmeter!(system, device; label = \"Wattmeter 2 (Bus 2)\", variance = 1e-4)\n\naddVarmeter!(system, device; to = \"Branch 3\", reactive = -0.044, variance = 1e-5)\nupdateVarmeter!(system, device; label = \"Varmeter 2 (Bus 2)\", reactive = -0.011)\n\nupdatePmu!(system, device; label = \"PMU 1 (Bus 2)\", polar = false)\n\nanalysis = gaussNewton(system, device) # <- Build ACStateEstimation for the updated model\nfor iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n break\n end\nend\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"note: Info\nThis concept removes the need to restart and recreate the Measurement type from the beginning when implementing changes to the existing measurement set.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#ACStateEstimationUpdateManual","page":"AC State Estimation","title":"State Estimation Update","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"An advanced methodology involves users establishing the ACStateEstimation type using gaussNewton or acLavStateEstimation just once. After this initial setup, users can seamlessly modify existing measurement devices without the need to recreate the ACStateEstimation type.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"This advancement extends beyond the previous scenario where recreating the Measurement type was unnecessary, to now include the scenario where ACStateEstimation also does not need to be recreated.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"tip: Tip\nThe addition of new measurements after the creation of ACStateEstimation is not practical in terms of reusing this type. Instead, we recommend that users create a final set of measurements and then utilize update functions to manage devices, either putting them in-service or out-of-service throughout the process.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"We can modify the prior example to achieve the same model without establishing ACStateEstimation twice:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\ndevice = measurement() # <- Initialize the Measurement instance\n\naddBus!(system; label = \"Bus 1\", type = 3)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.1, reactive = 0.01)\naddBus!(system; label = \"Bus 3\", type = 1, active = 2.5, reactive = 0.2)\n\n@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 3\", reactance = 0.05)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.03)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 3.2, reactive = 0.3)\n\n@voltmeter(label = \"Voltmeter ? (!)\", variance = 1e-3)\naddVoltmeter!(system, device; bus = \"Bus 1\", magnitude = 1.0)\n\n@wattmeter(label = \"Wattmeter ? (!)\", varianceBus = 1e-2)\naddWattmeter!(system, device; from = \"Branch 1\", active = 1.046)\naddWattmeter!(system, device; bus = \"Bus 2\", active = -0.1)\naddWattmeter!(system, device; from = \"Branch 3\", active = 0.924, status = 0)\n\n@varmeter(label = \"Varmeter ? (!)\", varianceFrom = 1e-3)\naddVarmeter!(system, device; from = \"Branch 1\", reactive = 0.059)\naddVarmeter!(system, device; bus = \"Bus 2\", reactive = -0.01)\naddVarmeter!(system, device; to = \"Branch 3\", reactive = -0.044, variance = 1e-5, status = 0)\n\n@pmu(label = \"PMU ? (!)\")\naddPmu!(system, device; bus = \"Bus 2\", magnitude = 0.976, angle = -0.052)\n\nanalysis = gaussNewton(system, device) # <- Build ACStateEstimation for the defined model\nfor iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n break\n end\nend\n\nupdateWattmeter!(system, device, analysis; label = \"Wattmeter 3 (From Branch 3)\", status = 1)\nupdateWattmeter!(system, device, analysis; label = \"Wattmeter 2 (Bus 2)\", variance = 1e-4)\n\nupdateVarmeter!(system, device, analysis; label = \"Varmeter 3 (To Branch 3)\", status = 1)\nupdateVarmeter!(system, device, analysis; label = \"Varmeter 2 (Bus 2)\", reactive = -0.011)\n\nupdatePmu!(system, device, analysis; label = \"PMU 1 (Bus 2)\", polar = false)\n\n# <- No need for re-build; we have already updated the existing ACStateEstimation instance\nfor iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n break\n end\nend\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"note: Info\nThis concept removes the need to rebuild both the Measurement and the ACStateEstimation from the beginning when implementing changes to the existing measurement set. In the scenario of employing the WLS model, JuliaGrid can reuse the symbolic factorizations of LU or LDLt, provided that the nonzero pattern of the gain matrix remains unchanged.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#ACSEPowerCurrentAnalysisManual","page":"AC State Estimation","title":"Power and Current Analysis","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"After obtaining the solution from the AC state estimation, we can calculate various electrical quantities related to buses and branches using the power! and current! functions. For instance, let us consider the model for which we obtained the AC state estimation solution:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", type = 3, susceptance = 0.002)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.1, reactive = 0.01)\naddBus!(system; label = \"Bus 3\", type = 1, active = 2.5, reactive = 0.2)\n\n@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 3\", reactance = 0.05)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.03)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 3.2, reactive = 0.3)\n\naddWattmeter!(system, device; from = \"Branch 1\", active = 1.046, variance = 1e-2)\naddWattmeter!(system, device; bus = \"Bus 2\", active = -0.1, variance = 1e-3)\naddWattmeter!(system, device; from = \"Branch 3\", active = 0.924, variance = 1e-3)\n\naddVarmeter!(system, device; from = \"Branch 1\", reactive = 0.059, variance = 1e-3)\naddVarmeter!(system, device; bus = \"Bus 2\", reactive = -0.01, variance = 1e-2)\naddVarmeter!(system, device; to = \"Branch 3\", reactive = -0.044, variance = 1e-3)\n\nanalysis = gaussNewton(system, device)\nfor iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n break\n end\nend","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"We can now utilize the provided functions to compute powers and currents:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"power!(system, analysis)\ncurrent!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"For instance, if we want to show the active power injections and the from-bus current angles, we can employ the following code:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"print(system.bus.label, analysis.power.injection.active)\nprint(system.branch.label, analysis.current.from.angle)","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"note: Info\nTo better understand the powers and currents associated with buses and branches that are calculated by the power! and current! functions, we suggest referring to the tutorials on AC State Estimation.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Print-Results-in-the-REPL-2","page":"AC State Estimation","title":"Print Results in the REPL","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Users can utilize any of the print functions outlined in the Print API. For example, to print state estimation data related to wattmeters, we can use:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"@power(MW, pu, pu)\nprintWattmeterData(system, device, analysis)\n@default(unit) # hide\nnothing # hide","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Save-Results-to-a-CSV-File","page":"AC State Estimation","title":"Save Results to a CSV File","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"For CSV output, users should first generate a simple table with style = false, and then save it to a CSV file:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"using CSV\n\nio = IOBuffer()\nprintWattmeterData(system, device, analysis, io; style = false)\nCSV.write(\"bus.csv\", CSV.File(take!(io); delim = \"|\"))","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Active-and-Reactive-Power-Injection","page":"AC State Estimation","title":"Active and Reactive Power Injection","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To calculate the active and reactive power injection associated with a specific bus, the function can be used:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"active, reactive = injectionPower(system, analysis; label = \"Bus 1\")","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Active-and-Reactive-Power-Injection-from-Generators","page":"AC State Estimation","title":"Active and Reactive Power Injection from Generators","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To calculate the active and reactive power injection from the generators at a specific bus, the function can be used:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"active, reactive = supplyPower(system, analysis; label = \"Bus 1\")","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Active-and-Reactive-Power-at-Shunt-Element","page":"AC State Estimation","title":"Active and Reactive Power at Shunt Element","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To calculate the active and reactive power associated with shunt element at a specific bus, the function can be used:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"active, reactive = shuntPower(system, analysis; label = \"Bus 1\")","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Active-and-Reactive-Power-Flow","page":"AC State Estimation","title":"Active and Reactive Power Flow","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Similarly, we can compute the active and reactive power flow at both the from-bus and to-bus ends of the specific branch by utilizing the provided functions below:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"active, reactive = fromPower(system, analysis; label = \"Branch 2\")\nactive, reactive = toPower(system, analysis; label = \"Branch 2\")","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Active-and-Reactive-Power-at-Charging-Admittances","page":"AC State Estimation","title":"Active and Reactive Power at Charging Admittances","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To calculate the active and reactive power linked with branch charging admittances of the particular branch, the function can be used:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"active, reactive = chargingPower(system, analysis; label = \"Branch 1\")","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Active powers indicate active losses within the branch's charging admittances. Moreover, charging admittances injected reactive powers into the power system due to their capacitive nature, as denoted by a negative sign.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Active-and-Reactive-Power-at-Series-Impedance","page":"AC State Estimation","title":"Active and Reactive Power at Series Impedance","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To calculate the active and reactive power across the series impedance of the branch, the function can be used:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"active, reactive = seriesPower(system, analysis; label = \"Branch 2\")","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The active power also considers active losses originating from the series resistance of the branch, while the reactive power represents reactive losses resulting from the impedance's inductive characteristics.","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Current-Injection","page":"AC State Estimation","title":"Current Injection","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To calculate the current injection associated with a specific bus, the function can be used:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"magnitude, angle = injectionCurrent(system, analysis; label = \"Bus 1\")","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Current-Flow","page":"AC State Estimation","title":"Current Flow","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"We can compute the current flow at both the from-bus and to-bus ends of the specific branch by utilizing the provided functions below:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"magnitude, angle = fromCurrent(system, analysis; label = \"Branch 2\")\nmagnitude, angle = toCurrent(system, analysis; label = \"Branch 2\")","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"manual/acStateEstimation/#Current-Through-Series-Impedance","page":"AC State Estimation","title":"Current Through Series Impedance","text":"","category":"section"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To calculate the current passing through the series impedance of the branch in the direction from the from-bus end to the to-bus end, we can use the following function:","category":"page"},{"location":"manual/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"magnitude, angle = seriesCurrent(system, analysis; label = \"Branch 2\")","category":"page"},{"location":"api/analysis/#PowerCurrentAnalysisAPI","page":"Power and Current Analysis","title":"Power and Current Analysis","text":"","category":"section"},{"location":"api/analysis/","page":"Power and Current Analysis","title":"Power and Current Analysis","text":"In the following section, we have provided a list of functions that can be utilized for post-processing analysis. Once the voltage values are obtained through power flow analysis, optimal power flow analysis, or state estimation, these functions can be used to calculate power or current values. The specific procedures for computing these values depend on the chosen analysis, which are described in separate manuals for further information.","category":"page"},{"location":"api/analysis/","page":"Power and Current Analysis","title":"Power and Current Analysis","text":"To load power system model API functionalities into the current scope, utilize the following command:","category":"page"},{"location":"api/analysis/","page":"Power and Current Analysis","title":"Power and Current Analysis","text":"using JuliaGrid","category":"page"},{"location":"api/analysis/","page":"Power and Current Analysis","title":"Power and Current Analysis","text":"","category":"page"},{"location":"api/analysis/#AC-Power-Analysis","page":"Power and Current Analysis","title":"AC Power Analysis","text":"","category":"section"},{"location":"api/analysis/","page":"Power and Current Analysis","title":"Power and Current Analysis","text":"power!\ninjectionPower\nsupplyPower\nshuntPower\nfromPower\ntoPower\nseriesPower\nchargingPower\ngeneratorPower","category":"page"},{"location":"api/analysis/#AC-Current-Analysis","page":"Power and Current Analysis","title":"AC Current Analysis","text":"","category":"section"},{"location":"api/analysis/","page":"Power and Current Analysis","title":"Power and Current Analysis","text":"current!\ninjectionCurrent\nfromCurrent\ntoCurrent\nseriesCurrent","category":"page"},{"location":"api/analysis/#DC-Power-Analysis","page":"Power and Current Analysis","title":"DC Power Analysis","text":"","category":"section"},{"location":"api/analysis/","page":"Power and Current Analysis","title":"Power and Current Analysis","text":"power!\ninjectionPower\nsupplyPower\nfromPower\ntoPower\ngeneratorPower","category":"page"},{"location":"api/analysis/","page":"Power and Current Analysis","title":"Power and Current Analysis","text":"","category":"page"},{"location":"api/analysis/#ACPowerAnalysisAPI","page":"Power and Current Analysis","title":"AC Power Analysis","text":"","category":"section"},{"location":"api/analysis/","page":"Power and Current Analysis","title":"Power and Current Analysis","text":"power!(::PowerSystem, ::ACPowerFlow)\ninjectionPower(::PowerSystem, ::AC)\nsupplyPower(::PowerSystem, ::ACPowerFlow)\nshuntPower(::PowerSystem, ::AC)\nfromPower(::PowerSystem, ::AC)\ntoPower(::PowerSystem, ::AC)\nseriesPower(::PowerSystem, ::AC)\nchargingPower(::PowerSystem, ::AC)\ngeneratorPower(::PowerSystem, ::ACPowerFlow)","category":"page"},{"location":"api/analysis/#JuliaGrid.power!-Tuple{PowerSystem, ACPowerFlow}","page":"Power and Current Analysis","title":"JuliaGrid.power!","text":"power!(system::PowerSystem, analysis::AC)\n\nThe function computes the active and reactive powers associated with buses, branches, and generators for AC analysis.\n\nUpdates\n\nThis function updates the power field of the AC abstract type by computing the following electrical quantities:\n\ninjection: Active and reactive power bus injections.\nsupply: Active and reactive power bus injections from the generators.\nshunt: Active and reactive power values associated with shunt element at each bus.\nfrom: Active and reactive power flows at the from-bus end of each branch.\nto: Active and reactive power flows at the to-bus end of each branch.\ncharging: Active and reactive power values linked with branch charging admittances for each branch.\nseries Active and reactive power losses through each branch series impedance.\ngenerator: Produced active and reactive power outputs of each generator (not for state estimation).\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\npower!(system, analysis)\n\n\n\n\n\n","category":"method"},{"location":"api/analysis/#JuliaGrid.injectionPower-Tuple{PowerSystem, AC}","page":"Power and Current Analysis","title":"JuliaGrid.injectionPower","text":"injectionPower(system::PowerSystem, analysis::AC, label)\n\nThe function returns the active and reactive power injections associated with a specific bus in the AC framework. The label keyword argument must match an existing bus label.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\nactive, reactive = injectionPower(system, analysis; label = 1)\n\n\n\n\n\n","category":"method"},{"location":"api/analysis/#JuliaGrid.supplyPower-Tuple{PowerSystem, ACPowerFlow}","page":"Power and Current Analysis","title":"JuliaGrid.supplyPower","text":"supplyPower(system::PowerSystem, analysis::AC, label)\n\nThe function returns the active and reactive power injections from the generators associated with a specific bus in the AC framework. The label keyword argument must match an existing bus label.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\nactive, reactive = supplyPower(system, analysis; label = 1)\n\n\n\n\n\n","category":"method"},{"location":"api/analysis/#JuliaGrid.shuntPower-Tuple{PowerSystem, AC}","page":"Power and Current Analysis","title":"JuliaGrid.shuntPower","text":"shuntPower(system::PowerSystem, analysis::AC, label)\n\nThe function returns the active and reactive power values of the shunt element associated with a specific bus in the AC framework. The label keyword argument must match an existing bus label.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\nactive, reactive = shuntPower(system, analysis; label = 9)\n\n```\n\n\n\n\n\n","category":"method"},{"location":"api/analysis/#JuliaGrid.fromPower-Tuple{PowerSystem, AC}","page":"Power and Current Analysis","title":"JuliaGrid.fromPower","text":"fromPower(system::PowerSystem, analysis::AC; label)\n\nThe function returns the active and reactive power flows at the from-bus end associated with a specific branch in the AC framework. The label keyword argument must match an existing branch label.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\nactive, reactive = fromPower(system, analysis; label = 2)\n\n\n\n\n\n","category":"method"},{"location":"api/analysis/#JuliaGrid.toPower-Tuple{PowerSystem, AC}","page":"Power and Current Analysis","title":"JuliaGrid.toPower","text":"toPower(system::PowerSystem, analysis::AC; label)\n\nThe function returns the active and reactive power flows at the to-bus end associated with a specific branch in the AC framework. The label keyword argument must match an existing branch label.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\nactive, reactive = toPower(system, analysis; label = 2)\n\n\n\n\n\n","category":"method"},{"location":"api/analysis/#JuliaGrid.seriesPower-Tuple{PowerSystem, AC}","page":"Power and Current Analysis","title":"JuliaGrid.seriesPower","text":"seriesPower(system::PowerSystem, analysis::AC; label)\n\nThe function returns the active and reactive power losses across the series impedance of a specific branch within the AC framework. The label keyword argument should correspond to an existing branch label.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\nactive, reactive = seriesPower(system, analysis; label = 2)\n\n\n\n\n\n","category":"method"},{"location":"api/analysis/#JuliaGrid.chargingPower-Tuple{PowerSystem, AC}","page":"Power and Current Analysis","title":"JuliaGrid.chargingPower","text":"chargingPower(system::PowerSystem, analysis::AC; label)\n\nThe function returns the active and reactive power values associated with the charging admittances of a specific branch in the AC framework. The label keyword argument must correspond to an existing branch label.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\nactive, reactive = chargingPower(system, analysis; label = 2)\n\n\n\n\n\n","category":"method"},{"location":"api/analysis/#JuliaGrid.generatorPower-Tuple{PowerSystem, ACPowerFlow}","page":"Power and Current Analysis","title":"JuliaGrid.generatorPower","text":"generatorPower(system::PowerSystem, analysis::AC)\n\nThe function returns the active and reactive powers associated with a specific generator in the AC framework. The label keyword argument must match an existing generator label.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\nactive, reactive = generatorPower(system, analysis; label = 1)\n\n\n\n\n\n","category":"method"},{"location":"api/analysis/","page":"Power and Current Analysis","title":"Power and Current Analysis","text":"","category":"page"},{"location":"api/analysis/#ACCurrentAnalysisAPI","page":"Power and Current Analysis","title":"AC Current Analysis","text":"","category":"section"},{"location":"api/analysis/","page":"Power and Current Analysis","title":"Power and Current Analysis","text":"current!(::PowerSystem, ::AC)\ninjectionCurrent(::PowerSystem, ::AC)\nfromCurrent(::PowerSystem, ::AC)\ntoCurrent(::PowerSystem, ::AC)\nseriesCurrent(::PowerSystem, ::AC)","category":"page"},{"location":"api/analysis/#JuliaGrid.current!-Tuple{PowerSystem, AC}","page":"Power and Current Analysis","title":"JuliaGrid.current!","text":"current!(system::PowerSystem, analysis::AC)\n\nThe function computes the currents in the polar coordinate system associated with buses and branches in the AC framework.\n\nUpdates\n\nThis function calculates various electrical quantities in the polar coordinate system:\n\ninjection: Current injections at each bus.\nfrom: Current flows at each from-bus end of the branch.\nto: Current flows at each to-bus end of the branch.\nseries: Current flows through the series impedance of the branch in the direction from the from-bus end to the to-bus end of the branch.\n\nExample\n\nusing Ipopt\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = acOptimalPowerFlow(system, Ipopt.Optimizer)\nsolve!(system, analysis)\ncurrent!(system, analysis)\n\n\n\n\n\n","category":"method"},{"location":"api/analysis/#JuliaGrid.injectionCurrent-Tuple{PowerSystem, AC}","page":"Power and Current Analysis","title":"JuliaGrid.injectionCurrent","text":"injectionCurrent(system::PowerSystem, analysis::AC; label)\n\nThe function returns the current injection in the polar coordinate system associated with a specific bus in the AC framework. The label keyword argument must match an existing bus label.\n\nExample\n\nusing Ipopt\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = acOptimalPowerFlow(system, Ipopt.Optimizer)\nsolve!(system, analysis)\nmagnitude, angle = injectionCurrent(system, analysis; label = 1)\n\n\n\n\n\n","category":"method"},{"location":"api/analysis/#JuliaGrid.fromCurrent-Tuple{PowerSystem, AC}","page":"Power and Current Analysis","title":"JuliaGrid.fromCurrent","text":"fromCurrent(system::PowerSystem, analysis::AC; label)\n\nThe function returns the current in the polar coordinate system at the from-bus end associated with a specific branch in the AC framework. The label keyword argument must match an existing branch label.\n\nExample\n\nusing Ipopt\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = acOptimalPowerFlow(system, Ipopt.Optimizer)\nsolve!(system, analysis)\nmagnitude, angle = fromCurrent(system, analysis; label = 2)\n\n\n\n\n\n","category":"method"},{"location":"api/analysis/#JuliaGrid.toCurrent-Tuple{PowerSystem, AC}","page":"Power and Current Analysis","title":"JuliaGrid.toCurrent","text":"toCurrent(system::PowerSystem, analysis::AC; label)\n\nThe function returns the current in the polar coordinate system at the to-bus end associated with a specific branch in the AC framework. The label keyword argument must match an existing branch label.\n\nExample\n\nusing Ipopt\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = acOptimalPowerFlow(system, Ipopt.Optimizer)\nsolve!(system, analysis)\nmagnitude, angle = toCurrent(system, analysis; label = 2)\n\n\n\n\n\n","category":"method"},{"location":"api/analysis/#JuliaGrid.seriesCurrent-Tuple{PowerSystem, AC}","page":"Power and Current Analysis","title":"JuliaGrid.seriesCurrent","text":"seriesCurrent(system::PowerSystem, analysis::AC; label)\n\nThe function returns the current in the polar coordinate system through series impedance associated with a specific branch in the direction from the from-bus end to the to-bus end of the branch within the AC framework. The label keyword argument must match an existing branch label.\n\nExample\n\nusing Ipopt\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = acOptimalPowerFlow(system, Ipopt.Optimizer)\nsolve!(system, analysis)\nmagnitude, angle = seriesCurrent(system, analysis; label = 2)\n\n\n\n\n\n","category":"method"},{"location":"api/analysis/","page":"Power and Current Analysis","title":"Power and Current Analysis","text":"","category":"page"},{"location":"api/analysis/#DCPowerAnalysisAPI","page":"Power and Current Analysis","title":"DC Power Analysis","text":"","category":"section"},{"location":"api/analysis/","page":"Power and Current Analysis","title":"Power and Current Analysis","text":"power!(::PowerSystem, ::DCPowerFlow)\ninjectionPower(::PowerSystem, ::DCPowerFlow)\nsupplyPower(::PowerSystem, ::DCPowerFlow)\nfromPower(::PowerSystem, ::DC)\ntoPower(::PowerSystem, ::DC)\ngeneratorPower(::PowerSystem, ::DCPowerFlow)","category":"page"},{"location":"api/analysis/#JuliaGrid.power!-Tuple{PowerSystem, DCPowerFlow}","page":"Power and Current Analysis","title":"JuliaGrid.power!","text":"power!(system::PowerSystem, analysis::DC)\n\nThe function calculates the active power values related to buses, branches, and generators within the DC analysis framework.\n\nUpdates\n\nThis function updates the power field of the DC abstract type by computing the following electrical quantities:\n\ninjection: Active power injections at each bus.\nsupply: Active power injections from the generators at each bus.\nfrom: Active power flows at each from-bus end of the branch.\nto: Active power flows at each to-bus end of the branch.\ngenerator: Output active powers of each generator (excluding for state estimation).\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndcModel!(system)\n\nanalysis = dcPowerFlow(system)\nsolve!(system, analysis)\npower!(system, analysis)\n\n\n\n\n\n","category":"method"},{"location":"api/analysis/#JuliaGrid.injectionPower-Tuple{PowerSystem, DCPowerFlow}","page":"Power and Current Analysis","title":"JuliaGrid.injectionPower","text":"injectionPower(system::PowerSystem, analysis::DC; label)\n\nThe function returns the active power injection associated with a specific bus in the DC framework. The label keyword argument must match an existing bus label.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndcModel!(system)\n\nanalysis = dcPowerFlow(system)\nsolve!(system, analysis)\ninjection = injectionPower(system, analysis; label = 2)\n\n\n\n\n\n","category":"method"},{"location":"api/analysis/#JuliaGrid.supplyPower-Tuple{PowerSystem, DCPowerFlow}","page":"Power and Current Analysis","title":"JuliaGrid.supplyPower","text":"supplyPower(system::PowerSystem, analysis::DC; label)\n\nThe function returns the active power injection from the generators associated with a specific bus in the DC framework. The label keyword argument must match an existing bus label.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndcModel!(system)\n\nanalysis = dcPowerFlow(system)\nsolve!(system, analysis)\nsupply = supplyPower(system, analysis; label = 2)\n\n\n\n\n\n","category":"method"},{"location":"api/analysis/#JuliaGrid.fromPower-Tuple{PowerSystem, DC}","page":"Power and Current Analysis","title":"JuliaGrid.fromPower","text":"fromPower(system::PowerSystem, analysis::DC; label)\n\nThe function returns the active power flow at the from-bus end associated with a specific branch in the DC framework. The label keyword argument must match an existing branch label.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndcModel!(system)\n\nanalysis = dcPowerFlow(system)\nsolve!(system, analysis)\nfrom = fromPower(system, analysis; label = 2)\n\n\n\n\n\n","category":"method"},{"location":"api/analysis/#JuliaGrid.toPower-Tuple{PowerSystem, DC}","page":"Power and Current Analysis","title":"JuliaGrid.toPower","text":"toPower(system::PowerSystem, analysis::DC; label)\n\nThe function returns the active power flow at the to-bus end associated with a specific branch in the DC framework. The label keyword argument must match an existing branch label.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndcModel!(system)\n\nanalysis = dcPowerFlow(system)\nsolve!(system, analysis)\nto = toPower(system, analysis; label = 2)\n\n\n\n\n\n","category":"method"},{"location":"api/analysis/#JuliaGrid.generatorPower-Tuple{PowerSystem, DCPowerFlow}","page":"Power and Current Analysis","title":"JuliaGrid.generatorPower","text":"generatorPower(system::PowerSystem, analysis::DC; label)\n\nThis function returns the output active power associated with a specific generator in the DC framework. The label keyword argument must match an existing generator label.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndcModel!(system)\n\nanalysis = dcPowerFlow(system)\nsolve!(system, analysis)\ngenerator = generatorPower(system, analysis; label = 1)\n\n\n\n\n\n","category":"method"},{"location":"tutorials/dcStateEstimation/#DCStateEstimationTutorials","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"section"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"To initiate the process, let us construct the PowerSystem type and formulate the DC model:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = 1, type = 3, angle = 0.0)\naddBus!(system; label = 2, type = 1, active = 0.1)\naddBus!(system; label = 3, type = 1, active = 1.3)\naddBranch!(system; label = 1, from = 1, to = 2, reactance = 0.2)\naddBranch!(system; label = 2, from = 1, to = 3, reactance = 0.1)\naddBranch!(system; label = 3, from = 2, to = 3, reactance = 0.3)\naddGenerator!(system; label = 1, bus = 1, active = 3.2)\n\ndcModel!(system)\nnothing # hide","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"To review, we can conceptualize the bus/branch model as the graph denoted by mathcalG = (mathcalN mathcalE), where we have the set of buses mathcalN = 1 dots n, and the set of branches mathcalE subseteq mathcalN times mathcalN within the power system:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"𝒩 = collect(keys(system.bus.label))\nℰ = [𝒩[system.branch.layout.from] 𝒩[system.branch.layout.to]]","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Following that, we will introduce the Measurement type and incorporate a set of measurement devices mathcalM into the graph mathcalG. In typical scenarios, the DC state estimation model relies solely on active power measurements originating from the set of wattmeters mathcalP. However, we provide the option for users to include measurements from the set of PMUs barmathcalP. Specifically, we utilize only the PMUs installed at the buses barmathcalP_textb subset barmathcalP that measure bus voltage angles. This process of adding measurement devices will be carried out in the State Estimation Model section. Currently, we are only initializing the Measurement type:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"device = measurement()\nnothing # hide","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"ukw: Notation\nHere, when referring to a vector mathbfa, we use the notation mathbfa = a_i or mathbfa = a_ij, where a_i represents the element related with bus i in mathcalN or measurement i in mathcalM, while a_ij denotes the element related with branch (ij) in mathcalE.","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/#DCSEModelTutorials","page":"DC State Estimation","title":"State Estimation Model","text":"","category":"section"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"In accordance with the DC Model, the DC state estimation is derived through the linearization of the non-linear model. In this linearized model, all bus voltage magnitudes are assumed to be V_i approx 1, i in mathcalN. Additionally, shunt elements and branch resistances are neglected. This simplification implies that the DC model disregards reactive powers and transmission losses, focusing solely on active powers. Consequently, the DC state estimation considers only bus voltage angles, represented as mathbf x equiv bm Theta, as the state variables. As a result, the total number of state variables is n-1, with one voltage angle corresponding to the slack bus.","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Within the JuliaGrid framework for DC state estimation, the methodology encompasses both active power flow and injection measurements from the set mathcalP, along with bus voltage angle measurements represented by the set barmathcalP_textb. These measurements contribute to the construction of a linear system of equations:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" mathbfz=mathbfh(bm Theta)+mathbfu","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"where mathbfh(bm Theta)= h_1(bm Theta), dots, h_k(bm Theta)^T is the vector of linear measurement functions, mathbfz = z_1dotsz_k^mathrmT is the vector of measurement values, and mathbfu = u_1dotsu_k^mathrmT is the vector of uncorrelated measurement errors, and this defines the vector of measurement variances mathbfv = v_1dotsv_k^mathrmT, where k = mathcalM.","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Therefore, the linear system of equations can be represented based on the specific devices from which measurements originate, whether wattmeters or PMUs:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" beginbmatrix\n mathbfz_mathcalP3pt\n mathbfz_barmathcalP_textb\n endbmatrix =\n beginbmatrix\n mathbfh_mathcalP(bm Theta)3pt\n mathbfh_barmathcalP_textb(bm Theta)\n endbmatrix +\n beginbmatrix\n mathbfu_mathcalP3pt\n mathbfu_barmathcalP_textb\n endbmatrix","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"In summary, upon user definition of the measurement devices, each i-th measurement device is linked to the measurement function h_i(bm Theta), the corresponding measurement value z_i, and the measurement variance v_i.","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/#Active-Power-Injection-Measurements","page":"DC State Estimation","title":"Active Power Injection Measurements","text":"","category":"section"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"When adding a wattmeter P_i in mathcalP at bus i in mathcalN, users specify that the wattmeter measures active power injection and define measurement value, variance and measurement function of vectors:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" mathbfz_mathcalP = z_P_i mathbfv_mathcalP = v_P_i mathbfh_mathcalP(bm Theta) = h_P_i(bm Theta)","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"For example:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"addWattmeter!(system, device; label = \"P₃\", bus = 3, active = -1.30, variance = 1e-3)\nnothing # hide","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Here, utilizing the DC Model, we derive the function defining the active power injection as follows:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" h_P_i(bm Theta) = B_iitheta_i + sum_j in mathcalN_i setminus i B_ij theta_j + P_texttri + P_textshi","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"where mathcalN_i setminus i contains buses incident to bus i, excluding bus i, with the following coefficient expressions:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" beginaligned\n cfracmathrm partialh_P_i(bm Theta)mathrm partial theta_i = B_ii \n cfracmathrm partialh_P_i(bm Theta)mathrm partial theta_j = B_ij\n endaligned","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/#From-Bus-End-Active-Power-Flow-Measurements","page":"DC State Estimation","title":"From-Bus End Active Power Flow Measurements","text":"","category":"section"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Additionally, when introducing a wattmeter at branch (ij) in mathcalE, users specify that the wattmeter measures active power flow. It can be positioned at the from-bus end, denoted as P_ij in mathcalP, specifying the measurement value, variance and measurement function of vectors:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" mathbfz_mathcalP = z_P_ij mathbfv_mathcalP = v_P_ij mathbfh_mathcalP(bm Theta) = h_P_ij(bm Theta)","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"For example:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"addWattmeter!(system, device; label = \"P₁₂\", from = 1, active = 0.28, variance = 1e-4)\nnothing # hide","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Here, the function describing active power flow at the from-bus end is defined as follows:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" h_P_ij(bm Theta) = cfrac1tau_ij x_ij (theta_i -theta_j-phi_ij)","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"with the following coefficient expressions:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" beginaligned\n cfracmathrm partialh_P_ij(bm Theta)mathrm partial theta_i = cfrac1tau_ij x_ij \n cfracmathrm partialh_P_ij(bm Theta)mathrm partial theta_j = -cfrac1tau_ij x_ij\n endaligned","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/#To-Bus-End-Active-Power-Flow-Measurements","page":"DC State Estimation","title":"To-Bus End Active Power Flow Measurements","text":"","category":"section"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Similarly, a wattmeter can be placed at the to-bus end, denoted as P_ji in mathcalP, specifying the measurement value, variance and measurement function of vectors:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" mathbfz_mathcalP = z_P_ji mathbfv_mathcalP = v_P_ji mathbfh_mathcalP(bm Theta) = h_P_ji(bm Theta)","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"For example:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"addWattmeter!(system, device; label = \"P₂₁\", to = 1, active = -0.28, variance = 1e-4)\nnothing # hide","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Thus, the function describing active power flow at the to-bus end is defined as follows:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" h_P_ji(bm Theta) = -cfrac1tau_ij x_ij (theta_i -theta_j-phi_ij)","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"with the following coefficient expressions:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" cfracmathrm partialh_P_ji(bm Theta)mathrm partial theta_i = -cfrac1tau_ij x_ij \n cfracmathrm partialh_P_ji(bm Theta)mathrm partial theta_j = cfrac1tau_ij x_ij","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/#Bus-Voltage-Angle-Measurements","page":"DC State Estimation","title":"Bus Voltage Angle Measurements","text":"","category":"section"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"If the user opts to include phasor measurements that measure bus voltage angle at bus i in mathcalN, denoted as theta_i in barmathcalP_textb, the user will specify the measurement values, variances, and measurement functions of vectors:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" mathbfz_barmathcalP_textb = z_theta_i mathbfv_barmathcalP_textb = v_theta_i mathbfh_barmathcalP_textb(bm Theta) = h_theta_i(bm Theta)","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"For example:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"addPmu!(system, device; label = \"V₁, θ₁\", bus = 1, magnitude = 1.0, angle = 0,\nvarianceMagnitude = 1e-5, varianceAngle = 1e-6)\nnothing # hide","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Here, the function defining the bus voltage angle measurement is straightforward:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" h_theta_i(bm Theta) = theta_i","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"with the following coefficient expression:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" cfracmathrm partialh_theta_i(bm Theta)mathrm partial theta_i=1","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/#DCSEWLSStateEstimationTutorials","page":"DC State Estimation","title":"Weighted Least-Squares Estimation","text":"","category":"section"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"The solution to the DC state estimation problem is determined by solving the linear weighted least-squares (WLS) problem, represented by the following formula:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"\tmathbf H^T bm Sigma^-1 mathbf H bm Theta = mathbf H^T bm Sigma^-1 (mathbf z - mathbfc)","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Here, mathbf z in mathbb R^k denotes the vector of measurement values, the vector mathbf c in mathbb R^k holds constant terms, mathbf H in mathbb R^k times (n-1) represents the coefficient matrix, and bm Sigma in mathbb R^k times k is the measurement error covariance matrix, where the diagonal elements hold measurement variances.","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"The inclusion of the vector mathbfc is necessary due to the fact that measurement functions associated with active power measurements may include constant terms, especially when there are non-zero shift angles of transformers or shunt elements in the system consuming active powers, as evident from the provided measurement functions.","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/#Implementation","page":"DC State Estimation","title":"Implementation","text":"","category":"section"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"JuliaGrid initiates the DC state estimation framework by setting up the WLS model, as illustrated in the following:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"analysis = dcStateEstimation(system, device)\nnothing # hide","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/#Coefficient-Matrix","page":"DC State Estimation","title":"Coefficient Matrix","text":"","category":"section"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Using the above-described equations, JuliaGrid forms the coefficient matrix mathbfH in mathbbR^k times (n-1):","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"𝐇 = analysis.method.coefficient","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Each row in the matrix corresponds to a specific measurement. The first mathcalP rows correspond to wattmeters, ordered as users add wattmeters, while the last barmathcalP_textb rows correspond to PMUs, also in the order users add PMUs.","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/#Precision-Matrix","page":"DC State Estimation","title":"Precision Matrix","text":"","category":"section"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"JuliaGrid opts not to retain the covariance matrix bm Sigma but rather stores its inverse, the precision or weighting matrix denoted as mathbf W = bm Sigma^-1. The order of these values corresponds to the description provided for the coefficient matrix. Users can access these values using the following command:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"𝐖 = analysis.method.precision","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/#Mean-Vector","page":"DC State Estimation","title":"Mean Vector","text":"","category":"section"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Users can access the vector mathbf z - mathbfc, which contains the means of Gaussian distributions describing each measurement, using the following command:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"𝐳 = analysis.method.mean","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"In the context of the power system, where phase-shifting transformers and shunt elements consuming active powers are absent, and the slack angle has a zero value, the vector mathbfc= mathbf0. Consequently, the vector of means holds values that are equal to the measurement values.","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/#Estimate-of-State-Variables","page":"DC State Estimation","title":"Estimate of State Variables","text":"","category":"section"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Once the model is established, we solve the WLS equation to derive the estimate of bus voltage angles:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"\thatbm Theta = mathbf H^T bm Sigma^-1 mathbf H^-1 mathbf H^T bm Sigma^-1 (mathbf z - mathbfc)","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"This process is executed using the solve! function:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"solve!(system, analysis)","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"The initial step involves the LU factorization of the gain matrix:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"\tmathbf G = mathbf H^T bm Sigma^-1 mathbf H = mathbf L mathbf U","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"tip: Tip\nBy default, JuliaGrid utilizes LU factorization as the primary method to factorize the gain matrix. However, users maintain the flexibility to opt for alternative factorization methods such as LDLt or QR.","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Access to the factorized gain matrix is available through:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"𝐋 = analysis.method.factorization.L\n𝐔 = analysis.method.factorization.U","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Finally, the estimated bus voltage angles hatbm Theta = hattheta_i, i in mathcalN, can be retrieved using the variable:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"𝚯 = analysis.voltage.angle","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"It is essential to note that the slack bus voltage angle is temporarily excluded from the gain matrix mathbf G during computation. It is important to emphasize that this internal handling does not alter the stored elements.","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/#DCSEOrthogonalWLSStateEstimationTutorials","page":"DC State Estimation","title":"Alternative Formulation","text":"","category":"section"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"The resolution of the WLS state estimation problem using the conventional method typically progresses smoothly. However, it is widely acknowledged that in certain situations common to real-world systems, this method can be vulnerable to numerical instabilities. Such conditions might impede the algorithm from converging to a satisfactory solution. In such cases, users may opt for an alternative formulation of the WLS state estimation, namely, employing an approach called orthogonal factorization [5, Sec. 3.2].","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"To address ill-conditioned situations arising from significant differences in measurement variances, users can employ an alternative approach:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"analysis = dcStateEstimation(system, device, Orthogonal)\nnothing # hide","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"To explain the method, we begin with the WLS equation:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"\tmathbf H^T mathbf W mathbf H bm Theta = mathbf H^T mathbf W (mathbf z - mathbfc)","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"where mathbf W = bm Sigma^-1. Subsequently, we can write:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" left(mathbf W^12 mathbf Hright)^T mathbf W^12 mathbf H bm Theta = left(mathbf W^12 mathbf Hright)^T mathbf W^12 (mathbf z - mathbfc)","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Consequently, we have:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" barmathbfH^T barmathbfH bm Theta = barmathbfH^T barmathbfz","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"where:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" barmathbfH = mathbf W^12 mathbf H barmathbfz = mathbf W^12 (mathbf z - mathbfc)","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"At this point, QR factorization is performed on the rectangular matrix:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" barmathbfH = mathbf W^12 mathbf H = mathbfQmathbfR","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Executing this procedure involves the solve! function:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"solve!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Access to the factorized matrix is possible through:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"𝐐 = analysis.method.factorization.Q\n𝐑 = analysis.method.factorization.R","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"To obtain the solution, JuliaGrid avoids materializing the orthogonal matrix mathbfQ and proceeds to solve the system, resulting in the estimate of state variables hatbm Theta = hattheta_i, where i in mathcalN:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"𝚯 = analysis.voltage.angle","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/#DCSEBadDataTutorials","page":"DC State Estimation","title":"Bad Data Processing","text":"","category":"section"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Besides the state estimation algorithm, one of the essential state estimation routines is the bad data processing, whose main task is to detect and identify measurement errors, and eliminate them if possible. This is usually done by processing the measurement residuals [5, Ch. 5], and typically, the largest normalized residual test is used to identify bad data. The largest normalized residual test is performed after we obtained the solution of the state estimation in the repetitive process of identifying and eliminating bad data measurements one after another [19].","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"To illustrate this process, let us introduce a new measurement that contains an obvious outlier:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"addWattmeter!(system, device; label = \"P₁\", bus = 1, active = 13.1, variance = 1e-4)\nnothing # hide","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Subsequently, we will construct the WLS state estimation model and solve it:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"analysis = dcStateEstimation(system, device)\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Now, the bad data processing can be executed:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"outlier = residualTest!(system, device, analysis; threshold = 4.0)\nnothing # hide","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"In this step, we employ the largest normalized residual test, guided by the analysis outlined in [5, Sec. 5.7]. To be more precise, we compute all measurement residuals based on the obtained estimate of state variables:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" r_i = z_i - h_i(hat bm Theta) i in mathcalM","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"The normalized residuals for all measurements are computed as follows:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" barr_i = cfracr_isqrtC_ii = cfracr_isqrtS_iiSigma_ii i in mathcalM","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"In this equation, we denote the diagonal entries of the residual covariance matrix mathbf C in mathbbR^k times k as C_ii = S_iiSigma_ii, where S_ii is the diagonal entry of the residual sensitivity matrix mathbf S representing the sensitivity of the measurement residuals to the measurement errors. For this specific configuration, the relationship is expressed as:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" mathbf C = mathbf S bm Sigma = bm Sigma - mathbf H mathbf H^T bm Sigma^-1 mathbf H^-1 mathbf H^T","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"It is important to note that only the diagonal entries of mathbf C are required. To obtain the inverse, the JuliaGrid package utilizes a computationally efficient sparse inverse method, retrieving only the necessary elements of the inverse.","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"The subsequent step involves selecting the largest normalized residual, and the j-th measurement is then suspected as bad data and potentially removed from the measurement set mathcalM:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" barr_j = textmax barr_i i in mathcalM ","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Users can access this information using the variable:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"outlier.maxNormalizedResidual","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"If the largest normalized residual, denoted as barr_j, satisfies the inequality:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" barr_j ge epsilon","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"the corresponding measurement is identified as bad data and subsequently removed. In this example, the bad data identification threshold is set to epsilon = 4. Users can verify the satisfaction of this inequality by inspecting the variable:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"outlier.detect","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"This indicates that the measurement labeled as:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"outlier.label","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"is removed from the DC model and marked as out-of-service.","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Subsequently, we can immediately solve the system again, but this time without the removed measurement:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"solve!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Following that, we check for outliers once more:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"outlier = residualTest!(system, device, analysis; threshold = 4.0)\nnothing # hide","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"To examine the value:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"outlier.maxNormalizedResidual","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"As this value is now less than the threshold epsilon = 4, the measurement is not removed, or there are no outliers. This can also be verified by observing the bad data flag:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"outlier.detect","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/#DCSELAVTutorials","page":"DC State Estimation","title":"Least Absolute Value Estimation","text":"","category":"section"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"The least absolute value (LAV) method provides an alternative estimation approach that is considered more robust in comparison to the WLS method. The WLS state estimation problem relies on specific assumptions about measurement errors, whereas robust estimators aim to remain unbiased even in the presence of various types of measurement errors and outliers. This characteristic eliminates the need for bad data processing, as discussed in [5, Ch. 6]. It is important to note that robustness often comes at the cost of increased computational complexity.","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"It can be demonstrated that the problem can be expressed as a linear programming problem. This section outlines the method as described in [5, Sec. 6.5]. To revisit, we consider the system of linear equations:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" mathbfz=mathbfh(bm Theta)+mathbfu","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Subsequently, the LAV state estimator is derived as the solution to the optimization problem:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" beginaligned\n textminimize mathbf a^T mathbf r\n textsubjectto mathbfz - mathbfHbm Theta - mathbfc =mathbf r\n endaligned","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Here, mathbf a in mathbb R^k is the vector with all entries equal to one, and mathbf r represents the vector of measurement residuals. Let bm eta be defined in a manner that ensures:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" mathbf r preceq bm eta","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"and replace the above inequality with two equalities using the introduction of two non-negative slack variables mathbf q in mathbb R_ge 0^k and mathbf w in mathbb R_ge 0^k:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" beginaligned\n mathbf r - mathbf q = -bm eta \n mathbf r + mathbf w = bm eta\n endaligned","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Let us now define four additional non-negative variables:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" bm Theta_x in mathbb R_ge 0^n bm Theta_y in mathbb R_ge 0^n \n mathbf r_x in mathbb R_ge 0^k mathbf r_y in mathbb R_ge 0^k","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"where:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" bm Theta = bm Theta_x - bm Theta_y mathbf r = mathbf r_x - mathbf r_y\n mathbf r_x = cfrac12 mathbf q mathbf r_y = cfrac12 mathbf w","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Then, the above two equalities become:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" beginaligned\n mathbf r - 2mathbf r_x = -2bm eta \n mathbf r + 2 mathbf r_y = 2bm eta\n endaligned","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"that is:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" beginaligned\n mathbf r_x + mathbf r_y = bm eta mathbf r = mathbf r_x - mathbf r_y\n endaligned","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Hence, the optimization problem can be written:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" beginaligned\n textminimize mathbf a^T (mathbf r_x + mathbf r_y)\n textsubjectto mathbfH(bm Theta_x - bm Theta_y) + mathbf r_x - mathbf r_y = mathbfz - mathbfc \n bm Theta_x succeq mathbf 0 bm Theta_y succeq mathbf 0 \n mathbf r_x succeq mathbf 0 mathbf r_y succeq mathbf 0\n endaligned","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"To form the above optimization problem, the user can call the following function:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"using Ipopt\nusing JuMP # hide\n\nanalysis = dcLavStateEstimation(system, device, Ipopt.Optimizer)\nnothing # hide","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Then the user can solve the optimization problem by:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"JuMP.set_silent(analysis.method.jump) # hide\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"As a result, we obtain optimal values for the four additional non-negative variables, while the state estimator is obtained by:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" hatbm Theta = bm Theta_x - bm Theta_y","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Users can retrieve the estimated bus voltage angles hatbm Theta = hattheta_i, i in mathcalN, using the variable:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"𝚯 = analysis.voltage.angle","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/#DCSEPowerAnalysisTutorials","page":"DC State Estimation","title":"Power Analysis","text":"","category":"section"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"After obtaining the solution from the DC state estimation, we can calculate powers related to buses and branches using the power! function:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"power!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"note: Info\nFor a clear comprehension of the equations, symbols provided below, as well as for a better grasp of power directions, please refer to the Unified Branch Model.","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/#Power-Injections","page":"DC State Estimation","title":"Power Injections","text":"","category":"section"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Active power injections are stored as the vector mathbfP = P_i, and can be retrieved using the following commands:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"𝐏 = analysis.power.injection.active","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/#Generator-Power-Injections","page":"DC State Estimation","title":"Generator Power Injections","text":"","category":"section"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"We can determine the active power supplied by generators to the buses by summing the active power injections and the active power demanded by consumers at each bus:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":" P_textpi = P_i + P_textdi i in mathcalN","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"The vector of active power injected by generators into the buses, denoted by mathbfP_textp = P_textpi, can be obtained using:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"𝐏ₚ = analysis.power.supply.active","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"tutorials/dcStateEstimation/#Power-Flows","page":"DC State Estimation","title":"Power Flows","text":"","category":"section"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"The resulting active power flows are stored as the vector mathbfP_texti = P_ij, which can be retrieved using:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"𝐏ᵢ = analysis.power.from.active","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Similarly, the resulting active power flows are stored as the vector mathbfP_textj = P_ji, which can be retrieved using:","category":"page"},{"location":"tutorials/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"𝐏ⱼ = analysis.power.to.active","category":"page"},{"location":"tutorials/powerSystemModel/#ACDCModelTutorials","page":"Power System Model","title":"Power System Model","text":"","category":"section"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Power system analyses commonly utilize the unified branch model that provides linear relationships between voltages and currents. However, as the focus is on power calculations rather than current calculations, the resulting equations become nonlinear, posing challenges in solving them [6]. Hence, to accurately analyze power systems without any approximations, we use the AC model, which is a crucial component of our framework. In contrast, to obtain a linear system of equations for various DC analyses, we introduce approximations in the unified branch model, resulting in the DC model.","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"note: Info\nIn this section, we not only describe the AC and DC models derived from the unified branch model but also furnish the power and current equations utilized in all JuliaGrid analyses.","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"A common way to describe the power system network topology is through the bus/branch model, which employs the two-port pi-model, which results in the unified branch model. The bus/branch model can be represented by a graph denoted by mathcalG = (mathcalN mathcalE), where the set of nodes mathcalN = 1 dots n corresponds to buses, and the set of edges mathcalE subseteq mathcalN times mathcalN represents the branches of the power network.","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Let us now construct the power system:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n@labels(Integer)\n\n@power(MW, MVAr, MVA)\n@voltage(pu, deg, V)\n\nsystem = powerSystem()\n\naddBus!(system; label = 1, type = 3)\naddBus!(system; label = 2, type = 1, active = 21.7, reactive = 12.7)\naddBus!(system; label = 3, type = 2, conductance = 2.1, susceptance = 1.2)\n\naddBranch!(system; from = 1, to = 2, resistance = 0.02, reactance = 0.06, susceptance = 0.05)\naddBranch!(system; from = 2, to = 3, reactance = 0.21, turnsRatio = 0.98, shiftAngle = 1.2)\n\naddGenerator!(system; bus = 1, active = 40.0, reactive = 42.4)\nnothing #hide","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The given example provides the set of buses mathcalN and the set of branches mathcalE:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"𝒩 = collect(keys(system.bus.label))\nℰ = [𝒩[system.branch.layout.from] 𝒩[system.branch.layout.to]]","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"ukw: Notation\nIn this section, when referring to a vector mathbfa, we use the notation mathbfa = a_ij, where a_ij represents the generic element associated with the branch (ij) in mathcalE.","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"tutorials/powerSystemModel/#ACModelTutorials","page":"Power System Model","title":"AC Model","text":"","category":"section"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"JuliaGrid is based on common network elements and benefits from the unified branch model to perform various analyses based on the system of nonlinear equations. To generate matrices and vectors for AC or nonlinear analysis, JuliaGrid employs the acModel! function:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"acModel!(system)\nnothing #hide","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"tutorials/powerSystemModel/#UnifiedBranchModelTutorials","page":"Power System Model","title":"Unified Branch Model","text":"","category":"section"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The equivalent unified pi-model for a branch (ij) in mathcalE incident to the buses ij in mathcalN is shown in Figure 1.","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"\n
Figure 1: The equivalent branch model, where the transformer is located at the from-bus end of the branch.
\n ","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"note: Info\nThe directions of the currents barI_ij, barI_ji, barI_textsi, and barI_textsj are vital for power flow analysis. Positive power aligns with the assumed current direction, moving away from the bus, while negative power implies a reverse flow towards the bus. JuliaGrid consistently uses these directions, along with barI_textlij, for power and current calculations.","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The branch series admittance y_ij is inversely proportional to the branch series impedance z_ij:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" y_ij = frac1z_ij = frac1r_ij + textjx_ij =\n fracr_ijr_ij^2 + x_ij^2 - textjfracx_ijr_ij^2 + x_ij^2 = g_ij + textjb_ij","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"where r_ij is a resistance, x_ij is a reactance, g_ij is a conductance and b_ij is a susceptance of the branch.","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The vectors of resistances, denoted by mathbfr = r_ij, and reactances, denoted by mathbfx = x_ij, are stored in the variables:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"𝐫 = system.branch.parameter.resistance\n𝐱 = system.branch.parameter.reactance","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Moreover, the ac field stores the computed vector of branch series admittances mathbfy = y_ij:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"𝐲 = system.model.ac.admittance","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The branch shunt admittance y_textsij is equal to:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"y_textsij = g_textsij + textjb_textsij","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"where g_textsij represents the shunt conductance of the branch, and b_textsij represents the shunt susceptance. Both of these values are positive for real line sections. It is worth noting that while the shunt conductance g_textsij is often insignificantly small and can be ignored in many cases, it is included in the analyses to ensure comprehensive consideration of all potential scenarios.","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Within JuliaGrid, the total shunt conductances and susceptances of branches are stored. In order to obtain the vectors mathbfg_texts = g_textsij and mathbfb_texts = b_textsij, the conductances and susceptances must be distributed by considering the ends of the branches:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"𝐠ₛ = 0.5 * system.branch.parameter.conductance\n𝐛ₛ = 0.5 * system.branch.parameter.susceptance","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The transformer complex ratio alpha_ij is defined:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" alpha_ij = cfrac1tau_ije^-textjphi_ij","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"where tau_ij neq 0 is a transformer turns ratio, while phi_ij is a transformer phase shift angle, always located at the from-bus end of the branch. Note, if tau_ij = 1 and phi_ij = 0 the model describes the line. In-phase transformers are defined if tau_ij neq 1, phi_ij = 0, and y_textsij = 0, while phase-shifting transformers are obtained if tau_ij neq 1, phi_ij neq 0, and y_textsij = 0.","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"These transformer parameters are stored in the vectors bmtau = tau_ij and bmphi = phi_ij, respectively:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"𝛕 = system.branch.parameter.turnsRatio\n𝚽 = system.branch.parameter.shiftAngle","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"tutorials/powerSystemModel/#BranchShuntElementsTutorials","page":"Power System Model","title":"Branch Shunt Elements","text":"","category":"section"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The currents flowing through shunt admittances denoted as y_textsij are defined as follows:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" beginaligned\n barI_textsi = alpha_ij y_textsijbarV_i (ij) in mathcalE \n barI_textsj = y_textsijbarV_j (ij) in mathcalE\n endaligned","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"With these specified currents in place, it becomes straightforward to compute both the total active and reactive power that branch shunt elements demand and inject concerning the power system:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" S_textsij = P_textsij + textjQ_textsij = alpha_ij barV_i barI_textsi^* + barV_j barI_textsj^* = y_textsij^*(alpha_ij^2 V_i^2 + V_j^2) (ij) in mathcalE","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"For real branch sections, the reactive power is negative, Q_textsij 0, signifying that the branch injects reactive power due to its capacitive nature. The negative sign implies that the power flow direction opposes the assumed direction set by the currents barI_textsi and barI_textsj. The active power P_textsij represents active losses within the branch shunt admittances.","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"tutorials/powerSystemModel/#BranchSeriesElementTutorials","page":"Power System Model","title":"Branch Series Element","text":"","category":"section"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The current flowing through a series admittance, denoted as y_ij, is defined as follows:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" barI_textlij = alpha_ij y_ijbarV_i - y_ijbarV_i (ij) in mathcalE","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Consequently, the active and reactive powers associated with the branch series element are as follows:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" S_textlij = P_textlij + textjQ_textlij = (alpha_ij barV_i - barV_j) barI_textlij^* = y_ij^* (alpha_ij barV_i - barV_j) (alpha_ij barV_i - barV_j)^* (ij) in mathcalE","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The active power P_textlij accounts for losses originating from the resistance r_ij of the branch, while the reactive power Q_textlij represents losses resulting from the inductive characteristics of the impedance defined by reactance x_ij. This can be observed when the reactive power is positive Q_textlij 0.","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"tutorials/powerSystemModel/#BranchNetworkEquationsTutorials","page":"Power System Model","title":"Branch Network Equations","text":"","category":"section"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Using Kirchhoff's circuit laws, the branch model can be described by complex expressions:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" beginbmatrix\n barI_ij barI_ji\n endbmatrix =\n beginbmatrix\n cfrac1tau_ij^2(y_ij + y_textsij) -alpha_ij^*y_ij\n -alpha_ijy_ij y_ij + y_textsij\n endbmatrix\n beginbmatrix\n barV_i barV_j\n endbmatrix","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The admittance parameters are stored in the vectors mathbfy_textii = (y_ij + y_textsij) tau_ij^2, mathbfy_textij = -alpha_ij^*y_ij, mathbfy_textji = -alpha_ijy_ij, and mathbfy_textjj = y_ij + y_textsij and can be found in the variables:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"𝐲ᵢᵢ = system.model.ac.nodalFromFrom\n𝐲ᵢⱼ = system.model.ac.nodalFromTo\n𝐲ⱼᵢ = system.model.ac.nodalToFrom\n𝐲ⱼⱼ = system.model.ac.nodalToTo","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"In this context, we have easily derived the active and reactive power flow at the from-bus end of the branch:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" S_ij = P_ij + textjQ_ij = barV_i leftcfrac1tau_ij^2(y_ij + y_textsij) barV_i - alpha_ij^*y_ij barV_jright^* (ij) in mathcalE","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Similarly, we can determine the active and reactive power flow at the to-bus end of the branch:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" S_ji = P_ji + textjQ_ji = barV_j left-alpha_ijy_ij barV_i + (y_ij + y_textsij) barV_jright^* (ij) in mathcalE","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Positive values of active or reactive power, P_ij 0 or Q_ij 0, indicate power flow originating from the from-bus and moving towards the to-bus, following the direction of the current barI_ij. Conversely, negative values, P_ij 0 or Q_ij 0, signify power flow in the opposite direction. The same principles apply to P_ji 0 or Q_ji 0, indicating power flow from the to-bus to the from-bus, aligned with the current barI_ji, while negative values, P_ji 0 or Q_ji 0, denote the reverse flow direction.","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"tutorials/powerSystemModel/#NodalNetworkEquationsTutorials","page":"Power System Model","title":"Nodal Network Equations","text":"","category":"section"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Let us consider an illustrative example from our case study, depicted in Figure 2. This example provides a smooth transition to the general case, demonstrating a system with three buses represented as mathcalN = 1 2 3 and two branches mathcalE = (1 2) (2 3), where bus 2 is incident to the shunt element with admittance y_textsh2.","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"\n
Figure 2: The example of the system with three buses and two branches.
\n ","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"note: Info\nThe current barI_textsh2 follows the convention of coming out from the bus in terms of its direction. When calculating powers related to shunt elements, this current direction is assumed. Therefore, in cases where power is positive, it signifies alignment with the assumed current direction, emerging away from the bus. Conversely, when power is negative, the direction is reversed, indicating a flow towards the bus.","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"According to the Branch Network Equations each branch is described using the system of equations as follows:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" beginbmatrix\n barI_12 barI_21\n endbmatrix =\n beginbmatrix\n cfrac1tau_12^2(y_12 + y_texts12) -alpha_12^*y_12\n -alpha_12y_12 y_12 + y_texts12\n endbmatrix\n beginbmatrix\n barV_1 barV_2\n endbmatrix","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" beginbmatrix\n barI_23 barI_32\n endbmatrix =\n beginbmatrix\n cfrac1tau_23^2(y_23 + y_texts23) -alpha_23^*y_23\n -alpha_23y_23 y_23 + y_texts23\n endbmatrix\n beginbmatrix\n barV_2 barV_3\n endbmatrix","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The complex current injections at buses are:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" beginaligned\n barI_1 = barI_12 = cfrac1tau_12^2(y_12 + y_texts12) barV_1 -alpha_12^*y_12 barV_2 \n barI_2 = barI_21 + barI_23 + barI_textsh2 = -alpha_12y_12 barV_1 + (y_12 + y_texts12) barV_2 +\n cfrac1tau_23^2(y_23 + y_texts23) barV_2 -alpha_23^*y_23 barV_3 + y_textsh2 barV_2 \n barI_3 = barI_32 = -alpha_23y_23 barV_2 + (y_23 + y_texts23) barV_3\n endaligned","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The system of equations can be written in the matrix form:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" beginbmatrix\n barI_1 barI_2 barI_3\n endbmatrix =\n beginbmatrix\n cfrac1tau_12^2(y_12 + y_texts12) -alpha_12^*y_12 0 \n -alpha_12y_12 y_12 + y_texts12 + cfrac1tau_23^2(y_23 + y_texts23) + y_textsh2 -alpha_23^*y_23 \n 0 -alpha_23y_23 y_23 + y_texts23\n endbmatrix\n beginbmatrix\n barV_1 barV_2 barV_3\n endbmatrix","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"This system of equations can be generalized to accommodate the scenario where the set mathcalN comprises n buses:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" mathbf bar I = mathbfY mathbf bar V","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"where mathbf bar V in mathbbC^n is the vector of bus complex voltages, and mathbf bar I in mathbbC^n is the vector of complex current injections at buses. The matrix mathbfY = mathbfG + textjmathbfB in mathbbC^n times n is the bus or nodal admittance matrix, with elements:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"the diagonal elements, where i in mathcalN, are equal to:\nY_ii = G_ii + textjB_ii = y_textshi +\nsumlimits_e in mathcalE e(1) = i cfrac1tau_ij^2(y_ij + y_textsij) + sumlimits_e in mathcalE e(2) = i (y_ji + y_textsji)\nthe non-diagonal elements, where i = e(1) j = e(2) e in mathcalE, are equal to:\n beginaligned\n Y_ij = G_ij + textjB_ij = -alpha_ij^*y_ij 4pt\n Y_ji = G_ji + textjB_ji = -alpha_ijy_ij\n endaligned","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"When a branch is not incident (or adjacent) to a bus the corresponding element in the nodal admittance matrix mathbfY is equal to zero. The nodal admittance matrix mathbfY is sparse (i.e., a small number of elements are non-zeros) for real-world power systems. Although it is often assumed that the matrix mathbfY is symmetrical, it is not a general case. For example, in the presence of phase shifting transformers the matrix mathbfY is not symmetric [7, Sec. 9.6]. JuliaGrid stores both the matrix mathbfY and its transpose mathbfY^T in the ac field of the PowerSystem type:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"𝐘 = system.model.ac.nodalMatrix\n𝐘ᵀ = system.model.ac.nodalMatrixTranspose","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"tutorials/powerSystemModel/#BusInjectionsTutorials","page":"Power System Model","title":"Bus Injections","text":"","category":"section"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"From the previous analysis, we can determine the complex current injection at each bus as follows:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" barI_i = sumlimits_j = 1^n Y_ij barV_j i in mathcalN","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Furthermore, the calculation of active and reactive power injection at each bus is expressed by the following equation:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" S_i = P_i + textjQ_i = barV_i sumlimits_j = 1^n Y_ij^* barV_j^* i in mathcalN","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Positive values of active or reactive powers, P_i 0 or Q_i 0, indicate that the bus is supplying power into the power system. Conversely, negative values, P_i 0 or Q_i 0, suggest that the bus is drawing active or reactive power from the power system.","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"tutorials/powerSystemModel/#BusShuntElementTutorials","page":"Power System Model","title":"Bus Shunt Element","text":"","category":"section"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Based on the previous analysis, we can determine the active and reactive power at the shunt element of each bus using the following equation:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" S_textshi = P_textshi + textjQ_textshi = barV_ibarI_textshi^* = y_textshi^*V_i^2 i in mathcalN","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The positive active power value P_textshi 0 indicates that the shunt element is consuming active power. In terms of power flow, this signifies that active power flows from bus i in mathcalN towards the ground. A negative reactive power value Q_textshi 0 suggests that the shunt element is injecting reactive power into the power system. This implies that the direction of reactive power is from the ground to bus i in mathcalN, illustrating the capacitive nature of the shunt component. Conversely, if Q_textshi 0, it indicates an inductive characteristic, implying that the shunt component is absorbing reactive power.","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"tutorials/powerSystemModel/#DCModelTutorials","page":"Power System Model","title":"DC Model","text":"","category":"section"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The DC model is obtained by linearization of the nonlinear model, and it provides an approximate solution. In the typical operating conditions, the difference of bus voltage angles between adjacent buses (ij) in mathcalE is very small theta_i-theta_j approx 0, which implies cos (theta_i-theta_j)approx 1 and sin (theta_i-theta_j) approx theta_i-theta_j. Further, all bus voltage magnitudes are V_i approx 1, i in mathcalN, and all branch shunt admittances and branch resistances can be neglected. This implies that the DC model ignores the reactive powers and transmission losses and takes into account only the active powers.","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Therefore, the DC power flow takes only bus voltage angles bm Theta in mathbbR^n as variables. To create vectors and matrices related to DC or linear analyses, JuliaGrid uses the function dcModel!:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"dcModel!(system)\nnothing # hide","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"tutorials/powerSystemModel/#DCBranchNetworkEquationsTutorials","page":"Power System Model","title":"Branch Network Equations","text":"","category":"section"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"According to the above assumptions, we start from the Unified Branch Model:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" beginbmatrix\n barI_ij barI_ji\n endbmatrix = cfrac1textjx_ij\n beginbmatrix\n cfrac1tau_ij^2 -alpha_ij^*\n -alpha_ij 1\n endbmatrix\n beginbmatrix\n barV_i barV_j\n endbmatrix","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"where barV_i = texte^textjtheta_i and barV_j = texte^textjtheta_j. Further, we have:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" beginaligned\n barI_ij = cfrac1textjx_ij leftcfrac1tau_ij^2 texte^textjtheta_i -\n cfrac1tau_ijtexte^textj(phi_ij + theta_j) right \n barI_ji = cfrac1textjx_ij left-cfrac1tau_ijtexte^textj(theta_i - phi_ij) + texte^textjtheta_j right\n endaligned","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The active power flows are derived as follows:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" beginaligned\n P_ij = RebarV_ibarI_ij^* =\n Re lefttextjcfrac1x_ij\n leftcfrac1tau_ij^2 - cfrac1tau_ije^textj(theta_i - theta_j - phi_ij) right right \n P_ji = RebarV_jbarI_ji^* =\n Re lefttextjcfrac1x_ij\n left1-cfrac1tau_ije^textj(-theta_i +theta_j + phi_ij) right right\n endaligned","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The real components are:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" beginaligned\n P_ij =cfrac1tau_ijx_ij sin(theta_i -theta_j-phi_ij) approx cfrac1tau_ij x_ij (theta_i -theta_j-phi_ij) \n P_ji =cfrac1tau_ijx_ij sin(theta_j -theta_i+phi_ij) approx -cfrac1tau_ij x_ij (theta_i - theta_j-phi_ij)\n endaligned","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"where 1(tau_ij x_ij) represents the branch admittance in the DC framework. To recall, the PowerSystem type stores the reactances as vector mathbfx = x_ij in the variable:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"𝐱 = system.branch.parameter.reactance","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Furthermore, the computed branch admittances in the DC framework are stored in the vector mathbfy = 1(tau_ij x_ij):","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"𝐲 = system.model.dc.admittance","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"We can conclude that P_ij=-P_ji holds. With the DC model, the linear network equations relate active powers to bus voltage angles, versus complex currents to complex bus voltages in the AC model [8]. Consequently, analogous to the Branch Network Equations we can write:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" beginbmatrix\n P_ij P_ji\n endbmatrix = cfrac1tau_ijx_ij\n beginbmatrix\n 1 -1\n -1 1\n endbmatrix\n beginbmatrix\n theta_i theta_j\n endbmatrix + cfracphi_ijtau_ijx_ij\n beginbmatrix\n -1 1\n endbmatrix","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"tutorials/powerSystemModel/#DCNodalNetworkEquationsTutorials","page":"Power System Model","title":"Nodal Network Equations","text":"","category":"section"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"As before, let us consider an illustrative example from our case study, depicted in Figure 3. This example provides a smooth transition to the general case, demonstrating a system with three buses represented as mathcalN = 1 2 3 and two branches mathcalE = (1 2) (2 3), where bus 2 is incident to the shunt element with admittance g_textsh2.","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"\n
Figure 3: The example of the system with three buses and two branches.
\n ","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Each branch in the DC framework is described with a system of equations as follows:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" beginbmatrix\n P_12 P_21\n endbmatrix = cfrac1tau_12x_12\n beginbmatrix\n 1 -1\n -1 1\n endbmatrix\n beginbmatrix\n theta_1 theta_2\n endbmatrix + cfracphi_12tau_12x_12\n beginbmatrix\n -1 1\n endbmatrix","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" beginbmatrix\n P_23 P_32\n endbmatrix = cfrac1tau_23x_23\n beginbmatrix\n 1 -1\n -1 1\n endbmatrix\n beginbmatrix\n theta_2 theta_3\n endbmatrix + cfracphi_23tau_23x_23\n beginbmatrix\n -1 1\n endbmatrix","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The active power injections at buses are:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" beginaligned\n P_1 = P_12 =cfrac1tau_12x_12 theta_1 - cfrac1tau_12x_12 theta_2 - cfracphi_12tau_12x_12 \n P_2 = P_21 + P_23 + P_textsh2 = -cfrac1tau_12x_12 theta_1 + cfrac1tau_12x_12 theta_2 + cfracphi_12tau_12x_12 +\n cfrac1tau_23x_23 theta_2 - cfrac1tau_23x_23 theta_3 - cfracphi_23tau_23x_23 + g_textsh2 \n P_3 = P_32 = -cfrac1tau_23x_23 theta_2 +cfrac1tau_23x_23 theta_3 + cfracphi_23tau_23x_23\n endaligned","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"where the active power injected by the shunt element at the bus 2 is equal to:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" P_textsh2 = RebarV_2barI_textsh2^* = RebarV_2y_textsh2^*barV_2^* = V_2^2 g_textsh2 = g_textsh2","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The system of equations can be written in the matrix form:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" beginbmatrix\n P_1 P_2 P_3\n endbmatrix =\n beginbmatrix\n cfrac1tau_12x_12 - cfrac1tau_12x_12 0 \n -cfrac1tau_12x_12 cfrac1tau_12x_12 + cfrac1tau_23x_23 -cfrac1tau_23x_23 \n 0 -cfrac1tau_23x_23 cfrac1tau_23x_23\n endbmatrix\n beginbmatrix\n theta_1 theta_2 theta_3\n endbmatrix +\n beginbmatrix\n - cfracphi_12tau_12x_12 cfracphi_12tau_12x_12 - cfracphi_23tau_23x_23 cfracphi_23tau_23x_23\n endbmatrix +\n beginbmatrix\n 0 g_textsh2 0\n endbmatrix","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"This system of equations can be generalized to accommodate the scenario where the set mathcalN comprises n buses:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" mathbf P = mathbfB bm Theta + mathbfP_texttr + mathbfP_textsh","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"where bm Theta in mathbbR^n is the vector of bus voltage angles.","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The vector mathbf P in mathbbR^n contains active power injections at buses caused by generators and demands. In JuliaGrid, the vector can be recovered using a command:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"𝐏 = system.bus.supply.active - system.bus.demand.active","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The vector mathbfP_texttr in mathbbR^n represents active powers related to the non-zero shift angle of transformers. This vector is stored in the dc field, and we can access it using:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"𝐏ₜᵣ = system.model.dc.shiftPower","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The vector mathbfP_textsh in mathbbR^n represents active powers consumed by shunt elements. We can access this vector using:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"𝐏ₛₕ = system.bus.shunt.conductance","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The bus or nodal matrix in the DC framework is given as mathbfB in mathbbR^n times n, with elements:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"the diagonal elements, where i in mathcalN, are equal to:\nB_ii = sumlimits_e in mathcalE i in e cfrac1tau_ijx_ij\nthe non-diagonal elements, where i = e(1) j = e(2) e in mathcalE, are equal to:\n beginaligned\n B_ij = -cfrac1tau_ijx_ij 3pt\n B_ji = -cfrac1tau_ijx_ij\n endaligned","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The sparse nodal matrix mathbfB is stored in the dc field, and we can access it using:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"𝐁 = system.model.dc.nodalMatrix","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"tutorials/powerSystemModel/#DCBusInjectionTutorials","page":"Power System Model","title":"Bus Injection","text":"","category":"section"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"From the previous analysis, the calculation of active power injection at each bus is expressed by:","category":"page"},{"location":"tutorials/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":" P_i = sum_j = 1^n B_ij theta_j + P_texttri + P_textshi i in mathcalN","category":"page"},{"location":"manual/dcOptimalPowerFlow/#DCOptimalPowerFlowManual","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Similar to AC Optimal Power Flow, JuliaGrid utilizes the JuMP package to construct optimal power flow models, enabling users to manipulate these models using the standard functions provided by JuMP. JuliaGrid supports popular solvers mentioned in the JuMP documentation to solve the optimization problem.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"To perform the DC optimal power flow, we first need to have the PowerSystem type that has been created with the DC model. After that, create the DCOptimalPowerFlow type to establish the DC optimal power flow framework using the function:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"dcOptimalPowerFlow.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"To solve the DC optimal power flow problem and acquire generator active power outputs and bus voltage angles, make use of the following function:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"solve!.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"After obtaining the solution for DC optimal power flow, JuliaGrid offers a post-processing analysis function to compute powers associated with buses and branches:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"power!.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Additionally, specialized functions are available for calculating specific types of powers for individual buses, branches, or generators.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#DCOptimalPowerFlowModelManual","page":"DC Optimal Power Flow","title":"Optimal Power Flow Model","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"To set up the DC optimal power flow, we begin by creating the model. To illustrate this, consider the following:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"using JuliaGrid # hide\nusing JuMP, HiGHS\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, angle = 0.17)\naddBus!(system; label = \"Bus 2\", active = 0.1, conductance = 0.04)\naddBus!(system; label = \"Bus 3\", active = 0.05)\n\n@branch(minDiffAngle = -3.1, maxDiffAngle = 3.1, minFromBus = -0.12, maxFromBus = 0.12)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 3\", reactance = 0.01)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.01)\n\n@generator(minActive = 0.0)\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 0.6, maxActive = 0.8)\naddGenerator!(system; label = \"Generator 2\", bus = \"Bus 2\", active = 0.1, maxActive = 0.3)\naddGenerator!(system; label = \"Generator 3\", bus = \"Bus 2\", active = 0.2, maxActive = 0.4)\n\ncost!(system; label = \"Generator 1\", active = 2, polynomial = [1100.2; 500; 80])\ncost!(system; label = \"Generator 2\", active = 1, piecewise = [8.0 11.0; 14.0 17.0])\ncost!(system; label = \"Generator 3\", active = 1, piecewise = [6.8 12.3; 8.7 16.8; 11.2 19.8])\n\ndcModel!(system)\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Next, the dcOptimalPowerFlow function is utilized to formulate the DC optimal power flow problem:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"analysis = dcOptimalPowerFlow(system, HiGHS.Optimizer)\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#DCOptimizationVariablesManual","page":"DC Optimal Power Flow","title":"Optimization Variables","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"In DC optimal power flow, generator active power outputs are linear functions of bus voltage angles. Thus, the model's variables include generator active power outputs and bus voltage angles:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"JuMP.all_variables(analysis.method.jump)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"It is important to highlight that when dealing with linear piecewise cost functions comprising multiple segments, as exemplified in the case of Generator 3, JuliaGrid automatically generates helper optimization variables, such as actwise[3], and formulates a set of linear constraints to appropriately handle these cost functions.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"However, in instances where a linear piecewise cost function consists of only a single segment, as demonstrated by Generator 2, the function is modelled as a standard linear function, eliminating the necessity for additional helper optimization variables.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Please note that JuliaGrid keeps references to all variables categorized into three fields:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"fieldnames(typeof(analysis.method.variable))","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Variable-Names","page":"DC Optimal Power Flow","title":"Variable Names","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Users have the option to define custom variable names for printing and writing equations, which can help present them in a more compact form. For example:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"analysis = dcOptimalPowerFlow(system, HiGHS.Optimizer; active = \"P\", angle = \"θ\")\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Add-Variables","page":"DC Optimal Power Flow","title":"Add Variables","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The user has the ability to easily add new variables to the defined DC optimal power flow model by using the @variable macro from the JuMP package:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"JuMP.@variable(analysis.method.jump, newVariable)\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"We can verify that the new variable is included in the defined model by using the function:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"JuMP.is_valid(analysis.method.jump, newVariable)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Delete-Variables","page":"DC Optimal Power Flow","title":"Delete Variables","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"To delete a variable, the delete function from the JuMP package can be used:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"JuMP.delete(analysis.method.jump, newVariable)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"After deletion, the variable is no longer part of the model:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"JuMP.is_valid(analysis.method.jump, newVariable)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#DCConstraintFunctionsManual","page":"DC Optimal Power Flow","title":"Constraint Functions","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"JuliGrid keeps track of all the references to internally formed constraints in the constraint field of the DCOptimalPowerFlow type. These constraints are divided into six fields:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"fieldnames(typeof(analysis.method.constraint))","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"note: Info\nWe suggest that readers refer to the tutorial on DC Optimal Power Flow for insights into the implementation.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Slack-Bus-Constraint","page":"DC Optimal Power Flow","title":"Slack Bus Constraint","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The slack field contains a reference to the equality constraint associated with the fixed bus voltage angle value of the slack bus. This constraint is set within the addBus! function using the angle keyword:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(system.bus.label, analysis.method.constraint.slack.angle)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Users have the flexibility to modify this constraint by changing which bus serves as the slack bus and by adjusting the value of the bus angle. This can be achieved using the updateBus! function, for example:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"updateBus!(system, analysis; label = \"Bus 1\", angle = -0.1)\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Subsequently, the updated slack constraint can be inspected as follows:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(system.bus.label, analysis.method.constraint.slack.angle)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Bus-Active-Power-Balance-Constraints","page":"DC Optimal Power Flow","title":"Bus Active Power Balance Constraints","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The balance field contains references to the equality constraints associated with the active power balance equations defined for each bus. The constant terms in these equations are determined by the active and conductance keywords within the addBus! function. Additionally, if there are phase shift transformers in the system, the constant terms can also be affected by the shiftAngle keyword within the addBranch! function:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(system.bus.label, analysis.method.constraint.balance.active)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"During the execution of functions that add or update power system components, these constraints are automatically adjusted to reflect the current configuration of the power system, for example:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"updateBus!(system, analysis; label = \"Bus 3\", active = 0.1)\nupdateGenerator!(system, analysis; label = \"Generator 2\", status = 0)\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Subsequently, the updated set of active power balance constraints can be examined as follows:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(system.bus.label, analysis.method.constraint.balance.active)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Bus-Voltage-Angle-Difference-Constraints","page":"DC Optimal Power Flow","title":"Bus Voltage Angle Difference Constraints","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The voltage field contains references to the inequality constraints associated with the minimum and maximum bus voltage angle difference between the from-bus and to-bus ends of each branch. These values are specified using the minDiffAngle and maxDiffAngle keywords within the addBranch! function:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(system.branch.label, analysis.method.constraint.voltage.angle)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"note: Info\nPlease note that if the limit constraints are set to minDiffAngle = -2π and maxDiffAngle = 2π for the corresponding branch, JuliGrid will omit the corresponding inequality constraint.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Additionally, by employing the updateBranch! function, we have the ability to modify these constraints as follows:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"updateBranch!(system, analysis; label = \"Branch 1\", minDiffAngle = -1.7, maxDiffAngle = 1.7)\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Subsequently, the updated set of voltage angle difference constraints can be examined as follows:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(system.branch.label, analysis.method.constraint.voltage.angle)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Branch-Active-Power-Flow-Constraints","page":"DC Optimal Power Flow","title":"Branch Active Power Flow Constraints","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The flow field refers to the inequality constraints associated with active power flow limits at the from-bus end of each branch. These limits are set using the minFromBus and maxFromBus keywords in the addBranch! function:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(system.branch.label, analysis.method.constraint.flow.active)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"note: Info\nIf the branch flow limits are set to minFromBus = 0.0 and maxFromBus = 0.0 for the corresponding branch, JuliGrid will omit the corresponding inequality constraint.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"By employing the updateBranch! function, we have the ability to modify these specific constraints, for example:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"updateBranch!(system, analysis; label = \"Branch 1\", status = 0)\nupdateBranch!(system, analysis; label = \"Branch 2\", reactance = 0.03, maxFromBus = 0.14)\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Subsequently, the updated set of active power flow constraints can be examined as follows:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(system.branch.label, analysis.method.constraint.flow.active)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Generator-Active-Power-Capability-Constraints","page":"DC Optimal Power Flow","title":"Generator Active Power Capability Constraints","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The capability field contains references to the inequality constraints associated with the minimum and maximum active power outputs of the generators. These limits are specified using the minActive and maxActive keywords within the addGenerator! function:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(system.generator.label, analysis.method.constraint.capability.active)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"As demonstrated, the active power output of Generator 2 is currently fixed at zero due to the earlier action of setting this generator out-of-service. Let us adjust this specific constraint using the updateGenerator! function:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"updateGenerator!(system, analysis; label = \"Generator 2\", status = 1, maxActive = 0.5)\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Subsequently, the updated set of active power capability constraints can be examined as follows:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(system.generator.label, analysis.method.constraint.capability.active)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"It is important to note that bringing back Generator 2 into service will also have an impact on the balance constraint, which will once again be influenced by the generator's output.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Active-Power-Piecewise-Constraints","page":"DC Optimal Power Flow","title":"Active Power Piecewise Constraints","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"In the context of active power modelling, the piecewise field serves as a reference to the inequality constraints related to linear piecewise cost functions. These constraints are created using the cost! function with active = 1 specified when dealing with linear piecewise cost functions comprising multiple segments. JuliaGrid takes care of establishing the appropriate inequality constraints for each segment of the linear piecewise cost:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(system.generator.label, analysis.method.constraint.piecewise.active)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"It is worth noting that these constraints can also be automatically updated using the cost! function, and readers can find more details in the section about the objective function.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Add-Constraints","page":"DC Optimal Power Flow","title":"Add Constraints","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Users can effortlessly introduce additional constraints into the defined DC optimal power flow model by utilizing the addBranch! or addGenerator! functions. Specifically, if a user wishes to include a new branch or generator in an already defined PowerSystem and DCOptimalPowerFlow type:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"addBranch!(system, analysis; label = \"Branch 4\", from = \"Bus 1\", to = \"Bus 2\", reactance = 1)\naddGenerator!(system, analysis; label = \"Generator 4\", bus = \"Bus 1\", maxActive = 0.2)\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"As a result, the flow and capability constraints will be adjusted as follows:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(system.branch.label, analysis.method.constraint.flow.active)\nprint(system.generator.label, analysis.method.constraint.capability.active)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Add-User-Defined-Constraints","page":"DC Optimal Power Flow","title":"Add User-Defined Constraints","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Users also have the option to include their custom constraints within the established DC optimal power flow model by employing the @constraint macro. For example, the addition of a new constraint can be achieved as follows:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"JuMP.@constraint(analysis.method.jump, 0.0 <= analysis.method.variable.active[4] <= 0.3)\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Delete-Constraints","page":"DC Optimal Power Flow","title":"Delete Constraints","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"To delete a constraint, users can make use of the delete function from the JuMP package. When handling constraints that have been internally created, users can refer to the constraint references stored in the constraint field of the DCOptimalPowerFlow type.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"For example, if the intention is to eliminate constraints related to the capability of Generator 4, the following code snippet can be employed:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"JuMP.delete(analysis.method.jump, analysis.method.constraint.capability.active[4])\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"note: Info\nIn the event that a user deletes a constraint and subsequently executes a function that updates bus, branch, or generator parameters, and if the deleted constraint is affected by these functions, JuliaGrid will automatically reinstate that constraint. Users should exercise caution when deleting constraints, as this action is considered potentially harmful since it operates independently of power system data.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#DCObjectiveFunctionManual","page":"DC Optimal Power Flow","title":"Objective Function","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The objective function of the DC optimal power flow is constructed using polynomial and linear piecewise cost functions of the generators, which are defined using the cost! functions. It is important to note that only polynomial cost functions up to the second degree are included in the objective. If there are polynomials of higher degrees, JuliaGrid will exclude them from the objective function.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"In the provided example, the objective function that needs to be minimized to obtain the optimal values of the active power outputs of the generators and the bus voltage angles is as follows:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"JuMP.objective_function(analysis.method.jump)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Additionally, JuliaGrid stores the objective function in a separate variable, allowing users to access it by referencing the variable analysis.objective.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Update-Objective-Function","page":"DC Optimal Power Flow","title":"Update Objective Function","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"By utilizing the cost! functions, users have the flexibility to modify the objective function by adjusting polynomial or linear piecewise cost coefficients or by changing the type of polynomial or linear piecewise function employed. For instance, consider Generator 3, which incorporates a piecewise cost structure with two segments. Now, we can define a polynomial function for this generator and activate it by specifying the keyword active = 2 as shown:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"cost!(system, analysis; label = \"Generator 3\", active = 2, polynomial = [853.4; 257; 40])","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"This results in the updated objective function, which can be observed as follows:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"analysis.method.objective","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#User-Defined-Objective-Function","page":"DC Optimal Power Flow","title":"User-Defined Objective Function","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Users can modify the objective function using the set_objective_function function from the JuMP package. This operation is considered destructive because it is independent of power system data; however, in certain scenarios, it may be more straightforward than using the cost! function for updates. Moreover, using this methodology, users can combine a defined function with a newly defined expression. Here is an example of how it can be achieved:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"expr = 100.2 * analysis.method.variable.active[1] * analysis.method.variable.active[1] + 123\nJuMP.set_objective_function(analysis.method.jump, analysis.method.objective - expr)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"We can now observe the updated objective function as follows:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"JuMP.objective_function(analysis.method.jump)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#SetupStartingPrimalValuesManual","page":"DC Optimal Power Flow","title":"Setup Starting Values","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"In JuliaGrid, the assignment of starting primal and dual values for optimization variables takes place when the solve! function is executed.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Starting-Primal-Values","page":"DC Optimal Power Flow","title":"Starting Primal Values","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Starting primal values are determined based on the generator and voltage fields within the DCOptimalPowerFlow type. By default, these values are initially established using the active power outputs of the generators and the initial bus voltage angles:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(system.generator.label, analysis.power.generator.active)\nprint(system.bus.label, analysis.voltage.angle)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Users have the flexibility to adjust these values according to their specifications, which will then be used as the starting primal values when executing the solve! function.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Using-DC-Power-Flow","page":"DC Optimal Power Flow","title":"Using DC Power Flow","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"In this perspective, users have the capability to conduct the DC power flow analysis and leverage the resulting solution to configure starting primal values. Here is an illustration of how this can be achieved:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"flow = dcPowerFlow(system)\nsolve!(system, flow)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"After obtaining the solution, we can calculate the active power outputs of the generators and utilize the bus voltage angles to set the starting values. In this case, the generator and voltage fields of the DCOptimalPowerFlow type can be employed to store the new starting values:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"for (key, idx) in system.generator.label\n analysis.power.generator.active[idx] = generatorPower(system, flow; label = key)\nend\n\nfor i = 1:system.bus.number\n analysis.voltage.angle[i] = flow.voltage.angle[i]\nend","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Starting-Dual-Values","page":"DC Optimal Power Flow","title":"Starting Dual Values","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Dual variables, often referred to as Lagrange multipliers or Kuhn-Tucker multipliers, represent the shadow prices or marginal costs associated with constraints. The assignment of initial dual values occurs when the solve! function is executed. Initially, the starting dual values are unknown, but users can access and manually set them. For example:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"analysis.method.dual.balance.active[1] = 0.4\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#DCOptimalPowerFlowSolutionManual","page":"DC Optimal Power Flow","title":"Optimal Power Flow Solution","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"To establish the DC optimal power flow problem, we can utilize the dcOptimalPowerFlow function. After setting up the problem, we can use the solve! function to compute the optimal values for the active power outputs of the generators and the bus voltage angles. Also, to turn off the solver output within the REPL, we use the set_silent function before calling solve! function. Here is an example:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"JuMP.set_silent(analysis.method.jump)\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"By executing this function, we will obtain the solution with the optimal values for the active power outputs of the generators and the bus voltage angles:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(system.generator.label, analysis.power.generator.active)\nprint(system.bus.label, analysis.voltage.angle)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Objective-Value","page":"DC Optimal Power Flow","title":"Objective Value","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"To obtain the objective value of the optimal power flow solution, we can use the objective_value function:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"JuMP.objective_value(analysis.method.jump)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Dual-Variables","page":"DC Optimal Power Flow","title":"Dual Variables","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The values of the dual variables are stored in the dual field of the DCOptimalPowerFlow type. For example:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"analysis.method.dual.balance.active[1]","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Print-Results-in-the-REPL","page":"DC Optimal Power Flow","title":"Print Results in the REPL","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Users can utilize the functions printBusData and printGeneratorData to display results. Additionally, the functions listed in the Print Constraint Data section allow users to print constraint data related to buses, branches, or generators in the desired units. For example:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"@power(MW, MVAr, pu)\nprintBusConstraint(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Next, users can easily customize the print results for specific constraint, for example:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"printBusConstraint(system, analysis; label = \"Bus 1\", header = true)\nprintBusConstraint(system, analysis; label = \"Bus 2\", footer = true)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Save-Results-to-a-File","page":"DC Optimal Power Flow","title":"Save Results to a File","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Users can also redirect print output to a file. For example, data can be saved in a text file as follows:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"open(\"bus.txt\", \"w\") do file\n printBusConstraint(system, analysis, file)\nend","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Save-Results-to-a-CSV-File","page":"DC Optimal Power Flow","title":"Save Results to a CSV File","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"For CSV output, users should first generate a simple table with style = false, and then save it to a CSV file:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"using CSV\n\nio = IOBuffer()\nprintBusConstraint(system, analysis, io; style = false)\nCSV.write(\"constraint.csv\", CSV.File(take!(io); delim = \"|\"))","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Primal-and-Dual-Warm-Start","page":"DC Optimal Power Flow","title":"Primal and Dual Warm Start","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Utilizing the DCOptimalPowerFlow type and proceeding directly to the solver offers the advantage of a \"warm start\". In this scenario, the starting primal and dual values for the subsequent solving step correspond to the solution obtained from the previous step.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Primal-Variables","page":"DC Optimal Power Flow","title":"Primal Variables","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"In the previous example, the following solution was obtained, representing the values of the primal variables:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(system.generator.label, analysis.power.generator.active)\nprint(system.bus.label, analysis.voltage.angle)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Dual-Variables-2","page":"DC Optimal Power Flow","title":"Dual Variables","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"We also obtained all dual values. Here, we list only the dual variables for one type of constraint as an example:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(system.branch.label, analysis.method.dual.flow.active)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Modify-Optimal-Power-Flow","page":"DC Optimal Power Flow","title":"Modify Optimal Power Flow","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Now, let us introduce changes to the power system from the previous example:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"updateGenerator!(system, analysis; label = \"Generator 2\", maxActive = 0.08)\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Next, we want to solve this modified optimal power flow problem. If we use solve! at this point, the primal and dual starting values will be set to the previously obtained values:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"solve!(system, analysis)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"As a result, we obtain a new solution:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(system.generator.label, analysis.power.generator.active)\nprint(system.bus.label, analysis.voltage.angle)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Reset-Primal-and-Dual-Values","page":"DC Optimal Power Flow","title":"Reset Primal and Dual Values","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Users retain the flexibility to reset these initial primal values to their default configurations at any juncture. This can be accomplished by utilizing the active power outputs of the generators and the initial bus voltage angles extracted from the PowerSystem type, employing the startingPrimal! function:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"startingPrimal!(system, analysis)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The primal starting values will now be identical to those that would be obtained if the dcOptimalPowerFlow function were executed after all the updates have been applied.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Using the startingDual! function, users can clear all dual variable values, resetting them to their default state:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"startingDual!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#DCOptimalPowerAnalysisManual","page":"DC Optimal Power Flow","title":"Power Analysis","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"After obtaining the solution from the DC optimal power flow, we can calculate powers related to buses and branches using the power! function. For instance, let us consider the power system for which we obtained the DC optimal power flow solution:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"using JuliaGrid, JuMP # hide\nusing HiGHS\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, angle = 0.17)\naddBus!(system; label = \"Bus 2\", active = 0.1, conductance = 0.04)\naddBus!(system; label = \"Bus 3\", active = 0.05)\n\n@branch(minDiffAngle = -pi, maxDiffAngle = pi, minFromBus = -0.12, maxFromBus = 0.12)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 3\", reactance = 0.01)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.01)\n\n@generator(minActive = 0.0)\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 3.2, maxActive = 0.5)\naddGenerator!(system; label = \"Generator 2\", bus = \"Bus 2\", active = 0.2, maxActive = 0.2)\n\ncost!(system; label = \"Generator 1\", active = 2, polynomial = [1100.2; 500; 80])\ncost!(system; label = \"Generator 2\", active = 1, piecewise = [10.8 12.3; 14.7 16.8])\n\nanalysis = dcOptimalPowerFlow(system, HiGHS.Optimizer)\nJuMP.set_silent(analysis.method.jump) # hide\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Now we can calculate the active powers using the following function:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"power!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Finally, to display the active power injections and from-bus active power flows, we can use the following code:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(system.bus.label, analysis.power.injection.active)\nprint(system.branch.label, analysis.power.from.active)","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"note: Info\nTo better understand the powers associated with buses and branches that are calculated by the power! function, we suggest referring to the tutorials on DC Optimal Power Flow.","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Print-Results-in-the-REPL-2","page":"DC Optimal Power Flow","title":"Print Results in the REPL","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Users can utilize any of the print functions outlined in the Print Power System Data or Print Power System Summary. For example, to create a bus data with the desired units, users can use the following function:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"@voltage(pu, deg, V)\n@power(MW, MVAr, pu)\nprintBusData(system, analysis)\n@default(unit) # hide\nnothing # hide","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Active-Power-Injection","page":"DC Optimal Power Flow","title":"Active Power Injection","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"To calculate active power injection associated with a specific bus, the function can be used:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"active = injectionPower(system, analysis; label = \"Bus 2\")","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Active-Power-Injection-from-Generators","page":"DC Optimal Power Flow","title":"Active Power Injection from Generators","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"To calculate active power injection from the generators at a specific bus, the function can be used:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"active = supplyPower(system, analysis; label = \"Bus 2\")","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"manual/dcOptimalPowerFlow/#Active-Power-Flow","page":"DC Optimal Power Flow","title":"Active Power Flow","text":"","category":"section"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Similarly, we can compute the active power flow at both the from-bus and to-bus ends of the specific branch by utilizing the provided functions below:","category":"page"},{"location":"manual/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"active = fromPower(system, analysis; label = \"Branch 2\")\nactive = toPower(system, analysis; label = \"Branch 2\")","category":"page"},{"location":"manual/powerSystemModel/#PowerSystemModelManual","page":"Power System Model","title":"Power System Model","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"JuliaGrid supports the type PowerSystem to preserve power system data, with the following fields: bus, branch, generator, base, and model. The bus, branch, and generator fields hold data related to buses, branches, and generators, respectively. The base field stores base values for power and voltages, with the default being three-phase power measured in volt-amperes for the base power and line-to-line voltages measured in volts for base voltages. Within the model field, the ac and dc subfields store vectors and matrices pertinent to the power system's topology and parameters, and these are utilized in either the AC or DC framework.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The type PowerSystem can be created using a function:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"powerSystem.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"JuliaGrid supports three modes for populating the PowerSystem type: using built-in functions, using HDF5 file format, and using Matpower case files.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"It is recommended to use the HDF5 format for large-scale systems. To facilitate this, JuliaGrid has the function:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"savePowerSystem.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Upon creation of the PowerSystem type, users can generate vectors and matrices based on the power system topology and parameters using the following functions:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"acModel!,\ndcModel!.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Once the PowerSystem type is created, users can add buses, branches, generators, or manage costs associated with the output powers of the generators, using the following functions:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"addBus!,\naddBranch!,\naddGenerator!,\ncost!.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"JuliaGrid also provides macros @bus, @branch, and @generator to define templates that aid in creating buses, branches, and generators. These templates help avoid entering the same parameters repeatedly.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Moreover, it is feasible to modify the parameters of buses, branches, and generators. When these functions are executed, all relevant fields within the PowerSystem type will be automatically updated, encompassing the ac and dc fields as well. These functions include:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"updateBus!,\nupdateBranch!,\nupdateGenerator!.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"tip: Tip\nThe functions addBranch!, addGenerator!, updateBus!, updateBranch!, updateGenerator!, and cost! serve a dual purpose. While their primary function is to modify the PowerSystem type, they are also designed to accept various analysis models like AC or DC power flow models. When feasible, these functions not only modify the PowerSystem type but also adapt the analysis model, often resulting in improved computational efficiency. Detailed instructions on utilizing this feature can be found in dedicated manuals for specific analyses.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#BuildModelManual","page":"Power System Model","title":"Build Model","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The powerSystem function generates the PowerSystem type and requires a string-formatted path to either Matpower cases or HDF5 files as input. Alternatively, the PowerSystem can be created without any initial data by initializing it as empty, allowing the user to construct the power system from scratch.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Matpower-File","page":"Power System Model","title":"Matpower File","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"For example, to create the PowerSystem type using the Matpower case file for the IEEE 14-bus test case, which is named case14.m and located in the folder C:\\matpower, the following Julia code can be used:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system = powerSystem(\"C:/matpower/case14.m\")","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#HDF5-File","page":"Power System Model","title":"HDF5 File","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"In order to use the HDF5 file as input to create the PowerSystem type, it is necessary to have saved the data using the savePowerSystem function beforehand. As an example, let us say we saved the power system as case14.h5 in the directory C:\\hdf5. In this case, the following Julia code can be used to construct the PowerSystem type:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system = powerSystem(\"C:/hdf5/case14.h5\")","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"tip: Tip\nIt is recommended to load the power system from the HDF5 file to reduce the loading time.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Model-from-Scratch","page":"Power System Model","title":"Model from Scratch","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Alternatively, the model can be built from scratch using built-in functions, for example:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"using JuliaGrid # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.1, base = 345e3)\naddBus!(system; label = \"Bus 2\", type = 1, reactive = 0.05, base = 345e3)\n\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Internal-Unit-System","page":"Power System Model","title":"Internal Unit System","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The PowerSystem type stores all electrical quantities in per-units and radians, except for the base values of power and voltages. The base power value is expressed in volt-amperes, while the base voltages are given in volts.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Change-Base-Unit-Prefixes","page":"Power System Model","title":"Change Base Unit Prefixes","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The user can retrieve the base power and base voltage values along with their respective units:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.base.power.value, system.base.power.unit\nsystem.base.voltage.value, system.base.voltage.unit","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"By using the @base macro, users can change the prefixes of the base units. For instance, if users wish to convert base power and base voltage values to megavolt-amperes (MVA) and kilovolts (kV) respectively, they can execute the following macro:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"@base(system, MVA, kV)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"After executing the macro, the base power and voltage values and their units will be modified accordingly:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.base.power.value, system.base.power.unit\nsystem.base.voltage.value, system.base.voltage.unit","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#SaveModelManual","page":"Power System Model","title":"Save Model","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Once the PowerSystem type has been created using one of the methods outlined in Build Model, the data can be stored in the HDF5 file by using the savePowerSystem function:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"savePowerSystem(system; path = \"C:/matpower/case14.h5\", reference = \"IEEE 14-bus test case\")","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"All electrical quantities saved in the HDF5 file are in per-units and radians, except for base values for power and voltages, which are given in volt-amperes and volts. Note that even if the user modifies the base units using the @base macro, the units will still be saved with the default settings.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#AddBusManual","page":"Power System Model","title":"Add Bus","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The buses can be added both to the loaded power system, or to the one created from scratch. As an illustration, we can initiate the PowerSystem type and then incorporate two buses by utilizing the addBus! function:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"using JuliaGrid # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.1, base = 345e3)\naddBus!(system; label = \"Bus 2\", type = 1, angle = -0.034907, base = 345e3)","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"In this case, we have created two buses where the active power demanded by the consumer at Bus 1 is specified in per-units, which are the same units used to store electrical quantities:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.bus.demand.active","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"It is worth noting that the base keyword is used to specify the base voltages, and its default input unit is in volts (V):","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.base.voltage.value, system.base.voltage.unit","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Also, we have defined the bus voltage angle in radians for Bus 2 as its initial value:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.bus.voltage.angle","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"note: Info\nWe recommend reading the documentation for the addBus! function, where we have provided a list of all the keywords that can be used.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Customizing-Input-Units-for-Keywords","page":"Power System Model","title":"Customizing Input Units for Keywords","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Typically, all keywords associated with electrical quantities are expected to be provided in per-units (pu) and radians (rad) by default, with the exception of base voltages, which should be specified in volts (V). However, users can choose to use different units than the default per-units and radians or modify the prefix of the base voltage unit by using macros such as the following:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"using JuliaGrid # hide\n\n@power(MW, MVAr, pu)\n@voltage(pu, deg, kV)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"This practical example showcases the customization approach. For keywords tied to active powers, the unit is set as megawatts (MW), while reactive powers employ megavolt-amperes reactive (MVAr). Apparent power, on the other hand, employs per-units (pu). As for keywords concerning voltage magnitude, per-units (pu) remain the choice, but voltage angle mandates degrees (deg). Lastly, the input unit for base voltage is elected to be kilovolts (kV).","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Now we can create identical two buses as before using new system of units as follows:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 10.0, base = 345.0)\naddBus!(system; label = \"Bus 2\", type = 1, angle = -2.0, base = 345.0)","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"As can be observed, electrical quantities will continue to be stored in per-units and radians format:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"[system.bus.demand.active system.bus.voltage.angle]","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The base voltage values will still be stored in volts (V) since we only changed the input unit prefix, and did not modify the internal unit prefix, as shown below:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.base.voltage.value, system.base.voltage.unit","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"To modify the internal unit prefix, the following macro can be used:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"@base(system, VA, kV)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"After executing this macro, the base voltage values will be stored in kilovolts (kV):","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.base.voltage.value, system.base.voltage.unit","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#AddBranchManual","page":"Power System Model","title":"Add Branch","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The branch connecting two buses can be added once those buses are defined, and from and to keywords must correspond to labels of those buses. For example:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"using JuliaGrid # hide\n@default(unit) # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.1)\naddBus!(system; label = \"Bus 2\", type = 1, angle = -0.2)\n\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12)","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Here, we created the branch from Bus 1 to Bus 2 with following parameter:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.branch.parameter.reactance","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"note: Info\nIt is recommended to consult the documentation for the addBranch! function, where we have provided a list of all the keywords that can be used.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Customizing-Input-Units-for-Keywords-2","page":"Power System Model","title":"Customizing Input Units for Keywords","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"To use units other than per-units (pu) and radians (rad), macros can be employed to change the input units. For example, if there is a need to use ohms (Ω), the macros below can be employed:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"using JuliaGrid # hide\n@parameter(Ω, pu)\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.1)\naddBus!(system; label = \"Bus 2\", type = 1, angle = -0.2)\n\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 22.8528)","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Still, all electrical quantities are stored in per-units, and the same branch as before is created:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.branch.parameter.reactance","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"It is important to note that, when working with impedance and admittance values in ohms (Ω) and siemens (S) that are related to a transformer, the assignment must be based on the primary side of the transformer.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#AddGeneratorManual","page":"Power System Model","title":"Add Generator","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The generator connected to a bus can be added once the bus is defined. Each generator must have a unique label, and the bus keyword should correspond to the unique label of the bus it is connected to. For instance:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"using JuliaGrid # hide\n@default(unit) # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 2\", active = 0.5, reactive = 0.1)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"In the above code, we add the generator to the Bus 2, with active and reactive power outputs set to:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.generator.output.active, system.generator.output.reactive","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Similar to buses and branches, the input units can be changed to units other than per-units using different macros.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"note: Info\nIt is recommended to refer to the documentation for the addGenerator! function, where we have provided a list of all the keywords that can be used.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#AddTemplatesManual","page":"Power System Model","title":"Add Templates","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The functions addBus!, addBranch!, and addGenerator! are used to add bus, branch, and generator to the power system, respectively. If certain keywords are not specified, default values are assigned to some parameters.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Default-Keyword-Values","page":"Power System Model","title":"Default Keyword Values","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Regarding the addBus! function, the bus type is automatically configured as a demand bus with type = 1. The initial bus voltage magnitude is set to magnitude = 1.0 per-unit, while the base voltage is established as base = 138e3 volts. Additionally, the minimum and maximum bus voltage magnitudes are set to minMagnitude = 0.9 per-unit and maxMagnitude = 1.1 per-unit, respectively.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Transitioning to the addBranch! function, the default operational status is status = 1, indicating that the branch is in-service. The off-nominal turns ratio for the transformer is specified as turnsRatio = 1.0, and the phase shift angle is set to shiftAngle = 0.0, collectively defining the line configuration with these standard settings. The flow rating is also configured as type = 1. Moreover, the minimum and maximum voltage angle differences between the from-bus and to-bus ends are set to minDiffAngle = -2pi and maxDiffAngle = 2pi, respectively.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Similarly, the addGenerator! function designates an operational generator by employing status = 1, and it sets magnitude = 1.0 per-unit, denoting the desired voltage magnitude setpoint.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The remaining parameters are initialized with default values of zero.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Change-Default-Keyword-Values","page":"Power System Model","title":"Change Default Keyword Values","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"In JuliaGrid, users have the flexibility to adjust default values and assign customized values using the @bus, @branch, and @generator macros. These macros create bus, branch, and generator templates that are used every time the addBus!, addBranch!, and addGenerator! functions are called. For instance, the code block shows an example of creating bus, branch, and generator templates with customized default values:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"using JuliaGrid # hide\n@default(unit) # hide\n\nsystem = powerSystem()\n\n@bus(type = 2, active = 0.1)\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.5)\n\n@branch(reactance = 0.12)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\")\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.06)\n\n@generator(magnitude = 1.1)\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 0.6)\naddGenerator!(system; label = \"Generator 2\", bus = \"Bus 1\", active = 0.2)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"This code example involves two uses of the addBus! and addBranch! functions. In the first use, the functions rely on the default values set by the templates created with the @bus and @branch macros. In contrast, the second use passes specific values that match the keywords used in the templates. As a result, the templates are ignored:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.bus.layout.type\nsystem.bus.demand.active\nsystem.branch.parameter.reactance","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"In the given example, the @generator macro is utilized instead of repeatedly specifying the magnitude keyword in the addGenerator! function. This macro creates a generator template with a default value for magnitude, which is automatically applied every time the addGenerator! function is called. Therefore, it eliminates the requirement to set the magnitude value for each individual generator:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.generator.voltage.magnitude","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Customizing-Input-Units-for-Keywords-3","page":"Power System Model","title":"Customizing Input Units for Keywords","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Templates can also be defined using a custom unit system, for example:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"using JuliaGrid # hide\n\nsystem = powerSystem()\n\n@power(MW, MVAr, MVA)\n@bus(active = 100, reactive = 200)\naddBus!(system; label = \"Bus 1\")\n\n@power(pu, pu, pu)\naddBus!(system; label = \"Bus 2\", active = 0.5)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"In this example, we create the bus template and one bus using SI power units, and then we switch to per-units and add the second bus. It is important to note that once the template is defined in any unit system, it remains valid regardless of subsequent unit system changes. The resulting power values are:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.bus.demand.active\nsystem.bus.demand.reactive","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Thus, JuliaGrid automatically tracks the unit system used to create templates and provides the appropriate conversion to per-units and radians. Even if the user switches to a different unit system later on, the previously defined template will still be valid.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Multiple-Templates","page":"Power System Model","title":"Multiple Templates","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"In the case of calling the @bus, @branch, or @generator macros multiple times, the provided keywords and values will be combined into a single template for the corresponding component (bus, branch, or generator), which will be used for generating the component.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Reset-Templates","page":"Power System Model","title":"Reset Templates","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"To reset the bus, branch, and generator templates to their default settings, users can utilize the following macros:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"@default(bus)\n@default(branch)\n@default(generator)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Additionally, users can reset all templates using the macro:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"@default(template)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#LabelsManual","page":"Power System Model","title":"Labels","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"As we have shown, JuliaGrid mandates a distinctive label for every bus, branch, or generator. These labels are stored in ordered dictionaries, functioning as pairs of strings and integers. The string signifies the exclusive label for the specific component, whereas the integer maintains an internal numbering of buses, branches, or generators.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"tip: Tip\nString labels improve readability, but in larger models, the overhead from using strings can become substantial. To reduce memory usage, users can configure ordered dictionaries to accept and store integers as labels:@labels(Integer)","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Integer-Based-Labeling","page":"Power System Model","title":"Integer-Based Labeling","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Let us take a look at the following illustration:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n@labels(Integer)\n\nsystem = powerSystem()\n\naddBus!(system; label = 1, type = 3, active = 0.1)\naddBus!(system; label = 2, type = 1, angle = -0.2)\n\naddBranch!(system; label = 1, from = 1, to = 2, reactance = 0.12)\n\naddGenerator!(system; label = 1, bus = 2, active = 0.5, reactive = 0.1)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"In this example, we use the macro @labels to specify that labels will be stored as integers. It is essential to run this macro; otherwise, even if integers are used in subsequent functions, they will be stored as strings.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Here, two buses are created with labels 1 and 2. A branch connects these two buses, assigned a unique label of 1. Finally, a generator is connected to bus 2, with its own label set to 1.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Automated-Labeling","page":"Power System Model","title":"Automated Labeling","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Users also possess the option to omit the label keyword, allowing JuliaGrid to independently allocate unique labels for buses, branches, or generators. In such instances, JuliaGrid employs an ordered set of incremental integers for labeling components. To illustrate, consider the subsequent example:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\n\naddBus!(system; type = 3, active = 0.1)\naddBus!(system; type = 1, angle = -0.2)\n\naddBranch!(system; from = 1, to = 2, reactance = 0.12)\n\naddGenerator!(system; bus = 2, active = 0.5, reactive = 0.1)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"This example models the same power system as before. In the previous case, we manually assigned labels using incremental integers. Here, we rely on the automatic labeling behavior, but since the macro @labels is not used, the labels will be stored as strings.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Automated-Labeling-Using-Templates","page":"Power System Model","title":"Automated Labeling Using Templates","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Additionally, users have the ability to generate labels through templates and employ the symbol ? to insert an incremental set of integers at any location. For instance:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\n\n@bus(label = \"Bus ? HV\")\naddBus!(system; type = 3, active = 0.1)\naddBus!(system; type = 1, angle = -0.2)\n\n@branch(label = \"Branch ?\")\naddBranch!(system; from = \"Bus 1 HV\", to = \"Bus 2 HV\", reactance = 0.12)\n\n@generator(label = \"Generator ?\")\naddGenerator!(system; bus = \"Bus 2 HV\", active = 0.5, reactive = 0.1)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"In this example, two buses are generated and labeled as Bus 1 HV and Bus 2 HV, along with one branch and one generator labeled as Branch 1 and Generator 1, respectively.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Retrieving-Labels","page":"Power System Model","title":"Retrieving Labels","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Finally, we will outline how users can retrieve stored labels. Let us consider the following power system creation:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"using JuliaGrid # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 2\")\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 3\")\n\naddBranch!(system; label = \"Branch 2\", from = \"Bus 2\", to = \"Bus 1\", reactance = 0.8)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.5)\n\naddGenerator!(system; label = \"Generator 2\", bus = \"Bus 1\")\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 3\")\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"For instance, the bus labels can be accessed using the variable:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.bus.label","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"If the objective is to obtain only labels, users can utilize the following:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"label = collect(keys(system.bus.label))","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"This approach can also be extended to branch and generator labels by making use of the variables present within the PowerSystem type, namely system.branch.label or system.generator.label.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Moreover, the from and to keywords associated with branches are stored based on internally assigned numerical values linked to bus labels. These values are stored in variables:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"[system.branch.layout.from system.branch.layout.to]","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"To recover the original from and to labels, we can utilize:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"[label[system.branch.layout.from] label[system.branch.layout.to]]","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Similarly, the bus keywords related to generators are saved based on internally assigned numerical values corresponding to bus labels and can be accessed using:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.generator.layout.bus","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"To recover the original bus labels, we can utilize:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"label[system.generator.layout.bus]","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"tip: Tip\nJuliaGrid offers the capability to print labels alongside various types of data, such as power system parameters, voltages, powers, currents, or constraints used in optimal power flow analyses. For instance:print(system.branch.label, system.branch.parameter.reactance)","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Loading-and-Saving-Labels","page":"Power System Model","title":"Loading and Saving Labels","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"When a user loads a power system from a Matpower file, the default behavior is to store labels as strings. However, this can be overridden by using the @labels macro to store labels as integers.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"When saving the power system to an HDF5 file, the label type (strings or integers) will match the type chosen during system setup. Likewise, when loading data from an HDF5 file, the label type will be preserved as saved, regardless of what is set by the @labels macro.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#ACDCModelManual","page":"Power System Model","title":"AC and DC Model","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"When we constructed the power system, we can create an AC and/or DC model, which include vectors and matrices related to the power system's topology and parameters. The following code snippet demonstrates this:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.1)\naddBus!(system; label = \"Bus 2\", type = 1, reactive = 0.05)\naddBus!(system; label = \"Bus 3\", type = 1, susceptance = 0.05)\n\naddBranch!(system; from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12, shiftAngle = 0.1745)\naddBranch!(system; from = \"Bus 2\", to = \"Bus 3\", resistance = 0.008, reactance = 0.05)\n\nacModel!(system)\ndcModel!(system)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"tip: Tip\nIn many instances throughout the JuliaGrid documentation, we explicitly mention these functions by their names, although it is not mandatory. If a user begins any of the various AC or DC analyses without having previously established the AC or DC model using the acModel! or dcModel! function, the respective function for setting the analysis will automatically create the AC or DC model.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The nodal matrices are one of the components of both the AC and DC models and are stored in the variables:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.model.ac.nodalMatrix\nsystem.model.dc.nodalMatrix","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"note: Info\nThe AC model is used for performing AC power flow, AC optimal power flow, AC state estimation, or state estimation with PMUs, whereas the DC model is essential for various DC or linear analyses. Consequently, once these models are developed, they can be applied to various types of simulations. We recommend that the reader refers to the tutorial on AC and DC models.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#New-Branch-Triggers-Model-Update","page":"Power System Model","title":"New Branch Triggers Model Update","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"We can execute the acModel! and dcModel! functions after defining the final number of buses, and each new branch added will trigger an update of the AC and DC matrices and vectors. Here is an example:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"using JuliaGrid # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.1)\naddBus!(system; label = \"Bus 2\", type = 1, reactive = 0.05)\naddBus!(system; label = \"Bus 3\", type = 1, susceptance = 0.05)\n\nacModel!(system)\ndcModel!(system)\n\naddBranch!(system; from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12, shiftAngle = 0.1745)\naddBranch!(system; from = \"Bus 2\", to = \"Bus 3\", resistance = 0.008, reactance = 0.05)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"For example, the nodal matrix in the DC framework has the same values as before:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.model.dc.nodalMatrix","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"tip: Tip\nIt is not fully recommended to create AC and DC models before adding a large number of branches if the execution time of functions is important. Instead, triggering updates to the AC and DC models using the addBranch! function is useful for power systems that require the addition of several branches. This update avoids the need to recreate vectors and matrices from scratch.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#New-Bus-Triggers-Model-Erasure","page":"Power System Model","title":"New Bus Triggers Model Erasure","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The AC and DC models must be defined once a finite number of buses has been defined, otherwise, adding a new bus will delete them. For example, if we attempt to add a new bus to the PowerSystem type that was previously created, the current AC and DC models will be completely erased:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"addBus!(system; label = \"Bus 4\", type = 2)\nsystem.model.ac.nodalMatrix\nsystem.model.dc.nodalMatrix","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#UpdateBusManual","page":"Power System Model","title":"Update Bus","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Once a bus has been added to the PowerSystem type, users have the flexibility to modify all parameters defined within the addBus! function. This means that when the updateBus! function is used, the PowerSystem type within AC and DC models that have been created is updated. This eliminates the need to recreate the AC and DC models from scratch.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"To illustrate, let us consider the following power system:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"using JuliaGrid # hide\n@default(unit) # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.1, conductance = 0.01)\naddBus!(system; label = \"Bus 2\", type = 2, reactive = 0.05)\naddBus!(system; label = \"Bus 3\", type = 1, susceptance = 0.05)\n\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.05)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 0.5)\naddGenerator!(system; label = \"Generator 2\", bus = \"Bus 1\", active = 0.2)\n\nacModel!(system)\ndcModel!(system)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"For instance, the nodal matrix in the AC framework has the following form:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.model.ac.nodalMatrix","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Now, let us add a shunt element to Bus 2:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"updateBus!(system; label = \"Bus 2\", conductance = 0.4, susceptance = 0.5)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"As we can observe, executing the function triggers an update of the AC nodal matrix:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.model.ac.nodalMatrix","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#UpdateBranchManual","page":"Power System Model","title":"Update Branch","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Once a branch has been added to the PowerSystem type, users have the flexibility to modify all parameters defined within the addBranch! function. This means that when the updateBranch! function is used, the PowerSystem type within AC and DC models that have been created is updated. This eliminates the need to recreate the AC and DC models from scratch.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"To illustrate, let us continue with the previous example and modify the parameters of Branch 1 as follows:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"updateBranch!(system; label = \"Branch 1\", resistance = 0.012, reactance = 0.3)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"We can observe the update in the AC nodal matrix:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.model.ac.nodalMatrix","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Next, let us switch the status of Branch 2 from in-service to out-of-service:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"updateBranch!(system; label = \"Branch 2\", status = 0)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"As before, the updated AC nodal matrix takes the following form:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.model.ac.nodalMatrix","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Drop-Zeros","page":"Power System Model","title":"Drop Zeros","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"After the last execution of the updateBranch! function, the nodal matrices will contain zeros, as demonstrated in the code example. If needed, the user can remove these zeros using the dropZeros! function, as shown below:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"dropZeros!(system.model.ac)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"note: Info\nIt is worth mentioning that in simulations conducted with the JuliaGrid package, the precision of the outcomes remains unaffected even if zero entries are retained. However, we recommend users utilize this function instead of dropzeros! from the SuiteSparse package to ensure seamless functioning of all JuliaGrid functionalities.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#UpdateGeneratorManual","page":"Power System Model","title":"Update Generator","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Finally, users can update all generator parameters defined within the addGenerator! function using the updateGenerator! function. The execution of this function will affect all variables within the PowerSystem type.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"In short, in addition to the generator field, JuliaGrid also retains variables associated with generators within the bus field. As an example, let us examine one of these variables and its values derived from a previous example:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.bus.supply.active","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Next, we will change the active output power of Generator 1:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"updateGenerator!(system; label = \"Generator 1\", active = 0.9)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"As we can see, executing the function triggers an update of the observed variable:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.bus.supply.active","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Hence, this function ensures the adjustment of generator parameters and updates all fields of the PowerSystem type affected by them.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#AddUpdateCostsManual","page":"Power System Model","title":"Add and Update Costs","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The cost! function is responsible for adding and updating costs associated with the active or reactive power produced by the corresponding generator. These costs are added only if the corresponding generator is defined.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"To start, let us create an example of a power system using the following code:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"using JuliaGrid # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 2\")\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Polynomial-Cost","page":"Power System Model","title":"Polynomial Cost","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Let us define a quadratic polynomial cost function for the active power produced by the Generator 1:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"cost!(system; label = \"Generator 1\", active = 2, polynomial = [1100.0; 500.0; 150.0])","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"In essence, what we have accomplished is the establishment of a cost function depicted as f(P_textg1) = 1100 P_textg1^2 + 500 P_textg1 + 150 through the code provided. In general, when constructing a polynomial cost function, the coefficients must be ordered from the highest degree to the lowest.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The default input units are in per-units (pu), with coefficients of the cost function having units of currency/pu²-hr for 1100, currency/pu-hr for 500, and currency/hr for 150. Therefore, the coefficients are stored exactly as entered:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.generator.cost.active.polynomial[1]","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"By setting active = 2 within the function, we express our intent to specify the active power cost using the active key. By using a value of 2, we signify our preference for employing a polynomial cost model for the associated generator. This flexibility is neccessary when we have also previously defined a piecewise linear cost function for the same generator. In such cases, we can set active = 1 to utilize the piecewise linear cost function to represent the cost of the corresponding generators. Thus, we retain the freedom to choose between these two cost functions according to the requirements of our simulation. Additionally, users have the option to define both piecewise and polynomial costs within a single function call, further enhancing the versatility of the implementation.","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Piecewise-Linear-Cost","page":"Power System Model","title":"Piecewise Linear Cost","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"We can also create a piecewise linear cost function, for example, let us create the reactive power cost function for the same generator using the following code:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"cost!(system; label = \"Generator 1\", reactive = 1, piecewise = [0.11 12.3; 0.15 16.8])\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"The first column denotes the generator's output reactive powers in per-units, while the second column specifies the corresponding costs for the specified reactive power in currency/hr. Thus, the data is stored exactly as entered:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.generator.cost.reactive.piecewise[1]","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"manual/powerSystemModel/#Customizing-Input-Units-for-Keywords-4","page":"Power System Model","title":"Customizing Input Units for Keywords","text":"","category":"section"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Changing input units from per-units (pu) can be particularly useful since cost functions are usually related to SI units. Let us set active powers in megawatts (MW) and reactive powers in megavolt-amperes reactive (MVAr) :","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"@power(MW, MVAr, pu)\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Now, we can add the quadratic polynomial function using megawatts:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"cost!(system; label = \"Generator 1\", active = 2, polynomial = [0.11; 5.0; 150.0])","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"After inspecting the resulting cost data, we can see that it is the same as before:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.generator.cost.active.polynomial[1]","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Similarly, we can define the linear piecewise cost using megavolt-amperes reactive:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"cost!(system; label = \"Generator 1\", reactive = 1, piecewise = [11.0 12.3; 15.0 16.8])\nnothing # hide","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"Upon inspection, we can see that the stored data is the same as before:","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"system.generator.cost.reactive.piecewise[1]","category":"page"},{"location":"manual/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"tip: Tip\nThe cost! function not only adds costs but also allows users to update previously defined cost functions. This functionality is particularly valuable in optimal power flow analyses, as it allows users to modify generator power costs without the need to recreate models from scratch.","category":"page"},{"location":"background/installation/#InstallationGuide","page":"Installation Guide","title":"Installation Guide","text":"","category":"section"},{"location":"background/installation/","page":"Installation Guide","title":"Installation Guide","text":"JuliaGrid is compatible with Julia version 1.9 and later. To get started with JuliaGrid, users should first install Julia and consider using a code editor for a smoother coding experience.","category":"page"},{"location":"background/installation/","page":"Installation Guide","title":"Installation Guide","text":"","category":"page"},{"location":"background/installation/#Install-Julia","page":"Installation Guide","title":"Install Julia","text":"","category":"section"},{"location":"background/installation/","page":"Installation Guide","title":"Installation Guide","text":"Begin by downloading and installing Julia. We can choose either the Current Stable Release or the Long-term Support Release.","category":"page"},{"location":"background/installation/","page":"Installation Guide","title":"Installation Guide","text":"The Current Stable Release is the most recent version of Julia, providing access to the latest features and typically offering better performance. For most users, we recommend installing the Current Stable Release. The Long-term Support Release is an older version of Julia that has continued to receive bug and security fixes. However, it may not have the latest features or performance improvements.","category":"page"},{"location":"background/installation/","page":"Installation Guide","title":"Installation Guide","text":"","category":"page"},{"location":"background/installation/#Install-Code-Editor","page":"Installation Guide","title":"Install Code Editor","text":"","category":"section"},{"location":"background/installation/","page":"Installation Guide","title":"Installation Guide","text":"For a smoother development experience, we recommend using a code editor. While you can write Julia code in any text editor, using an integrated development environment (IDE) makes coding easier and more efficient. We suggest installing Visual Studio Code, which provides excellent support for Julia through its dedicated Julia extension. Visual Studio Code offers features like syntax highlighting, debugging, and autocompletion, making it an ideal choice for both beginners and experienced users.","category":"page"},{"location":"background/installation/","page":"Installation Guide","title":"Installation Guide","text":"The Julia extension for Visual Studio Code includes built-in dynamic autocompletion, inline results, plot pane, integrated REPL, variable view, code navigation, and many other advanced language features. For a step-by-step guide on how to use Julia in Visual Studio Code, you can follow the tutorial available here.","category":"page"},{"location":"background/installation/","page":"Installation Guide","title":"Installation Guide","text":"","category":"page"},{"location":"background/installation/#Install-JuliaGrid","page":"Installation Guide","title":"Install JuliaGrid","text":"","category":"section"},{"location":"background/installation/","page":"Installation Guide","title":"Installation Guide","text":"To get the JuliaGrid package installed, execute the following Julia command:","category":"page"},{"location":"background/installation/","page":"Installation Guide","title":"Installation Guide","text":"import Pkg\nPkg.add(\"JuliaGrid\")","category":"page"},{"location":"background/installation/","page":"Installation Guide","title":"Installation Guide","text":"When a new version of JuliaGrid is released, you can update it with the following command:","category":"page"},{"location":"background/installation/","page":"Installation Guide","title":"Installation Guide","text":"import Pkg\nPkg.update(\"JuliaGrid\")","category":"page"},{"location":"tutorials/pmuStateEstimation/#PMUStateEstimationTutorials","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To initiate the process, let us construct the PowerSystem type and formulate the AC model:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = 1, type = 3, active = 0.5)\naddBus!(system; label = 2, type = 1, reactive = 0.3)\naddBus!(system; label = 3, type = 1, active = 0.5)\n\n@branch(resistance = 0.02, susceptance = 0.04)\naddBranch!(system; label = 1, from = 1, to = 2, reactance = 0.6)\naddBranch!(system; label = 2, from = 1, to = 3, reactance = 0.7)\naddBranch!(system; label = 3, from = 2, to = 3, reactance = 0.2)\n\naddGenerator!(system; label = 1, bus = 1, active = 3.2, reactive = 0.2)\n\nacModel!(system)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To review, we can conceptualize the bus/branch model as the graph denoted by mathcalG = (mathcalN mathcalE), where we have the set of buses mathcalN = 1 dots n, and the set of branches mathcalE subseteq mathcalN times mathcalN within the power system:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝒩 = collect(keys(system.bus.label))\nℰ = [𝒩[system.branch.layout.from] 𝒩[system.branch.layout.to]]","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Following that, we will introduce the Measurement type and incorporate a set of PMUs mathcalM equiv barmathcalP into the graph mathcalG, that capture both bus voltage and branch current phasors. To construct the linear PMU state estimation model, we represent the vector of state variables, as well as phasor measurements, in the rectangular coordinate system. This process of adding measurement devices will be carried out in the State Estimation Model section. Currently, we are only initializing the Measurement type:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"device = measurement()\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"ukw: Notation\nHere, when referring to a vector mathbfa, we use the notation mathbfa = a_i or mathbfa = a_ij, where a_i represents the element related with bus i in mathcalN or measurement i in mathcalM, while a_ij denotes the element related with branch (ij) in mathcalE.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#PMUSEModelTutorials","page":"PMU State Estimation","title":"State Estimation Model","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Initially, PMUs output phasor measurements in polar coordinates. However, these measurements can be interpreted in rectangular coordinates, where the real and imaginary parts of bus voltages and branch current phasors serve as measurements. Additionally, to obtain the linear system of equations, we observe a vector of state variables in rectangular coordinates mathbf x equivmathbfV_textremathbfV_textim:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"mathbfV_mathrmre =bigRe(barV_1)dotsRe(barV_n)big^T, representing the real parts of complex bus voltages,\nmathbfV_mathrmim =bigIm(barV_1)dotsIm(barV_n)big^T, representing the imaginary parts of complex bus voltages.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Consequently, the total number of state variables is 2n. It is worth noting that in this approach to state estimation, we do not require the slack bus.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The primary drawback of this method stems from measurement errors, which are associated with polar coordinates. Consequently, the covariance matrix must be transformed from polar to rectangular coordinates. As a result, errors from a single PMU are correlated, leading to a non-diagonal covariance matrix. Despite this, the covariance matrix is commonly treated as diagonal, impacting the state estimation accuracy in such scenarios.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Hence, the model includes real and imaginary parts of bus voltage and current phasor measurements from the set mathcalM, contributing to the formulation of a linear system of equations:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" mathbfz=mathbfh(mathbf x) + mathbfu","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Here, mathbfh(mathbf x)= h_1(mathbf x), dots, h_k(mathbf x)^T represents the vector of linear measurement functions, where k = 2barmathcalP is the number of measurement functions, mathbfz = z_1dotsz_k^T denotes the vector of measurement values, and mathbfu = u_1dotsu_k^T represents the vector of measurement errors.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"These errors are assumed to follow a Gaussian distribution with a zero mean and covariance matrix bm Sigma. The diagonal elements of bm Sigma correspond to the measurement variances mathbfv = v_1dotsv_k^T, while the off-diagonal elements represent the covariances between the measurement errors mathbfw = w_1dotsw_k^T.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"In summary, upon defining the PMU, each i-th PMU is associated with two measurement functions h_2i-1(mathbf x), h_2i(mathbf x), along with their respective measurement values z_2i-1, z_2i, as well as their variances v_2i-1, v_2i, and possibly covariances w_2i-1, w_2i.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#Bus-Voltage-Phasor-Measurements","page":"PMU State Estimation","title":"Bus Voltage Phasor Measurements","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"When a PMU (V_i theta_i) in barmathcalP is introduced at bus i in mathcalN in this type of state estimation, users specify the measurement values, variances, and measurement functions of vectors as follows:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" mathbfz = z_Re(barV_i) z_Im(barV_i) mathbfv = v_Re(barV_i) v_Im(barV_i) mathbfh(mathbf x) = h_Re(barV_i)(mathbf x) h_Im(barV_i)(mathbf x)","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"For example:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"addPmu!(system, device; label = \"V₂, θ₂\", bus = 2, magnitude = 0.9, angle = -0.1,\nvarianceMagnitude = 1e-5, varianceAngle = 1e-5)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Here, measurement values are obtained according to:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" beginaligned\n z_Re(barV_i) = z_V_i cos z_theta_i\n z_Im(barV_i) = z_V_i sin z_theta_i\n endaligned","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Utilizing the classical theory of propagation of uncertainty [16], the variances can be calculated as follows:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" beginaligned\n v_Re(barV_i) =\n v_V_i left cfracmathrm partial mathrm partial z_V_i (z_V_i cos z_theta_i) right^2 +\n v_theta_i left cfracmathrm partial mathrm partial z_theta_i (z_V_i cos z_theta_i)right^2 =\n v_V_i (cos z_theta_i)^2 + v_theta_i (z_V_i sin z_theta_i)^2\n v_Im(barV_i) =\n v_V_i left cfracmathrm partial mathrm partial z_V_i (z_V_i sin z_theta_i) right^2 +\n v_theta_i left cfracmathrm partial mathrm partial z_theta_i (z_V_i sin z_theta_i)right^2 =\n v_V_i (sin z_theta_i)^2 + v_theta_i (z_V_i cos z_theta_i)^2\n endaligned","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Lastly, the functions defining the bus voltage phasor measurement are:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" beginaligned\n h_Re(barV_i)(mathbf x) = Re(barV_i)\n h_Im(barV_i)(mathbf x) = Im(barV_i)\n endaligned","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The coefficient expressions for measurement functions are as follows:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" cfracmathrm partialh_Re(barV_i)(mathbf x)mathrm partial Re(barV_i)=1 \n cfracmathrm partialh_Im(barV_i)(mathbf x)mathrm partial Im(barV_i)=1","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"In the previous example, the user neglected the covariances between the real and imaginary parts of the measurement. However, if desired, the user can also include them in the state estimation model by specifying the covariances of the vector:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" mathbfw = w_Re(barV_i) w_Im(barV_i)","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"addPmu!(system, device; label = \"V₃, θ₃\", bus = 3, magnitude = 0.9, angle = -0.2,\nvarianceMagnitude = 1e-5, varianceAngle = 1e-5, correlated = true)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Then, the covariances are obtained as follows:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" w_Re(barV_i) = w_Im(barV_i) =\n v_V_i cfracmathrm partial mathrm partial z_V_i (z_V_i cos z_theta_i)\n cfracmathrm partial mathrm partial z_V_i (z_V_i sin z_theta_i) +\n v_theta_i cfracmathrm partial mathrm partial z_theta_i (z_V_i cos z_theta_i)\n cfracmathrm partial mathrm partial z_theta_i (z_V_i sin z_theta_i)","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"which results in the solution:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" w_Re(barV_i) = w_Im(barV_i) = cos z_theta_i sin z_theta_i(v_V_i - v_theta_i z_V_i^2)","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#From-Bus-End-Current-Phasor-Measurements","page":"PMU State Estimation","title":"From-Bus End Current Phasor Measurements","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"If the user chooses to include phasor measurement (I_ij psi_ij) in barmathcalP in the state estimation model, the user will specify the measurement values, variances, and measurement functions of vectors:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" mathbfz = z_Re(barI_ij) z_Im(barI_ij) mathbfv = v_Re(barI_ij) v_Im(barI_ij) mathbfh(mathbf x) = h_Re(barI_ij)(mathbf x) h_Im(barI_ij)(mathbf x)","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"For example:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"addPmu!(system, device; label = \"I₂₃, ψ₂₃\", from = 3, magnitude = 0.3, angle = 0.4,\nvarianceMagnitude = 1e-3, varianceAngle = 1e-4)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Here, measurement values are obtained according to:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" beginaligned\n z_Re(barI_ij) = z_I_ij cos z_psi_ij\n z_Im(barI_ij) = z_I_ij sin z_psi_ij\n endaligned","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Utilizing the classical theory of propagation of uncertainty [16], the variances can be calculated as follows:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" beginaligned\n v_Re(barI_ij) = v_I_ij (cos z_psi_ij)^2 + v_psi_ij (z_I_ij sin z_psi_ij)^2 \n v_Im(barI_ij) = v_I_ij (sin z_psi_ij)^2 + v_psi_ij (z_I_ij cos z_psi_ij)^2\n endaligned","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The functions defining the current phasor measurement at the from-bus end are:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" beginaligned\n h_Re(barI_ij)(mathbf x) = A Re(barV_i) - B Im(barV_i) - left(C cosphi_ij - D sin phi_ijright) Re(barV_j) + left(Csin phi_ij + Dcos phi_ij right) Im(barV_j) \n h_Im(barI_ij)(mathbf x) = B Re(barV_i) + A Im(barV_i) - left(C sin phi_ij + D cosphi_ijright) Re(barV_j) - left(Ccos phi_ij - Dsin phi_ij right)Im(barV_j)\n endaligned","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"where:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" beginaligned\n A = cfracg_ij + g_textsijtau_ij^2\n B = cfracb_ij+b_textsij tau_ij^2\n C = cfracg_ijtau_ij\n D = cfracb_ijtau_ij\n endaligned","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The coefficient expressions for measurement functions are as follows:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" beginaligned\n cfracmathrm partialh_Re(barI_ij)(mathbf x)mathrm partial Re(barV_i) =\n cfracmathrm partialh_Im(barI_ij)(mathbf x)mathrm partial Im(barV_i) = A \n cfracmathrm partialh_Re(barI_ij)(mathbf x) mathrm partial Re(barV_j) =\n cfracmathrm partialh_Im(barI_ij)(mathbf x) mathrm partial Im(barV_j) =\n - left(C cosphi_ij - D sin phi_ijright)\n cfracmathrm partialh_Re(barI_ij)(mathbf x)mathrm partial Im(barV_i) =-\n cfracmathrm partialh_Im(barI_ij)(mathbf x)mathrm partial Re(barV_i) =\n -B \n cfracmathrm partialh_Re(barI_ij)(mathbf x)mathrm partial Im(barV_j) = -\n cfracmathrm partialh_Im(barI_ij)(mathbf x)mathrm partialRe(barV_j) =\n left(Csin phi_ij + D cos phi_ij right)\n endaligned","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"In the previous example, the user neglects the covariances between the real and imaginary parts of the measurement. However, if desired, the user can also include them in the state estimation model by specifying the covariances of the vector:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" mathbfw = w_Re(barI_ij) w_Im(barI_ij)","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"addPmu!(system, device; label = \"I₁₃, ψ₁₃\", from = 2, magnitude = 0.3, angle = -0.5,\nvarianceMagnitude = 1e-5, varianceAngle = 1e-5, correlated = true)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Then, the covariances are obtained as follows:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" w_Re(barI_ij) = w_Im(barI_ij) = sin z_psi_ij cos z_psi_ij(v_I_ij - v_psi_ij z_I_ij^2)","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#To-Bus-End-Current-Phasor-Measurements","page":"PMU State Estimation","title":"To-Bus End Current Phasor Measurements","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"If the user chooses to include phasor measurement (I_ji psi_ji) in barmathcalP in the state estimation model, the user will specify the measurement values, variances, and measurement functions of vectors:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" mathbfz = z_Re(barI_ji) z_Im(barI_ji) mathbfv = v_Re(barI_ji) v_Im(barI_ji) mathbfh(mathbf x) = h_Re(barI_ji)(mathbf x) h_Im(barI_ji)(mathbf x)","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"For example:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"addPmu!(system, device; label = \"I₃₂, ψ₃₂\", to = 3, magnitude = 0.3, angle = -2.9,\nvarianceMagnitude = 1e-5, varianceAngle = 1e-5)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Here, measurement values are obtained according to:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" beginaligned\n z_Re(barI_ji) = z_I_ji cos z_psi_ji\n z_Im(barI_ji) = z_I_ji sin z_psi_ji\n endaligned","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The variances can be calculated as follows:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" beginaligned\n v_Re(barI_ji) = v_I_ji (cos z_psi_ji)^2 + v_psi_ji (z_I_ji sin z_psi_ji)^2 \n v_Im(barI_ji) = v_I_ji (sin z_psi_ji)^2 + v_psi_ji (z_I_ji cos z_psi_ji)^2\n endaligned","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The functions defining the current phasor measurement at the to-bus end are:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" beginaligned\n h_Re(barI_ji)(mathbf x) = tau_ij^2 A Re(barV_j) - tau_ij^2 B Im(barV_j) - left(C cosphi_ij + D sin phi_ijright) Re(barV_i) - left( Csin phi_ij - Dcos phi_ij right) Im(barV_i)\n h_Im(barI_ji)(mathbf x) = tau_ij^2 B Re(barV_j) + tau_ij^2 A Im(barV_j) + left(C sin phi_ij - D cosphi_ij right) Re(barV_i) - left(Ccos phi_ij + Dsin phi_ijright) Im(barV_i)\n endaligned","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The coefficient expressions for measurement functions are as follows:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" beginaligned\n cfracmathrm partialh_Re(barI_ji)(mathbf x)mathrm partial Re(barV_i) =\n cfracmathrm partialh_Im(barI_ji)(mathbf x)mathrm partial Im(barV_i) =\n - left(C cosphi_ij + D sin phi_ijright)\n cfracmathrm partialh_Re(barI_ji)(mathbf x) mathrm partial Re(barV_j) =\n cfracmathrm partialh_Im(barI_ji)(mathbf x) mathrm partial Im(barV_j) = tau_ij^2A\n cfracmathrm partialh_Re(barI_ji)(mathbf x)mathrm partial Im(barV_i) = -\n cfracmathrm partialh_Im(barI_ji)(mathbf x)mathrm partial Re(barV_i) =\n -left(Csin phi_ij - Dcos phi_ij right) \n cfracmathrm partialh_Re(barI_ji)(mathbf x)mathrm partial Im(barV_j) = -\n cfracmathrm partialh_Im(barI_ji)(mathbf x)mathrm partial Re(barV_j) =\n -tau_ij^2B\n endaligned","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"As before, we are neglecting the covariances between the real and imaginary parts of the measurement. If desired, we can include them in the state estimation model by specifying the covariances of the vector:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" mathbfw = w_Re(barI_ji) w_Im(barI_ji)","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"addPmu!(system, device; label = \"I₃₁, ψ₃₁\", to = 2, magnitude = 0.3, angle = 2.5,\nvarianceMagnitude = 1e-5, varianceAngle = 1e-5, correlated = true)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Then, the covariances are obtained as follows:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" w_Re(barI_ji) = w_Im(barI_ji) = sin z_psi_ji cos z_psi_ji(v_I_ji - v_psi_ji z_I_ji^2)","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#PMUSEWLSStateEstimationTutorials","page":"PMU State Estimation","title":"Weighted Least-Squares Estimation","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The solution to the PMU state estimation problem is determined by solving the linear weighted least-squares (WLS) problem, represented by the following formula:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"\tmathbf H^T bm Sigma^-1 mathbf H mathbf x = mathbf H^T bm Sigma^-1 mathbf z","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Here, mathbf z in mathbb R^k denotes the vector of measurement values, mathbf H in mathbb R^k times 2n represents the coefficient matrix, and bm Sigma in mathbb R^k times k is the measurement error covariance matrix.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#Implementation","page":"PMU State Estimation","title":"Implementation","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"JuliaGrid initiates the PMU state estimation framework by setting up the WLS model, as illustrated in the following:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"analysis = pmuStateEstimation(system, device)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#Coefficient-Matrix","page":"PMU State Estimation","title":"Coefficient Matrix","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Using the above-described equations, JuliaGrid forms the coefficient matrix mathbfH in mathbbR^k times 2n:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐇 = analysis.method.coefficient","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"In this matrix, each row corresponds to a specific measurement in the rectangular coordinate system. Therefore, the i-th PMU is associated with the 2i - 1 index of the row, representing the real part of the phasor measurement, while the 2i row corresponds to the imaginary part of the phasor measurement. Columns are ordered based on how the state variables are defined mathbf x equivmathbfV_textremathbfV_textim.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#Precision-Matrix","page":"PMU State Estimation","title":"Precision Matrix","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"JuliaGrid opts not to retain the covariance matrix bm Sigma but rather stores its inverse, the precision or weighting matrix denoted as mathbf W = bm Sigma^-1. The order of these values corresponds to the description provided for the coefficient matrix. Users can access these values using the following command:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐖 = analysis.method.precision","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The precision matrix does not maintain a diagonal form, indicating that correlations between the real and imaginary parts of the phasor measurements are included in the model. To ignore these correlations, simply omit the correlated keyword within the function that adds a PMU. For example:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"device = measurement()\n\n@pmu(label = \"PMU ?\", noise = false)\naddPmu!(system, device; bus = 1, magnitude = 1.0, angle = 0.0)\naddPmu!(system, device; bus = 2, magnitude = 0.87, angle = -0.15)\naddPmu!(system, device; from = 1, magnitude = 0.30, angle = -0.71)\naddPmu!(system, device; from = 2, magnitude = 0.31, angle = -0.49)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Following this, we recreate the WLS state estimation model:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"analysis = pmuStateEstimation(system, device)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Upon inspection, it becomes evident that the precision matrix maintains a diagonal structure:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐖 = analysis.method.precision","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#Mean-Vector","page":"PMU State Estimation","title":"Mean Vector","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To retrieve the vector mathbf z, containing the means of Gaussian distributions for each measurement, users can utilize:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐳 = analysis.method.mean","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"These values represent measurement values in the rectangular coordinate system as described earlier.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#Estimate-of-State-Variables","page":"PMU State Estimation","title":"Estimate of State Variables","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Next, the WLS equation is solved to obtain the estimate of state variables:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"\thatmathbf x = mathbf H^T bm Sigma^-1 mathbf H^-1 mathbf H^T bm Sigma^-1 mathbf z","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"This process is executed using the solve! function:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"solve!(system, analysis)","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The initial step involves the LU factorization of the gain matrix:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"\tmathbf G = mathbf H^T bm Sigma^-1 mathbf H = mathbf L mathbf U","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"tip: Tip\nBy default, JuliaGrid utilizes LU factorization as the primary method to factorize the gain matrix. However, users maintain the flexibility to opt for alternative factorization methods such as LDLt or QR.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Access to the factorized gain matrix is available through:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐋 = analysis.method.factorization.L\n𝐔 = analysis.method.factorization.U","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Finally, JuliaGrid obtains the solution in the rectangular coordinate system and then transforms these solutions into the standard form given in the polar coordinate system.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The estimated bus voltage magnitudes hatmathbf V = hatV_i and angles hatbm Theta = hattheta_i, i in mathcalN, can be retrieved using the variables:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐕 = analysis.voltage.magnitude\n𝚯 = analysis.voltage.angle","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"note: Info\nIt is essential to note that the slack bus does not exist in the case of the PMU state estimation model.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#PMUSEOrthogonalWLSStateEstimationTutorials","page":"PMU State Estimation","title":"Alternative Formulation","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The resolution of the WLS state estimation problem using the conventional method typically progresses smoothly. However, it is widely acknowledged that in certain situations common to real-world systems, this method can be vulnerable to numerical instabilities. Such conditions might impede the algorithm from converging to a satisfactory solution. In such cases, users may opt for an alternative formulation of the WLS state estimation, namely, employing an approach called orthogonal factorization [5, Sec. 3.2]. This approach is suitable when measurement errors are uncorrelated, and the precision matrix remains diagonal.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To address ill-conditioned situations arising from significant differences in measurement variances, users can employ an alternative approach:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"analysis = pmuStateEstimation(system, device, Orthogonal)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To explain the method, we begin with the WLS equation:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"\tmathbf H^T mathbf W mathbf H hatmathbf x = mathbf H^T mathbf W mathbf z","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"where mathbf W = bm Sigma^-1. Subsequently, we can write:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" left(mathbf W^12 mathbf Hright)^T mathbf W^12 mathbf H hatmathbf x = left(mathbf W^12 mathbf Hright)^T mathbf W^12 mathbf z","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Consequently, we have:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" barmathbfH^T barmathbfH hatmathbf x = barmathbfH^T barmathbfz","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"where:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" barmathbfH = mathbf W^12 mathbf H barmathbfz = mathbf W^12 mathbf z","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"At this point, QR factorization is performed on the rectangular matrix:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" barmathbfH = mathbf W^12 mathbf H = mathbfQmathbfR","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Executing this procedure involves the solve! function:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"solve!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Access to the factorized matrix is possible through:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐐 = analysis.method.factorization.Q\n𝐑 = analysis.method.factorization.R","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To obtain the solution, JuliaGrid avoids materializing the orthogonal matrix mathbfQ and proceeds to solve the system, resulting in the estimate of bus voltage magnitudes hatmathbf V = hatV_i and angles hatbm Theta = hattheta_i, where i in mathcalN:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐕 = analysis.voltage.magnitude\n𝚯 = analysis.voltage.angle","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#PMUSEBadDataTutorials","page":"PMU State Estimation","title":"Bad Data Processing","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Besides the state estimation algorithm, one of the essential state estimation routines is the bad data processing, whose main task is to detect and identify measurement errors, and eliminate them if possible. This is usually done by processing the measurement residuals [5, Ch. 5], and typically, the largest normalized residual test is used to identify bad data. The largest normalized residual test is performed after we obtained the solution of the state estimation in the repetitive process of identifying and eliminating bad data measurements one after another [19].","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To illustrate this process, let us introduce a new measurement that contains an obvious outlier:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"addPmu!(system, device; bus = 3, magnitude = 2.5, angle = 0.1)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Subsequently, we will construct the WLS state estimation model and solve it:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"analysis = pmuStateEstimation(system, device)\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Now, the bad data processing can be executed:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"outlier = residualTest!(system, device, analysis; threshold = 4.0)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"In this step, we employ the largest normalized residual test, guided by the analysis outlined in [5, Sec. 5.7]. To be more precise, we compute all measurement residuals in the rectangular coordinate system based on the obtained estimate of state variables:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" r_i = z_i - h_i(hat mathbf x) i in mathcalM","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The normalized residuals for all measurements are computed as follows:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" barr_i = cfracr_isqrtC_ii = cfracr_isqrtS_iiSigma_ii i in mathcalM","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"In this equation, we denote the diagonal entries of the residual covariance matrix mathbf C in mathbbR^k times k as C_ii = S_iiSigma_ii, where S_ii is the diagonal entry of the residual sensitivity matrix mathbf S representing the sensitivity of the measurement residuals to the measurement errors. For this specific configuration, the relationship is expressed as:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" mathbf C = mathbf S bm Sigma = bm Sigma - mathbf H mathbf H^T bm Sigma^-1 mathbf H^-1 mathbf H^T","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"It is important to note that only the diagonal entries of mathbf C are required. To obtain the inverse, the JuliaGrid package utilizes a computationally efficient sparse inverse method, retrieving only the necessary elements of the inverse.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The subsequent step involves selecting the largest normalized residual, and the j-th measurement is then suspected as bad data and potentially removed from the measurement set mathcalM:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" barr_j = textmax barr_i i in mathcalM ","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Users can access this information using the variable:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"outlier.maxNormalizedResidual","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"If the largest normalized residual, denoted as barr_j, satisfies the inequality:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" barr_j ge epsilon","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"the corresponding measurement is identified as bad data and subsequently removed. In this example, the bad data identification threshold is set to epsilon = 4. Users can verify the satisfaction of this inequality by inspecting:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"outlier.detect","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"This indicates that the measurement labeled as:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"outlier.label","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"is removed from the PMU model and marked as out-of-service. Specifically, either the real or imaginary part of the corresponding measurement is identified as the outlier. Consequently, both parts of the measurement are removed from the PMU state estimation model.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Subsequently, we can immediately solve the system again, but this time without the removed measurement:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"solve!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Following that, we check for outliers once more:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"outlier = residualTest!(system, device, analysis; threshold = 4.0)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To examine the value:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"outlier.maxNormalizedResidual","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"As this value is now less than the threshold epsilon = 4, the measurement is not removed, or there are no outliers. This can also be verified by observing the bad data flag:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"outlier.detect","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#PMUSELAVTutorials","page":"PMU State Estimation","title":"Least Absolute Value Estimation","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The least absolute value (LAV) method provides an alternative estimation approach that is considered more robust in comparison to the WLS method. The WLS state estimation problem relies on specific assumptions about measurement errors, whereas robust estimators aim to remain unbiased even in the presence of various types of measurement errors and outliers. This characteristic eliminates the need for bad data processing, as discussed in [5, Ch. 6]. It is important to note that robustness often comes at the cost of increased computational complexity.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"It can be demonstrated that the problem can be expressed as a linear programming problem. This section outlines the method as described in [5, Sec. 6.5]. To revisit, we consider the system of linear equations:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" mathbfz=mathbfh(mathbf x)+mathbfu+mathbfw","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Subsequently, the LAV state estimator is derived as the solution to the optimization problem:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" beginaligned\n textminimize mathbf a^T mathbf r\n textsubjectto mathbfz - mathbfH mathbf x =mathbf r\n endaligned","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Here, mathbf a in mathbb R^k is the vector with all entries equal to one, and mathbf r represents the vector of measurement residuals. Let bm eta be defined in a manner that ensures:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" mathbf r preceq bm eta","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"and replace the above inequality with two equalities using the introduction of two non-negative slack variables mathbf q in mathbb R_ge 0^k and mathbf w in mathbb R_ge 0^k:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" beginaligned\n mathbf r - mathbf q = -bm eta \n mathbf r + mathbf w = bm eta\n endaligned","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Let us now define four additional non-negative variables:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" mathbf x_x in mathbb R_ge 0^n mathbf x_y in mathbb R_ge 0^n \n mathbf r_x in mathbb R_ge 0^k mathbf r_y in mathbb R_ge 0^k","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"where:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" mathbf x = mathbf x_x - mathbf x_y mathbf r = mathbf r_x - mathbf r_y\n mathbf r_x = cfrac12 mathbf q mathbf r_y = cfrac12 mathbf w","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Then, the above two equalities become:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" beginaligned\n mathbf r - 2mathbf r_x = -2bm eta \n mathbf r + 2 mathbf r_y = 2bm eta\n endaligned","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"that is:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" beginaligned\n mathbf r_x + mathbf r_y = bm eta mathbf r = mathbf r_x - mathbf r_y\n endaligned","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Hence, the optimization problem can be written:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" beginaligned\n textminimize mathbf a^T (mathbf r_x + mathbf r_y)\n textsubjectto mathbfH(mathbf x_x - mathbf x_y) + mathbf r_x - mathbf r_y = mathbfz \n mathbf x_x succeq mathbf 0 mathbf x_y succeq mathbf 0 \n mathbf r_x succeq mathbf 0 mathbf r_y succeq mathbf 0\n endaligned","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To form the above optimization problem, the user can call the following function:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"using Ipopt\nusing JuMP # hide\n\nanalysis = pmuLavStateEstimation(system, device, Ipopt.Optimizer)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Then the user can solve the optimization problem by:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"JuMP.set_silent(analysis.method.jump) # hide\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"As a result, we obtain optimal values for the four additional non-negative variables, while the state estimator is obtained by:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" hatmathbf x = mathbf x_x - mathbf x_y","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Users can retrieve the estimated bus voltage magnitudes hatmathbf V = hatV_i and angles hatbm Theta = hattheta_i, i in mathcalN, using:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐕 = analysis.voltage.magnitude\n𝚯 = analysis.voltage.angle","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#optimalpmu","page":"PMU State Estimation","title":"Optimal PMU Placement","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"JuliaGrid utilizes the optimal PMU placement algorithm proposed in [23]. The optimal positioning of PMUs is framed as an integer linear programming problem, expressed as:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" beginaligned\n textminimize sum_i=1^n d_i\n textsubjectto mathbf A mathbf d ge mathbf a\n endaligned","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Here, the vector mathbf d = d_1dotsd_n^T serves as the optimization variable, where d_i in mathbbF = 01 is the PMU placement or a binary decision variable associated with the bus i in mathcalN. The all-one vector mathbf a is of dimension n. The binary connectivity matrix mathbf A in mathbbF^n times n can be directly derived from the bus nodal matrix mathbf Y by converting its entries into binary form [24].","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Consequently, we obtain the binary vector mathbf d = d_1dotsd_n^T, where d_i = 1, i in mathcalN, suggests that a PMU should be placed at bus i. The primary aim of PMU placement in the power system is to determine a minimal set of PMUs such that the entire system is observable without relying on traditional measurements [23]. Specifically, when we observe d_i = 1, it indicates that the PMU is installed at bus i in mathcalN to measure bus voltage phasor as well as all current phasors across branches incident to bus i.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Determining the optimal PMU placement involves analyzing the created power system. For example:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"using GLPK\nusing JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = 1, type = 3, active = 0.5)\naddBus!(system; label = 2, type = 1, reactive = 0.3)\naddBus!(system; label = 3, type = 1, active = 0.5)\n\n@branch(resistance = 0.02, susceptance = 0.04)\naddBranch!(system; label = 1, from = 1, to = 2, reactance = 0.6)\naddBranch!(system; label = 2, from = 1, to = 2, reactance = 0.7)\naddBranch!(system; label = 3, from = 2, to = 3, reactance = 0.2)\n\naddGenerator!(system; label = 1, bus = 1, active = 3.2, reactive = 0.2)\n\nacModel!(system)\nplacement = pmuPlacement(system, GLPK.Optimizer)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The placement variable contains data regarding the optimal placement of measurements. It lists all buses i in mathcalN that satisfy d_i = 1:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"placement.bus","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"This PMU installed at bus 2 will measure the bus voltage phasor at the corresponding bus and all current phasors at the branches incident to bus 2 located at the from-bus or to-bus ends. These data are stored in the variables:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"placement.from\nplacement.to","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#PMUPowerAnalysisTutorials","page":"PMU State Estimation","title":"Power Analysis","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Once the computation of voltage magnitudes and angles at each bus is completed, various electrical quantities can be determined. JuliaGrid offers the power! function, which enables the calculation of powers associated with buses and branches. Here is an example code snippet demonstrating its usage:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"power!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The function stores the computed powers in the rectangular coordinate system. It calculates the following powers related to buses and branches:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Bus Active Reactive\nInjections mathbfP = P_i mathbfQ = Q_i\nGenerator injections mathbfP_textp = P_textpi mathbfQ_textp = Q_textpi\nShunt elements mathbfP_textsh = P_textshi mathbfQ_textsh = Q_textshi","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Branch Active Reactive\nFrom-bus end flows mathbfP_texti = P_ij mathbfQ_texti = Q_ij\nTo-bus end flows mathbfP_textj = P_ji mathbfQ_textj = Q_ji\nShunt elements mathbfP_texts = P_textsij mathbfP_texts = P_textsij\nSeries elements mathbfP_textl = P_textlij mathbfQ_textl = Q_textlij","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"note: Info\nFor a clear comprehension of the equations, symbols presented in this section, as well as for a better grasp of power directions, please refer to the Unified Branch Model.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#Power-Injections","page":"PMU State Estimation","title":"Power Injections","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Active and reactive power injections are stored as the vectors mathbfP = P_i and mathbfQ = Q_i, respectively, and can be retrieved using the following commands:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐏 = analysis.power.injection.active\n𝐐 = analysis.power.injection.reactive","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#PMUGeneratorPowerInjectionsManual","page":"PMU State Estimation","title":"Generator Power Injections","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"We can calculate the active and reactive power injections supplied by generators at each bus i in mathcalN by summing the active and reactive power injections and the active and reactive power demanded by consumers at each bus:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":" beginaligned\n P_textpi = P_i + P_textdi\n Q_textpi = Q_i + Q_textdi\n endaligned","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The active and reactive power injections from the generators at each bus are stored as vectors, denoted by mathbfP_textp = P_textpi and mathbfQ_textp = Q_textpi, which can be obtained using:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐏ₚ = analysis.power.supply.active\n𝐐ₚ = analysis.power.supply.reactive","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#Power-at-Bus-Shunt-Elements","page":"PMU State Estimation","title":"Power at Bus Shunt Elements","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Active and reactive powers associated with the shunt elements at each bus are represented by the vectors mathbfP_textsh = P_textshi and mathbfQ_textsh = Q_textshi. To retrieve these powers in JuliaGrid, use the following commands:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐏ₛₕ = analysis.power.shunt.active\n𝐐ₛₕ = analysis.power.shunt.reactive","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#Power-Flows","page":"PMU State Estimation","title":"Power Flows","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The resulting active and reactive power flows at each from-bus end are stored as the vectors mathbfP_texti = P_ij and mathbfQ_texti = Q_ij respectively, and can be retrieved using the following commands:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐏ᵢ = analysis.power.from.active\n𝐐ᵢ = analysis.power.from.reactive","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Similarly, the vectors of active and reactive power flows at the to-bus end are stored as mathbfP_textj = P_ji and mathbfQ_textj = Q_ji, respectively, and can be retrieved using the following code:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐏ⱼ = analysis.power.to.active\n𝐐ⱼ = analysis.power.to.reactive","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#Power-at-Branch-Shunt-Elements","page":"PMU State Estimation","title":"Power at Branch Shunt Elements","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Active and reactive powers associated with the branch shunt elements at each branch are represented by the vectors mathbfP_texts = P_textsij and mathbfQ_texts = Q_textsij. We can retrieve these values using the following code:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐏ₛ = analysis.power.charging.active\n𝐐ₛ = analysis.power.charging.reactive","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#Power-at-Branch-Series-Elements","page":"PMU State Estimation","title":"Power at Branch Series Elements","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Active and reactive powers associated with the branch series element at each branch are represented by the vectors mathbfP_textl = P_textlij and mathbfQ_textl = Q_textlij. We can retrieve these values using the following code:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐏ₗ = analysis.power.series.active\n𝐐ₗ = analysis.power.series.reactive","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#PMUCurrentAnalysisTutorials","page":"PMU State Estimation","title":"Current Analysis","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"JuliaGrid offers the current! function, which enables the calculation of currents associated with buses and branches. Here is an example code snippet demonstrating its usage:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"current!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The function stores the computed currents in the polar coordinate system. It calculates the following currents related to buses and branches:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Bus Magnitude Angle\nInjections mathbfI = I_i bmpsi = psi_i","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Branch Magnitude Angle\nFrom-bus end flows mathbfI_texti = I_ij bmpsi_texti = psi_ij\nTo-bus end flows mathbfI_textj = I_ji bmpsi_textj = psi_ji\nSeries elements mathbfI_textl = I_textlij bmpsi_textl = psi_textlij","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"note: Info\nFor a clear comprehension of the equations, symbols presented in this section, as well as for a better grasp of power directions, please refer to the Unified Branch Model.","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#Current-Injections","page":"PMU State Estimation","title":"Current Injections","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"In JuliaGrid, complex current injections are stored in the vector of magnitudes denoted as mathbfI = I_i and the vector of angles represented as bmpsi = psi_i. You can retrieve them using the following commands:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐈 = analysis.current.injection.magnitude\n𝛙 = analysis.current.injection.angle","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#Current-Flows","page":"PMU State Estimation","title":"Current Flows","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To obtain the vectors of magnitudes mathbfI_texti = I_ij and angles bmpsi_texti = psi_ij for the resulting complex current flows, you can use the following commands:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐈ᵢ = analysis.current.from.magnitude\n𝛙ᵢ = analysis.current.from.angle","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Similarly, we can obtain the vectors of magnitudes mathbfI_textj = I_ji and angles bmpsi_textj = psi_ji of the resulting complex current flows using the following code:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐈ⱼ = analysis.current.to.magnitude\n𝛙ⱼ = analysis.current.to.angle","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"tutorials/pmuStateEstimation/#Current-at-Branch-Series-Elements","page":"PMU State Estimation","title":"Current at Branch Series Elements","text":"","category":"section"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To obtain the vectors of magnitudes mathbfI_textl = I_textlij and angles bmpsi_textl = psi_textlij of the resulting complex current flows, one can use the following code:","category":"page"},{"location":"tutorials/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"𝐈ₗ = analysis.current.series.magnitude\n𝛙ₗ = analysis.current.series.angle","category":"page"},{"location":"api/powerFlow/#PowerFlowAPI","page":"Power Flow","title":"Power Flow","text":"","category":"section"},{"location":"api/powerFlow/","page":"Power Flow","title":"Power Flow","text":"For further information on this topic, please see the AC Power Flow or DC Power Flow sections of the Manual. Below, we have provided a list of functions that can be utilized for power flow analysis.","category":"page"},{"location":"api/powerFlow/","page":"Power Flow","title":"Power Flow","text":"To load power flow API functionalities into the current scope, utilize the following command:","category":"page"},{"location":"api/powerFlow/","page":"Power Flow","title":"Power Flow","text":"using JuliaGrid","category":"page"},{"location":"api/powerFlow/","page":"Power Flow","title":"Power Flow","text":"","category":"page"},{"location":"api/powerFlow/#AC-Power-Flow","page":"Power Flow","title":"AC Power Flow","text":"","category":"section"},{"location":"api/powerFlow/","page":"Power Flow","title":"Power Flow","text":"newtonRaphson\nfastNewtonRaphsonBX\nfastNewtonRaphsonXB\ngaussSeidel\nmismatch!\nsolve!\nstartingVoltage!\nreactiveLimit!\nadjustAngle!","category":"page"},{"location":"api/powerFlow/#DC-Power-Flow","page":"Power Flow","title":"DC Power Flow","text":"","category":"section"},{"location":"api/powerFlow/","page":"Power Flow","title":"Power Flow","text":"dcPowerFlow\nsolve!","category":"page"},{"location":"api/powerFlow/","page":"Power Flow","title":"Power Flow","text":"","category":"page"},{"location":"api/powerFlow/#AC-Power-Flow-2","page":"Power Flow","title":"AC Power Flow","text":"","category":"section"},{"location":"api/powerFlow/","page":"Power Flow","title":"Power Flow","text":"newtonRaphson\nfastNewtonRaphsonBX\nfastNewtonRaphsonXB\ngaussSeidel\nmismatch!(::PowerSystem, ::ACPowerFlow{NewtonRaphson})\nsolve!(::PowerSystem, ::ACPowerFlow{NewtonRaphson})\nstartingVoltage!\nreactiveLimit!\nadjustAngle!","category":"page"},{"location":"api/powerFlow/#JuliaGrid.newtonRaphson","page":"Power Flow","title":"JuliaGrid.newtonRaphson","text":"newtonRaphson(system::PowerSystem, [factorization::Factorization = LU])\n\nThe function sets up the Newton-Raphson method to solve the AC power flow.\n\nArguments\n\nThe function requires the PowerSystem composite type to establish the framework. Next, the Factorization argument, while optional, determines the method used to solve the linear system of equations within each iteration. It can take one of the following values:\n\nLU: utilizes LU factorization (default),\nQR: utilizes QR factorization.\n\nUpdates\n\nIf the AC model has not been created, the function automatically initiates an update within the ac field of the PowerSystem type. It also performs a check on bus types and rectifies any mistakes present.\n\nReturns\n\nThe function returns an instance of the ACPowerFlow type, which includes the following fields:\n\nvoltage: The bus voltage magnitudes and angles.\npower: The variable allocated to store the active and reactive powers.\ncurrent: The variable allocated to store the currents.\nmethod: The Jacobian matrix, its factorization, mismatches, increments, and indices.\n\nExamples\n\nSet up the Newton-Raphson method utilizing LU factorization:\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = newtonRaphson(system)\n\nSet up the Newton-Raphson method utilizing QR factorization:\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = newtonRaphson(system, QR)\n\n\n\n\n\n","category":"function"},{"location":"api/powerFlow/#JuliaGrid.fastNewtonRaphsonBX","page":"Power Flow","title":"JuliaGrid.fastNewtonRaphsonBX","text":"fastNewtonRaphsonBX(system::PowerSystem, [factorization::Factorization = LU])\n\nThe function sets up the fast Newton-Raphson method of version BX to solve the AC power flow.\n\nArguments\n\nThe function requires the PowerSystem composite type to establish the framework. Next, the Factorization argument, while optional, determines the method used to solve the linear system of equations within each iteration. It can take one of the following values:\n\nLU: utilizes LU factorization (default),\nQR: utilizes QR factorization.\n\nUpdates\n\nIf the AC model has not been created, the function automatically initiates an update within the ac field of the PowerSystem type. It also performs a check on bus types and rectifies any mistakes present.\n\nReturns\n\nThe function returns an instance of the ACPowerFlow type, which includes the following fields:\n\nvoltage: The bus voltage magnitudes and angles.\npower: The variable allocated to store the active and reactive powers.\ncurrent: The variable allocated to store the currents.\nmethod: The Jacobian matrices, their factorizations, mismatches, increments, and indices.\n\nExamples\n\nSet up the fast Newton-Raphson method utilizing LU factorization:\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = fastNewtonRaphsonBX(system)\n\nSet up the fast Newton-Raphson method utilizing QR factorization:\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = fastNewtonRaphsonBX(system, QR)\n\n\n\n\n\n","category":"function"},{"location":"api/powerFlow/#JuliaGrid.fastNewtonRaphsonXB","page":"Power Flow","title":"JuliaGrid.fastNewtonRaphsonXB","text":"fastNewtonRaphsonXB(system::PowerSystem, [factorization::Factorization = LU])\n\nThe function sets up the fast Newton-Raphson method of version XB to solve the AC power flow.\n\nArguments\n\nThe function requires the PowerSystem composite type to establish the framework. Next, the Factorization argument, while optional, determines the method used to solve the linear system of equations within each iteration. It can take one of the following values:\n\nLU: utilizes LU factorization (default),\nQR: utilizes QR factorization.\n\nUpdates\n\nIf the AC model has not been created, the function automatically initiates an update within the ac field of the PowerSystem type. It also performs a check on bus types and rectifies any mistakes present.\n\nReturns\n\nThe function returns an instance of the ACPowerFlow type, which includes the following fields:\n\nvoltage: The bus voltage magnitudes and angles.\npower: The variable allocated to store the active and reactive powers.\ncurrent: The variable allocated to store the currents.\nmethod: The Jacobian matrices, their factorizations, mismatches, increments, and indices.\n\nExamples\n\nSet up the fast Newton-Raphson method utilizing LU factorization:\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = fastNewtonRaphsonXB(system)\n\nSet up the fast Newton-Raphson method utilizing QR factorization:\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = fastNewtonRaphsonXB(system, QR)\n\n\n\n\n\n","category":"function"},{"location":"api/powerFlow/#JuliaGrid.gaussSeidel","page":"Power Flow","title":"JuliaGrid.gaussSeidel","text":"gaussSeidel(system::PowerSystem)\n\nThe function sets up the Gauss-Seidel method to solve the AC power flow.\n\nArguments\n\nThe function requires the PowerSystem composite type to establish the framework.\n\nUpdates\n\nIf the AC model has not been created, the function automatically initiates an update within the ac field of the PowerSystem type. It also performs a check on bus types and rectifies any mistakes present.\n\nReturns\n\nThe function returns an instance of the ACPowerFlow type, which includes the following fields:\n\nvoltage: The bus voltage magnitudes and angles.\npower: The variable allocated to store the active and reactive powers.\ncurrent: The variable allocated to store the currents.\nmethod: The bus complex voltages and indices.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = gaussSeidel(system)\n\n\n\n\n\n","category":"function"},{"location":"api/powerFlow/#JuliaGrid.mismatch!-Tuple{PowerSystem, ACPowerFlow{NewtonRaphson}}","page":"Power Flow","title":"JuliaGrid.mismatch!","text":"mismatch!(system::PowerSystem, analysis::ACPowerFlow)\n\nThe function calculates both active and reactive power injection mismatches.\n\nUpdates\n\nThis function updates the mismatch variables in the Newton-Raphson and fast Newton-Raphson methods. It should be employed during the iteration loop before invoking the solve! function.\n\nReturns\n\nThe function returns maximum absolute values of the active and reactive power injection mismatches, which can be utilized to terminate the iteration loop of the Newton-Raphson, fast Newton-Raphson, or Gauss-Seidel methods employed to solve the AC power flow problem.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = newtonRaphson(system)\nmismatch!(system, analysis)\n\n\n\n\n\n","category":"method"},{"location":"api/powerFlow/#JuliaGrid.solve!-Tuple{PowerSystem, ACPowerFlow{NewtonRaphson}}","page":"Power Flow","title":"JuliaGrid.solve!","text":"solve!(system::PowerSystem, analysis::ACPowerFlow)\n\nThe function employs the Newton-Raphson, fast Newton-Raphson, or Gauss-Seidel method to solve the AC power flow model and calculate bus voltage magnitudes and angles.\n\nAfter the mismatch! function is called, this function should be executed to perform a single iteration of the method.\n\nUpdates\n\nThe calculated voltages are stored in the voltage field of the ACPowerFlow type.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\n\n\n\n\n\n","category":"method"},{"location":"api/powerFlow/#JuliaGrid.startingVoltage!","page":"Power Flow","title":"JuliaGrid.startingVoltage!","text":"startingVoltage!(system::PowerSystem, analysis::ACPowerFlow)\n\nThe function extracts bus voltage magnitudes and angles from the PowerSystem composite type and assigns them to the ACPowerFlow type, enabling users to initialize voltage values as required.\n\nUpdates\n\nThis function only updates the voltage field of the ACPowerFlow type.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\n\nupdateBus!(system, analysis; label = 14, reactive = 0.13, magnitude = 1.2, angle = -0.17)\n\nstartingVoltage!(system, analysis)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\n\n\n\n\n\n","category":"function"},{"location":"api/powerFlow/#JuliaGrid.reactiveLimit!","page":"Power Flow","title":"JuliaGrid.reactiveLimit!","text":"reactiveLimit!(system::PowerSystem, analysis::ACPowerFlow)\n\nThe function verifies whether the generators in a power system exceed their reactive power limits. This is done by setting the reactive power of the generators to within the limits if they are violated after determining the bus voltage magnitudes and angles. If the limits are violated, the corresponding generator buses or the slack bus are converted to demand buses.\n\nUpdates\n\nThe function assigns values to the generator.output.active and bus.supply.active variables of the PowerSystem type.\n\nAdditionally, it examines the reactive powers of the generators and adjusts them to their maximum or minimum values if they exceed the specified threshold. This results in the modification of the variable generator.output.reactive of the PowerSystem type accordingly.\n\nAs a result of this adjustment, the bus.supply.reactive variable is also updated, and the bus types specified in bus.layout.type are modified. If the slack bus is converted, the bus.layout.slack field is correspondingly adjusted.\n\nReturns\n\nThe function returns the variable to indicate which buses violate the limits, with -1 indicating a violation of the minimum limits and 1 indicating a violation of the maximum limits.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\n\nviolate = reactiveLimit!(system, analysis)\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\n\n\n\n\n\n","category":"function"},{"location":"api/powerFlow/#JuliaGrid.adjustAngle!","page":"Power Flow","title":"JuliaGrid.adjustAngle!","text":"adjustAngle!(system::PowerSystem, analysis::ACPowerFlow; slack)\n\nThe function modifies the bus voltage angles based on a different slack bus than the one identified by the bus.layout.slack field.\n\nFor instance, if the reactive power of the generator exceeds the limit on the slack bus, the reactiveLimit! function will change that bus to the demand bus and designate the first generator bus in the sequence as the new slack bus. After obtaining the updated AC power flow solution based on the new slack bus, it is possible to adjust the voltage angles to align with the angle of the original slack bus.\n\nKeyword\n\nThe slack keyword specifies the bus label for which we want to adjust voltage angles.\n\nUpdates\n\nThis function only updates the voltage.angle variable of the ACPowerFlow type.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\n\nreactiveLimit!(system, analysis)\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\n\nadjustAngle!(system, analysis; slack = 1)\n\n\n\n\n\n","category":"function"},{"location":"api/powerFlow/","page":"Power Flow","title":"Power Flow","text":"","category":"page"},{"location":"api/powerFlow/#DC-Power-Flow-2","page":"Power Flow","title":"DC Power Flow","text":"","category":"section"},{"location":"api/powerFlow/","page":"Power Flow","title":"Power Flow","text":"dcPowerFlow\nsolve!(::PowerSystem, ::DCPowerFlow)","category":"page"},{"location":"api/powerFlow/#JuliaGrid.dcPowerFlow","page":"Power Flow","title":"JuliaGrid.dcPowerFlow","text":"dcPowerFlow(system::PowerSystem, [factorization::Factorization = LU])\n\nThe function sets up the framework to solve the DC power flow.\n\nArguments\n\nThe function requires the PowerSystem composite type to establish the framework. Next, the Factorization argument, while optional, determines the method used to solve the linear system of equations. It can take one of the following values:\n\nLU: utilizes LU factorization (default),\nLDLt: utilizes LDLt factorization,\nQR: utilizes QR factorization.\n\nUpdates\n\nIf the DC model was not created, the function will automatically initiate an update of the dc field within the PowerSystem composite type. Additionally, if the slack bus lacks an in-service generator, JuliaGrid considers it a mistake and defines a new slack bus as the first generator bus with an in-service generator in the bus type list.\n\nReturns\n\nThe function returns an instance of the DCPowerFlow type, which includes the following fields:\n\nvoltage: The variable allocated to store the bus voltage angles.\npower: The variable allocated to store the active powers.\nmethod: The factorized nodal matrix.\n\nExamples\n\nSet up the DC power flow utilizing LU factorization:\n\nsystem = powerSystem(\"case14.h5\")\ndcModel!(system)\n\nanalysis = dcPowerFlow(system)\n\nSet up the DC power flow utilizing QR factorization:\n\nsystem = powerSystem(\"case14.h5\")\ndcModel!(system)\n\nanalysis = dcPowerFlow(system, QR)\n\n\n\n\n\n","category":"function"},{"location":"api/powerFlow/#JuliaGrid.solve!-Tuple{PowerSystem, DCPowerFlow}","page":"Power Flow","title":"JuliaGrid.solve!","text":"solve!(system::PowerSystem, analysis::DCPowerFlow)\n\nThe function solves the DC power flow model and calculates bus voltage angles.\n\nUpdates\n\nThe calculated voltage angles are stored in the voltage field of the DCPowerFlow type.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndcModel!(system)\n\nanalysis = dcPowerFlow(system)\nsolve!(system, analysis)\n\n\n\n\n\n","category":"method"},{"location":"tutorials/acStateEstimation/#ACStateEstimationTutorials","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To initiate the process, let us construct the PowerSystem type and formulate the AC model:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = 1, type = 3, active = 0.5)\naddBus!(system; label = 2, type = 1, reactive = 0.3)\naddBus!(system; label = 3, type = 1, active = 0.5)\n\n@branch(resistance = 0.02, susceptance = 0.04)\naddBranch!(system; label = 1, from = 1, to = 2, reactance = 0.6)\naddBranch!(system; label = 2, from = 1, to = 3, reactance = 0.7)\naddBranch!(system; label = 3, from = 2, to = 3, reactance = 0.2)\n\naddGenerator!(system; label = 1, bus = 1, active = 3.2, reactive = 0.2)\n\nacModel!(system)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To review, we can conceptualize the bus/branch model as the graph denoted by mathcalG = (mathcalN mathcalE), where we have the set of buses mathcalN = 1 dots n, and the set of branches mathcalE subseteq mathcalN times mathcalN within the power system:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝒩 = collect(keys(system.bus.label))\nℰ = [𝒩[system.branch.layout.from] 𝒩[system.branch.layout.to]]","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Following that, we will introduce the Measurement type and incorporate a set of measurement devices mathcalM into the graph mathcalG. The AC state estimation includes a set of voltmeters mathcalV, ammeters mathcalI, wattmeters mathcalP, varmeters mathcalQ, and PMUs barmathcalP, with PMUs being able to integrate into AC state estimation in either rectangular coordinates or polar coordinates. This process of adding measurement devices will be carried out in the State Estimation Model section. Currently, we are only initializing the Measurement type at this stage:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"device = measurement()\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"ukw: Notation\nHere, when referring to a vector mathbfa, we use the notation mathbfa = a_i or mathbfa = a_ij, where a_i represents the element related with bus i in mathcalN or measurement i in mathcalM, while a_ij denotes the element related with branch (ij) in mathcalE.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#ACSEModelTutorials","page":"AC State Estimation","title":"State Estimation Model","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"In accordance with the AC Model, the AC state estimation treats bus voltages as state variables, which we denoted by mathbf x equiv bm Theta mathbfV^T. The state vector encompasses two components:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"bm Theta in mathbbR^n-1, representing bus voltage angles,\nmathbf V in mathbbR^n, representing bus voltage magnitudes.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Consequently, the total number of state variables is n_textu = 2n-1, accounting for the fact that the voltage angle for the slack bus is known.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Within the JuliaGrid framework for AC state estimation, the methodology encompasses bus voltage magnitudes, branch current magnitudes, active powers, reactive powers, and phasor measurements. These measurements contribute to the construction of a nonlinear system of equations:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfz=mathbfh(mathbf x) + mathbfu","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Here, mathbfh(mathbf x)= h_1(mathbf x), dots, h_k(mathbf x)^T represents the vector of nonlinear measurement functions, where k is the number of measurements, mathbfz = z_1dotsz_k^T denotes the vector of measurement values, and mathbfu = u_1dotsu_k^T represents the vector of measurement errors. It is worth noting that the number of equations in the system is equal to k = mathcalV cup mathcalI cup mathcalP cup mathcalQ + 2barmathcalP.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"These errors are assumed to follow a Gaussian distribution with a zero mean and covariance matrix bm Sigma. The diagonal elements of bm Sigma correspond to the measurement variances mathbfv = v_1dotsv_k^T, while the off-diagonal elements represent the covariances between the measurement errors mathbfw = w_1dotsw_k^T. These covariances exist only if PMUs are observed in rectangular coordinates and correlation is required.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Hence, the nonlinear system of equations is structured according to the specific devices:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginbmatrix\n mathbfz_mathcalV3pt\n mathbfz_mathcalI3pt\n mathbfz_mathcalP3pt\n mathbfz_mathcalQ3pt\n mathbfz_barmathcalP\n endbmatrix =\n beginbmatrix\n mathbfh_mathcalV(mathbf x)3pt\n mathbfh_mathcalI(mathbf x)3pt\n mathbfh_mathcalP(mathbf x)3pt\n mathbfh_mathcalQ(mathbf x)3pt\n mathbfh_barmathcalP(mathbf x)\n endbmatrix +\n beginbmatrix\n mathbfu_mathcalV3pt\n mathbfu_mathcalI3pt\n mathbfu_mathcalP3pt\n mathbfu_mathcalQ3pt\n mathbfu_barmathcalP\n endbmatrix","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Please note that each error vector, denoted as mathbfu_i, where i in mathcalV mathcalI mathcalP mathcalQ, is associated with the variance vector mathbfv_i. However, for PMUs, the error vector mathbfu_barmathcalP, along with its variance vector mathbfv_barmathcalP, can also be associated with the covariance vector mathbfw_barmathcalP.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"In summary, upon user definition of the measurement devices, each i-th legacy measurement device is linked to the measurement function h_i(mathbf x), the corresponding measurement value z_i, and the measurement variance v_i. Meanwhile, each i-th PMU is associated with two measurement functions h_2i-1(mathbf x), h_2i(mathbf x), along with their respective measurement values z_2i-1, z_2i, as well as their variances v_2i-1, v_2i, and possibly covariances w_2i-1, w_2i.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Typically, the AC state estimator is obtained using the Gauss-Newton method or its variation, which involves constructing the Jacobian matrix. Therefore, in addition to the aforementioned elements, we also need Jacobian expressions corresponding to the measurement functions, which are also provided below.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Bus-Voltage-Magnitude-Measurements","page":"AC State Estimation","title":"Bus Voltage Magnitude Measurements","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"When introducing a voltmeter V_i in mathcalV at bus i in mathcalN, users specify the measurement value, variance, and measurement function of vectors:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfz_mathcalV = z_V_i mathbfv_mathcalV = v_V_i mathbfh_mathcalV(mathbf x) = h_V_i(mathbf x)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"For example:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addVoltmeter!(system, device; label = \"V₁\", bus = 1, magnitude = 1.0, variance = 1e-3)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Here, the bus voltage magnitude measurement function is simply defined as:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" h_V_i(mathbf x) = V_i","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"with the following Jacobian expression:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" \tcfracmathrm partialh_V_i(mathbf x) mathrm partial V_i=1","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#FromCurrentMagnitudeMeasurements","page":"AC State Estimation","title":"From-Bus End Current Magnitude Measurements","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"When introducing an ammeter at branch (ij) in mathcalE, it can be placed at the from-bus end, denoted as I_ij in mathcalI, specifying the measurement value, variance, and measurement function of vectors:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfz_mathcalI = z_I_ij mathbfv_mathcalI = v_I_ij mathbfh_mathcalI(mathbf x) = h_I_ij(mathbf x)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"For example:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addAmmeter!(system, device; label = \"I₁₂\", from = 1, magnitude = 0.3, variance = 1e-2)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Here, following the guidelines outlined in the AC Model, the function defining the current magnitude at the from-bus end is expressed as:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" h_I_ij(mathbf x) = sqrtA_I_ijV_i^2 + B_I_ijV_j^2 - 2C_I_ij cos(theta_ij - phi_ij) - D_I_ijsin(theta_ij - phi_ij)V_iV_j","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"where:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" begingathered\n A_I_ij = cfrac(g_ij + g_textsi)^2+(b_ij+b_textsi)^2tau_ij^4 B_I_ij = cfracg_ij^2+b_ij^2tau_ij^2 \n C_I_ij = cfracg_ij(g_ij+g_textsi)+b_ij(b_ij+b_textsi)tau_ij^3 D_I_ij = cfracg_ijb_textsi - b_ijg_textsitau_ij^3\n endgathered","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Jacobian expressions corresponding to the measurement function h_I_ij(mathbf x) are defined as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n cfracmathrm partialh_I_ij(mathbf x)mathrm partial theta_i =-\n cfracmathrm partialh_I_ij(mathbf x)mathrm partial theta_j =\n cfrac C_I_ijsin(theta_ij - phi_ij) + D_I_ijcos(theta_ij - phi_ij)V_i V_jh_I_ij(mathbf x) \n cfracmathrm partialh_I_ij(mathbf x)mathrm partial V_i =\n cfracA_I_ijV_i - C_I_ijcos(theta_ij - phi_ij) - D_I_ijsin(theta_ij - phi_ij)V_jh_I_ij(mathbf x) \n cfracmathrm partialh_I_ij(mathbf x)mathrm partial V_j =\n cfracB_I_ijV_j - C_I_ijcos(theta_ij - phi_ij) - D_I_ijsin(theta_ij - phi_ij)V_ih_I_ij(mathbf x) \n\tendaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#ToCurrentMagnitudeMeasurements","page":"AC State Estimation","title":"To-Bus End Current Magnitude Measurements","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"In addition to the scenario where we add ammeters at the from-bus end, an ammeter can also be positioned at the to-bus end, denoted as I_ji in mathcalI, specifying the measurement value, variance, and measurement function of vectors:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfz_mathcalI = z_I_ji mathbfv_mathcalI = v_I_ji mathbfh_mathcalI(mathbf x) = h_I_ji(mathbf x)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"For example:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addAmmeter!(system, device; label = \"I₂₁\", to = 1, magnitude = 0.3, variance = 1e-3)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Now, the measurement function is as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" h_I_ji(mathbf x) = sqrtA_I_jiV_i^2 + B_I_jiV_j^2 - 2C_I_ji cos(theta_ij - phi_ij) + D_I_jisin(theta_ij - phi_ij)V_iV_j","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"where:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" begingathered\n A_I_ji = cfracg_ij^2+b_ij^2tau_ij^2 B_I_ji = (g_ij + g_textsi)^2+(b_ij+b_textsi)^2 \n C_I_ji = cfracg_ij(g_ij+g_textsi)+b_ij(b_ij+b_textsi)tau_ij D_I_ji = cfracg_ijb_textsi - b_ijg_textsitau_ij\n endgathered","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Jacobian expressions corresponding to the measurement function h_I_ji(mathbf x) are defined as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n cfracmathrm partialh_I_ji(mathbf x)mathrm partial theta_i =-\n cfracmathrm partialh_I_ji(mathbf x)mathrm partial theta_j =\n cfracC_I_jisin(theta_ij - phi_ij) - D_I_jicos(theta_ij- phi_ij)V_i V_jh_I_ji(mathbf x) \n cfracmathrm partialh_I_ji(mathbf x)mathrm partial V_i =\n cfracA_I_jiV_i - C_I_jicos(theta_ij - phi_ij) + D_I_jisin(theta_ij - phi_ij)V_jh_I_ji(mathbf x) \n cfracmathrm partialh_I_ji(mathbf x)mathrm partial V_j =\n cfracB_I_jiV_j - C_I_jicos(theta_ij - phi_ij) + D_I_jisin(theta_ij - phi_ij)V_ih_I_ji(mathbf x) \n\tendaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Active-Power-Injection-Measurements","page":"AC State Estimation","title":"Active Power Injection Measurements","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"When adding a wattmeter P_i in mathcalP at bus i in mathcalN, users specify that the wattmeter measures active power injection and define measurement value, variance, and measurement function of vectors:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfz_mathcalP = z_P_i mathbfv_mathcalP = v_P_i mathbfh_mathcalP(mathbf x) = h_P_i(mathbf x)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"For example:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addWattmeter!(system, device; label = \"P₃\", bus = 3, active = -0.5, variance = 1e-3)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Here, utilizing the AC Model, we derive the function defining the active power injection as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" h_P_i(mathbf x) = V_isumlimits_j in mathcalN_i (G_ijcostheta_ij + B_ijsintheta_ij)V_j","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"where mathcalN_i contains buses incident to bus i, including bus i, with the following Jacobian expressions:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n cfracmathrm partialh_P_i(mathbf x)mathrm partial theta_i =\n V_isum_j in mathcalN_i (-G_ijsintheta_ij+B_ijcostheta_ij)V_j - B_iiV_i^2\n cfracmathrm partialh_P_i(mathbf x)mathrm partial theta_j =\n (G_ijsintheta_ij-B_ijcostheta_ij)V_iV_j \n cfracmathrm partialh_P_i(mathbf x)mathrm partial V_i =\n sum_j in mathcalN_i (G_ijcostheta_ij+B_ij sintheta_ij)V_j + G_ii V_i\n cfracmathrm partialh_P_i(mathbf x)mathrm partial V_j =\n (G_ijcostheta_ij+B_ijsintheta_ij)V_i\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#From-Bus-End-Active-Power-Flow-Measurements","page":"AC State Estimation","title":"From-Bus End Active Power Flow Measurements","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Additionally, when introducing a wattmeter at branch (ij) in mathcalE, users specify that the wattmeter measures active power flow. It can be positioned at the from-bus end, denoted as P_ij in mathcalP, specifying the measurement value, variance, and measurement function of vectors:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfz_mathcalP = z_P_ij mathbfv_mathcalP = v_P_ij mathbfh_mathcalP(mathbf x) = h_P_ij(mathbf x)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"For example:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addWattmeter!(system, device; label = \"P₁₂\", from = 1, active = 0.2, variance = 1e-4)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Here, the function describing active power flow at the from-bus end is defined as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" h_P_ij(mathbf x) = cfracg_ij + g_textsitau_ij^2 V_i^2 - cfrac1tau_ij leftg_ijcos(theta_ij - phi_ij) + b_ijsin(theta_ij - phi_ij)rightV_iV_j","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"with the following Jacobian expressions:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n cfracmathrm partialh_P_ij(mathbf x)mathrm partial theta_i =-\n cfracmathrm partialh_P_ij(mathbf x)mathrm partial theta_j =\n cfrac1tau_ij leftg_ijsin(theta_ij - phi_ij) - b_ijcos(theta_ij - phi_ij)right V_iV_j \n cfracmathrm partialh_P_ij(mathbf x)mathrm partial V_i =\n 2cfracg_ij + g_textsitau_ij^2 V_i -\n cfrac1tau_ij leftg_ijcos(theta_ij - phi_ij) + b_ijsin(theta_ij - phi_ij)right V_j \n cfracmathrm partialh_P_ij(mathbf x)mathrm partial V_j = -\n cfrac1tau_ij leftg_ij cos(theta_ij - phi_ij) + b_ij sin(theta_ij - phi_ij)right V_i\n\tendaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#To-Bus-End-Active-Power-Flow-Measurements","page":"AC State Estimation","title":"To-Bus End Active Power Flow Measurements","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Similarly, a wattmeter can be placed at the to-bus end, denoted as P_ji in mathcalP, specifying the measurement value, variance, and measurement function of vectors:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfz_mathcalP = z_P_ji mathbfv_mathcalP = v_P_ji mathbfh_mathcalP(mathbf x) = h_P_ji(mathbf x)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"For example:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addWattmeter!(system, device; label = \"P₂₁\", to = 1, active = -0.2, variance = 1e-4)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Thus, the function describing active power flow at the to-bus end is defined as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" h_P_ji(mathbf x) = (g_ij + g_textsi) V_j^2 - cfrac1tau_ij leftg_ij cos(theta_ij - phi_ij) - b_ij sin(theta_ij- phi_ij)right V_i V_j","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"with the following Jacobian expressions:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n cfracmathrm partialh_P_ji(mathbf x)mathrm partial theta_i = -\n cfracmathrm partialh_P_ji(mathbf x)mathrm partial theta_j =\n cfrac1tau_ij leftg_ijsin(theta_ij - phi_ij) + b_ijcos(theta_ij - phi_ij)right V_iV_j \n cfracmathrm partialh_P_ji(mathbf x)mathrm partial V_i = -\n cfrac1tau_ij leftg_ij cos(theta_ij - phi_ij) - b_ij sin(theta_ij - phi_ij)right V_j \n cfracmathrm partialh_P_ji(mathbf x)mathrm partial V_j = 2(g_ij + g_textsi) V_j-\n cfrac1tau_ij leftg_ij cos(theta_ij - phi_ij) - b_ij sin(theta_ij - phi_ij)right V_i\n\tendaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Reactive-Power-Injection-Measurements","page":"AC State Estimation","title":"Reactive Power Injection Measurements","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"When adding a varmeter Q_i in mathcalQ at bus i in mathcalN, users specify that the varmeter measures reactive power injection and define the measurement value, variance, and measurement function of vectors:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfz_mathcalQ = z_Q_i mathbfv_mathcalQ = v_Q_i mathbfh_mathcalQ(mathbf x) = h_Q_i(mathbf x)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"For example:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addVarmeter!(system, device; label = \"Q₃\", bus = 3, reactive = 0, variance = 1e-3)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Here, utilizing the AC Model, we derive the function defining the reactive power injection as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" h_Q_i(mathbf x) = V_isumlimits_j in mathcalN_i (G_ijsintheta_ij - B_ijcostheta_ij)V_j","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"where mathcalN_i contains buses incident to bus i, including bus i, with the following Jacobian expressions:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n cfracmathrm partialh_Q_i(mathbf x)mathrm partial theta_i =\n V_isum_j in mathcalN_i (G_ijcostheta_ij+B_ijsintheta_ij)V_j - G_iiV_i^2\n cfracmathrm partialh_Q_i(mathbf x)mathrm partial theta_j =\n -(G_ijcostheta_ij+B_ijsintheta_ij)V_iV_j \n cfracmathrm partialh_Q_i(mathbf x)mathrm partial V_i =\n sum_j in mathcalN_i (G_ijsintheta_ij-B_ijcostheta_ij)V_j - B_iiV_i\n cfracmathrm partialh_Q_i(mathbf x)mathrm partial V_j =\n (G_ijsintheta_ij-B_ijcostheta_ij)V_i\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#From-Bus-End-Reactive-Power-Flow-Measurements","page":"AC State Estimation","title":"From-Bus End Reactive Power Flow Measurements","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Additionally, when introducing a varmeter at branch (ij) in mathcalE, users specify that the varmeter measures reactive power flow. It can be positioned at the from-bus end, denoted as Q_ij in mathcalQ, with its measurement value, variance, and measurement function included in vectors:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfz_mathcalQ = z_Q_ij mathbfv_mathcalQ = v_Q_ij mathbfh_mathcalQ(mathbf x) = h_Q_ij(mathbf x)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"For example:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addVarmeter!(system, device; label = \"Q₁₂\", from = 1, reactive = 0.2, variance = 1e-4)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Here, the function describing reactive power flow at the from-bus end is defined as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" h_Q_ij(mathbf x) = -cfracb_ij + b_textsitau_ij^2 V_i^2 - cfrac1tau_ij leftg_ijsin(theta_ij - phi_ij) - b_ijcos(theta_ij - phi_ij)right V_iV_j","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"with the following Jacobian expressions:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n cfracmathrm partialh_Q_ij(mathbf x)mathrm partial theta_i = -\n cfracmathrm partialh_Q_ij(mathbf x)mathrm partial theta_j = -\n cfrac1tau_ij leftg_ijcos(theta_ij - phi_ij) + b_ijsin(theta_ij - phi_ij)right V_iV_j \n cfracmathrm partialh_Q_ij(mathbf x)mathrm partial V_i = -\n 2cfracb_ij + b_textsitau_ij^2 V_i -\n cfrac1tau_ij leftg_ijsin(theta_ij - phi_ij) - b_ijcos(theta_ij - phi_ij)right V_j\n cfracmathrm partialh_Q_ij(mathbf x)mathrm partial V_j = -\n cfrac1tau_ij leftg_ijsin(theta_ij - phi_ij) - b_ijcos(theta_ij - phi_ij)right V_i\n\tendaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#To-Bus-End-Reactive-Power-Flow-Measurements","page":"AC State Estimation","title":"To-Bus End Reactive Power Flow Measurements","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Similarly, a varmeter can be placed at the to-bus end, denoted as Q_ji in mathcalQ, with its own measurement value, variance, and measurement function included in vectors:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfz_mathcalQ = z_Q_ji mathbfv_mathcalQ = v_Q_ji mathbfh_mathcalQ(mathbf x) = h_Q_ji(mathbf x)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"For example:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addVarmeter!(system, device; label = \"Q₂₁\", to = 1, reactive = -0.2, variance = 1e-4)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Thus, the function describing reactive power flow at the to-bus end is defined as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" h_Q_ji(mathbf x) = -(b_ij + b_textsi) V_j^2 + cfrac1tau_ij leftg_ij sin(theta_ij - phi_ij) + b_ij cos(theta_ij - phi_ij)right V_iV_j","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"with the following Jacobian expressions:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n cfracmathrm partialh_Q_ji(mathbf x)mathrm partial theta_i = -\n cfracmathrm partialh_Q_ji(mathbf x)mathrm partial theta_j =\n cfrac1tau_ij leftg_ijcos(theta_ij - phi_ij) - b_ijsin(theta_ij - phi_ij)right V_iV_j \n cfracmathrm partialh_Q_ji(mathbf x)mathrm partial V_i =\n cfrac1tau_ij leftg_ij sin(theta_ij - phi_ij) + b_ij cos(theta_ij - phi_ij)right V_j\n cfracmathrm partialh_Q_ji(mathbf x)mathrm partial V_j = -\n 2(b_ij + b_textsi) V_j +\n cfrac1tau_ij leftg_ij sin(theta_ij - phi_ij) + b_ij cos(theta_ij - phi_ij)right V_i\n\tendaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Rectangular-Bus-Voltage-Phasor-Measurements","page":"AC State Estimation","title":"Rectangular Bus Voltage Phasor Measurements","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"When a PMU (V_i theta_i) in barmathcalP is introduced at bus i in mathcalN, it will be incorporated into the AC state estimation model using rectangular coordinates by default. It will define the measurement values, variances, and measurement functions of vectors:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfz_barmathcalP = z_Re(barV_i) z_Im(barV_i) mathbfv_barmathcalP = v_Re(barV_i) v_Im(barV_i) mathbfh_barmathcalP(mathbf x) = h_Re(barV_i)(mathbf x) h_Im(barV_i)(mathbf x)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"For example:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addPmu!(system, device; label = \"V₂, θ₂\", bus = 2, magnitude = 0.9, angle = -0.1,\nvarianceMagnitude = 1e-5, varianceAngle = 1e-5)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Here, measurement values are obtained according to:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n z_Re(barV_i) = z_V_i cos z_theta_i\n z_Im(barV_i) = z_V_i sin z_theta_i\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Utilizing the classical theory of propagation of uncertainty [16], the variances can be calculated as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n v_Re(barV_i) =\n v_V_i left cfracmathrm partial mathrm partial z_V_i (z_V_i cos z_theta_i) right^2 +\n v_theta_i left cfracmathrm partial mathrm partial z_theta_i (z_V_i cos z_theta_i)right^2 =\n v_V_i (cos z_theta_i)^2 + v_theta_i (z_V_i sin z_theta_i)^2\n v_Im(barV_i) =\n v_V_i left cfracmathrm partial mathrm partial z_V_i (z_V_i sin z_theta_i) right^2 +\n v_theta_i left cfracmathrm partial mathrm partial z_theta_i (z_V_i sin z_theta_i)right^2 =\n v_V_i (sin z_theta_i)^2 + v_theta_i (z_V_i cos z_theta_i)^2\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Lastly, the functions defining the bus voltage phasor measurement are:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n h_Re(barV_i)(mathbf x) = V_icos theta_i\n h_Im(barV_i)(mathbf x) = V_isin theta_i\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Jacobian expressions corresponding to the measurement function h_Re(barV_i)(mathbf x) are defined as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n \tcfracmathrm partialh_Re(barV_i)(mathbf x)mathrm partial theta_i=-V_isin theta_i \n \tcfracmathrm partialh_Re(barV_i)(mathbf x)mathrm partial V_i=cos theta_i\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"while Jacobian expressions corresponding to the measurement function h_Im(barV_i)(mathbf x) are:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n \tcfracmathrm partialh_Im(barV_i)(mathbf x)mathrm partial theta_i=V_icos theta_i\n \tcfracmathrm partialh_Im(barV_i)(mathbf x)mathrm partial V_i=sin theta_i\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"In the previous example, the user neglects the covariances between the real and imaginary parts of the measurement. However, if desired, the user can also include them in the state estimation model by specifying the covariances of the vector:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfw_barmathcalP = w_Re(barV_i) w_Im(barV_i)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addPmu!(system, device; label = \"V₃, θ₃\", bus = 3, magnitude = 0.9, angle = -0.2,\nvarianceMagnitude = 1e-5, varianceAngle = 1e-5, correlated = true)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Then, the covariances are obtained as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" w_Re(barV_i) = w_Im(barV_i) =\n v_V_i cfracmathrm partial mathrm partial z_V_i (z_V_i cos z_theta_i)\n cfracmathrm partial mathrm partial z_V_i (z_V_i sin z_theta_i) +\n v_theta_i cfracmathrm partial mathrm partial z_theta_i (z_V_i cos z_theta_i)\n cfracmathrm partial mathrm partial z_theta_i (z_V_i sin z_theta_i)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"which results in the solution:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" w_Re(barV_i) = w_Im(barV_i) = cos z_theta_i sin z_theta_i(v_V_i - v_theta_i z_V_i^2)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Polar-Bus-Voltage-Phasor-Measurements","page":"AC State Estimation","title":"Polar Bus Voltage Phasor Measurements","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"If the user chooses to include phasor measurement (V_i theta_i) in barmathcalP in polar coordinates in the AC state estimation model, the user will specify the measurement values, variances, and measurement functions of vectors:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfz_barmathcalP = z_V_i z_theta_i mathbfv_barmathcalP = v_V_i v_theta_i mathbfh_barmathcalP(mathbf x) = h_V_i(mathbf x) h_theta_i(mathbf x)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"For example:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addPmu!(system, device; label = \"V₁, θ₁\", bus = 1, magnitude = 1.0, angle = 0,\nvarianceMagnitude = 1e-5, varianceAngle = 1e-6, polar = true)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Here, the functions defining the bus voltage phasor measurement are straightforward:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n h_V_i(mathbf x) = V_i\n h_theta_i(mathbf x) = theta_i\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"with the following Jacobian expressions:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n \tcfracmathrm partialh_V_i(mathbf x)mathrm partial V_i=1 \n cfracmathrm partialh_theta_i(mathbf x)mathrm partial theta_i=1\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Rectangular-From-Bus-End-Current-Phasor-Measurements","page":"AC State Estimation","title":"Rectangular From-Bus End Current Phasor Measurements","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"When introducing a PMU at branch (ij) in mathcalE, it can be placed at the from-bus end, denoted as (I_ij psi_ij) in barmathcalP, and it will be integrated into the AC state estimation model using rectangular coordinates by default. Incorporating current phasor measurements in the polar coordinate system is highly susceptible to ill-conditioned problems, especially when dealing with small values of current magnitudes. This is the reason why we typically include PMUs in the rectangular coordinate system by default.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Therefore, here we specify the measurement values, variances, and measurement functions of vectors:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfz_barmathcalP = z_Re(barI_ij) z_Im(barI_ij) mathbfv_barmathcalP = v_Re(barI_ij) v_Im(barI_ij) mathbfh_barmathcalP(mathbf x) = h_Re(barI_ij)(mathbf x) h_Im(barI_ij)(mathbf x)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"For example:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addPmu!(system, device; label = \"I₂₃, ψ₂₃\", from = 3, magnitude = 0.3, angle = 0.4,\nvarianceMagnitude = 1e-5, varianceAngle = 1e-4)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Here, measurement values are obtained according to:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n z_Re(barI_ij) = z_I_ij cos z_psi_ij\n z_Im(barI_ij) = z_I_ij sin z_psi_ij\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Utilizing the classical theory of propagation of uncertainty [16], the variances can be calculated as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n v_Re(barI_ij) = v_I_ij (cos z_psi_ij)^2 + v_psi_ij (z_I_ij sin z_psi_ij)^2 \n v_Im(barI_ij) = v_I_ij (sin z_psi_ij)^2 + v_psi_ij (z_I_ij cos z_psi_ij)^2\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The functions defining the current phasor measurement at the from-bus end are:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n h_Re(barI_ij)(mathbf x) = (A_psi_ij cos theta_i - B_psi_ij sin theta_i)V_i - C_psi_ij cos (theta_j + phi_ij) - D_psi_ij sin (theta_j + phi_ij)V_j \n h_Im(barI_ij)(mathbf x) = (A_psi_ij sin theta_i + B_psi_ij cos theta_i)V_i - C_psi_ij sin (theta_j + phi_ij) + D_psi_ij cos (theta_j + phi_ij)V_j\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Jacobian expressions corresponding to the measurement function h_Re(barI_ij)(mathbf x) are defined as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n cfracmathrm partialh_Re(barI_ij)(mathbf x)mathrm partial theta_i =\n -(A_psi_ij sin theta_i + B_psi_ij cos theta_i)V_i\n cfracmathrm partialh_Re(barI_ij)(mathbf x)mathrm partial theta_j =\n C_psi_ij sin(theta_j + phi_ij) + D_psi_ij cos(theta_j + phi_ij) V_j \n cfracmathrm partialh_Re(barI_ij)(mathbf x)mathrm partial V_i =\n A_psi_ij cos theta_i - B_psi_ij sintheta_i\n cfracmathrm partialh_Re(barI_ij)(mathbf x)mathrm partial V_j =\n -C_psi_ij cos(theta_j + phi_ij) + D_psi_ij sin(theta_j + phi_ij)\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"while Jacobian expressions corresponding to the measurement function h_Im(barI_ij)(mathbf x) are:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n cfracmathrm partialh_Im(barI_ij)(mathbf x)mathrm partial theta_i =\n (A_psi_ij cos theta_i - B_psi_ij sin theta_i)V_i\n cfracmathrm partialh_Im(barI_ij)(mathbf x)mathrm partial theta_j =\n -C_psi_ij cos(theta_j + phi_ij) + D_psi_ij sin(theta_j + phi_ij) V_j \n cfracmathrm partialh_Im(barI_ij)(mathbf x)mathrm partial V_i =\n A_psi_ij sin theta_i + B_psi_ij costheta_i\n cfracmathrm partialh_Im(barI_ij)(mathbf x)mathrm partial V_j =\n -C_psi_ij sin(theta_j + phi_ij) - D_psi_ij cos(theta_j + phi_ij)\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"In the previous example, the user neglects the covariances between the real and imaginary parts of the measurement. However, if desired, the user can also include them in the state estimation model by specifying the covariances of the vector:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfw_barmathcalP = w_Re(barI_ij) w_Im(barI_ij)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addPmu!(system, device; label = \"I₁₃, ψ₁₃\", from = 2, magnitude = 0.3, angle = -0.5,\nvarianceMagnitude = 1e-4, varianceAngle = 1e-5, correlated = true)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Then, the covariances are obtained as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" w_Re(barI_ij) = w_Im(barI_ij) = sin z_psi_ij cos z_psi_ij(v_I_ij - v_psi_ij z_I_ij^2)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Polar-From-Bus-End-Current-Phasor-Measurements","page":"AC State Estimation","title":"Polar From-Bus End Current Phasor Measurements","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"If the user chooses to include phasor measurement (I_ij psi_ij) in barmathcalP in polar coordinates in the AC state estimation model, the user will specify the measurement values, variances, and measurement functions of vectors:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfz_barmathcalP = z_I_ij z_psi_ij mathbfv_barmathcalP = v_I_ij v_psi_ij mathbfh_barmathcalP(mathbf x) = h_I_ij(mathbf x) h_psi_ij(mathbf x)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"For example:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addPmu!(system, device; label = \"I₁₂, ψ₁₂\", from = 1, magnitude = 0.3, angle = -0.7,\nvarianceMagnitude = 1e-5, varianceAngle = 1e-4, polar = true)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Here, the function associated with the branch current magnitude at the from-bus end remains identical to the one provided in From-Bus End Current Magnitude Measurements. However, the function defining the branch current angle measurement is expressed as:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" h_psi_ij(mathbf x) = mathrmatanBigg\n cfrac(A_psi_ij sintheta_i + B_psi_ij costheta_i)V_i - C_psi_ij sin(theta_j+phi_ij) + D_psi_ijcos(theta_j+phi_ij)V_j\n (A_psi_ij costheta_i - B_psi_ij sintheta_i)V_i - C_psi_ij cos(theta_j+phi_ij) - D_psi_ij sin(theta_j+phi_ij)V_j Bigg","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"where:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" A_psi_ij = cfracg_ij + g_textsitau_ij^2 B_psi_ij = cfracb_ij+b_textsitau_ij^2 \n C_psi_ij = cfracg_ijtau_ij D_psi_ij = cfracb_ijtau_ij","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Jacobian expressions associated with the branch current magnitude function h_I_ij(mathbf x) remains identical to the one provided in From-Bus End Current Magnitude Measurements. Further, Jacobian expressions corresponding to the measurement function h_psi_ij(mathbf x) are defined as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n cfracmathrm partialh_psi_ij(mathbf x)mathrm partial theta_i =\n cfracA_I_ij V_i^2- C_I_ij cos(theta_ij- phi_ij) - D_I_ij sin (theta_ij - phi_ij) V_iV_jh_I_ij^2(mathbf x) \n cfracmathrm partialh_psi_ij(mathbf x)mathrm partial theta_j =\n cfracB_I_ij V_j^2 - C_I_ij cos (theta_ij - phi_ij) - D_I_ij sin(theta_ij- phi_ij)V_iV_jh_I_ij^2(mathbf x) \n cfracmathrm partialh_psi_ij(mathbf x)mathrm partial V_i = -\n cfracC_I_ij sin (theta_ij - phi_ij) + D_I_ij cos(theta_ij- phi_ij)V_j h_I_ij^2(mathbf x)\n cfracmathrm partialh_psi_ij(mathbf x)mathrm partial V_j =\n cfracC_I_ij sin (theta_ij - phi_ij) + D_I_ij cos(theta_ij- phi_ij)V_i h_I_ij^2(mathbf x)\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Rectangular-To-Bus-End-Current-Phasor-Measurements","page":"AC State Estimation","title":"Rectangular To-Bus End Current Phasor Measurements","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"When introducing a PMU at branch (ij) in mathcalE, it can be placed at the to-bus end, denoted as (I_ji psi_ji) in barmathcalP, and it will be integrated into the AC state estimation model using rectangular coordinates by default. The user will specify the measurement values, variances, and measurement functions of vectors:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfz_barmathcalP = z_Re(barI_ji) z_Im(barI_ji) mathbfv_barmathcalP = v_Re(barI_ji) v_Im(barI_ji) mathbfh_barmathcalP(mathbf x) = h_Re(barI_ji)(mathbf x) h_Im(barI_ji)(mathbf x)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"For example:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addPmu!(system, device; label = \"I₃₂, ψ₃₂\", to = 3, magnitude = 0.3, angle = -2.9,\nvarianceMagnitude = 1e-5, varianceAngle = 1e-5)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Here, measurement values are obtained according to:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n z_Re(barI_ji) = z_I_ji cos z_psi_ji\n z_Im(barI_ji) = z_I_ji sin z_psi_ji\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The variances can be calculated as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n v_Re(barI_ji) = v_I_ji (cos z_psi_ji)^2 + v_psi_ji (z_I_ji sin z_psi_ji)^2 \n v_Im(barI_ji) = v_I_ji (sin z_psi_ji)^2 + v_psi_ji (z_I_ji cos z_psi_ji)^2\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The functions defining the current phasor measurement at the to-bus end are:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n h_Re(barI_ji)(mathbf x) = (A_psi_ji cos theta_j - B_psi_ji sin theta_j)V_j - C_psi_ji cos (theta_i - phi_ij) - D_psi_ji sin (theta_i + phi_ij)V_i\n h_Im(barI_ji)(mathbf x) = (A_psi_ji sin theta_j + B_psi_ji cos theta_j)V_j - C_psi_ji sin (theta_i + phi_ij) + D_psi_ji cos (theta_i + phi_ij)V_i\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Jacobian expressions corresponding to the measurement function h_Re(barI_ji)(mathbf x) are defined as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n cfracmathrm partialh_Re(barI_ji)(mathbf x)mathrm partial theta_i =\n C_psi_ji sin (theta_i - phi_ij) + D_psi_ji cos (theta_i - phi_ij)V_i\n cfracmathrm partialh_Re(barI_ji)(mathbf x)mathrm partial theta_j =\n -(A_psi_ji sintheta_j + B_psi_ji cos theta_j ) V_j \n cfracmathrm partialh_Re(barI_ji)(mathbf x)mathrm partial V_i =\n - C_psi_ji cos (theta_i - phi_ij) + D_psi_ji sin(theta_i - phi_ij)\n cfracmathrm partialh_Re(barI_ji)(mathbf x)mathrm partial V_j =\n A_psi_ji cos theta_j - B_psi_ji sin theta_j\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"while Jacobian expressions corresponding to the measurement function h_Im(barI_ji)(mathbf x) are:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n cfracmathrm partialh_Im(barI_ji)(mathbf x)mathrm partial theta_i =\n -C_psi_ji cos (theta_i - phi_ij) + D_psi_ji sin (theta_i - phi_ij)V_i\n cfracmathrm partialh_Im(barI_ji)(mathbf x)mathrm partial theta_j =\n (A_psi_ji costheta_j - B_psi_ji sin theta_j ) V_j \n cfracmathrm partialh_Im(barI_ji)(mathbf x)mathrm partial V_i =\n - C_psi_ji sin (theta_i - phi_ij) - D_psi_ji cos(theta_i - phi_ij)\n cfracmathrm partialh_Im(barI_ji)(mathbf x)mathrm partial V_j =\n A_psi_ji sin theta_j + B_psi_ji cos theta_j\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"As before, we are neglecting the covariances between the real and imaginary parts of the measurement. If desired, we can include them in the state estimation model by specifying the covariances of the vector:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfw_barmathcalP = w_Re(barI_ji) w_Im(barI_ji)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addPmu!(system, device; label = \"I₃₁, ψ₃₁\", to = 2, magnitude = 0.3, angle = 2.5,\nvarianceMagnitude = 1e-5, varianceAngle = 1e-5, correlated = true)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Then, the covariances are obtained as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" w_Re(barI_ji) = w_Im(barI_ji) = sin z_psi_ji cos z_psi_ji(v_I_ji - v_psi_ji z_I_ji^2)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Polar-To-Bus-End-Current-Phasor-Measurements","page":"AC State Estimation","title":"Polar To-Bus End Current Phasor Measurements","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"If the user chooses to include phasor measurement (I_ji psi_ji) in barmathcalP in polar coordinates in the AC state estimation model, the user will specify the measurement values, variances, and measurement functions of vectors:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfz_barmathcalP = z_I_ji z_psi_ji mathbfv_barmathcalP = v_I_ji v_psi_ji mathbfh_barmathcalP(mathbf x) = h_I_ji(mathbf x) h_psi_ji(mathbf x)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"For example:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addPmu!(system, device; label = \"I₂₁, ψ₂₁\", to = 1, magnitude = 0.3, angle = 2.3,\nvarianceMagnitude = 1e-2, varianceAngle = 1e-3, polar = true)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Here, the function associated with the branch current magnitude at the to-bus end remains identical to the one provided in To-Bus End Current Magnitude Measurements. However, the function defining the branch current angle measurement is expressed as:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" h_psi_ji(mathbf x) = mathrmatanBigg\n cfrac(A_psi_ji sintheta_j + B_psi_ji costheta_j)V_j - C_psi_ji sin(theta_i-phi_ij) + D_psi_jicos(theta_i-phi_ij)V_i\n (A_psi_ji costheta_j - B_psi_ji sintheta_j)V_j - C_psi_ji cos(theta_i-phi_ij) - D_psi_ji sin(theta_i-phi_ij)V_i Bigg","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"where:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" A_psi_ji = g_ij + g_textsi B_psi_ji = b_ij + b_textsi \n C_psi_ji = cfracg_ijtau_ij D_psi_ji = cfracb_ijtau_ij","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Jacobian expressions associated with the branch current magnitude function h_I_ji(mathbf x) remains identical to the one provided in To-Bus End Current Magnitude Measurements. Further, Jacobian expressions corresponding to the measurement function h_psi_ji(mathbf x) are defined as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n cfracmathrm partialh_psi_ji(mathbf x)mathrm partial theta_i =\n cfracA_I_ji V_i^2- C_I_ji cos(theta_ij- phi_ij) + D_I_ji sin (theta_ij - phi_ij) V_iV_jh_I_ji^2(mathbf x) \n cfracmathrm partialh_psi_ji(mathbf x)mathrm partial theta_j =\n cfracB_I_ji V_j^2 - C_I_ji cos (theta_ij - phi_ij) + D_I_ji sin(theta_ij- phi_ij)V_iV_jh_I_ji^2(mathbf x) \n cfracmathrm partialh_psi_ji(mathbf x)mathrm partial V_i =\n -cfracC_I_ji sin (theta_ij - phi_ij) - D_I_ji cos(theta_ij- phi_ij)V_j h_I_ji^2(mathbf x)\n cfracmathrm partialh_psi_ji(mathbf x)mathrm partial V_j =\n cfracC_I_ji sin (theta_ij - phi_ij) - D_I_ji cos(theta_ij- phi_ij)V_i h_I_ji^2(mathbf x)\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#ACSEWLSStateEstimationTutorials","page":"AC State Estimation","title":"Weighted Least-Squares Estimation","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Given the available set of measurements mathcalM, the weighted least-squares estimator hatmathbf x, i.e., the solution of the weighted least-squares problem, can be found using the Gauss-Newton method:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"\t\tBigmathbf J (mathbf x^(nu))^T bm Sigma^-1 mathbf J (mathbf x^(nu))Big mathbf Delta mathbf x^(nu) =\n\t\tmathbf J (mathbf x^(nu))^T bm Sigma^-1 mathbf r (mathbf x^(nu))","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"\t\tmathbf x^(nu+1) = mathbf x^(nu) + mathbf Delta mathbf x^(nu)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"where nu = 012dots is the iteration index, mathbf Delta mathbf x in mathbb R^n_textu is the vector of increments of the state variables, mathbf J (mathbf x)in mathbb R^k times n_textu is the Jacobian matrix of measurement functions mathbf h (mathbf x) at mathbf x=mathbf x^(nu), bm Sigma in mathbb R^k times k is a measurement error covariance matrix, and mathbf r (mathbf x) = mathbfz - mathbf h (mathbf x) is the vector of residuals [13, Ch. 10]. It is worth noting that assuming uncorrelated measurement errors leads to a diagonal covariance matrix bm Sigma corresponding to measurement variances. However, when incorporating PMUs in a rectangular coordinate system and aiming to observe error correlation, this matrix loses its diagonal form.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The non-linear or AC state estimation represents a non-convex problem arising from the non-linear measurement functions [17]. Due to the fact that the values of state variables usually fluctuate in narrow boundaries, the non-linear model represents the mildly non-linear problem, where solutions are in a reasonable-sized neighborhood which enables the use of the Gauss-Newton method. The Gauss-Newton method can produce different rates of convergence, which can be anywhere from linear to quadratic [18, Sec. 9.2]. The convergence rate in regard to power system state estimation depends on the topology and measurements, and if parameters are consistent (e.g., free bad data measurement set), the method shows near quadratic convergence rate [13, Sec. 11.2].","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Initialization","page":"AC State Estimation","title":"Initialization","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Let us begin by setting up a new set of measurements for the defined power system:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"device = measurement()\n\n@wattmeter(label = \"Watmeter ?\")\naddWattmeter!(system, device; bus = 3, active = -0.5, variance = 1e-3)\naddWattmeter!(system, device; from = 1, active = 0.2, variance = 1e-4)\n\n@varmeter(label = \"Varmeter ?\")\naddVarmeter!(system, device; bus = 2, reactive = -0.3, variance = 1e-3)\naddVarmeter!(system, device; from = 1, reactive = 0.2, variance = 1e-4)\n\n@pmu(label = \"PMU ?\")\naddPmu!(system, device; bus = 1, magnitude = 1.0, angle = 0, polar = true)\naddPmu!(system, device; bus = 3, magnitude = 0.9, angle = -0.2)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To compute the voltage magnitudes and angles of buses using the Gauss-Newton method in JuliaGrid, we need to first execute the acModel! function to set up the system. Then, initialize the Gauss-Newton method using the gaussNewton function. The following code snippet demonstrates this process:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"acModel!(system)\nanalysis = gaussNewton(system, device)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Initially, the gaussNewton function constructs the mean vector holding measurement values:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐳 = analysis.method.mean","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Additionally, it forms the precision or weighting matrix denoted as mathbf W = bm Sigma^-1. We can access these values using the following command:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐖 = analysis.method.precision","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Finally, using initial bus voltage magnitudes and angles from the PowerSystem type, the function creates the starting vector mathbfx^(0) of bus voltage magnitudes mathbfV^(0) and angles bmTheta^(0) for the Gauss-Newton method:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐕⁽⁰⁾ = analysis.voltage.magnitude\n𝚯⁽⁰⁾ = analysis.voltage.angle","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Here, we utilize a \"flat start\" approach in our method. It is important to keep in mind that when dealing with initial conditions in this manner, the Gauss-Newton method may encounter difficulties.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Iterative-Process","page":"AC State Estimation","title":"Iterative Process","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To apply the Gauss-Newton method, JuliaGrid provides the solve! function. This function is utilized iteratively until a stopping criterion is met, as demonstrated in the following code snippet:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"for iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n break\n end\nend","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The function solve! calculates the vector of residuals at each iteration using the equation:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbf r (mathbf x^(nu)) = mathbfz - mathbf h (mathbf x^(nu))","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The resulting vector from these calculations is stored in the residual variable of the ACStateEstimation type and can be accessed through the following line of code:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐫 = analysis.method.residual","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The order of the residual vector follows a specific pattern. If all device types exist, the first mathcalV elements correspond to voltmeters, followed by mathcalI elements corresponding to ammeters. Then we have mathcalP elements for wattmeters and mathcalQ elements for varmeters. Finally, we have 2barmathcalP elements for PMUs. The order of these elements within specific devices follows the same order as they appear in the input data defined by the Measurement type.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"At the same time, the function forms the Jacobian matrix mathbfJ (mathbfx^(nu)) and calculates the gain matrix mathbfG (mathbfx^(nu)) using:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"\t\tmathbf G (mathbf x^(nu)) = mathbf J (mathbf x^(nu))^T bm Sigma^-1 mathbf J (mathbf x^(nu))","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The Jacobian matrix and factorized gain matrix are stored in the ACStateEstimation type and can be accessed after each iteration:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐉 = analysis.method.jacobian\n𝐋 = analysis.method.factorization.L\n𝐔 = analysis.method.factorization.U","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Then finally, the function computes the vector of state variable increments using the equation:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"\t\tmathbf Delta mathbf x^(nu) = mathbf G (mathbf x^(nu))^-1 mathbf J (mathbf x^(nu))^T bm Sigma^-1 mathbf r (mathbf x^(nu))","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"tip: Tip\nBy default, JuliaGrid uses LU factorization as the primary method for factorizing the gain matrix mathbfG = mathbfLmathbfU, aiming to compute the increments. Nevertheless, users have the flexibility to opt for QR or LDLt factorization as an alternative method.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Increment values are stored in the ACStateEstimation type and can be accessed after each iteration:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝚫𝐱 = analysis.method.increment","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Here again, the JuliaGrid implementation of the AC state estimation follows a specific order to store the increment vector and Jacobian matrix. The vector of increments first contains n increments of bus voltage angles mathbf Delta bmTheta, followed by n increments of bus voltage magnitudes mathbf Delta mathbfV. This order also corresponds to the columns of the Jacobian matrix, while the order of rows of the Jacobian is defined according to the order of the residual vector.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Note that the increment vector and Jacobian matrix hold the slack bus with a known voltage angle. An element of the increment vector and a column of the Jacobian matrix are not deleted, and the presence on the slack bus is handled internally by JuliaGrid, which is evident from the factorization of the gain matrix.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The function solve! adds the computed increment term to the previous solution to obtain a new solution:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbf x^(nu + 1) = mathbf x^(nu) + mathbf Delta mathbf x^(nu)","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Therefore, the bus voltage magnitudes mathbfV = V_i and angles bmTheta = theta_i are stored in the following vectors:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐕 = analysis.voltage.magnitude\n𝚯 = analysis.voltage.angle","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Finally, the solve! function provides the maximum absolute value of state variable increments, typically employed as the termination criterion for the iteration loop. Specifically, if it falls below a predefined stopping criterion epsilon, the algorithm converges:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" max Delta x_i forall i epsilon","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Jacobian-Matrix","page":"AC State Estimation","title":"Jacobian Matrix","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"As a reminder, the Jacobian matrix consists of n columns representing bus voltage angles bmTheta, followed by n columns representing bus voltage magnitudes mathbfV. The arrangement of rows is structured such that the first mathcalV rows correspond to voltmeters, followed by mathcalI rows corresponding to ammeters. Then, we have mathcalP rows for wattmeters and mathcalQ rows for varmeters. Finally, there are 2barmathcalP rows for PMUs. The elements are computed based on the provided Jacobian expressions.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Precision-Matrix","page":"AC State Estimation","title":"Precision Matrix","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Let us revisit the precision matrix mathbf W. In the previous example, we introduced a PMU in rectangular coordinates without considering correlations between measurement errors. Now, let us update that PMU to include correlation between measurement errors:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"updatePmu!(system, device, analysis; label = \"PMU 2\", correlated = true)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Subsequently, we can examine the updated precision matrix mathbf W:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐖 = analysis.method.precision","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Observing the precision matrix, we notice that it loses its diagonal form due to the inclusion of measurement covariances in the model.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Alternative-Formulation","page":"AC State Estimation","title":"Alternative Formulation","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The resolution of the WLS state estimation problem using the conventional method typically progresses smoothly. However, it is widely acknowledged that in certain situations common to real-world systems, this method can be vulnerable to numerical instabilities. Such conditions might impede the algorithm from converging to a satisfactory solution. In such cases, users may opt for an alternative formulation of the WLS state estimation, namely, employing an approach called orthogonal factorization [5, Sec. 3.2].","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"This approach is suitable when measurement errors are uncorrelated, and the precision matrix remains diagonal. Therefore, as a preliminary step, we need to eliminate the correlation, as we did previously:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"updatePmu!(system, device; label = \"PMU 2\", correlated = false)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To address ill-conditioned situations arising from significant differences in measurement variances, users can now employ the orthogonal factorization approach:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"analysis = gaussNewton(system, device, Orthogonal)\n\nfor iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n break\n end\nend\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To explain the method, we begin with the WLS equation:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"\t Bigmathbf J (mathbf x^(nu))^T mathbf W mathbf J (mathbf x^(nu))Big mathbf Delta mathbf x^(nu) =\n\t\tmathbf J (mathbf x^(nu))^T mathbf W mathbf r (mathbf x^(nu))","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"where mathbf W = bm Sigma^-1. Subsequently, we can write:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" leftmathbf W^12 mathbf J (mathbf x^(nu))right^T mathbf W^12 mathbf J (mathbf x^(nu)) Delta mathbf x^(nu) =\n leftmathbf W^12 mathbf J (mathbf x^(nu))right^T mathbf W^12 mathbf r (mathbf x^(nu))","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Consequently, we have:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" barmathbf J(mathbf x^(nu))^T barmathbf J(mathbf x^(nu)) Delta mathbf x^(nu) = barmathbf J(mathbf x^(nu))^T barmathbf r (mathbf x^(nu))","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"where:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" barmathbf J(mathbf x^(nu)) = mathbf W^12 mathbf J (mathbf x^(nu)) barmathbf r (mathbf x^(nu)) = mathbf W^12 mathbf r (mathbf x^(nu))","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Therefore, within each iteration of the Gauss-Newton method, JuliaGrid conducts QR factorization on the rectangular matrix:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" barmathbf J(mathbf x^(nu)) = mathbf W^12 mathbf J (mathbf x^(nu)) = mathbfQmathbfR","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Access to the factorized matrix is possible through:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐐 = analysis.method.factorization.Q\n𝐑 = analysis.method.factorization.R","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To obtain the solution, JuliaGrid avoids explicitly forming the orthogonal matrix mathbfQ. Once the algorithm converges, estimates of bus voltage magnitudes hatmathbf V = hatV_i and angles hatbm Theta = hattheta_i, where i in mathcalN can be accessed using variables:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐕 = analysis.voltage.magnitude\n𝚯 = analysis.voltage.angle","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#ACBadDataTutorials","page":"AC State Estimation","title":"Bad Data Processing","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Besides the state estimation algorithm, one of the essential state estimation routines is the bad data processing, whose main task is to detect and identify measurement errors, and eliminate them if possible. This is usually done by processing the measurement residuals [5, Ch. 5], and typically, the largest normalized residual test is used to identify bad data. The largest normalized residual test is performed after we obtained the solution of the state estimation in the repetitive process of identifying and eliminating bad data measurements one after another [19].","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To illustrate this process, let us introduce a new measurement that contains an obvious outlier:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addWattmeter!(system, device; bus = 3, active = 5.1, variance = 1e-3)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Subsequently, we will construct the AC state estimation model and solve it:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"analysis = gaussNewton(system, device)\nfor iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n break\n end\nend\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Now, the bad data processing can be executed:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"outlier = residualTest!(system, device, analysis; threshold = 4.0)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"In this step, we employ the largest normalized residual test, guided by the analysis outlined in [5, Sec. 5.7]. To be more precise, we compute all measurement residuals based on the obtained estimate of state variables:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" r_i = z_i - h_i(hat mathbf x) i in mathcalM","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The normalized residuals for all measurements are computed as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" barr_i = cfracr_isqrtC_ii = cfracr_isqrtS_iiSigma_ii i in mathcalM","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"In this equation, we denote the diagonal entries of the residual covariance matrix mathbf C in mathbbR^k times k as C_ii = S_iiSigma_ii, where S_ii is the diagonal entry of the residual sensitivity matrix mathbf S representing the sensitivity of the measurement residuals to the measurement errors. For this specific configuration, the relationship is expressed as:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbf C = mathbf S bm Sigma = bm Sigma - mathbf J (hat mathbf x) mathbf J (hat mathbf x)^T bm Sigma^-1 mathbf J (hat mathbf x)^-1 mathbf J (hat mathbf x)^T","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"It is important to note that only the diagonal entries of mathbf C are required. To obtain the inverse, the JuliaGrid package utilizes a computationally efficient sparse inverse method, retrieving only the necessary elements of the inverse.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The subsequent step involves selecting the largest normalized residual, and the j-th measurement is then suspected as bad data and potentially removed from the measurement set mathcalM:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" barr_j = textmax barr_i i in mathcalM ","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Users can access this information using the variable:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"outlier.maxNormalizedResidual","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"If the largest normalized residual, denoted as barr_j, satisfies the inequality:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" barr_j ge epsilon","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"the corresponding measurement is identified as bad data and subsequently removed. In this example, the bad data identification threshold is set to epsilon = 4. Users can verify the satisfaction of this inequality by inspecting:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"outlier.detect","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"This indicates that the measurement labeled as:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"outlier.label","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"is removed from the measurement set and marked as out-of-service.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Subsequently, we can solve the system again, but this time without the removed measurement:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"analysis = gaussNewton(system, device)\nfor iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n break\n end\nend\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Following that, we check for outliers once more:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"outlier = residualTest!(system, device, analysis; threshold = 4.0)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To examine the value:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"outlier.maxNormalizedResidual","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"As this value is now less than the threshold epsilon = 4, the measurement is not removed, or there are no outliers. This can also be verified by observing the bad data flag:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"outlier.detect","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#ACLAVTutorials","page":"AC State Estimation","title":"Least Absolute Value Estimation","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The least absolute value (LAV) method provides an alternative estimation approach that is considered more robust in comparison to the WLS method. The WLS state estimation problem relies on specific assumptions about measurement errors, whereas robust estimators aim to remain unbiased even in the presence of various types of measurement errors and outliers. This characteristic eliminates the need for bad data processing, as discussed in [5, Ch. 6]. It is important to note that robustness often comes at the cost of increased computational complexity.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"This section outlines the method as described in [5, Sec. 6.5]. Hence, we consider the system of nonlinear equations:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbfz=mathbfh(mathbf x)+mathbfu","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Subsequently, the LAV state estimator is derived as the solution to the optimization problem:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n textminimize sum_i in mathcalM r_i\n textsubjectto z_i - h_i(mathbf x) = r_i forall i in mathcalM\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"where r_i represents the i-th measurement residual. Let eta_i be defined in a manner that ensures:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" r_i leq eta_i","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"and replace the above inequality with two equalities using two non-negative slack variables q_i and w_i:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n r_i - q_i = -eta_i \n r_i + w_i = eta_i\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Let us now define two additional non-negative variables overliner_i and underliner_i, which satisfy the following relationships:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n r_i = overliner_i - underliner_i\n overliner_i = cfrac12 q_i \n underliner_i = cfrac12 w_i\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Then, the above two equalities become:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n r_i - 2overliner_i = -2 eta_i \n r_i + 2 underliner_i = 2 eta_i\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"that is:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n overliner_i + underliner_i = eta_i\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Next, we define a vector of state variables according to two additional nonnegative vectors overlinemathbf x in mathbb R_ge 0^n_textu and underlinemathbf x in mathbb R_ge 0^n_textu, which satisfy the following relationships:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbf x = overlinemathbf x - underlinemathbf x","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Hence, the optimization problem can be written:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n textminimize sum_i in mathcalM (overliner_i + underliner_i) \n textsubjectto h_i(overlinemathbf x - underlinemathbf x) + overliner_i - underliner_i = z_i forall i in mathcalM \n overliner_i geq 0 underliner_i geq 0 forall i in mathcalM \n overlinemathbf x succeq mathbf 0 underlinemathbf x succeq mathbf 0\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To form the above optimization problem, the user can call the following function:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"using Ipopt\nusing JuMP # hide\n\nanalysis = acLavStateEstimation(system, device, Ipopt.Optimizer)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Then the user can solve the optimization problem by:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"JuMP.set_silent(analysis.method.jump) # hide\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"As a result, we obtain optimal values for the four non-negative variables, while the state estimator is obtained by:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" hatmathbf x = overlinemathbf x - underlinemathbf x","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Users can retrieve the estimated bus voltage magnitudes hatmathbf V = hatV_i and angles hatbm Theta = hattheta_i, i in mathcalN, using:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐕 = analysis.voltage.magnitude\n𝚯 = analysis.voltage.angle","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#ACObservabilityAnalysisTutorials","page":"AC State Estimation","title":"Observability Analysis","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The state estimation algorithm aims to estimate the values of the state variables based on the measurement model described as a system of equations. Prior to applying the state estimation algorithm, the observability analysis determines the existence and uniqueness of the solution for the underlying system of equations. In cases where a unique solution is not guaranteed, the observability analysis identifies observable islands and prescribes an additional set of equations (pseudo-measurements) to achieve a unique solution [20].","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Identification-of-Observable-Islands","page":"AC State Estimation","title":"Identification of Observable Islands","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"JuliaGrid employs standard observability analysis performed on the linear decoupled measurement model [13, Ch. 7]. Active power measurements from wattmeters are utilized to estimate bus voltage angles, while reactive power measurements from varmeters are used to estimate bus voltage magnitudes. This necessitates that measurements of active and reactive power come in pairs.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Let us illustrate this concept with the following example, where measurements form an unobservable system:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", type = 3)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.1, reactive = 0.01)\naddBus!(system; label = \"Bus 3\", type = 2, active = 0.5, reactive = 0.01)\naddBus!(system; label = \"Bus 4\", type = 1, active = 0.2, reactive = 0.02)\naddBus!(system; label = \"Bus 5\", type = 1, active = 0.3, reactive = 0.03)\n\n@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.002)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.01)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 4\", reactance = 0.02)\naddBranch!(system; label = \"Branch 4\", from = \"Bus 3\", to = \"Bus 4\", reactance = 0.03)\naddBranch!(system; label = \"Branch 5\", from = \"Bus 4\", to = \"Bus 5\", reactance = 0.05)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 4.2, reactive = 0.2)\naddGenerator!(system; label = \"Generator 2\", bus = \"Bus 3\", active = 0.2, reactive = 0.1)\n\naddWattmeter!(system, device; label = \"Wattmeter 1\", from = \"Branch 1\", active = 0.93)\naddVarmeter!(system, device; label = \"Varmeter 1\", from = \"Branch 1\", reactive = -0.41)\n\naddWattmeter!(system, device; label = \"Wattmeter 2\", bus = \"Bus 2\", active = -0.1)\naddVarmeter!(system, device; label = \"Varmeter 2\", bus = \"Bus 2\", reactive = -0.01)\n\naddWattmeter!(system, device; label = \"Wattmeter 3\", bus = \"Bus 3\", active = -0.30)\naddVarmeter!(system, device; label = \"Varmeter 3\", bus = \"Bus 3\", reactive = 0.52)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"If the system lacks observability, the observability analysis needs to identify all potential observable islands that can be independently solved. An observable island is defined as follows: It is a segment of the power system where the flows across all branches within that island can be calculated solely from the available measurements. This independence holds regardless of the values chosen for the bus voltage angle at the slack bus [13, Sec. 7.1.1]. Within this context, two types of observable islands are evident:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"flow observale islands,\nmaximal observable islands.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The selection between them relies on the power system's structure and the available measurements. Opting for detecting only flow observable islands simplifies the island detection function's complexity but increases the complexity in the restoration function compared to identifying maximal observable islands.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Flow-Observale-Islands","page":"AC State Estimation","title":"Flow Observale Islands","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To identify flow observable islands, JuliaGrid employs a topological method outlined in [21]. The process begins with the examination of all active power flow measurements from wattmeters, aiming to determine the largest sets of connected buses within the network linked by branches with active power flow measurements. Subsequently, the analysis considers individual boundary or tie active power injection measurements, involving two islands that may potentially be merged into a single observable island. The user can initiate this process by calling the function:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"islands = islandTopologicalFlow(system, device)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"As a result, four flow observable islands are identified. The first island comprises Bus 1 and Bus 2, while the second, third, and fourth islands consist of Bus 3, Bus 4, and Bus 5, respectively:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"islands.island","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Additionally, users can inspect the tie buses and branches resulting from the observability analysis we conducted:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"islands.tie.bus\nislands.tie.branch","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"This tie data will be utilized throughout the restoration step, where we introduce pseudo-measurements to merge the observable flow islands obtained.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Maximal-Observale-Islands","page":"AC State Estimation","title":"Maximal Observale Islands","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To identify maximal observable islands, we extend the analysis with an additional processing step. After processing individual injection tie measurements, we are left with a series of injection measurements that are not entirely contained within any observable zone. In this set of remaining tie injections, we now examine pairs involving three and only three previously determined observable zones (including individual buses). If we find such a pair, the three islands may be merged, and all injection measurements involving only nodes of this new island are excluded from further consideration. The procedure then restarts at the stage where we process tie active power injection measurements involving two and only two islands. If no mergers are possible with pairs, we then consider sets of three injection measurements involving four islands, and so on [21]. The user can initiate this by calling the function:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"islands = islandTopological(system, device)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The outcome reveals the identification of two maximal observable islands:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"islands.island","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"It is evident that upon comparing this result with the flow islands, the merging of the two injection measurements at Bus 2 and Bus 3 consolidated the first, second, and third flow observable islands into a single island.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Here we can observe tie data:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"islands.tie.bus\nislands.tie.branch","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Compared to the tie data obtained after detecting flow observable islands, we now have a smaller set, indicating that the restoration step will be more computationally efficient.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Observability-Restoration","page":"AC State Estimation","title":"Observability Restoration","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Before commencing the restoration of observability in the context of the linear decoupled measurement model and observability analysis, it is imperative to ensure that the system possesses one bus voltage magnitude measurement. This necessity arises from the fact that observable islands are identified based on wattmeters, where wattmeters are tasked with estimating voltage angles. Since one voltage angle is already known from the slack bus, the same principle should be applied to bus voltage magnitudes. Therefore, to address this requirement, we add:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"addVoltmeter!(system, device; bus = \"Bus 1\", magnitude = 1.0)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"After determining the islands, the observability analysis merges these islands in a manner that protect previously determined observable states from being altered by the new set of equations defined by the additional measurements, called pseudo-measurements. In general, this can be achieved by ensuring that the set of new measurements forms a non-redundant set [13, Sec. 7.3.2], i.e., the set of equations must be linearly independent with respect to the global system. The goal of observability restoration is to find this non-redundant set.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The outcome of the island detection step results in the power system being divided into m islands. Subsequently, we focus on the set of measurements mathcalM_textr subset mathcalM, which exclusively consists of:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"active power injection measurements at tie buses,\nbus voltage phasor measurements.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"These measurements are retained from the phase where we identify observable islands, and are crucial in determining whether we need additional pseudo-measurements to be included in the measurement set mathcalM. In this specific example, we do not have active power injection measurements at tie buses remaining after the identification of maximal observable islands. However, if we proceed with flow observable islands to the restoration step, we will have two injection measurements at Bus 2 and Bus 3.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"However, let us introduce the matrix mathbf M_textr in mathbbR^r times m, where r = mathcalM_textr. This matrix can be conceptualized as the coefficient matrix of a reduced network, with m columns corresponding to islands and r rows associated with the set mathcalM_textr. More precisely, if we construct the coefficient matrix mathbf H_textr linked to the set mathcalM_textr in the DC framework, the matrix mathbf M_textr can be constructed by summing the columns of mathbf H_textr that belong to a specific island [22].","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Subsequently, the user needs to establish a set of pseudo-measurements, where measurements must come in pairs as well. Let us create that set:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"pseudo = measurement()\n\naddWattmeter!(system, pseudo; label = \"Pseudo-Wattmeter 1\", bus = \"Bus 1\", active = 0.93)\naddVarmeter!(system, pseudo; label = \"Pseudo-Varmeter 1\", bus = \"Bus 1\", reactive = -0.41)\n\naddWattmeter!(system, pseudo; label = \"Pseudo-Wattmeter 2\", from = \"Branch 5\", active = 0.30)\naddVarmeter!(system, pseudo; label = \"Pseudo-Varmeter 2\", from = \"Branch 5\", reactive = 0.03)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"From this set, the restoration step will only utilize the following:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"active power flow measurements between tie buses,\nactive power injection measurements at tie buses,\nbus voltage phasor measurements.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"These pseudo-measurements mathcalM_textp will define the reduced coefficient matrix mathbf M_textp in mathbbR^p times m, where p = mathcalM_textp. In the current example, only Pseudo-Wattmeter 2 will contribute to the construction of the matrix mathbf M_textp. Similar to the previous case, measurement functions linked to the set mathcalM_textp define the coefficient matrix mathbf H_textp, and the matrix mathbf M_textp can be viewed as the sum of the columns of mathbf H_textp belonging to a specific flow island.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Additionally, users have the option to include bus voltage angle measurements from PMUs. In this scenario, restoration can be conducted without merging observable islands into one island, as each island becomes globally observable when one angle is known. It is important to note that during the restoration step, JuliaGrid initially processes active power measurements and subsequently handles bus voltage angle measurements if they are present in the set of pseudo-measurements.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Users can execute the observability restoration procedure with the following:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"restorationGram!(system, device, pseudo, islands; threshold = 1e-6)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The function constructs the reduced coefficient matrix as follows:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbf M = beginbmatrix mathbf M_textr mathbf M_textp endbmatrix","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"and forms the corresponding Gram matrix:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" mathbf D = mathbf M mathbf M^T","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The decomposition of mathbf D into its mathbf Q and mathbf R factors is achieved through QR factorization. Non-redundant measurements are identified by non-zero diagonal elements in mathbf R. Specifically, if the diagonal element satisfies:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" R_ii epsilon","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"JuliaGrid designates the corresponding measurement as redundant, where epsilon represents a pre-determined zero pivot threshold, set to 1e-6 in this example. The minimal set of pseudo-measurements for observability restoration corresponds to the non-zero diagonal elements at positions associated with the candidate pseudo-measurements. It is essential to note that an inappropriate choice of the zero pivot threshold may adversely affect observability restoration. Additionally, there is a possibility that the set of pseudo-measurements mathcalM_textp may not be sufficient for achieving observability restoration.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Finally, the Pseudo-Wattmeter 2, and consequently Pseudo-Varmeter 2 measurements successfully restore observability, and these measurements are added to the device variable, which stores actual measurements:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"device.wattmeter.label\ndevice.varmeter.label","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Here, we can confirm that the new measurement set establishes the observable system formed by a single island:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"islands = islandTopological(system, device);\n\nislands.island","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Next, we can construct the AC state estimation model and resolve it to obtain estimates of bus voltages:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"analysis = gaussNewton(system, device)\nfor iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n break\n end\nend\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#ACPowerAnalysisTutorials","page":"AC State Estimation","title":"Power Analysis","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Once the computation of voltage magnitudes and angles at each bus is completed, various electrical quantities can be determined. JuliaGrid offers the power! function, which enables the calculation of powers associated with buses and branches. Here is an example code snippet demonstrating its usage:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"power!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The function stores the computed powers in the rectangular coordinate system. It calculates the following powers related to buses and branches:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Bus Active Reactive\nInjections mathbfP = P_i mathbfQ = Q_i\nGenerator injections mathbfP_textp = P_textpi mathbfQ_textp = Q_textpi\nShunt elements mathbfP_textsh = P_textshi mathbfQ_textsh = Q_textshi","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Branch Active Reactive\nFrom-bus end flows mathbfP_texti = P_ij mathbfQ_texti = Q_ij\nTo-bus end flows mathbfP_textj = P_ji mathbfQ_textj = Q_ji\nShunt elements mathbfP_texts = P_textsij mathbfP_texts = P_textsij\nSeries elements mathbfP_textl = P_textlij mathbfQ_textl = Q_textlij","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"note: Info\nFor a clear comprehension of the equations, symbols presented in this section, as well as for a better grasp of power directions, please refer to the Unified Branch Model.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Power-Injections","page":"AC State Estimation","title":"Power Injections","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Active and reactive power injections are stored as the vectors mathbfP = P_i and mathbfQ = Q_i, respectively, and can be retrieved using the following commands:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐏 = analysis.power.injection.active\n𝐐 = analysis.power.injection.reactive","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#ACGeneratorPowerInjectionsManual","page":"AC State Estimation","title":"Generator Power Injections","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"We can calculate the active and reactive power injections supplied by generators at each bus i in mathcalN by summing the active and reactive power injections and the active and reactive power demanded by consumers at each bus:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":" beginaligned\n P_textpi = P_i + P_textdi\n Q_textpi = Q_i + Q_textdi\n endaligned","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The active and reactive power injections from the generators at each bus are stored as vectors, denoted by mathbfP_textp = P_textpi and mathbfQ_textp = Q_textpi, which can be obtained using:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐏ₚ = analysis.power.supply.active\n𝐐ₚ = analysis.power.supply.reactive","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Power-at-Bus-Shunt-Elements","page":"AC State Estimation","title":"Power at Bus Shunt Elements","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Active and reactive powers associated with the shunt elements at each bus are represented by the vectors mathbfP_textsh = P_textshi and mathbfQ_textsh = Q_textshi. To retrieve these powers in JuliaGrid, use the following commands:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐏ₛₕ = analysis.power.shunt.active\n𝐐ₛₕ = analysis.power.shunt.reactive","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Power-Flows","page":"AC State Estimation","title":"Power Flows","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The resulting active and reactive power flows at each from-bus end are stored as the vectors mathbfP_texti = P_ij and mathbfQ_texti = Q_ij respectively, and can be retrieved using the following commands:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐏ᵢ = analysis.power.from.active\n𝐐ᵢ = analysis.power.from.reactive","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Similarly, the vectors of active and reactive power flows at the to-bus end are stored as mathbfP_textj = P_ji and mathbfQ_textj = Q_ji, respectively, and can be retrieved using the following code:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐏ⱼ = analysis.power.to.active\n𝐐ⱼ = analysis.power.to.reactive","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Power-at-Branch-Shunt-Elements","page":"AC State Estimation","title":"Power at Branch Shunt Elements","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Active and reactive powers associated with the branch shunt elements at each branch are represented by the vectors mathbfP_texts = P_textsij and mathbfQ_texts = Q_textsij. We can retrieve these values using the following code:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐏ₛ = analysis.power.charging.active\n𝐐ₛ = analysis.power.charging.reactive","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Power-at-Branch-Series-Elements","page":"AC State Estimation","title":"Power at Branch Series Elements","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Active and reactive powers associated with the branch series element at each branch are represented by the vectors mathbfP_textl = P_textlij and mathbfQ_textl = Q_textlij. We can retrieve these values using the following code:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐏ₗ = analysis.power.series.active\n𝐐ₗ = analysis.power.series.reactive","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#PMUCurrentAnalysisTutorials","page":"AC State Estimation","title":"Current Analysis","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"JuliaGrid offers the current! function, which enables the calculation of currents associated with buses and branches. Here is an example code snippet demonstrating its usage:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"current!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"The function stores the computed currents in the polar coordinate system. It calculates the following currents related to buses and branches:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Bus Magnitude Angle\nInjections mathbfI = I_i bmpsi = psi_i","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Branch Magnitude Angle\nFrom-bus end flows mathbfI_texti = I_ij bmpsi_texti = psi_ij\nTo-bus end flows mathbfI_textj = I_ji bmpsi_textj = psi_ji\nSeries elements mathbfI_textl = I_textlij bmpsi_textl = psi_textlij","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"note: Info\nFor a clear comprehension of the equations, symbols presented in this section, as well as for a better grasp of power directions, please refer to the Unified Branch Model.","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Current-Injections","page":"AC State Estimation","title":"Current Injections","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"In JuliaGrid, complex current injections are stored in the vector of magnitudes denoted as mathbfI = I_i and the vector of angles represented as bmpsi = psi_i. You can retrieve them using the following commands:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐈 = analysis.current.injection.magnitude\n𝛙 = analysis.current.injection.angle","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Current-Flows","page":"AC State Estimation","title":"Current Flows","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To obtain the vectors of magnitudes mathbfI_texti = I_ij and angles bmpsi_texti = psi_ij for the resulting complex current flows, you can use the following commands:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐈ᵢ = analysis.current.from.magnitude\n𝛙ᵢ = analysis.current.from.angle","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"Similarly, we can obtain the vectors of magnitudes mathbfI_textj = I_ji and angles bmpsi_textj = psi_ji of the resulting complex current flows using the following code:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐈ⱼ = analysis.current.to.magnitude\n𝛙ⱼ = analysis.current.to.angle","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"","category":"page"},{"location":"tutorials/acStateEstimation/#Current-at-Branch-Series-Elements","page":"AC State Estimation","title":"Current at Branch Series Elements","text":"","category":"section"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"To obtain the vectors of magnitudes mathbfI_textl = I_textlij and angles bmpsi_textl = psi_textlij of the resulting complex current flows, one can use the following code:","category":"page"},{"location":"tutorials/acStateEstimation/","page":"AC State Estimation","title":"AC State Estimation","text":"𝐈ₗ = analysis.current.series.magnitude\n𝛙ₗ = analysis.current.series.angle","category":"page"},{"location":"api/powerSystemModel/#powerSystemModelAPI","page":"Power System Model","title":"Power System Model","text":"","category":"section"},{"location":"api/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"For further information on this topic, please see the Power System Model section of the Manual. Below, we have provided a list of functions that can be used to create, save, and manipulate power system structures, as well as to build AC and DC models of power systems.","category":"page"},{"location":"api/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"To load power system model API functionalities into the current scope, utilize the following command:","category":"page"},{"location":"api/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"using JuliaGrid","category":"page"},{"location":"api/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"api/powerSystemModel/#Power-System","page":"Power System Model","title":"Power System","text":"","category":"section"},{"location":"api/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"powerSystem\nsavePowerSystem\nacModel!\ndcModel!","category":"page"},{"location":"api/powerSystemModel/#Bus","page":"Power System Model","title":"Bus","text":"","category":"section"},{"location":"api/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"addBus!\nupdateBus!\n@bus","category":"page"},{"location":"api/powerSystemModel/#Branch","page":"Power System Model","title":"Branch","text":"","category":"section"},{"location":"api/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"addBranch!\nupdateBranch!\n@branch","category":"page"},{"location":"api/powerSystemModel/#Generator","page":"Power System Model","title":"Generator","text":"","category":"section"},{"location":"api/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"addGenerator!\nupdateGenerator!\ncost!\n@generator","category":"page"},{"location":"api/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"api/powerSystemModel/#Power-System-2","page":"Power System Model","title":"Power System","text":"","category":"section"},{"location":"api/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"powerSystem\nsavePowerSystem\nacModel!\ndcModel!","category":"page"},{"location":"api/powerSystemModel/#JuliaGrid.powerSystem","page":"Power System Model","title":"JuliaGrid.powerSystem","text":"powerSystem(file::String)\n\nThe function builds the composite type PowerSystem and populates bus, branch, generator and base fields. Once the composite type PowerSystem has been created, it is possible to add new buses, branches, or generators, or modify the parameters of existing ones.\n\nArgument\n\nIt requires a string path to:\n\nthe HDF5 file with the .h5 extension,\nthe Matpower file with the .m extension.\n\nReturns\n\nThe PowerSystem composite type with the following fields:\n\nbus: Data related to buses.\nbranch: Data related to branches.\ngenerator: Data related to generators.\nbase: Base power and base voltages.\nmodel: Data associated with AC and DC analyses.\n\nUnits\n\nJuliaGrid stores all data in per-units and radians format which are fixed, the exceptions are base values in volt-amperes and volts. The prefixes for these base values can be changed using the @base macro.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\n\n\n\n\n\npowerSystem()\n\nAlternatively, the PowerSystem composite type can be initialized by calling the function without any arguments. This allows the model to be built from scratch and modified as needed. This generates an empty PowerSystem type, with only the base power initialized to 1.0e8 volt-amperes (VA).\n\nExample\n\nsystem = powerSystem()\n\n\n\n\n\n","category":"function"},{"location":"api/powerSystemModel/#JuliaGrid.savePowerSystem","page":"Power System Model","title":"JuliaGrid.savePowerSystem","text":"savePowerSystem(system::PowerSystem; path::String, reference::String, note::String)\n\nThe function saves the power system's data in the HDF5 file using the fields bus, branch, generator, and base from the PowerSystem composite type.\n\nKeywords\n\nThe location and file name of the HDF5 file is specified by the mandatory keyword path in the format of \"path/name.h5\". Additional information can be provided by the optional keywords reference and note, which can be saved along with the power system data.\n\nView HDF5 File\n\nTo view the saved HDF5 file, you can use the HDFView software.\n\nExample\n\nsystem = powerSystem(\"case14.m\")\nsavePowerSystem(system; path = \"D:/case14.h5\")\n\n\n\n\n\n","category":"function"},{"location":"api/powerSystemModel/#JuliaGrid.acModel!","page":"Power System Model","title":"JuliaGrid.acModel!","text":"acModel!(system::PowerSystem)\n\nThe function generates vectors and matrices based on the power system topology and parameters associated with AC analyses.\n\nUpdates\n\nThe function updates the model.ac field within the PowerSystem composite type, populating the following variables:\n\nnodalMatrix: The nodal matrix.\nnodalMatrixTranspose: The transpose of the nodal matrix.\nnodalFromFrom: The Y-parameters of the two-port branches.\nnodalFromTo: The Y-parameters of the two-port branches.\nnodalToTo: The Y-parameters of the two-port branches.\nnodalToFrom: The Y-parameters of the two-port branches.\nadmittance: The branch admittances.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\nacModel!(system)\n\n\n\n\n\n","category":"function"},{"location":"api/powerSystemModel/#JuliaGrid.dcModel!","page":"Power System Model","title":"JuliaGrid.dcModel!","text":"dcModel!(system::PowerSystem)\n\nThe function generates vectors and matrices based on the power system topology and parameters associated with DC analyses.\n\nUpdates\n\nThe function updates the model.dc field within the PowerSystem composite type, populating the following variables:\n\nnodalMatrix: The nodal matrix.\nadmittance: The branch admittances.\nshiftPower: The active powers related to phase-shifting transformers.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndcModel!(system)\n\n\n\n\n\n","category":"function"},{"location":"api/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"api/powerSystemModel/#Bus-2","page":"Power System Model","title":"Bus","text":"","category":"section"},{"location":"api/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"addBus!\nupdateBus!\n@bus","category":"page"},{"location":"api/powerSystemModel/#JuliaGrid.addBus!","page":"Power System Model","title":"JuliaGrid.addBus!","text":"addBus!(system::PowerSystem; label, type, active, reactive, conductance, susceptance,\n magnitude, angle, minMagnitude, maxMagnitude, base, area, lossZone)\n\nThe function adds a new bus to the PowerSystem composite type.\n\nKeywords\n\nThe bus is defined with the following keywords:\n\nlabel: Unique label for the bus.\ntype: Bus type:\ntype = 1: demand bus (PQ),\ntype = 2: generator bus (PV),\ntype = 3: slack bus (Vθ).\nactive (pu or W): Active power demand at the bus.\nreactive (pu or VAr): Reactive power demand at the bus.\nconductance (pu or W): Active power demanded of the shunt element.\nsusceptance (pu or VAr): Reactive power injected/demanded of the shunt element.\nmagnitude (pu or V): Initial value of the bus voltage magnitude.\nangle (rad or deg): Initial value of the bus voltage angle.\nminMagnitude (pu or V): Minimum bus voltage magnitude value.\nmaxMagnitude (pu or V): Maximum bus voltage magnitude value.\nbase (V): Voltage base value.\narea: Area number.\nlossZone: Loss zone.\n\nUpdates\n\nThe function updates the bus field of the PowerSystem composite type.\n\nDefault Settings\n\nThe default settings for certain keywords are as follows: type = 1, magnitude = 1.0, minMagnitude = 0.9, maxMagnitude = 1.1, and base = 138e3. The rest of the keywords are initialized with a value of zero. However, the user can modify these default settings by utilizing the @bus macro.\n\nUnits\n\nBy default, the keyword parameters use per-units (pu) and radians (rad) as units, with the exception of the base keyword argument, which is in volts (V). However, users have the option to use other units instead of per-units and radians, or to specify prefixes for base voltage by using the @power and @voltage macros.\n\nExamples\n\nAdding a bus using the default unit system:\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", active = 0.25, angle = 0.175, base = 132e3)\n\nAdding a bus using a custom unit system:\n\n@power(MW, MVAr, MVA)\n@voltage(pu, deg, kV)\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", active = 25.0, angle = 10.026, base = 132.0)\n\n\n\n\n\n","category":"function"},{"location":"api/powerSystemModel/#JuliaGrid.updateBus!","page":"Power System Model","title":"JuliaGrid.updateBus!","text":"updateBus!(system::PowerSystem, [analysis::Analysis]; kwargs...)\n\nThe function allows for the alteration of parameters for an existing bus.\n\nArguments\n\nIf the Analysis type is omitted, the function applies changes to the PowerSystem composite type only. However, when including the Analysis type, it updates both the PowerSystem and Analysis types. This streamlined process avoids the need to completely rebuild vectors and matrices when adjusting these parameters.\n\nKeywords\n\nTo update a specific bus, provide the necessary kwargs input arguments in accordance with the keywords specified in the addBus! function, along with their respective values. Ensure that the label keyword matches the label of the existing bus you want to modify. If any keywords are omitted, their corresponding values will remain unchanged.\n\nUpdates\n\nThe function updates the bus field within the PowerSystem composite type, and in cases where parameters impact variables in the ac field, it automatically adjusts the field. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.\n\nUnits\n\nUnits for input parameters can be changed using the same method as described for the addBus! function.\n\nExample\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.25, reactive = -0.04)\nupdateBus!(system; label = \"Bus 1\", active = 0.15, susceptance = 0.15)\n\n\n\n\n\n","category":"function"},{"location":"api/powerSystemModel/#JuliaGrid.@bus","page":"Power System Model","title":"JuliaGrid.@bus","text":"@bus(kwargs...)\n\nThe macro generates a template for a bus, which can be utilized to define a bus using the addBus! function.\n\nKeywords\n\nTo define the bus template, the kwargs input arguments must be provided in accordance with the keywords specified within the addBus! function, along with their corresponding values.\n\nUnits\n\nBy default, the keyword parameters use per-units (pu) and radians (rad) as units, with the exception of the base keyword argument, which is in volts (V). However, users have the option to use other units instead of per-units and radians, or to specify prefixes for base voltage by using the @power and @voltage macros.\n\nExamples\n\nAdding a bus template using the default unit system:\n\nsystem = powerSystem()\n\n@bus(type = 2, active = 0.25, angle = 0.1745)\naddBus!(system; label = \"Bus 1\", reactive = -0.04, base = 132e3)\n\nAdding a bus template using a custom unit system:\n\n@power(MW, MVAr, MVA)\n@voltage(pu, deg, kV)\nsystem = powerSystem()\n\n@bus(type = 2, active = 25.0, angle = 10.0, base = 132.0)\naddBus!(system; label = \"Bus 1\", reactive = -4.0)\n\n\n\n\n\n","category":"macro"},{"location":"api/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"api/powerSystemModel/#Branch-2","page":"Power System Model","title":"Branch","text":"","category":"section"},{"location":"api/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"addBranch!\nupdateBranch!\n@branch","category":"page"},{"location":"api/powerSystemModel/#JuliaGrid.addBranch!","page":"Power System Model","title":"JuliaGrid.addBranch!","text":"addBranch!(system::PowerSystem, [analysis::Analysis]; label, from, to, status,\n resistance, reactance, conductance, susceptance, turnsRatio, shiftAngle,\n minDiffAngle, maxDiffAngle, minFromBus, maxFromBus, minToBus, maxToBus, type)\n\nThe function adds a new branch to the PowerSystem composite type. A branch can be added between already defined buses.\n\nArguments\n\nIf the Analysis type is omitted, the function applies changes to the PowerSystem composite type only. However, when including the Analysis type, it updates both the PowerSystem and Analysis types. This streamlined approach circumvents the necessity for completely reconstructing vectors and matrices when adding a new branch.\n\nKeywords\n\nThe branch is defined with the following keywords:\n\nlabel: Unique label for the branch.\nfrom: From-bus label, corresponds to the bus label.\nto: To-bus label, corresponds to the bus label.\nstatus: Operating status of the branch:\nstatus = 1: in-service,\nstatus = 0: out-of-service.\nresistance (pu or Ω): Series resistance.\nreactance (pu or Ω): Series reactance.\nconductance (pu or S): Total shunt conductance.\nsusceptance (pu or S): Total shunt susceptance.\nturnsRatio: Transformer off-nominal turns ratio, equal to one for a line.\nshiftAngle (rad or deg): Transformer phase shift angle, where positive value defines delay.\nminDiffAngle (rad or deg): Minimum voltage angle difference value between from-bus and to-bus ends.\nmaxDiffAngle (rad or deg): Maximum voltage angle difference value between from-bus and to-bus ends.\nminFromBus (pu, VA, W, or A): Minimum branch flow rating at the from-bus end.\nmaxFromBus (pu, VA, W, or A): Maximum branch flow rating at the from-bus end.\nminToBus (pu, VA, W, or A): Minimum branch flow rating at the to-bus end.\nmaxToBus (pu, VA, W, or A): Maximum branch flow rating at the to-bus end.\ntype: Types of minFromBus, maxFromBus, minToBus, and maxToBus branch flow ratings:\ntype = 1: apparent power flow (pu or VA),\ntype = 2: active power flow (pu or W),\ntype = 3: current magnitude flow (pu or A).\n\nUpdates\n\nThe function updates the branch field within the PowerSystem composite type, and in cases where parameters impact variables in the ac and dc fields, it automatically adjusts the fields. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.\n\nDefault Settings\n\nBy default, certain keywords are assigned default values: status = 1, turnsRatio = 1.0, type = 1, minDiffAngle = -2pi, and maxDiffAngle = 2pi. The rest of the keywords are initialized with a value of zero. However, the user can modify these default settings by utilizing the @branch macro.\n\nUnits\n\nThe default units for the keyword parameters are per-units (pu) and radians (rad). However, the user can choose to use other units besides per-units and radians by utilizing macros such as @power, @voltage, @current, and @parameter.\n\nExamples\n\nAdding a branch using the default unit system:\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.25, reactive = -0.04)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.15, reactive = 0.08)\n\naddBranch!(system; from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12, shiftAngle = 0.1745)\n\nAdding a branch using a custom unit system:\n\n@voltage(pu, deg, kV)\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.25, reactive = -0.04)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.15, reactive = 0.08)\n\naddBranch!(system; from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12, shiftAngle = 10)\n\n\n\n\n\n","category":"function"},{"location":"api/powerSystemModel/#JuliaGrid.updateBranch!","page":"Power System Model","title":"JuliaGrid.updateBranch!","text":"updateBranch!(system::PowerSystem, [analysis::Analysis]; kwargs...)\n\nThe function allows for the alteration of parameters for an existing branch.\n\nArguments\n\nIf the Analysis type is omitted, the function applies changes to the PowerSystem composite type only. However, when including the Analysis type, it updates both the PowerSystem and Analysis types. This streamlined process avoids the need to completely rebuild vectors and matrices when adjusting these parameter\n\nKeywords\n\nTo update a specific branch, provide the necessary kwargs input arguments in accordance with the keywords specified in the addBranch! function, along with their respective values. Ensure that the label keyword matches the label of the existing branch you want to modify. If any keywords are omitted, their corresponding values will remain unchanged.\n\nUpdates\n\nThe function updates the branch field within the PowerSystem composite type, and in cases where parameters impact variables in the ac and dc fields, it automatically adjusts the fields. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.\n\nUnits\n\nUnits for input parameters can be changed using the same method as described for the addBranch! function.\n\nExample\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.25, reactive = -0.04)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.15, reactive = 0.08)\n\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12)\nupdateBranch!(system; label = \"Branch 1\", reactance = 0.02, susceptance = 0.062)\n\n\n\n\n\n","category":"function"},{"location":"api/powerSystemModel/#JuliaGrid.@branch","page":"Power System Model","title":"JuliaGrid.@branch","text":"@branch(kwargs...)\n\nThe macro generates a template for a branch, which can be utilized to define a branch using the addBranch! function.\n\nKeywords\n\nTo define the branch template, the kwargs input arguments must be provided in accordance with the keywords specified within the addBranch! function, along with their corresponding values.\n\nUnits\n\nThe default units for the keyword parameters are per-units and radians. However, the user can choose to use other units besides per-units and radians by utilizing macros such as @power, @voltage, and @parameter.\n\nExamples\n\nAdding a branch template using the default unit system:\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.25, reactive = -0.04)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.15, reactive = 0.08)\n\n@branch(reactance = 0.12, shiftAngle = 0.1745)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\")\n\nAdding a branch template using a custom unit system:\n\n@voltage(pu, deg, kV)\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.25, reactive = -0.04)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.15, reactive = 0.08)\n\n@branch(shiftAngle = 10)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12)\n\n\n\n\n\n","category":"macro"},{"location":"api/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"","category":"page"},{"location":"api/powerSystemModel/#Generator-2","page":"Power System Model","title":"Generator","text":"","category":"section"},{"location":"api/powerSystemModel/","page":"Power System Model","title":"Power System Model","text":"addGenerator!\nupdateGenerator!\ncost!\n@generator","category":"page"},{"location":"api/powerSystemModel/#JuliaGrid.addGenerator!","page":"Power System Model","title":"JuliaGrid.addGenerator!","text":"addGenerator!(system::PowerSystem, [analysis::Analysis]; label, bus, status,\n active, reactive, magnitude, minActive, maxActive, minReactive, maxReactive,\n lowActive, minLowReactive, maxLowReactive, upActive, minUpReactive, maxUpReactive,\n loadFollowing, reactiveRamp, reserve10min, reserve30min, area)\n\nThe function adds a new generator to the PowerSystem composite type. The generator can be added to an already defined bus.\n\nArguments\n\nIf the Analysis type is omitted, the function applies changes to the PowerSystem composite type only. However, when including the Analysis type, it updates both the PowerSystem and Analysis types. This streamlined approach circumvents the necessity for completely reconstructing vectors and matrices when adding a new generator.\n\nKeywords\n\nThe generator is defined with the following keywords:\n\nlabel: Unique label for the generator.\nbus: Label of the bus to which the generator is connected.\nstatus: Operating status of the generator:\nstatus = 1: in-service,\nstatus = 0: out-of-service.\nactive (pu or W): Output active power.\nreactive (pu or VAr): Output reactive power.\nmagnitude (pu or V): Voltage magnitude setpoint.\nminActive (pu or W): Minimum allowed output active power value.\nmaxActive (pu or W): Maximum allowed output active power value.\nminReactive (pu or VAr): Minimum allowed output reactive power value.\nmaxReactive (pu or VAr): Maximum allowed output reactive power value.\nlowActive (pu or W): Lower allowed active power output value of PQ capability curve.\nminLowReactive (pu or VAr): Minimum allowed reactive power output value at lowActive value.\nmaxLowReactive (pu or VAr): Maximum allowed reactive power output value at lowActive value.\nupActive (pu or W): Upper allowed active power output value of PQ capability curve.\nminUpReactive (pu or VAr): Minimum allowed reactive power output value at upActive value.\nmaxUpReactive (pu or VAr): Maximum allowed reactive power output value at upActive value.\nloadFollowing (pu/min or W/min): Ramp rate for load following/AG.\nreserve10min (pu or W): Ramp rate for 10-minute reserves.\nreserve30min (pu or W): Ramp rate for 30-minute reserves.\nreactiveRamp (pu/min or VAr/min): Ramp rate for reactive power, two seconds timescale.\narea: Area participation factor.\n\nUpdates\n\nThe function updates the generator field within the PowerSystem composite type, and in cases where parameters impact variables in the bus field, it automatically adjusts the field. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.\n\nDefault Settings\n\nBy default, certain keywords are assigned default values: status = 1 and magnitude = 1.0 per-unit. The rest of the keywords are initialized with a value of zero. However, the user can modify these default settings by utilizing the @generator macro.\n\nUnits\n\nBy default, the input units are associated with per-units (pu) as shown. However, users have the option to use other units instead of per-units using the @power and @voltage macros.\n\nExamples\n\nAdding a generator using the default unit system:\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 2, active = 0.2, base = 132e3)\n\naddGenerator!(system; bus = \"Bus 1\", active = 0.5, magnitude = 1.1)\n\nAdding a generator using a custom unit system:\n\n@power(MW, MVAr, MVA)\n@voltage(kV, deg, kV)\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 2, active = 20, base = 132)\n\naddGenerator!(system; bus = \"Bus 1\", active = 50, magnitude = 145.2)\n\n\n\n\n\n","category":"function"},{"location":"api/powerSystemModel/#JuliaGrid.updateGenerator!","page":"Power System Model","title":"JuliaGrid.updateGenerator!","text":"updateGenerator!(system::PowerSystem, [analysis::Analysis]; kwargs...)\n\nThe function allows for the alteration of parameters for an existing generator.\n\nArguments\n\nIf the Analysis type is omitted, the function applies changes to the PowerSystem composite type only. However, when including the Analysis type, it updates both the PowerSystem and Analysis types. This streamlined process avoids the need to completely rebuild vectors and matrices when adjusting these parameter\n\nKeywords\n\nTo update a specific generator, provide the necessary kwargs input arguments in accordance with the keywords specified in the addGenerator! function, along with their respective values. Ensure that the label keyword matches the label of the existing generator you want to modify. If any keywords are omitted, their corresponding values will remain unchanged.\n\nUpdates\n\nThe function updates the generator field within the PowerSystem composite type, and in cases where parameters impact variables in the bus field, it automatically adjusts the field. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.\n\nUnits\n\nUnits for input parameters can be changed using the same method as described for the addBranch! function.\n\nExample\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 2, active = 0.2, base = 132e3)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 0.5)\nupdateGenerator!(system; label = \"Generator 1\", active = 0.6, reactive = 0.2)\n\n\n\n\n\n","category":"function"},{"location":"api/powerSystemModel/#JuliaGrid.cost!","page":"Power System Model","title":"JuliaGrid.cost!","text":"cost!(system::PowerSystem, [analysis::Analysis]; label, active, reactive,\n piecewise, polynomial)\n\nThe function either adds a new cost or modifies an existing one for the active or reactive power generated by the corresponding generator within the PowerSystem composite type. It has the capability to append a cost to an already defined generator.\n\nArguments\n\nIf the Analysis type is omitted, the function applies changes to the PowerSystem composite type only. However, when including the Analysis type, it updates both the PowerSystem and Analysis types. This streamlined approach circumvents the necessity for completely reconstructing vectors and matrices when adding a new branch.\n\nKeywords\n\nThe function accepts five keywords:\n\nlabel: Corresponds to the already defined generator label.\nactive: Active power cost model:\nactive = 1: adding or updating cost, and piecewise linear is being used,\nactive = 2: adding or updating cost, and polynomial is being used.\nreactive: Reactive power cost model:\nreactive = 1: adding or updating cost, and piecewise linear is being used,\nreactive = 2: adding or updating cost, and polynomial is being used.\npiecewise: Cost model defined by input-output points given as Vector{Float64}:\nfirst column (pu, W or VAr): active or reactive power output of the generator,\nsecond column (€/hr): cost for the specified active or reactive power output.\npolynomial: The n-th degree polynomial coefficients given as Vector{Float64}:\nfirst element (€/puⁿ-hr, €/Wⁿhr or €/VArⁿ-hr): coefficient of the n-th degree term, ....,\npenultimate element (€/pu-hr, €/W-hr or €/VAr-hr): coefficient of the first degree term,\nlast element (€/hr): constant coefficient.\n\nUpdates\n\nThe function updates the generator.cost field within the PowerSystem composite type. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.\n\nUnits\n\nBy default, the input units related with active powers are per-units (pu), but they can be modified using the macro @power.\n\nExamples\n\nAdding a cost using the default unit system:\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", active = 0.25, reactive = -0.04, base = 132e3)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 0.5)\ncost!(system; label = \"Generator 1\", active = 2, polynomial = [1100.0; 500.0; 150.0])\n\nAdding a cost using a custom unit system:\n\n@power(MW, MVAr, MVA)\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", active = 25, reactive = -4, base = 132e3)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 50, reactive = 10)\ncost!(system; label = \"Generator 1\", active = 2, polynomial = [0.11; 5.0; 150.0])\n\n\n\n\n\n","category":"function"},{"location":"api/powerSystemModel/#JuliaGrid.@generator","page":"Power System Model","title":"JuliaGrid.@generator","text":"@generator(kwargs...)\n\nThe macro generates a template for a generator, which can be utilized to define a generator using the addGenerator! function.\n\nKeywords\n\nTo define the generator template, the kwargs input arguments must be provided in accordance with the keywords specified within the addGenerator! function, along with their corresponding values.\n\nUnits\n\nBy default, the input units are associated with per-units (pu) as shown. However, users have the option to use other units instead of per-units using the @power and @voltage macros.\n\nExamples\n\nAdding a generator using the default unit system:\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 2, active = 0.25, reactive = -0.04, base = 132e3)\n\n@generator(magnitude = 1.1)\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 0.5, reactive = 0.1)\n\nAdding a generator using a custom unit system:\n\n@power(MW, MVAr, MVA)\n@voltage(kV, deg, kV)\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 2, active = 25, reactive = -4, base = 132)\n\n@generator(magnitude = 145.2)\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 50, reactive = 10)\n\n\n\n\n\n","category":"macro"},{"location":"tutorials/dcPowerFlow/#DCPowerFlowTutorials","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"section"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"JuliaGrid employs standard network components and the Unified Branch Model to obtain the DC power flow solution. To begin, let us generate the PowerSystem type, as illustrated by the following example:","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n@labels(Integer)\n\n@power(MW, MVAr, MVA)\n@voltage(pu, deg, V)\n\nsystem = powerSystem()\n\naddBus!(system; label = 1, type = 3)\naddBus!(system; label = 2, type = 1, active = 21.7)\naddBus!(system; label = 3, type = 2, conductance = 0.07)\n\naddBranch!(system; from = 1, to = 2, reactance = 0.26)\naddBranch!(system; from = 1, to = 3, reactance = 0.38)\naddBranch!(system; from = 2, to = 3, reactance = 0.17, turnsRatio = 0.97)\n\naddGenerator!(system; bus = 1, active = 2.0)\naddGenerator!(system; bus = 1, active = 4.0)\naddGenerator!(system; bus = 3, active = 5.0)\nnothing #hide","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"To review, we can conceptualize the bus/branch model as the graph denoted by mathcalG = (mathcalN mathcalE), where we have the set of buses mathcalN = 1 dots n, and the set of branches mathcalE subseteq mathcalN times mathcalN within the power system:","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"𝒩 = collect(keys(system.bus.label))\nℰ = [𝒩[system.branch.layout.from] 𝒩[system.branch.layout.to]]","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"ukw: Notation\nIn this section, when referring to a vector mathbfa, we use the notation mathbfa = a_i or mathbfa = a_ij, where a_i represents the element associated with bus i in mathcalN, and a_ij represents the element associated with branch (ij) in mathcalE.","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"tutorials/dcPowerFlow/#DCPowerFlowSolutionTutorials","page":"DC Power Flow","title":"Power Flow Solution","text":"","category":"section"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"As discussed in section DC Model, the DC power flow problem can be represented by a set of linear equations:","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":" mathbf P = mathbfB bm Theta + mathbfP_texttr + mathbfP_textsh","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"tutorials/dcPowerFlow/#Implementation","page":"DC Power Flow","title":"Implementation","text":"","category":"section"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"JuliaGrid offers a set of functions to solve the DC power flow problem and obtain the bus voltage angles. Firstly, the power system is loaded and the DC model is built using the following code sequence:","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"dcModel!(system)\nnothing # hide","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"The DC power flow solution is obtained through a non-iterative approach by solving the system of linear equations:","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":" bm Theta = mathbfB^-1(mathbf P - mathbfP_texttr - mathbfP_textsh)","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"JuliaGrid begins the process by establishing the DC power flow framework:","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"analysis = dcPowerFlow(system)\nnothing # hide","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"The subsequent step involves performing the LU factorization of the nodal matrix mathbfB = mathbfLmathbfU and computing the bus voltage angles using:","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"solve!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"tip: Tip\nBy default, JuliaGrid utilizes LU factorization as the primary method to factorize the nodal matrix. However, users maintain the flexibility to opt for alternative factorization methods such as LDLt or QR.","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"The factorization of the nodal matrix can be accessed using:","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"𝐋 = analysis.method.factorization.L\n𝐔 = analysis.method.factorization.U","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"It is important to note that the slack bus voltage angle is excluded from the vector bmTheta only during the computation step. Consequently, the corresponding elements in the vectors mathbf P, mathbfP_texttr, mathbfP_textsh, and the corresponding row and column of the matrix mathbfB are removed. It is worth mentioning that this process is handled internally, and the stored elements remain unchanged.","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"Finally, the resulting bus voltage angles are saved in the vector as follows:","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"𝚯 = analysis.voltage.angle","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"tutorials/dcPowerFlow/#DCPowerAnalysisTutorials","page":"DC Power Flow","title":"Power Analysis","text":"","category":"section"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"After obtaining the solution from the DC power flow, we can calculate powers related to buses, branches, and generators using the power! function:","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"power!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"note: Info\nFor a clear comprehension of the equations, symbols provided below, as well as for a better grasp of power directions, please refer to the Unified Branch Model.","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"tutorials/dcPowerFlow/#Power-Injections","page":"DC Power Flow","title":"Power Injections","text":"","category":"section"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"Active power injections are stored as the vector mathbfP = P_i, and can be retrieved using the following commands:","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"𝐏 = analysis.power.injection.active","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"tutorials/dcPowerFlow/#Generator-Power-Injections","page":"DC Power Flow","title":"Generator Power Injections","text":"","category":"section"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"The active power supplied by generators to the buses can be calculated by summing the given generator active powers in the input data, except for the slack bus, which can be determined as:","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":" P_textpi = P_i + P_textdi i in mathcalN_textsb","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"where P_textdi represents the active power demanded by consumers at the slack bus. The vector of active powers injected by generators into the buses, denoted by mathbfP_textp = P_textpi, can be obtained using the following command:","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"𝐏ₚ = analysis.power.supply.active","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"tutorials/dcPowerFlow/#Power-Flows","page":"DC Power Flow","title":"Power Flows","text":"","category":"section"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"The resulting from-bus active power flows are stored as the vector mathbfP_texti = P_ij, which can be retrieved using:","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"𝐏ᵢ = analysis.power.from.active","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"Similarly, the resulting to-bus active power flows are stored as the vector mathbfP_textj = P_ji, which can be retrieved using:","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"𝐏ⱼ = analysis.power.to.active","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"tutorials/dcPowerFlow/#Generators-Power-Outputs","page":"DC Power Flow","title":"Generators Power Outputs","text":"","category":"section"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"The output active power of each generator located at bus i in mathcalN_textpv cup mathcalN_textpq is equal to the active power specified in the input data. If there are multiple generators, their output active powers are also equal to the active powers specified in the input data. However, the output active power of a generator located at the slack bus will be:","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":" P_textgi = P_i + P_textdi i in mathcalN_textsb","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"In the case of multiple generators connected to the slack bus, the first generator in the input data is assigned the obtained value of P_textgi. Then, this amount of power is reduced by the output active power of the other generators.","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"To retrieve the vector of active power outputs of generators, denoted as mathbfP_textg = P_textgi, i in mathcalS, where the set mathcalS represents the set of generators, users can utilize the following command:","category":"page"},{"location":"tutorials/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"𝐏ₒ = analysis.power.generator.active","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#ACOptimalPowerFlowTutorials","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To begin, let us generate the PowerSystem type, as illustrated by the following example:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"using JuliaGrid # hide\nusing JuMP, Ipopt\n@default(unit) # hide\n@default(template) # hide\n\n@labels(Integer)\n\nsystem = powerSystem()\n\n@bus(minMagnitude = 0.95, maxMagnitude = 1.05)\naddBus!(system; label = 1, type = 3, active = 0.1, angle = -0.1)\naddBus!(system; label = 2, reactive = 0.01, magnitude = 1.1)\n\n@branch(minDiffAngle = -pi, maxDiffAngle = pi, reactance = 0.5, type = 2)\naddBranch!(system; label = 1, from = 1, to = 2, maxFromBus = 0.15, maxToBus = 0.15)\n\n@generator(maxActive = 0.5, minReactive = -0.1, maxReactive = 0.1)\naddGenerator!(system; label = 1, bus = 1, active = 0.4, reactive = 0.2)\naddGenerator!(system; label = 2, bus = 2, active = 0.2, reactive = 0.1)\n\ncost!(system; label = 1, active = 2, polynomial = [900.0; 500.0; 80.0; 5.0])\ncost!(system; label = 2, active = 1, piecewise = [10.8 12.3; 14.7 16.8; 18 18.1])\n\ncost!(system; label = 1, reactive = 1, piecewise = [10.0 20.0; 20.0 40.0])\ncost!(system; label = 2, reactive = 2, polynomial = [2.0])\nnothing # hide","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To review, we can conceptualize the bus/branch model as the graph denoted by mathcalG = (mathcalN mathcalE), where we have the set of buses mathcalN = 1 dots n, and the set of branches mathcalE subseteq mathcalN times mathcalN within the power system:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝒩 = collect(keys(system.bus.label))\nℰ = [𝒩[system.branch.layout.from] 𝒩[system.branch.layout.to]]","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Moreover, we identify the set of generators as mathcalS = 1 dots n_textg within the power system:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝒮 = collect(keys(system.generator.label))","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"ukw: Notation\nHere, when referring to a vector mathbfa, we use the notation mathbfa = a_i or mathbfa = a_ij, where a_i represents the element related with bus i in mathcalN or generator i in mathcalS, while a_ij denotes the element related with branch (ij) in mathcalE.","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#ACOptimalPowerFlowModelTutorials","page":"AC Optimal Power Flow","title":"Optimal Power Flow Model","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"In the AC optimal power flow model, the active and reactive power outputs of the generators, denoted as mathbf P_textg = P_textgi and mathbf Q_textg = Q_textgi, where i in mathcalS, are expressed as nonlinear functions of the bus voltage magnitudes and angles, denoted as mathbf V = V_i and bmTheta = theta_i, where i in mathcalN. Consequently, the optimization variables encompass the active and reactive power outputs of the generators, as well as the bus voltage magnitudes and angles.","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The AC optimal power flow problem can be formulated as follows:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"beginaligned\n textminimize sum_i in mathcalS left f_i(P_textgi) + f_i(Q_textgi) right \n textsubjectto theta_i - theta_texts = 0 i in mathcalN_textsb 5pt\n h_P_i(mathbf P_textg mathbf V bmTheta) = 0 forall i in mathcalN \n h_Q_i(mathbf Q_textg mathbf V bmTheta) = 0 forall i in mathcalN 5pt\n V_i^textmin leq V_i leq V_i^textmax forall i in mathcalN \n theta_ij^textmin leq theta_i - theta_j leq theta_ij^textmax forall (ij) in mathcalE 5pt\n F_ij^textmin leq h_ij(mathbf V bmTheta) leq F_ij^textmax forall (ij) in mathcalE \n F_ji^textmin leq h_ji(mathbf V bmTheta) leq F_ji^textmax forall (ij) in mathcalE 5pt\n P_textgi^textmin leq P_textgi leq P_textgi^textmax forall i in mathcalS \n Q_textgi^textmin leq Q_textgi leq Q_textgi^textmax forall i in mathcalS\nendaligned","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"In essence, the AC optimal power flow aims to minimize the objective function associated with the costs of generator's active and reactive power output while ensuring the fulfillment of all constraints. This optimization task plays a pivotal role in effectively managing electrical power systems. By striking a balance between cost reduction and constraint adherence, the AC optimal power flow contributes to efficient and reliable electricity supply in complex grid environments.","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Build-Optimal-Power-Flow-Model","page":"AC Optimal Power Flow","title":"Build Optimal Power Flow Model","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To build the AC optimal power flow model, we must first load the power system and establish the AC model:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"acModel!(system)\nnothing # hide","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Afterward, the AC optimal power flow model is created using the acOptimalPowerFlow function:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"analysis = acOptimalPowerFlow(\n system, Ipopt.Optimizer; active = \"Pg\", reactive = \"Qg\", magnitude = \"V\", angle = \"θ\"\n)\nnothing # hide","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Optimization-Variables","page":"AC Optimal Power Flow","title":"Optimization Variables","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The variables within this model encompass the active and reactive power outputs of the generators, denoted as mathbfP_textg = P_textgi and mathbfQ_textg = Q_textgi, where i in mathcalS, and the bus voltage magnitudes and angles represented by mathbfV = V_i and bmTheta = theta_i, where i in mathcalN. We can access these variables using the following code:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐏ₒ = analysis.method.variable.active\n𝐐ₒ = analysis.method.variable.reactive\n𝐕 = analysis.method.variable.magnitude\n𝚯 = analysis.method.variable.angle","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Objective-Function","page":"AC Optimal Power Flow","title":"Objective Function","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The objective function represents the sum of the active and reactive power cost functions f_i(P_textgi) and f_i(Q_textgi), where i in mathcalS, for each generator, where these cost functions can be polynomial or linear piecewise. Typically, the AC optimal power flow focuses on minimizing the cost of active power outputs only, but for comprehensive analysis, we also consider the costs associated with reactive power outputs.","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Polynomial-Cost-Function","page":"AC Optimal Power Flow","title":"Polynomial Cost Function","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"In the following analysis, we will focus on the cost function of generating active power, denoted as f_i(P_textgi). However, please note that the same analysis can be applied to the cost function f_i(Q_textgi) for reactive power.","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"In the AC optimal power flow, the cost function f_i(P_textgi) can be represented as an n-th degree polynomial:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"f_i(P_textgi) = sum_k=0^n a_k P_textgi^k","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Typically, cost functions are represented as linear, quadratic, or cubic, as shown in Figure 1:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"beginaligned\n f_i(P_textgi) = a_1P_textgi + a_0 \n f_i(P_textgi) = a_2 P_textgi^2 + a_1P_textgi + a_0 \n f_i(P_textgi) = a_3 P_textgi^3 + a_2 P_textgi^2 + a_1P_textgi + a_0 \nendaligned","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"\n
Figure 1: The polynomial cost functions of generator active power output.
\n ","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"When using the cost! function in JuliaGrid and specifying the polynomial keyword, the polynomial is constructed with coefficients arranged in descending order of their degrees, from the highest degree to the lowest. For example, in the case study provided, we generated a cubic polynomial cost function for the active output power of Generator 1, which is represented as:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"beginaligned\n f_1(P_textg1) = 900 P_textg1^3 + 500 P_textg1^2 + 80 P_textg1 + 5\nendaligned","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To access these coefficients, users can utilize the variable:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"f₁ = system.generator.cost.active.polynomial[1]","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Linear-Piecewise-Cost-Function","page":"AC Optimal Power Flow","title":"Linear Piecewise Cost Function","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The second option for defining cost functions in the AC optimal power flow is to use linear piecewise functions as approximations of the polynomial functions, as illustrated in Figure 2.","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"\n
Figure 2: The linear piecewise cost functions of generator active power output.
\n ","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To define linear piecewise functions in JuliaGrid, users can utilize the cost! function with the piecewise keyword. The linear piecewise function is constructed using a matrix where each row defines a single point. The first column holds the generator's active or reactive power output, while the second column corresponds to the associated cost value. For example, in the provided case study, a linear piecewise function is created and can be accessed as follows:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"f₂ = system.generator.cost.active.piecewise[2]","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuliaGrid handles convex linear piecewise functions using a constrained cost variable method. In this approach, the piecewise linear cost function is replaced by a helper variable and a set of linear inequality constraints for each segment of the function defined by two neighboring points along the line. However, for linear piecewise functions that have only one segment defined by two points, JuliaGrid transforms it into a standard linear function without introducing a helper variable.","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Hence, for a piecewise cost function denoted as f_i(P_textgi) with k segments (where k 1), the j-th segment, defined by the points P_textgij f_i(P_textgij) and P_textgij+1 f_i(P_textgij+1), is characterized by the following inequality constraints:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"cfracf_i(P_textgij+1) - f_i(P_textgij)P_textgij+1 - P_textgij(P_textgi - P_textgij) + f_i(P_textgij) leq H_i i in mathcalS j = 1dotsk","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"where H_i represents the helper variable. To finalize this method, we simply need to include the helper variable H_i in the objective function. This approach efficiently handles linear piecewise cost functions, providing the flexibility to capture nonlinear characteristics while still benefiting from the advantages of linear optimization techniques.","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"As an example, in the provided case study, the helper variable is defined as follows:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"H₂ = analysis.method.variable.actwise[2]","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Lastly, the set of constraints introduced by the linear piecewise cost function is displayed as follows:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(analysis.method.constraint.piecewise.active)","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Objective-Function-2","page":"AC Optimal Power Flow","title":"Objective Function","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"As previously explained, the objective function relies on the defined polynomial or linear piecewise cost functions and represents the sum of these costs. In the provided example, the objective function that must be minimized to obtain the optimal values for the active and reactive power outputs of the generators and the bus voltage magnitudes and angles can be accessed using the following:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuMP.objective_function(analysis.method.jump)","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Constraint-Functions","page":"AC Optimal Power Flow","title":"Constraint Functions","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"In the following section, we will examine the various constraints defined within the AC optimal power flow model.","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Slack-Bus-Constraint","page":"AC Optimal Power Flow","title":"Slack Bus Constraint","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The first equality constraint is linked to the slack bus, where the bus voltage angle denoted as theta_i is fixed to a constant value theta_texts. It can be expressed as follows:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"theta_i - theta_texts = 0 i in mathcalN_textsb","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"where the set mathcalN_textsb contains the index of the slack bus. To access the equality constraint from the model, we can utilize the variable:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(analysis.method.constraint.slack.angle)","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Bus-Power-Balance-Constraints","page":"AC Optimal Power Flow","title":"Bus Power Balance Constraints","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The second equality constraint in the optimization problem is associated with the active power balance equation:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"beginaligned\nh_P_i(mathbf P_textg mathbf V bmTheta) = 0 forall i in mathcalN\nendaligned","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"As elaborated in the Bus Injections section, we can express the equation as follows:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"h_P_i(mathbf P_textg mathbf V bmTheta) = V_isumlimits_j=1^n (G_ijcostheta_ij+B_ijsintheta_ij)V_j - sum_k in mathcalS_i P_textgk + P_textdi","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"In this equation, the set mathcalS_i subseteq mathcalS encompasses all generators connected to bus i in mathcalN, and P_textgk represents the active power output of the k-th generator within the set mathcalS_i. More Precisely, the variable P_textgk represents the optimization variable, along with the bus voltage angles theta_ij = theta_i - theta_j and the bus voltage magnitudes V_i and V_j.","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The constant term is determined by the active power demand P_textdi at bus i in mathcalN. The values representing this constant term, denoted as mathbfP_textd = P_textdi, i in mathcalN, can be accessed using the following:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐏ₒ = system.bus.demand.active","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"We can access the references to the active power balance constraints using the following snippet:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(analysis.method.constraint.balance.active)","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Similarly, the next constraint in the optimization problem is associated with the reactive power balance equation:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"beginaligned\nh_Q_i(mathbf Q_textg mathbf V bmTheta) = 0 forall i in mathcalN\nendaligned","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"As elaborated in the Bus Injections section, we can express the equation as follows:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"h_Q_i(mathbf Q_textg mathbf V bmTheta) = V_isumlimits_j=1^n (G_ijsintheta_ij-B_ijcostheta_ij)V_j - sum_k in mathcalS_i Q_textgk + Q_textdi","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"As mentioned earlier for active power, Q_textgk represents the reactive power output of the k-th generator within the set mathcalS_i. The variable Q_textgk serves as an optimization variable, as well as the bus voltage angles theta_ij = theta_i - theta_j, and the bus voltage magnitudes V_i and V_j.","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The constant term is determined by the reactive power demand Q_textdi at bus i in mathcalN. The values representing this constant term, denoted as mathbfQ_textd = Q_textdi, i in mathcalN, can be accessed using the following:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐐ₒ = system.bus.demand.reactive","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"We can access the references to the reactive power balance constraints using the following snippet:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(analysis.method.constraint.balance.reactive)","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Bus-Voltage-Constraints","page":"AC Optimal Power Flow","title":"Bus Voltage Constraints","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The inequality constraints associated with the voltage magnitude ensure that the bus voltage magnitudes are within specified limits:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"V_i^textmin leq V_i leq V_i^textmax forall i in mathcalN","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"where V_i^textmin represents the minimum voltage magnitude, and V_i^textmax represents the maximum voltage magnitude for bus i in mathcalN. The values representing these voltage magnitude limits, denoted as mathbfV_textlm = V_i^textmin V_i^textmax, i in mathcalN, can be accessed using the following:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐕ₗₘ = [system.bus.voltage.minMagnitude system.bus.voltage.maxMagnitude]","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To retrieve this inequality constraint from the model, we can use the following:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(analysis.method.constraint.voltage.magnitude)","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The inequality constraint related to the minimum and maximum bus voltage angle difference between the from-bus and to-bus ends of each branch is defined as follows:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"theta_ij^textmin leq theta_i - theta_j leq theta_ij^textmax forall (ij) in mathcalE","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"where theta_ij^textmin represents the minimum, while theta_ij^textmax represents the maximum of the angle difference between adjacent buses. The values representing the voltage angle difference, denoted as bmTheta_textlm = theta_ij^textmin theta_ij^textmax, (ij) in mathcalE, are provided as follows:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝚯ₗₘ = [system.branch.voltage.minDiffAngle system.branch.voltage.maxDiffAngle]","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To retrieve this inequality constraint from the model, we can use the following:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(analysis.method.constraint.voltage.angle)","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Branch-Flow-Constraints","page":"AC Optimal Power Flow","title":"Branch Flow Constraints","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The inequality constraints related to the branch flow ratings can be associated with the limits on apparent power flow, active power flow, or current magnitude at the from-bus and to-bus ends of each branch. The type of constraint applied is determined by the type keyword within the addBranch! function.","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Specifically, type = 1 is used for apparent power flow, type = 2 for active power flow, and type = 3 for current magnitude. These constraints can be expressed using the equations h_ij(mathbf V bmTheta) and h_ji(mathbf V bmTheta), representing the rating constraints at the from-bus and to-bus ends of each branch, respectively:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"beginaligned\n F_ij^textmin leq h_ij(mathbf V bmTheta) leq F_ij^textmax forall (ij) in mathcalE \n F_ji^textmin leq h_ji(mathbf V bmTheta) leq F_ji^textmax forall (ij) in mathcalE\nendaligned","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The branch flow limits at the from-bus and to-bus ends, denoted as mathbfF_textf = F_ij^textmin F_ij^textmax and mathbfF_textt = F_ji^textmin F_ji^textmax, (ij) in mathcalE, can be retrieved as follows:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐅ₒ = [system.branch.flow.minFromBus system.branch.flow.maxFromBus]\n𝐅ₜ = [system.branch.flow.minToBus system.branch.flow.maxToBus]","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"By default, JuliaGrid employs the rating constraints linked with the apparent power flow (type = 1). This constraint at the from-bus is specified as:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":" h_ij(mathbf V bmTheta) = sqrt A_ij V_i^4 + B_ij V_i^2 V_j^2 - 2 C_ij cos(theta_ij - phi_ij) - D_ij sin(theta_ij - phi_ij)V_i^3 V_j","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"where:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":" begingathered\n A_ij = cfrac(g_ij + g_textsi)^2+(b_ij+b_textsi)^2tau_ij^4 B_ij = cfracg_ij^2+b_ij^2tau_ij^2 \n C_ij = cfracg_ij(g_ij+g_textsi)+b_ij(b_ij+b_textsi)tau_ij^3 D_ij = cfracg_ijb_textsi - b_ijg_textsitau_ij^3\n endgathered","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Furthermore, this constraint at the to-bus is specified as:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":" h_ji(mathbf V bmTheta) = sqrt A_ji V_j^4 + B_ji V_i^2 V_j^2 - 2 C_ji cos(theta_ij - phi_ij) + D_ij sin(theta_ij - phi_ij)V_i V_j^3 ","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"where:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":" begingathered\n A_ji = (g_ij + g_textsi)^2+(b_ij+b_textsi)^2 B_ji = cfracg_ij^2+b_ij^2tau_ij^2 \n C_ji = cfracg_ij(g_ij+g_textsi)+b_ij(b_ij+b_textsi)tau_ij D_ji = cfracg_ijb_textsi - b_ijg_textsitau_ij\n endgathered","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The second option is to define the limit keywords for active power flow constraints (type = 2) at the from-bus and to-bus ends of each branch:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":" beginaligned\n h_ij(mathbf V bmTheta) =\n cfrac g_ij + g_textsijtau_ij^2 V_i^2 -\n cfrac1tau_ij leftg_ijcos(theta_ij - phi_ij) + b_ijsin(theta_ij - phi_ij)rightV_iV_j \n h_ji(mathbf V bmTheta) = (g_ij + g_textsij) V_j^2 -\n cfrac1tau_ij leftg_ij cos(theta_ij - phi_ij) - b_ij sin(theta_ij- phi_ij)right V_i V_j\n endaligned","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"In our example, we have chosen to utilize this type of flow constraints. To access the flow constraints of branches at the from-bus end, you can use the following code snippet:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(analysis.method.constraint.flow.from)","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Similarly, to access the to-bus end flow constraints of branches you can use the following code snippet:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(analysis.method.constraint.flow.to)","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The last option involves defining the limit keywords for current magnitude constraints (type = 3) at the from-bus and to-bus ends of each branch. In this case, the constraints are implemented as follows:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":" beginaligned\n h_ij(mathbf V bmTheta) = sqrtA_ijV_i^2 + B_ijV_j^2 - 2C_ij cos(theta_ij - phi_ij) - D_ijsin(theta_ij - phi_ij)V_iV_j \n h_ji(mathbf V bmTheta) = sqrtA_jiV_j^2 + B_jiV_i^2 - 2C_ji cos(theta_ij - phi_ij) + D_jisin(theta_ij - phi_ij)V_iV_j\n endaligned","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#ACPowerCapabilityConstraintsTutorials","page":"AC Optimal Power Flow","title":"Generator Power Capability Constraints","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The next set of constraints pertains to the minimum and maximum limits of active and reactive power outputs of the generators. These constraints ensure that the power outputs of the generators remain within specified bounds:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"P_textgi^textmin leq P_textgi leq P_textgi^textmax forall i in mathcalS","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"In this representation, the lower and upper limits are determined by the vector mathbfP_textm = P_textgi^textmin P_textgi^textmax, i in mathcalS. We can access these bounds using the following:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐏ₘ = [system.generator.capability.minActive, system.generator.capability.maxActive]","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To access these constraints, you can utilize the following snippet:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(analysis.method.constraint.capability.active)","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Similarly, constraints related to the minimum and maximum limits of reactive power outputs of the generators ensure that the reactive powers remain within specified boundaries:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Q_textgi^textmin leq Q_textgi leq Q_textgi^textmax forall i in mathcalS","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Thus, the lower and upper limits are determined by the vector mathbfQ_textm = Q_textgi^textmin Q_textgi^textmax, i in mathcalS. We can access these bounds using the following:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐐ₘ = [system.generator.capability.minReactive system.generator.capability.maxReactive]","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To access these constraints, you can use the following snippet:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(analysis.method.constraint.capability.reactive)","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"These capability limits of the generators define the feasible region, represented as a gray area in Figure 3, which forms the solution space for the active and reactive output powers of the generators.","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"\n
Figure 3: The feasible region created by the active and reactive power capability constraints.
\n ","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"However, this representation might not be the most accurate depiction of the generator's output power behavior. In reality, there exists a tradeoff between the active and reactive power outputs of the generators [8]. Specifically, when a generator operates at its maximum active power P_textgi^textmax, it may not be able to produce the maximum Q_textgi^textmax or minimum Q_textgi^textmin reactive power. To capture this tradeoff, we introduce the ability to include additional upper and lower constraints on the feasible region, leading to its reduction as shown in Figure 4.","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"\n
Figure 4: The feasible region created by the active and reactive power capability constraints with additional upper and lower constraints.
\n ","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"If a user wishes to incorporate the tradeoff between active and reactive power outputs into the optimization model, they can define the points shown in Figure 4 within the addGenerator! function using the following keywords:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Keyword Coordinate\nlowActive P_textgi^textlow\nminLowReactive Q_textgitextlow^textmin\nmaxLowReactive Q_textgitextlow^textmax\nupActive P_textgi^textup\nminUpReactive Q_textgitextup^textmin\nmaxUpReactive Q_textgitextup^textmax","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"When using these points, JuliaGrid constructs two additional capability constraints per generator as follows:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"beginaligned\n (Q_textgitextlow^textmax - Q_textgitextup^textmax)P_textgi + (P_textgi^textup - P_textgi^textlow)Q_textgi\n leq (Q_textgitextlow^textmax - Q_textgitextup^textmax)P_textgi^textlow + (P_textgi^textup - P_textgi^textlow)Q_textgitextlow^textmax \n (Q_textgitextup^textmin - Q_textgitextlow^textmin)P_textgi + (P_textgi^textlow - P_textgi^textup)Q_textgi\n leq (Q_textgitextup^textmin - Q_textgitextlow^textmin)P_textgi^textlow + (P_textgi^textlow - P_textgi^textup)Q_textgitextlow^textmin\nendaligned","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To ensure numerical stability, these constraints are normalized by introducing two scaling factors:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"beginaligned\n s_1 = sqrt(Q_textgitextlow^textmax - Q_textgitextup^textmax)^2 + (P_textgi^textup - P_textgi^textlow)^2\n s_2 = sqrt(Q_textgitextup^textmin - Q_textgitextlow^textmin)^2 + (P_textgi^textlow - P_textgi^textup)^2\nendaligned","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"When these constraints exist in the system, users can access them using the following variables:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"analysis.method.constraint.capability.upper\nanalysis.method.constraint.capability.lower\nnothing # hide","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"These additional capability constraints allow us to accurately represent the tradeoff between active and reactive power outputs of the generators while maintaining numerical stability.","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#ACOptimalPowerFlowSolutionTutorials","page":"AC Optimal Power Flow","title":"Optimal Power Flow Solution","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To obtain the optimal values of active and reactive power outputs for generators and the bus voltage magnitudes and angles, the user needs to invoke the following function:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuMP.set_silent(analysis.method.jump) # hide\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"After solving the AC optimal power flow problem, you can retrieve the vectors of output active and reactive power for generators, denoted as mathbfP_textg = P_textgi and mathbfQ_textg = Q_textgi, where i in mathcalS, using the following commands:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐏ₒ = analysis.power.generator.active\n𝐐ₒ = analysis.power.generator.reactive","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Similarly, the resulting bus voltage magnitudes and angles, represented by mathbfV = V_i and bmTheta = theta_i, where i in mathcalN, are stored in the vectors as follows:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐕 = analysis.voltage.magnitude\n𝚯 = analysis.voltage.angle","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"By accessing these vectors, you can analyze and utilize the optimal power flow solution for further studies or operational decision-making in the power system.","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#ACOptimalPowerAnalysisTutorials","page":"AC Optimal Power Flow","title":"Power Analysis","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Once the computation of voltage magnitudes and angles at each bus is completed, various electrical quantities can be determined. JuliaGrid offers the power! function, which enables the calculation of powers associated with buses and branches. Here is an example code snippet demonstrating its usage:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"power!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The function stores the computed powers in the rectangular coordinate system. It calculates the following powers related to buses and branches:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Bus Active Reactive\nInjections mathbfP = P_i mathbfQ = Q_i\nGenerator injections mathbfP_textp = P_textpi mathbfQ_textp = Q_textpi\nShunt elements mathbfP_textsh = P_textshi mathbfQ_textsh = Q_textshi","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Branch Active Reactive\nFrom-bus end flows mathbfP_texti = P_ij mathbfQ_texti = Q_ij\nTo-bus end flows mathbfP_textj = P_ji mathbfQ_textj = Q_ji\nShunt elements mathbfP_texts = P_textsij mathbfP_texts = P_textsij\nSeries elements mathbfP_textl = P_textlij mathbfQ_textl = Q_textlij","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"note: Info\nFor a clear comprehension of the equations, symbols presented in this section, as well as for a better grasp of power directions, please refer to the Unified Branch Model.","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Power-Injections","page":"AC Optimal Power Flow","title":"Power Injections","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Active and reactive power injections are stored as the vectors mathbfP = P_i and mathbfQ = Q_i, respectively, and can be retrieved using the following commands:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐏 = analysis.power.injection.active\n𝐐 = analysis.power.injection.reactive","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#OptGeneratorPowerInjectionsManual","page":"AC Optimal Power Flow","title":"Generator Power Injections","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The power! function in JuliaGrid also provides the computation of active and reactive power injections from the generators at each bus. To calculate the active power supplied by generators to the buses, one can simply sum the active power outputs of the generators obtained from the AC optimal power flow. This can be represented as:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":" P_textpi = sum_k in mathcalS_i P_textgk forall i in mathcalN","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"where the set mathcalS_i subseteq mathcalS encompasses all generators connected to bus i in mathcalN. The active power injections from the generators at each bus are stored as a vector denoted by mathbfP_textp = P_textpi, and can be obtained using:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐏ₚ = analysis.power.supply.active","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Similarly, we can obtain the reactive power supplied by generators to the buses:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":" Q_textpi = sum_k in mathcalS_i Q_textgk forall i in mathcalN","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The vector of these reactive power injections by the generators to the buses, denoted by mathbfQ_textp = Q_textpi, can be retrieved using the following command:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐐ₚ = analysis.power.supply.reactive","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Power-at-Bus-Shunt-Elements","page":"AC Optimal Power Flow","title":"Power at Bus Shunt Elements","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Active and reactive powers associated with the shunt elements at each bus are represented by the vectors mathbfP_textsh = P_textshi and mathbfQ_textsh = Q_textshi. To retrieve these powers in JuliaGrid, use the following commands:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐏ₛₕ = analysis.power.shunt.active\n𝐐ₛₕ = analysis.power.shunt.reactive","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Power-Flows","page":"AC Optimal Power Flow","title":"Power Flows","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The resulting active and reactive power flows at each from-bus end are stored as the vectors mathbfP_texti = P_ij and mathbfQ_texti = Q_ij respectively, and can be retrieved using the following commands:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐏ᵢ = analysis.power.from.active\n𝐐ᵢ = analysis.power.from.reactive","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Similarly, the vectors of active and reactive power flows at the to-bus end are stored as mathbfP_textj = P_ji and mathbfQ_textj = Q_ji, respectively, and can be retrieved using the following code:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐏ⱼ = analysis.power.to.active\n𝐐ⱼ = analysis.power.to.reactive","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Power-at-Branch-Shunt-Elements","page":"AC Optimal Power Flow","title":"Power at Branch Shunt Elements","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Active and reactive powers associated with the branch shunt elements at each branch are represented by the vectors mathbfP_texts = P_textsij and mathbfQ_texts = Q_textsij. We can retrieve these values using the following code:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐏ₛ = analysis.power.charging.active\n𝐐ₛ = analysis.power.charging.reactive","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Power-at-Branch-Series-Elements","page":"AC Optimal Power Flow","title":"Power at Branch Series Elements","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Active and reactive powers associated with the branch series element at each branch are represented by the vectors mathbfP_textl = P_textlij and mathbfQ_textl = Q_textlij. We can retrieve these values using the following code:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐏ₗ = analysis.power.series.active\n𝐐ₗ = analysis.power.series.reactive","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Current-Analysis","page":"AC Optimal Power Flow","title":"Current Analysis","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuliaGrid offers the current! function, which enables the calculation of currents associated with buses and branches. Here is an example code snippet demonstrating its usage:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"current!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The function stores the computed currents in the polar coordinate system. It calculates the following currents related to buses and branches:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Bus Magnitude Angle\nInjections mathbfI = I_i bmpsi = psi_i","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Branch Magnitude Angle\nFrom-bus end flows mathbfI_texti = I_ij bmpsi_texti = psi_ij\nTo-bus end flows mathbfI_textj = I_ji bmpsi_textj = psi_ji\nSeries elements mathbfI_textl = I_textlij bmpsi_textl = psi_textlij","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"note: Info\nFor a clear comprehension of the equations, symbols presented in this section, as well as for a better grasp of power directions, please refer to the Unified Branch Model.","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Current-Injections","page":"AC Optimal Power Flow","title":"Current Injections","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"In JuliaGrid, complex current injections are stored in the vector of magnitudes denoted as mathbfI = I_i and the vector of angles represented as bmpsi = psi_i. You can retrieve them using the following commands:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐈 = analysis.current.injection.magnitude\n𝛙 = analysis.current.injection.angle","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Current-Flows","page":"AC Optimal Power Flow","title":"Current Flows","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To obtain the vectors of magnitudes mathbfI_texti = I_ij and angles bmpsi_texti = psi_ij for the resulting complex current flows, you can use the following commands:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐈ᵢ = analysis.current.from.magnitude\n𝛙ᵢ = analysis.current.from.angle","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Similarly, we can obtain the vectors of magnitudes mathbfI_textj = I_ji and angles bmpsi_textj = psi_ji of the resulting complex current flows using the following code:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐈ⱼ = analysis.current.to.magnitude\n𝛙ⱼ = analysis.current.to.angle","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/acOptimalPowerFlow/#Current-at-Branch-Series-Elements","page":"AC Optimal Power Flow","title":"Current at Branch Series Elements","text":"","category":"section"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To obtain the vectors of magnitudes mathbfI_textl = I_textlij and angles bmpsi_textl = psi_textlij of the resulting complex current flows, one can use the following code:","category":"page"},{"location":"tutorials/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"𝐈ₗ = analysis.current.series.magnitude\n𝛙ₗ = analysis.current.series.angle","category":"page"},{"location":"api/measurementModel/#measurementModelAPI","page":"Measurement Model","title":"Measurement Model","text":"","category":"section"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"For further information on this topic, please see the Measurement Model section of the Manual. Below, we have provided a list of functions that can be used to create, save, and manipulate with measurement devices.","category":"page"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"To load measurement model API functionalities into the current scope, utilize the following command:","category":"page"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid","category":"page"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"api/measurementModel/#Measurement-Data","page":"Measurement Model","title":"Measurement Data","text":"","category":"section"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"measurement\nsaveMeasurement\nstatus!","category":"page"},{"location":"api/measurementModel/#Voltmeter","page":"Measurement Model","title":"Voltmeter","text":"","category":"section"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addVoltmeter!\nupdateVoltmeter!\nstatusVoltmeter!\n@voltmeter","category":"page"},{"location":"api/measurementModel/#Ammeter","page":"Measurement Model","title":"Ammeter","text":"","category":"section"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addAmmeter!\nupdateAmmeter!\nstatusAmmeter!\n@ammeter","category":"page"},{"location":"api/measurementModel/#Wattmeter","page":"Measurement Model","title":"Wattmeter","text":"","category":"section"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addWattmeter!\nupdateWattmeter!\nstatusWattmeter!\n@wattmeter","category":"page"},{"location":"api/measurementModel/#Varmeter","page":"Measurement Model","title":"Varmeter","text":"","category":"section"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addVarmeter!\nupdateVarmeter!\nstatusVarmeter!\n@varmeter","category":"page"},{"location":"api/measurementModel/#PMU","page":"Measurement Model","title":"PMU","text":"","category":"section"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addPmu!\nupdatePmu!\nstatusPmu!\n@pmu","category":"page"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"api/measurementModel/#Measurement-Data-2","page":"Measurement Model","title":"Measurement Data","text":"","category":"section"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"measurement\nsaveMeasurement\nstatus!","category":"page"},{"location":"api/measurementModel/#JuliaGrid.measurement","page":"Measurement Model","title":"JuliaGrid.measurement","text":"measurement(file::String)\n\nThe function builds the composite type Measurement and populates voltmeter, ammeter, wattmeter, varmeter, and pmu fields. In general, once the composite type Measurement has been created, it is possible to add new measurement devices, or modify the parameters of existing ones.\n\nArgument\n\nIt requires a string path to the HDF5 file with the .h5 extension.\n\nReturns\n\nThe Measurement composite type with the following fields:\n\nvoltmeter: Bus voltage magnitude measurements.\nammeter: Branch current magnitude measurements.\nwattmeter: Active power injection and active power flow measurements.\nvarmeter: Reactive power injection and reactive power flow measurements.\npmu: Bus voltage and branch current phasor measurements.\n\nUnits\n\nJuliaGrid stores all data in per-units and radians format.\n\nExample\n\ndevice = measurement(\"measurement14.h5\")\n\n\n\n\n\nmeasurement()\n\nAlternatively, the Measurement composite type can be initialized by calling the function without any arguments. This allows the model to be built from scratch and modified as needed.\n\nExample\n\ndevice = measurement()\n\n\n\n\n\n","category":"function"},{"location":"api/measurementModel/#JuliaGrid.saveMeasurement","page":"Measurement Model","title":"JuliaGrid.saveMeasurement","text":"saveMeasurement(device::Measurement; path::String, reference::String, note::String)\n\nThe function saves the measurement's data in the HDF5 file using the fields voltmeter, ammeter, wattmeter, varmeter, and pmu from the Measurement composite type.\n\nKeywords\n\nThe location and file name of the HDF5 file is specified by the mandatory keyword path in the format of \"path/name.h5\". Additional information can be provided by the optional keywords reference and note, which can be saved along with the power system data.\n\nView HDF5 File\n\nTo view the saved HDF5 file, you can use the HDFView software.\n\nExample\n\nusing Ipopt\n\nsystem = powerSystem(\"case14.m\")\ndevice = measurement()\n\nacModel!(system)\nanalysis = acOptimalPowerFlow(system, Ipopt.Optimizer)\nsolve!(system, analysis)\npower!(system, analysis)\n\naddVoltmeter!(system, device, analysis)\naddWattmeter!(system, device, analysis)\n\nsaveMeasurement(device; path = \"D:/measurement14.h5\")\n\n\n\n\n\n","category":"function"},{"location":"api/measurementModel/#JuliaGrid.status!","page":"Measurement Model","title":"JuliaGrid.status!","text":"status!(system::PowerSystem, device::Measurement; inservice, outservice, redundancy)\n\nThe function generates a set of measurements, assigning measurement devices randomly to either in-service or out-of-service states based on specified keywords.\n\nKeywords\n\nOnly one of the following keywords can be used at a time to configure the measurement set:\n\ninservice: Sets the number of in-service devices.\noutservice: Sets the number of out-of-service devices.\nredundancy: Determines in-service devices based on redundancy.\n\nUpdates\n\nThe function updates all the status fields within the Measurement type.\n\nExamples\n\nCreating a measurement set with a specific number of in-service devices:\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement()\n\nacModel!(system)\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\npower!(system, analysis)\n\naddVoltmeter!(system, device, analysis)\naddWattmeter!(system, device, analysis)\n\nstatus!(system, device; inservice = 30)\n\nCreating a measurement set using redundancy:\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement()\n\nacModel!(system)\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\npower!(system, analysis)\n\naddVoltmeter!(system, device, analysis)\naddWattmeter!(system, device, analysis)\naddVarmeter!(system, device, analysis)\n\nstatus!(system, device; redundancy = 2.5)\n\n\n\n\n\n","category":"function"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"api/measurementModel/#Voltmeter-2","page":"Measurement Model","title":"Voltmeter","text":"","category":"section"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addVoltmeter!(::PowerSystem, ::Measurement)\naddVoltmeter!(::PowerSystem, ::Measurement, ::AC)\nupdateVoltmeter!\nstatusVoltmeter!\n@voltmeter","category":"page"},{"location":"api/measurementModel/#JuliaGrid.addVoltmeter!-Tuple{PowerSystem, Measurement}","page":"Measurement Model","title":"JuliaGrid.addVoltmeter!","text":"addVoltmeter!(system::PowerSystem, device::Measurement; label, bus, magnitude, variance,\n noise, status)\n\nThe function adds a new voltmeter that measures bus voltage magnitude to the Measurement type within a given PowerSystem type. The voltmeter can be added to an already defined bus.\n\nKeywords\n\nThe voltmeter is defined with the following keywords:\n\nlabel: Unique label for the voltmeter.\nbus: Label of the bus to which the voltmeter is connected.\nmagnitude (pu or V): Bus voltage magnitude value.\nvariance (pu or V): Variance of the bus voltage magnitude measurement.\nnoise: Specifies how to generate the measurement mean:\nnoise = true: adds white Gaussian noise with the variance to the magnitude,\nnoise = false: uses the magnitude value only.\nstatus: Operating status of the voltmeter:\nstatus = 1: in-service,\nstatus = 0: out-of-service.\n\nUpdates\n\nThe function updates the voltmeter field of the Measurement composite type.\n\nDefault Settings\n\nDefault settings for certain keywords are as follows: variance = 1e-2, noise = false, status = 1, and users can modify these default settings using the @voltmeter macro.\n\nUnits\n\nThe default units for the magnitude and variance keywords are per-units (pu). However, users can choose to use volts (V) as the units by applying the @voltage macro.\n\nExamples\n\nAdding a voltmeter using the default unit system:\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 132e3)\n\naddVoltmeter!(system, device; label = \"Voltmeter 1\", bus = \"Bus 1\", magnitude = 1.1)\n\nAdding a voltmeter using a custom unit system:\n\n@voltage(kV, rad, kV)\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 132.0)\n\naddVoltmeter!(system, device; label = \"Voltmeter 1\", bus = \"Bus 1\", magnitude = 145.2)\n\n\n\n\n\n","category":"method"},{"location":"api/measurementModel/#JuliaGrid.addVoltmeter!-Tuple{PowerSystem, Measurement, AC}","page":"Measurement Model","title":"JuliaGrid.addVoltmeter!","text":"addVoltmeter!(system::PowerSystem, device::Measurement, analysis::AC; variance, noise,\n status)\n\nThe function incorporates voltmeters into the Measurement composite type for every bus within the PowerSystem type. These measurements are derived from the exact bus voltage magnitudes defined in the AC type.\n\nKeywords\n\nUsers have the option to configure the following keywords:\n\nvariance (pu or V): Variance of bus voltage magnitude measurements.\nnoise: Specifies how to generate the measurement mean:\nnoise = true: adds white Gaussian noise with the variance to the voltage magnitudes,\nnoise = false: uses the exact voltage magnitude values.\nstatus: Operating status of the voltmeters:\nstatus = 1: in-service,\nstatus = 0: out-of-service.\n\nUpdates\n\nThe function updates the voltmeter field of the Measurement composite type.\n\nDefault Settings\n\nDefault settings for keywords are as follows: variance = 1e-2, noise = false, and status = 1, and users can modify these default settings using the @voltmeter macro.\n\nUnits\n\nBy default, the unit for variance is per-unit (pu). However, users can choose to use volts (V) as the units by applying the @voltage macro.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement()\n\nacModel!(system)\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\n\n@voltmeter(label = \"Voltmeter ?\")\naddVoltmeter!(system, device, analysis; variance = 1e-3, noise = true)\n\n\n\n\n\n","category":"method"},{"location":"api/measurementModel/#JuliaGrid.updateVoltmeter!","page":"Measurement Model","title":"JuliaGrid.updateVoltmeter!","text":"updateVoltmeter!(system::PowerSystem, device::Measurement, [analysis::Analysis];\n kwargs...)\n\nThe function allows for the alteration of parameters for a voltmeter.\n\nArguments\n\nIf the Analysis type is omitted, the function applies changes to the Measurement composite type only. However, when including the Analysis type, it updates both the Measurement and Analysis types. This streamlined process avoids the need to completely rebuild vectors and matrices when adjusting these parameters.\n\nKeywords\n\nTo update a specific voltmeter, provide the necessary kwargs input arguments in accordance with the keywords specified in the addVoltmeter! function, along with their respective values. Ensure that the label keyword matches the label of the existing voltmeter you want to modify. If any keywords are omitted, their corresponding values will remain unchanged.\n\nUpdates\n\nThe function updates the voltmeter field within the Measurement composite type. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.\n\nUnits\n\nUnits for input parameters can be changed using the same method as described for the addVoltmeter! function.\n\nExample\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 132e3)\n\naddVoltmeter!(system, device; label = \"Voltmeter 1\", bus = \"Bus 1\", magnitude = 1.1)\nupdateVoltmeter!(system, device; label = \"Voltmeter 1\", magnitude = 0.9)\n\n\n\n\n\n","category":"function"},{"location":"api/measurementModel/#JuliaGrid.statusVoltmeter!","page":"Measurement Model","title":"JuliaGrid.statusVoltmeter!","text":"statusVoltmeter!(system::PowerSystem, device::Measurement; inservice, outservice,\n redundancy)\n\nThe function generates a set of voltmeters, assigning voltmeters randomly to either in-service or out-of-service states based on specified keywords.\n\nKeywords\n\nOnly one of the following keywords can be used at a time to configure the measurement set:\n\ninservice: Sets the number of in-service voltmeters.\noutservice: Sets the number of out-of-service voltmeters.\nredundancy: Determines in-service voltmeters based on redundancy.\n\nUpdates\n\nThe function updates the status field within the Voltmeter type.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement()\n\nacModel!(system)\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\n\naddVoltmeter!(system, device, analysis)\nstatusVoltmeter!(system, device; inservice = 10)\n\n\n\n\n\n","category":"function"},{"location":"api/measurementModel/#JuliaGrid.@voltmeter","page":"Measurement Model","title":"JuliaGrid.@voltmeter","text":"@voltmeter(label, variance, noise, status)\n\nThe macro generates a template for a voltmeter, which can be utilized to define a voltmeter using the addVoltmeter! function.\n\nKeywords\n\nTo establish the voltmeter template, users can specify default values for the variance, noise, and status keywords, along with pattern for labels using the label keyword.\n\nUnits\n\nBy default, the unit for variance is per-unit (pu). However, users can choose to use volts (V) as the units by applying the @voltage macro.\n\nExamples\n\nAdding a voltmeter using the default unit system:\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 132e3)\n\n@voltmeter(label = \"Voltmeter ?\", variance = 1e-5)\naddVoltmeter!(system, device; bus = \"Bus 1\", magnitude = 1.1)\n\nAdding a voltmeter using a custom unit system:\n\n@voltage(kV, rad, kV)\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 132.0)\n\n@voltmeter(label = \"Voltmeter ?\", variance = 0.00132)\naddVoltmeter!(system, device; bus = \"Bus 1\", magnitude = 145.2)\n\n\n\n\n\n","category":"macro"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"api/measurementModel/#Ammeter-2","page":"Measurement Model","title":"Ammeter","text":"","category":"section"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addAmmeter!(::PowerSystem, ::Measurement)\naddAmmeter!(::PowerSystem, ::Measurement, ::AC)\nupdateAmmeter!\nstatusAmmeter!\n@ammeter","category":"page"},{"location":"api/measurementModel/#JuliaGrid.addAmmeter!-Tuple{PowerSystem, Measurement}","page":"Measurement Model","title":"JuliaGrid.addAmmeter!","text":"addAmmeter!(system::PowerSystem, device::Measurement; label, from, to, magnitude,\n variance, noise, status)\n\nThe function adds a new ammeter that measures branch current magnitude to the Measurement type within a given PowerSystem type. The ammeter can be added to an already defined branch.\n\nKeywords\n\nThe ammeter is defined with the following keywords:\n\nlabel: Unique label for the ammeter.\nfrom: Label of the branch if the ammeter is located at the from-bus end.\nto: Label of the branch if the ammeter is located at the to-bus end.\nmagnitude (pu or A): Branch current magnitude value.\nvariance (pu or A): Variance of the branch current magnitude measurement.\nnoise: Specifies how to generate the measurement mean:\nnoise = true: adds white Gaussian noise with the variance to the magnitude,\nnoise = false: uses the magnitude value only.\nstatus: Operating status of the ammeter:\nstatus = 1: in-service,\nstatus = 0: out-of-service.\n\nUpdates\n\nThe function updates the ammeter field of the Measurement composite type.\n\nDefault Settings\n\nDefault settings for certain keywords are as follows: variance = 1e-2, noise = false, status = 1, which apply to ammeters located at both the from-bus and to-bus ends. Users can fine-tune these settings by explicitly specifying the variance and status for ammeters positioned on either the from-bus or to-bus ends of branches using the @ammeter macro.\n\nUnits\n\nThe default units for the magnitude and variance keywords are per-units (pu). However, users can choose to use amperes (A) as the units by applying the @current macro.\n\nExamples\n\nAdding ammeters using the default unit system:\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 132e3)\naddBus!(system; label = \"Bus 2\", base = 132e3)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.2)\n\naddAmmeter!(system, device; label = \"Ammeter 1\", from = \"Branch 1\", magnitude = 1.1)\naddAmmeter!(system, device; label = \"Ammeter 2\", to = \"Branch 1\", magnitude = 1.0)\n\nAdding ammeters using a custom unit system:\n\n@current(A, rad)\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 132e3)\naddBus!(system; label = \"Bus 2\", base = 132e3)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.2)\n\naddAmmeter!(system, device; label = \"Ammeter 1\", from = \"Branch 1\", magnitude = 481.125)\naddAmmeter!(system, device; label = \"Ammeter 2\", to = \"Branch 1\", magnitude = 437.386)\n\n\n\n\n\n","category":"method"},{"location":"api/measurementModel/#JuliaGrid.addAmmeter!-Tuple{PowerSystem, Measurement, AC}","page":"Measurement Model","title":"JuliaGrid.addAmmeter!","text":"addAmmeter!(system::PowerSystem, device::Measurement, analysis::AC; varianceFrom,\n statusFrom, varianceTo, statusTo, noise)\n\nThe function incorporates ammeters into the Measurement type for every branch within the PowerSystem type. These measurements are derived from the exact branch current magnitudes defined in the AC type.\n\nKeywords\n\nUsers have the option to configure the following keywords:\n\nvarianceFrom (pu or A): Measurement variance for ammeters at the from-bus ends.\nstatusFrom: Operating status of the ammeters at the from-bus ends:\nstatusFrom = 1: in-service,\nstatusFrom = 0: out-of-service.\nvarianceTo (pu or A): Measurement variance for ammeters at the to-bus ends.\nstatusTo: Operating status of the ammeters at the to-bus ends:\nstatusTo = 1: in-service,\nstatusTo = 0: out-of-service.\nnoise: Specifies how to generate the measurement mean:\nnoise = true: adds white Gaussian noise with the variance to the current magnitudes,\nnoise = false: uses the exact current magnitude values.\n\nUpdates\n\nThe function updates the ammeter field of the Measurement composite type.\n\nDefault Settings\n\nDefault settings for keywords are as follows: varianceFrom = 1e-2, statusFrom = 1, varianceTo = 1e-2, statusTo = 1, and noise = false. Users can change these default settings using the @ammeter macro.\n\nUnits\n\nThe default units for the varianceFrom and varianceTo keywords are per-units (pu). However, users can choose to use amperes (A) as the units by applying the @current macro.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement()\n\nacModel!(system)\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\ncurrent!(system, analysis)\n\n@ammeter(label = \"Ammeter ?\")\naddAmmeter!(system, device, analysis; varianceFrom = 1e-3, statusTo = 0)\n\n\n\n\n\n","category":"method"},{"location":"api/measurementModel/#JuliaGrid.updateAmmeter!","page":"Measurement Model","title":"JuliaGrid.updateAmmeter!","text":"updateAmmeter!(system::PowerSystem, device::Measurement, [analysis::Analysis];\n kwargs...)\n\nThe function allows for the alteration of parameters for an ammeter.\n\nArguments\n\nIf the Analysis type is omitted, the function applies changes to the Measurement composite type only. However, when including the Analysis type, it updates both the Measurement and Analysis types. This streamlined process avoids the need to completely rebuild vectors and matrices when adjusting these parameters.\n\nKeywords\n\nTo update a specific ammeter, provide the necessary kwargs input arguments in accordance with the keywords specified in the addAmmeter! function, along with their respective values. Ensure that the label keyword matches the label of the existing ammeter you want to modify. If any keywords are omitted, their corresponding values will remain unchanged.\n\nUpdates\n\nThe function updates the ammeter field within the Measurement composite type. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.\n\nUnits\n\nUnits for input parameters can be changed using the same method as described for the addAmmeter! function.\n\nExample\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 132e3)\naddBus!(system; label = \"Bus 2\", base = 132e3)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.2)\n\naddAmmeter!(system, device; label = \"Ammeter 1\", from = \"Branch 1\", magnitude = 1.1)\nupdateAmmeter!(system, device; label = \"Ammeter 1\", magnitude = 1.2, variance = 1e-4)\n\n\n\n\n\n","category":"function"},{"location":"api/measurementModel/#JuliaGrid.statusAmmeter!","page":"Measurement Model","title":"JuliaGrid.statusAmmeter!","text":"statusAmmeter!(system::PowerSystem, ammeter::Ammeter; inservice, inserviceFrom,\n inserviceTo, outservice, outserviceFrom, outserviceTo, redundancy, redundancyFrom,\n redundancyTo)\n\nThe function generates a set of ammeters, assigning ammeters randomly to either in-service or out-of-service states based on specified keywords.\n\nKeywords\n\nUsers may use either one main keyword or two fine-tuning keywords that specify distinct locations per function call:\n\ninservice: Sets the number of in-service ammeters or allows fine-tuning:\ninserviceFrom: sets only ammeters loacted at the from-bus end,\ninserviceTo: sets only ammeters loacted at the to-bus end.\noutservice: Sets the number of out-of-service ammeters or allows fine-tuning:\noutserviceFrom: sets only ammeters loacted at the from-bus end,\noutserviceTo: sets only ammeters loacted at the to-bus end.\nredundancy: Determines in-service ammeters based on redundancy or allows fine-tuning:\nredundancyFrom: determines only ammeters loacted at the from-bus end,\nredundancyTo: determines only ammeters loacted at the to-bus end.\n\nUpdates\n\nThe function updates the status field within the Ammeter type.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement()\n\nacModel!(system)\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\ncurrent!(system, analysis)\n\naddAmmeter!(system, device, analysis)\nstatusAmmeter!(system, device; inserviceFrom = 5, inserviceTo = 10)\n\n\n\n\n\n","category":"function"},{"location":"api/measurementModel/#JuliaGrid.@ammeter","page":"Measurement Model","title":"JuliaGrid.@ammeter","text":"@ammeter(label, varianceFrom, statusFrom, varianceTo, statusTo, noise)\n\nThe macro generates a template for an ammeter, which can be utilized to define an ammeter using the addAmmeter! function.\n\nKeywords\n\nTo establish the ammeter template, users can set default variance and status values for ammeters at both the from-bus and to-bus ends of branches, using varianceFrom and statusFrom for the former and varianceTo and statusTo for the latter. Users can also configure label patterns with the label keyword, as well as specify the noise type.\n\nUnits\n\nThe default units for the varianceFrom and varianceTo keywords are per-units (pu). However, users can choose to use amperes (A) as the units by applying the @current macro.\n\nExamples\n\nAdding an ammeter using the default unit system:\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 132e3)\naddBus!(system; label = \"Bus 2\", base = 132e3)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.2)\n\n@ammeter(label = \"Ammeter ?\", varianceTo = 1e-3, statusTo = 0)\naddAmmeter!(system, device; to = \"Branch 1\", magnitude = 1.1)\n\nAdding an ammeter using a custom unit system:\n\n@current(A, rad)\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 132e3)\naddBus!(system; label = \"Bus 2\", base = 132e3)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.2)\n\n@ammeter(label = \"Ammeter ?\", varianceTo = 0.004374, statusTo = 0)\naddAmmeter!(system, device; label = \"Ammeter 1\", to = \"Branch 1\", magnitude = 481.125)\n\n\n\n\n\n","category":"macro"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"api/measurementModel/#Wattmeter-2","page":"Measurement Model","title":"Wattmeter","text":"","category":"section"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addWattmeter!(::PowerSystem, ::Measurement)\naddWattmeter!(::PowerSystem, ::Measurement, ::AC)\nupdateWattmeter!\nstatusWattmeter!\n@wattmeter","category":"page"},{"location":"api/measurementModel/#JuliaGrid.addWattmeter!-Tuple{PowerSystem, Measurement}","page":"Measurement Model","title":"JuliaGrid.addWattmeter!","text":"addWattmeter!(system::PowerSystem, device::Measurement; label, bus, from, to, active,\n variance, noise, status)\n\nThe function adds a new wattmeter that measures active power injection or active power flow to the Measurement type within a given PowerSystem type. The wattmeter can be added to an already defined bus or branch.\n\nKeywords\n\nThe wattmeter is defined with the following keywords:\n\nlabel: Unique label for the wattmeter.\nbus: Label of the bus if the wattmeter is located at the bus.\nfrom: Label of the branch if the wattmeter is located at the from-bus end.\nto: Label of the branch if the wattmeter is located at the to-bus end.\nactive (pu or W): Active power value.\nvariance (pu or W): Variance of the active power measurement.\nnoise: Specifies how to generate the measurement mean:\nnoise = true: adds white Gaussian noise with the variance to the active,\nnoise = false: uses the active value only.\nstatus: Operating status of the wattmeter:\nstatus = 1: in-service,\nstatus = 0: out-of-service.\n\nUpdates\n\nThe function updates the wattmeter field of the Measurement composite type.\n\nDefault Settings\n\nDefault settings for certain keywords are as follows: variance = 1e-2, noise = false, and status = 1, which apply to wattmeters located at the bus, as well as at both the from-bus and to-bus ends. Users can fine-tune these settings by explicitly specifying the variance and status for wattmeters positioned at the buses, from-bus ends, or to-bus ends of branches using the @wattmeter macro.\n\nUnits\n\nThe default units for the active and variance keywords are per-units (pu). However, users can choose to use watts (W) as the units by applying the @power macro.\n\nExamples\n\nAdding wattmeters using the default unit system:\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.2)\n\naddWattmeter!(system, device; label = \"Wattmeter 1\", bus = \"Bus 2\", active = 0.4)\naddWattmeter!(system, device; label = \"Wattmeter 2\", from = \"Branch 1\", active = 0.1)\n\nAdding wattmeters using a custom unit system:\n\n@power(MW, pu, pu)\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.2)\n\naddWattmeter!(system, device; label = \"Wattmeter 1\", bus = \"Bus 2\", active = 40.0)\naddWattmeter!(system, device; label = \"Wattmeter 2\", from = \"Branch 1\", active = 10.0)\n\n\n\n\n\n","category":"method"},{"location":"api/measurementModel/#JuliaGrid.addWattmeter!-Tuple{PowerSystem, Measurement, AC}","page":"Measurement Model","title":"JuliaGrid.addWattmeter!","text":"addWattmeter!(system::PowerSystem, device::Measurement, analysis::AC;\n varianceBus, statusBus, varianceFrom, statusFrom, varianceTo, statusTo, noise)\n\nThe function incorporates wattmeters into the Measurement composite type for every bus and branch within the PowerSystem type. These measurements are derived from the exact active power injections at buses and active power flows in branches defined in the AC type.\n\nKeywords\n\nUsers have the option to configure the following keywords:\n\nvarianceBus (pu or W): Measurement variance for wattmeters at the buses.\nstatusBus: Operating status of the wattmeters at the buses:\nstatusBus = 1: in-service,\nstatusBus = 0: out-of-service.\nvarianceFrom (pu or W): Measurement variance for wattmeters at the from-bus ends.\nstatusFrom: Operating status of the wattmeters at the from-bus ends:\nstatusFrom = 1: in-service,\nstatusFrom = 0: out-of-service.\nvarianceTo (pu or W): Measurement variance for wattmeters at the to-bus ends.\nstatusTo: Operating status of the wattmeters at the to-bus ends:\nstatusTo = 1: in-service,\nstatusTo = 0: out-of-service.\nnoise: Specifies how to generate the measurement mean:\nnoise = true: adds white Gaussian noise with the variance to the active powers,\nnoise = false: uses the exact active power values.\n\nUpdates\n\nThe function updates the wattmeter field of the Measurement composite type.\n\nDefault Settings\n\nDefault settings for keywords are as follows: varianceBus = 1e-2, statusBus = 1, varianceFrom = 1e-2, statusFrom = 1, varianceTo = 1e-2, statusTo = 1, and noise = false. Users can change these default settings using the @wattmeter macro.\n\nUnits\n\nThe default units for the varianceBus, varianceFrom, and varianceTo keywords are per-units (pu). However, users can choose to use watts (W) as the units by applying the @power macro.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement()\n\nacModel!(system)\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\npower!(system, analysis)\n\n@wattmeter(label = \"Wattmeter ?\")\naddWattmeter!(system, device, analysis; varianceBus = 1e-3, statusFrom = 0)\n\n\n\n\n\n","category":"method"},{"location":"api/measurementModel/#JuliaGrid.updateWattmeter!","page":"Measurement Model","title":"JuliaGrid.updateWattmeter!","text":"updateWattmeter!(system::PowerSystem, device::Measurement, [analysis::Analysis];\n kwargs...)\n\nThe function allows for the alteration of parameters for a wattmeter.\n\nArguments\n\nIf the Analysis type is omitted, the function applies changes to the Measurement composite type only. However, when including the Analysis type, it updates both the Measurement and Analysis types. This streamlined process avoids the need to completely rebuild vectors and matrices when adjusting these parameters.\n\nKeywords\n\nTo update a specific wattmeter, provide the necessary kwargs input arguments in accordance with the keywords specified in the addWattmeter! function, along with their respective values. Ensure that the label keyword matches the label of the existing wattmeter you want to modify. If any keywords are omitted, their corresponding values will remain unchanged.\n\nUpdates\n\nThe function updates the wattmeter field within the Measurement composite type. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.\n\nUnits\n\nUnits for input parameters can be changed using the same method as described for the addWattmeter! function.\n\nExample\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 132e3)\naddBus!(system; label = \"Bus 2\", base = 132e3)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.2)\n\naddWattmeter!(system, device; label = \"Wattmeter 1\", from = \"Branch 1\", active = 1.1)\nupdateWattmeter!(system, device; label = \"Wattmeter 1\", active = 1.2, variance = 1e-4)\n\n\n\n\n\n","category":"function"},{"location":"api/measurementModel/#JuliaGrid.statusWattmeter!","page":"Measurement Model","title":"JuliaGrid.statusWattmeter!","text":"statusWattmeter!(system::PowerSystem, device::Measurement; inservice, inserviceBus,\n inserviceFrom, inserviceTo, outservice, outserviceBus outserviceFrom, outserviceTo,\n redundancy, redundancyBus, redundancyFrom, redundancyTo)\n\nThe function generates a set of wattmeters, assigning wattmeters randomly to either in-service or out-of-service states based on specified keywords.\n\nKeywords\n\nUsers may use either one main keyword or three fine-tuning keywords that specify distinct locations per function call:\n\ninservice: Sets the number of in-service wattmeters or allows fine-tuning:\ninserviceBus: sets only wattmeters loacted at the bus,\ninserviceFrom: sets only wattmeters loacted at the from-bus end,\ninserviceTo: sets only wattmeters loacted at the to-bus end.\noutservice: Sets the number of out-of-service wattmeters or allows fine-tuning:\noutserviceBus: sets only wattmeters loacted at the bus,\noutserviceFrom: sets only wattmeters loacted at the from-bus end,\noutserviceTo: sets only wattmeters loacted at the to-bus end.\nredundancy: Determines in-service wattmeters based on redundancy or allows fine-tuning:\nredundancyBus: determines only wattmeters loacted at the bus,\nredundancyFrom: determines only wattmeters loacted at the from-bus end,\nredundancyTo: determines only wattmeters loacted at the to-bus end.\n\nUpdates\n\nThe function updates the status field within the Wattmeter type.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement()\n\nacModel!(system)\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\npower!(system, analysis)\n\naddWattmeter!(system, device, analysis)\nstatusWattmeter!(system, device; outserviceBus = 14, inserviceFrom = 10, outserviceTo = 2)\n\n\n\n\n\n","category":"function"},{"location":"api/measurementModel/#JuliaGrid.@wattmeter","page":"Measurement Model","title":"JuliaGrid.@wattmeter","text":"@wattmeter(label, varianceBus, statusBus, varianceFrom, statusFrom, varianceTo, statusTo,\n noise)\n\nThe macro generates a template for a wattmeter, which can be utilized to define a wattmeter using the addWattmeter! function.\n\nKeywords\n\nTo establish the wattmeter template, users can set default variance and status values for wattmeters at buses using varianceBus and statusBus, and at both the from-bus and to-bus ends of branches using varianceFrom and statusFrom for the former and varianceTo and statusTo for the latter. Users can also configure label patterns with the label keyword, as well as specify the noise type.\n\nUnits\n\nThe default units for the varianceBus, varianceFrom, and varianceTo keywords are per-units (pu). However, users can choose to use watts (W) as the units by applying the @power macro.\n\nExamples\n\nAdding wattmeters using the default unit system:\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.2)\n\n@wattmeter(label = \"Wattmeter ?\", varianceBus = 1e-3, varianceFrom = 1e-4)\naddWattmeter!(system, device; bus = \"Bus 2\", active = 0.4)\naddWattmeter!(system, device; from = \"Branch 1\", active = 0.1)\n\nAdding wattmeters using a custom unit system:\n\n@power(MW, pu, pu)\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.2)\n\n@wattmeter(label = \"Wattmeter ?\", varianceBus = 1e-1, varianceFrom = 1e-2)\naddWattmeter!(system, device; bus = \"Bus 2\", active = 40.0)\naddWattmeter!(system, device; from = \"Branch 1\", active = 10.0)\n\n\n\n\n\n","category":"macro"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"api/measurementModel/#Varmeter-2","page":"Measurement Model","title":"Varmeter","text":"","category":"section"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addVarmeter!(::PowerSystem, ::Measurement)\naddVarmeter!(::PowerSystem, ::Measurement, ::AC)\nupdateVarmeter!\nstatusVarmeter!\n@varmeter","category":"page"},{"location":"api/measurementModel/#JuliaGrid.addVarmeter!-Tuple{PowerSystem, Measurement}","page":"Measurement Model","title":"JuliaGrid.addVarmeter!","text":"addVarmeter!(system::PowerSystem, device::Measurement; label, bus, from, to, reactive,\n variance, noise, status)\n\nThe function adds a new varmeter that measures reactive power injection or reactive power flow to the Measurement type within a given PowerSystem type. The varmeter can be added to an already defined bus or branch.\n\nKeywords\n\nThe varmeter is defined with the following keywords:\n\nlabel: Unique label for the varmeter.\nbus: Label of the bus if the varmeter is located at the bus.\nfrom: Label of the branch if the varmeter is located at the from-bus end.\nto: Label of the branch if the varmeter is located at the to-bus end.\nreactive (pu or VAr): Reactive power value.\nvariance (pu or VAr): Variance of the reactive power measurement.\nnoise: Specifies how to generate the measurement mean:\nnoise = true: adds white Gaussian noise with the variance to the reactive,\nnoise = false: uses the reactive value only.\nstatus: Operating status of the varmeter:\nstatus = 1: in-service,\nstatus = 0: out-of-service.\n\nUpdates\n\nThe function updates the varmeter field of the Measurement composite type.\n\nDefault Settings\n\nDefault settings for certain keywords are as follows: variance = 1e-2, noise = false, and status = 1, which apply to varmeters located at the bus, as well as at both the from-bus and to-bus ends. Users can fine-tune these settings by explicitly specifying the variance and status for varmeters positioned at the buses, from-bus ends, or to-bus ends of branches using the @varmeter macro.\n\nUnits\n\nThe default units for the reactive and variance keywords are per-units (pu). However, users can choose to use volt-amperes reactive (VAr) as the units by applying the @power macro.\n\nExamples\n\nAdding varmeters using the default unit system:\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.2)\n\naddVarmeter!(system, device; label = \"Varmeter 1\", bus = \"Bus 2\", reactive = 0.4)\naddVarmeter!(system, device; label = \"Varmeter 2\", from = \"Branch 1\", reactive = 0.1)\n\nAdding varmeters using a custom unit system:\n\n@power(MW, pu, pu)\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.2)\n\naddVarmeter!(system, device; label = \"Varmeter 1\", bus = \"Bus 2\", reactive = 40.0)\naddVarmeter!(system, device; label = \"Varmeter 2\", from = \"Branch 1\", reactive = 10.0)\n\n\n\n\n\n","category":"method"},{"location":"api/measurementModel/#JuliaGrid.addVarmeter!-Tuple{PowerSystem, Measurement, AC}","page":"Measurement Model","title":"JuliaGrid.addVarmeter!","text":"addVarmeter!(system::PowerSystem, device::Measurement, analysis::AC;\n varianceBus, statusBus, varianceFrom, statusFrom, varianceTo, statusTo, noise)\n\nThe function incorporates varmeters into the Measurement composite type for every bus and branch within the PowerSystem type. These measurements are derived from the exact reactive power injections at buses and reactive power flows in branches defined in the AC type.\n\nKeywords\n\nvarianceBus (pu or VAr): Measurement variance for varmeters at the buses.\nstatusBus: Operating status of the varmeters at the buses:\nstatusBus = 1: in-service,\nstatusBus = 0: out-of-service.\nvarianceFrom (pu or VAr): Measurement variance for varmeters at the from-bus ends.\nstatusFrom: Operating status of the varmeters at the from-bus ends:\nstatusFrom = 1: in-service,\nstatusFrom = 0: out-of-service.\nvarianceTo (pu or VAr): Measurement variance for varmeters at the to-bus ends.\nstatusTo: Operating status of the varmeters at the to-bus ends:\nstatusTo = 1: in-service,\nstatusTo = 0: out-of-service.\nnoise: Specifies how to generate the measurement mean:\nnoise = true: adds white Gaussian noise with the variance to the reactive powers,\nnoise = false: uses the exact reactive power values.\n\nUpdates\n\nThe function updates the varmeter field of the Measurement composite type.\n\nDefault Settings\n\nDefault settings for keywords are as follows: varianceBus = 1e-2, statusBus = 1, varianceFrom = 1e-2, statusFrom = 1, varianceTo = 1e-2, statusTo = 1, and noise = false. Users can change these default settings using the @varmeter macro.\n\nUnits\n\nThe default units for the varianceBus, varianceFrom, and varianceTo keywords are per-units (pu). However, users can choose to use volt-amperes reactive (VAr) as the units by applying the @power macro.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement()\n\nacModel!(system)\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\npower!(system, analysis)\n\n@varmeter(label = \"Varmeter ?\")\naddVarmeter!(system, device, analysis; varianceFrom = 1e-3, statusBus = 0)\n\n\n\n\n\n","category":"method"},{"location":"api/measurementModel/#JuliaGrid.updateVarmeter!","page":"Measurement Model","title":"JuliaGrid.updateVarmeter!","text":"updateVarmeter!(system::PowerSystem, device::Measurement, [analysis::Analysis];\n kwargs...)\n\nThe function allows for the alteration of parameters for a varmeter.\n\nArguments\n\nIf the Analysis type is omitted, the function applies changes to the Measurement composite type only. However, when including the Analysis type, it updates both the Measurement and Analysis types. This streamlined process avoids the need to completely rebuild vectors and matrices when adjusting these parameters.\n\nKeywords\n\nTo update a specific varmeter, provide the necessary kwargs input arguments in accordance with the keywords specified in the addVarmeter! function, along with their respective values. Ensure that the label keyword matches the label of the existing varmeter you want to modify. If any keywords are omitted, their corresponding values will remain unchanged.\n\nUpdates\n\nThe function updates the varmeter field within the Measurement composite type. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.\n\nUnits\n\nUnits for input parameters can be changed using the same method as described for the addVarmeter! function.\n\nExample\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 132e3)\naddBus!(system; label = \"Bus 2\", base = 132e3)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.2)\n\naddVarmeter!(system, device; label = \"Varmeter 1\", from = \"Branch 1\", reactive = 1.1)\nupdateVarmeter!(system, device; label = \"Varmeter 1\", reactive = 1.2, variance = 1e-4)\n\n\n\n\n\n","category":"function"},{"location":"api/measurementModel/#JuliaGrid.statusVarmeter!","page":"Measurement Model","title":"JuliaGrid.statusVarmeter!","text":"statusVarmeter!(system::PowerSystem, device::Measurement; inservice, inserviceBus,\n inserviceFrom, inserviceTo, outservice, outserviceBus outserviceFrom, outserviceTo,\n redundancy, redundancyBus, redundancyFrom, redundancyTo)\n\nThe function generates a set of varmeters, assigning varmeters randomly to either in-service or out-of-service states based on specified keywords.\n\nKeywords\n\nUsers may use either one main keyword or three fine-tuning keywords that specify distinct locations per function call:\n\ninservice: Sets the number of in-service varmeters or allows fine-tuning:\ninserviceBus: sets only varmeters loacted at the bus,\ninserviceFrom: sets only varmeters loacted at the from-bus end,\ninserviceTo: sets only varmeters loacted at the to-bus end.\noutservice: Sets the number of out-of-service varmeters or allows fine-tuning:\noutserviceBus: sets only varmeters loacted at the bus,\noutserviceFrom: sets only varmeters loacted at the from-bus end,\noutserviceTo: sets only varmeters loacted at the to-bus end.\nredundancy: Determines in-service varmeters based on redundancy or allows fine-tuning:\nredundancyBus: determines only varmeters loacted at the bus,\nredundancyFrom: determines only varmeters loacted at the from-bus end,\nredundancyTo: determines only varmeters loacted at the to-bus end.\n\nUpdates\n\nThe function updates the status field within the Varmeter type.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement()\n\nacModel!(system)\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\npower!(system, analysis)\n\naddVarmeter!(system, device, analysis)\nstatusVarmeter!(system, device; inserviceFrom = 20)\n\n\n\n\n\n","category":"function"},{"location":"api/measurementModel/#JuliaGrid.@varmeter","page":"Measurement Model","title":"JuliaGrid.@varmeter","text":"@varmeter(label, varinaceBus, varianceFrom, varianceTo, statusBus, statusFrom, statusTo,\n noise)\n\nThe macro generates a template for a varmeter, which can be utilized to define a varmeter using the addVarmeter! function.\n\nKeywords\n\nTo establish the varmeter template, users can set default variance and status values for varmeters at buses using varianceBus and statusBus, and at both the from-bus and to-bus ends of branches using varianceFrom and statusFrom for the former and varianceTo and statusTo for the latter. Users can also configure label patterns with the label keyword, as well as specify the noise type.\n\nUnits\n\nThe default units for the varianceBus, varianceFrom, and varianceTo keywords are per-units (pu). However, users can choose to usevolt-amperes reactive (VAr) as the units by applying the @power macro.\n\nExamples\n\nAdding varmeters using the default unit system:\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.2)\n\n@varmeter(label = \"Varmeter ?\", varianceBus = 1e-3, varianceFrom = 1e-4)\naddVarmeter!(system, device; bus = \"Bus 2\", reactive = 0.4)\naddVarmeter!(system, device; from = \"Branch 1\", reactive = 0.1)\n\nAdding varmeters using a custom unit system:\n\n@power(MW, pu, pu)\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.2)\n\n@varmeter(label = \"Varmeter ?\", varianceBus = 1e-1, varianceFrom = 1e-2)\naddVarmeter!(system, device; bus = \"Bus 2\", reactive = 40.0)\naddVarmeter!(system, device; from = \"Branch 1\", reactive = 10.0)\n\n\n\n\n\n","category":"macro"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"api/measurementModel/#PMU-2","page":"Measurement Model","title":"PMU","text":"","category":"section"},{"location":"api/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addPmu!(::PowerSystem, ::Measurement)\naddPmu!(::PowerSystem, ::Measurement, ::AC)\nupdatePmu!\nstatusPmu!\n@pmu","category":"page"},{"location":"api/measurementModel/#JuliaGrid.addPmu!-Tuple{PowerSystem, Measurement}","page":"Measurement Model","title":"JuliaGrid.addPmu!","text":"addPmu!(system::PowerSystem, device::Measurement; label, bus, from, to, magnitude,\n varianceMagnitude, statusMagnitude, angle, varianceAngle, statusAngle,\n noise, correlated, polar)\n\nThe function adds a new PMU to the Measurement type within a given PowerSystem type. The PMU can be added to an already defined bus or branch. When defining the PMU, it is essential to provide the bus voltage magnitude and angle if the PMU is located at a bus or the branch current magnitude and angle if the PMU is located at a branch.\n\nKeywords\n\nThe PMU is defined with the following keywords:\n\nlabel: Unique label for the PMU.\nbus: Label of the bus if the PMU is located at the bus.\nfrom: Label of the branch if the PMU is located at the from-bus end.\nto: Label of the branch if the PMU is located at the to-bus end.\nmagnitude (pu or V, A): Bus voltage or branch current magnitude value.\nvarianceMagnitude (pu or V, A): Magnitude measurement variance.\nstatusMagnitude: Operating status of the magnitude measurement:\nstatusMagnitude = 1: in-service,\nstatusMagnitude = 0: out-of-service.\nangle (rad or deg): Bus voltage or branch current angle value.\nvarianceAngle (rad or deg): Angle measurement variance.\nstatusAngle: Operating status of the angle measurement:\nstatusAngle = 1: in-service,\nstatusAngle = 0: out-of-service.\nnoise: Specifies how to generate the measurement means:\nnoise = true: adds white Gaussian noises with variances to the magnitude and angle,\nnoise = false: uses the magnitude and angle values only.\ncorrelated: Specifies error correlation for PMUs for algorithms utilizing rectangular coordinates:\ncorrelated = true: considers correlated errors,\ncorrelated = false: disregards correlations between errors.\npolar: Chooses the coordinate system for including phasor measurements in AC state estimation:\npolar = true: adopts the polar coordinate system,\npolar = false: adopts the rectangular coordinate system.\n\nUpdates\n\nThe function updates the pmu field of the Measurement composite type.\n\nDefault Settings\n\nDefault settings for certain keywords are as follows: varianceMagnitude = 1e-5, statusMagnitude = 1, varianceAngle = 1e-5, statusAngle = 1, noise = false, correlated = false, and polar = false, which apply to PMUs located at the bus, as well as at both the from-bus and to-bus ends. Users can fine-tune these settings by explicitly specifying the variance and status for PMUs positioned at the buses, from-bus ends, or to-bus ends of branches using the @pmu macro.\n\nUnits\n\nThe default units for the magnitude, varianceMagnitude, and angle, varianceAngle keywords are per-units (pu) and radians (rad). However, users have the option to switch to volts (V) and degrees (deg) when the PMU is located at a bus using the @voltage macro, or amperes (A) and degrees (deg) when the PMU is located at a branch through the use of the @current macro.\n\nExamples\n\nAdding PMUs using the default unit system:\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 131.8e3)\naddBus!(system; label = \"Bus 2\", base = 131.8e3)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.2)\n\naddPmu!(system, device; label = \"PMU 1\", bus = \"Bus 1\", magnitude = 1.1, angle = -0.1)\naddPmu!(system, device; label = \"PMU 2\", from = \"Branch 1\", magnitude = 1.1, angle = 0.1)\n\nAdding PMUs using a custom unit system:\n\n@voltage(kV, deg, kV)\n@current(A, deg)\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 131.8)\naddBus!(system; label = \"Bus 2\", base = 131.8)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.2)\n\naddPmu!(system, device; label = \"PMU 1\", bus = \"Bus 1\", magnitude = 145, angle = -5.7)\naddPmu!(system, device; label = \"PMU 2\", from = \"Branch 1\", magnitude = 481, angle = 5.7)\n\n\n\n\n\n","category":"method"},{"location":"api/measurementModel/#JuliaGrid.addPmu!-Tuple{PowerSystem, Measurement, AC}","page":"Measurement Model","title":"JuliaGrid.addPmu!","text":"addPmu!(system::PowerSystem, device::Measurement, analysis::AC;\n varianceMagnitudeBus, statusMagnitudeBus, varianceAngleBus, statusAngleBus,\n varianceMagnitudeFrom, statusMagnitudeFrom, varianceAngleFrom, statusAngleFrom,\n varianceMagnitudeTo, statusMagnitudeTo, varianceAngleTo, statusAngleTo,\n correlated, polar, noise)\n\nThe function incorporates PMUs into the Measurement composite type for every bus and branch within the PowerSystem type. These measurements are derived from the exact bus voltage magnitudes and angles, as well as branch current magnitudes and angles defined in the AC type.\n\nKeywords\n\nUsers have the option to configure the following keywords:\n\nvarianceMagnitudeBus (pu or V): Variance of magnitude measurements at buses.\nstatusMagnitudeBus: Operating status of magnitude measurements at buses:\nstatusMagnitudeBus = 1: in-service,\nstatusMagnitudeBus = 0: out-of-service.\nvarianceAngleBus (rad or deg): Variance of angle measurements at buses.\nstatusAngleBus: Operating status of angle measurements at buses:\nstatusAngleBus = 1: in-service,\nstatusAngleBus = 0: out-of-service.\nvarianceMagnitudeFrom (pu or A): Variance of magnitude measurements at the from-bus ends.\nstatusMagnitudeFrom: Operating status of magnitude measurements at the from-bus ends:\nstatusMagnitudeFrom = 1: in-service,\nstatusMagnitudeFrom = 0: out-of-service.\nvarianceAngleFrom (rad or deg): Variance of angle measurements at the from-bus ends.\nstatusAngleFrom: Operating status of angle measurements at the from-bus ends:\nstatusAngleFrom = 1: in-service,\nstatusAngleFrom = 0: out-of-service.\nvarianceMagnitudeTo (pu or A): Variance of magnitude measurements at the to-bus ends.\nstatusMagnitudeTo: Operating status of magnitude measurements at the to-bus ends:\nstatusMagnitudeTo = 1: in-service,\nstatusMagnitudeTo = 0: out-of-service.\nvarianceAngleTo (rad or deg): Variance of angle measurements at the to-bus ends.\nstatusAngleTo: Operating status of angle measurements at the to-bus ends:\nstatusAngleTo = 1: in-service,\nstatusAngleTo = 0: out-of-service.\ncorrelated: Specifies error correlation for PMUs for algorithms utilizing rectangular coordinates:\ncorrelated = true: considers correlated errors,\ncorrelated = false: disregards correlations between errors.\npolar: Chooses the coordinate system for including phasor measurements in AC state estimation:\npolar = true: adopts the polar coordinate system,\npolar = false: adopts the rectangular coordinate system.\nnoise: Specifies how to generate the measurement mean:\nnoise = true: adds white Gaussian noise with the variance to the magnitudes and angles,\nnoise = false: uses the exact magnitude and angles values.\n\nUpdates\n\nThe function updates the pmu field of the Measurement composite type.\n\nDefault Settings\n\nDefault settings for variance keywords are established at 1e-5, with all statuses set to 1, polar = false, correlated = false, and noise = false. Users can change these default settings using the @pmu macro.\n\nUnits\n\nThe default units for the variance keywords are in per-units (pu) and radians (rad). However, users have the option to switch to volts (V) and degrees (deg) when the PMU is located at a bus using the @voltage macro, or amperes (A) and degrees (deg) when the PMU is located at a branch through the use of the @current macro.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement()\n\nacModel!(system)\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\ncurrent!(system, analysis)\n\n@pmu(label = \"PMU ?\")\naddPmu!(system, device, analysis; varianceMagnitudeBus = 1e-3)\n\n\n\n\n\n","category":"method"},{"location":"api/measurementModel/#JuliaGrid.updatePmu!","page":"Measurement Model","title":"JuliaGrid.updatePmu!","text":"updatePmu!(system::PowerSystem, device::Measurement, [analysis::Analysis];\n kwargs...)\n\nThe function allows for the alteration of parameters for a PMU.\n\nArguments\n\nIf the Analysis type is omitted, the function applies changes to the Measurement composite type only. However, when including the Analysis type, it updates both the Measurement and Analysis types. This streamlined process avoids the need to completely rebuild vectors and matrices when adjusting these parameters.\n\nKeywords\n\nTo update a specific PMU, provide the necessary kwargs input arguments in accordance with the keywords specified in the addPmu! function, along with their respective values. Ensure that the label keyword matches the label of the existing PMU you want to modify. If any keywords are omitted, their corresponding values will remain unchanged.\n\nUpdates\n\nThe function updates the pmu field within the Measurement composite type. Furthermore, it guarantees that any modifications to the parameters are transmitted to the Analysis type.\n\nUnits\n\nUnits for input parameters can be changed using the same method as described for the addPmu! function.\n\nExample\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 132e3)\n\naddPmu!(system, device; label = \"PMU 1\", bus = \"Bus 1\", magnitude = 1.1, angle = -0.1)\nupdatePmu!(system, device; label = \"PMU 1\", magnitude = 1.05)\n\n\n\n\n\n","category":"function"},{"location":"api/measurementModel/#JuliaGrid.statusPmu!","page":"Measurement Model","title":"JuliaGrid.statusPmu!","text":"statusPmu!(system::PowerSystem, device::Measurement; inservice, inserviceBus,\n inserviceFrom, inserviceTo, outservice, outserviceBus outserviceFrom, outserviceTo,\n redundancy, redundancyBus, redundancyFrom, redundancyTo)\n\nThe function generates a set of PMUs, assigning PMUs randomly to either in-service or out-of-service states based on specified keywords. It is important to note that when we refer to PMU, we encompass both magnitude and angle measurements.\n\nKeywords\n\nUsers may use either one main keyword or three fine-tuning keywords that specify distinct locations per function call:\n\ninservice: Sets the number of in-service PMUs or allows fine-tuning:\ninserviceBus: sets only PMUs loacted at the bus,\ninserviceFrom: sets only PMUs loacted at the from-bus end,\ninserviceTo: sets only PMUs loacted at the to-bus end.\noutservice: Sets the number of out-of-service PMUs or allows fine-tuning:\noutserviceBus: sets only PMUs loacted at the bus,\noutserviceFrom: sets only PMUs loacted at the from-bus end,\noutserviceTo: sets only PMUs loacted at the to-bus end.\nredundancy: Determines in-service PMUs based on redundancy or allows fine-tuning:\nredundancyBus: determines only PMUs loacted at the bus,\nredundancyFrom: determines only PMUs loacted at the from-bus end,\nredundancyTo: determines only PMUs loacted at the to-bus end.\n\nUpdates\n\nThe function updates the status fields within the PMU type.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement()\n\nacModel!(system)\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\ncurrent!(system, analysis)\n\naddPmu!(system, device, analysis)\nstatusPmu!(system, device; inserviceBus = 14)\n\n\n\n\n\n","category":"function"},{"location":"api/measurementModel/#JuliaGrid.@pmu","page":"Measurement Model","title":"JuliaGrid.@pmu","text":"@pmu(label, varianceMagnitudeBus, statusMagnitudeBus, varianceAngleBus, statusAngleBus,\n varianceMagnitudeFrom, statusMagnitudeFrom, varianceAngleFrom, statusAngleFrom,\n varianceMagnitudeTo, statusMagnitudeTo, varianceAngleTo, statusAngleTo, noise,\n correlated, polar)\n\nThe macro generates a template for a PMU, which can be utilized to define a PMU using the addPmu! function.\n\nKeywords\n\nTo establish the PMU template, users have the option to set default values for magnitude and angle variances, as well as statuses for each component of the phasor. This can be done for PMUs located at the buses using the varianceMagnitudeBus, varianceAngleBus, statusMagnitudeBus, and statusAngleBus keywords.\n\nThe same configuration can be applied at both the from-bus ends of the branches using the varianceMagnitudeFrom, varianceAngleFrom, statusMagnitudeFrom, and statusAngleFrom keywords.\n\nFor PMUs located at the to-bus ends of the branches, users can use the varianceMagnitudeTo, varianceAngleTo, statusMagnitudeTo, and statusAngleTo keywords.\n\nAdditionally, users can configure the pattern for labels using the label keyword, specify the type of noise, and indicate the correlated and polar system utilized for managing phasors during state estimation.\n\nUnits\n\nBy default, the units for variances are per-units (pu) and radians (rad). However, users have the option to switch to volts (V) and degrees (deg) as the units for PMUs located at the buses by using the @voltage macro, or they can switch to amperes (A) and degrees (deg) as the units for PMUs located at the branches by using the @current macro.\n\nExamples\n\nAdding PMUs using the default unit system:\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 132e3)\naddBus!(system; label = \"Bus 2\", base = 132e3)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.2)\n\n@pmu(label = \"PMU ?\", varianceAngleBus = 1e-6, varianceMagnitudeFrom = 1e-4)\naddPmu!(system, device; bus = \"Bus 1\", magnitude = 1.1, angle = -0.1)\naddPmu!(system, device; from = \"Branch 1\", magnitude = 1.1, angle = -0.2)\n\nAdding PMUs using a custom unit system:\n\n@voltage(kV, deg, kV)\n@current(A, deg)\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 132.0)\naddBus!(system; label = \"Bus 2\", base = 132.0)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.2)\n\n@pmu(label = \"PMU ?\", varianceAngleBus = 5.73e-5, varianceMagnitudeFrom = 0.0481)\naddPmu!(system, device; bus = \"Bus 1\", magnitude = 145.2, angle = -5.73)\naddPmu!(system, device; from = \"Branch 1\", magnitude = 481.125, angle = -11.46)\n\n\n\n\n\n","category":"macro"},{"location":"manual/dcStateEstimation/#DCStateEstimationManual","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"section"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"To perform the DC state estimation, we first need to have the PowerSystem type that has been created with the DC model, alongside the Measurement type that retains measurement data. Subsequently, we can formulate either the weighted least-squares (WLS) or the least absolute value (LAV) DC state estimation model encapsulated within the type DCStateEstimation using:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"dcStateEstimation,\ndcLavStateEstimation.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"For resolving the DC state estimation problem and obtaining bus voltage angles, utilize the following function:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"solve!.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"After executing the function solve!, where the user employs the WLS method, the user has the ability to check if the measurement set contains outliers throughout bad data analysis and remove those measurements using:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"residualTest!.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Moreover, before creating the DCStateEstimation type, users can initiate observability analysis to identify observable islands and restore observability by employing:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"islandTopologicalFlow,\nislandTopological,\nrestorationGram!.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"For more detailed information, users can refer to the Observability Analysis section within AC state estimation documentation. It is worth noting that when the system becomes observable within the AC model, it will also be observable within the DC state estimation model.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"After obtaining the solution for DC state estimation, JuliaGrid offers a post-processing analysis function to compute active powers associated with buses and branches:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"power!.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Additionally, specialized functions are available for calculating specific types of powers for individual buses or branches.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"manual/dcStateEstimation/#DCSEBusTypeModificationManual","page":"DC State Estimation","title":"Bus Type Modification","text":"","category":"section"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Just like in the Bus Type Modification section, when establishing the DCStateEstimation type, the initially assigned slack bus is evaluated and may be altered. If the designated slack bus (type = 3) lacks a connected in-service generator, it will be changed to a demand bus (type = 1). Conversely, the first generator bus (type = 2) with an active in-service generator linked to it will be reassigned as the new slack bus (type = 3).","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"manual/dcStateEstimation/#DCWLSStateEstimationSolutionManual","page":"DC State Estimation","title":"Weighted Least-Squares Estimator","text":"","category":"section"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"To solve the DC state estimation and derive WLS estimates using JuliaGrid, the process initiates by defining PowerSystem and Measurement types. Here is an illustrative example:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", type = 3)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.2)\naddBus!(system; label = \"Bus 3\", type = 1, active = 0.4)\n\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.5)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 3\", reactance = 0.2)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.3)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 3.2)\n\n@wattmeter(label = \"Wattmeter ?\")\naddWattmeter!(system, device; bus = \"Bus 1\", active = 0.6, variance = 1e-3)\naddWattmeter!(system, device; bus = \"Bus 3\", active = -0.4, variance = 1e-2)\naddWattmeter!(system, device; from = \"Branch 1\", active = 0.18, variance = 1e-4)\naddWattmeter!(system, device; to = \"Branch 2\", active = -0.42, variance = 1e-4)\nnothing # hide","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"The dcStateEstimation function serves to establish the DC state estimation problem:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"analysis = dcStateEstimation(system, device)\nnothing # hide","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"tip: Tip\nHere, the user triggers LU factorization as the default method for solving the DC state estimation problem. However, the user also has the option to select alternative factorization methods such as LDLt or QR:analysis = dcStateEstimation(system, device, LDLt)","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"To obtain the bus voltage angles, the solve! function can be invoked as shown:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"solve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Upon obtaining the solution, access the bus voltage angles using:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"print(system.bus.label, analysis.voltage.angle)\nnothing # hide","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"note: Info\nWe recommend that readers refer to the tutorial on DC State Estimation for insights into the implementation.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"manual/dcStateEstimation/#Alternative-Formulation","page":"DC State Estimation","title":"Alternative Formulation","text":"","category":"section"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"The resolution of the WLS state estimation problem using the conventional method typically progresses smoothly. However, it is widely acknowledged that in certain situations common to real-world systems, this method can be vulnerable to numerical instabilities. Such conditions might impede the algorithm from finding a satisfactory solution. In such cases, users may opt for an alternative formulation of the WLS state estimation, namely, employing an approach called orthogonal factorization [5, Sec. 3.2].","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Specifically, by specifying the Orthogonal argument in the dcStateEstimation function, JuliaGrid implements a more robust approach to obtain the WLS estimator, which proves particularly beneficial when substantial differences exist among measurement variances:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"analysis = dcStateEstimation(system, device, Orthogonal)\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"manual/dcStateEstimation/#Print-Results-in-the-REPL","page":"DC State Estimation","title":"Print Results in the REPL","text":"","category":"section"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Users have the option to print the results in the REPL using any units that have been configured, such as:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"@voltage(pu, deg, V)\nprintBusData(system, analysis)\n@default(unit) # hide","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Next, users can easily customize the print results for specific buses, for example:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"printBusData(system, analysis; label = \"Bus 1\", header = true)\nprintBusData(system, analysis; label = \"Bus 2\")\nprintBusData(system, analysis; label = \"Bus 3\", footer = true)","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"manual/dcStateEstimation/#Save-Results-to-a-File","page":"DC State Estimation","title":"Save Results to a File","text":"","category":"section"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Users can also redirect print output to a file. For example, data can be saved in a text file as follows:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"open(\"bus.txt\", \"w\") do file\n printBusData(system, analysis, file)\nend","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"tip: Tip\nWe also provide functions to print state estimation results, such as estimated values and residuals. For more details, users can consult the Power Analysis section of this manual.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"manual/dcStateEstimation/#DCBadDataDetectionManual","page":"DC State Estimation","title":"Bad Data Processing","text":"","category":"section"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"After acquiring the WLS solution using the solve! function, users can conduct bad data analysis employing the largest normalized residual test. Continuing with our defined power system and measurement set, let us introduce a new wattmeter. Upon proceeding to find the solution for this updated state:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"addWattmeter!(system, device; from = \"Branch 2\", active = 4.1, variance = 1e-4)\n\nanalysis = dcStateEstimation(system, device)\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Following the solution acquisition, we can verify the presence of erroneous data. Detection of such data is determined by the threshold keyword. If the largest normalized residual's value exceeds the threshold, the measurement will be identified as bad data and consequently removed from the DC state estimation model:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"outlier = residualTest!(system, device, analysis; threshold = 4.0)\nnothing # hide","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Users can examine the data obtained from the bad data analysis:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"outlier.detect\noutlier.maxNormalizedResidual\noutlier.label","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Hence, upon detecting bad data, the detect variable will hold true. The maxNormalizedResidual variable retains the value of the largest normalized residual, while the label contains the label of the measurement identified as bad data. JuliaGrid will mark the respective measurements as out-of-service within the Measurement type.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Moreover, JuliaGrid will adjust the coefficient matrix and mean vector within the DCStateEstimation type based on measurements now designated as out-of-service. To optimize the algorithm's efficiency, JuliaGrid resets non-zero elements to zero in the coefficient matrix and mean vector, effectively removing the impact of the corresponding measurement on the solution:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"analysis.method.mean\nanalysis.method.coefficient","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Hence, after removing bad data, a new estimate can be computed without considering this specific measurement:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"solve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"note: Info\nWe suggest that readers refer to the tutorial on Bad Data Processing for insights into the implementation.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"manual/dcStateEstimation/#DCLAVtateEstimationSolutionManual","page":"DC State Estimation","title":"Least Absolute Value Estimator","text":"","category":"section"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"The LAV method presents an alternative estimation technique known for its increased robustness compared to WLS. While the WLS method relies on specific assumptions regarding measurement errors, robust estimators like LAV are designed to maintain unbiasedness even in the presence of various types of measurement errors and outliers. This characteristic often eliminates the need for extensive bad data processing procedures [5, Ch. 6]. However, it is important to note that achieving robustness typically involves increased computational complexity.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"To obtain an LAV estimator, users need to employ one of the solvers listed in the JuMP documentation. In many common scenarios, the Ipopt solver proves sufficient to obtain a solution:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"using Ipopt\nusing JuMP # hide\n\nanalysis = dcLavStateEstimation(system, device, Ipopt.Optimizer)\nJuMP.set_silent(analysis.method.jump) # hide\nnothing # hide","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"manual/dcStateEstimation/#Setup-Starting-Primal-Values","page":"DC State Estimation","title":"Setup Starting Primal Values","text":"","category":"section"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"In JuliaGrid, the assignment of starting primal values for optimization variables takes place when the solve! function is executed. Starting primal values are determined based on the voltage fields within the DCStateEstimation type. By default, these values are initially established using the initial bus voltage angles from PowerSystem type:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"print(system.bus.label, analysis.voltage.angle)","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Users have the flexibility to customize these values according to their requirements, and they will be utilized as the starting primal values when executing the solve! function.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"manual/dcStateEstimation/#Solution","page":"DC State Estimation","title":"Solution","text":"","category":"section"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"To solve the formulated LAV state estimation model, simply execute the following function:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"solve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Upon obtaining the solution, access the bus voltage angles using:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"print(system.bus.label, analysis.voltage.angle)\nnothing # hide","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"note: Info\nWe suggest that readers refer to the tutorial on Least Absolute Value Estimation for insights into the implementation.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"manual/dcStateEstimation/#DCMeasurementsAlterationManual","page":"DC State Estimation","title":"Measurement Set Update","text":"","category":"section"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"After establishing the Measurement type using the measurement function, users gain the capability to incorporate new measurement devices or update existing ones.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Once updates are completed, users can seamlessly progress towards generating the DCStateEstimation type using the dcStateEstimation or dcLavStateEstimation function. Ultimately, resolving the DC state estimation is achieved through the utilization of the solve! function:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\ndevice = measurement() # <- Initialize the Measurement instance\n\naddBus!(system; label = \"Bus 1\", type = 3)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.1)\n\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.5)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 0.1)\n\n@wattmeter(label = \"Wattmeter ?\")\naddWattmeter!(system, device; bus = \"Bus 2\", active = -0.11, variance = 1e-3)\naddWattmeter!(system, device; from = \"Branch 1\", active = 0.09, variance = 1e-4)\n\nanalysis = dcStateEstimation(system, device) # <- Build DCStateEstimation for the model\nsolve!(system, analysis)\n\naddWattmeter!(system, device; to = \"Branch 1\", active = -0.12, variance = 1e-4)\nupdateWattmeter!(system, device; label = \"Wattmeter 1\", status = 0)\nupdateWattmeter!(system, device; label = \"Wattmeter 2\", active = 0.1, noise = false)\n\nanalysis = dcStateEstimation(system, device) # <- Build DCStateEstimation for new model\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"note: Info\nThis concept removes the need to restart and recreate the Measurement type from the beginning when implementing changes to the existing measurement set.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"manual/dcStateEstimation/#DCStateEstimationUpdateManual","page":"DC State Estimation","title":"State Estimation Update","text":"","category":"section"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"An advanced methodology involves users establishing the DCStateEstimation type using dcStateEstimation or dcLavStateEstimation just once. After this initial setup, users can seamlessly modify existing measurement devices without the need to recreate the DCStateEstimation type.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"This advancement extends beyond the previous scenario where recreating the Measurement type was unnecessary, to now include the scenario where DCStateEstimation also does not need to be recreated. Such efficiency can be particularly advantageous in cases where JuliaGrid can reuse gain matrix factorization.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"tip: Tip\nThe addition of new measurements after the creation of DCStateEstimation is not practical in terms of reusing this type. Instead, we recommend that users create a final set of measurements and then utilize update functions to manage devices, either putting them in-service or out-of-service throughout the process.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"We can modify the prior example to achieve the same model without establishing DCStateEstimation twice:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\ndevice = measurement() # <- Initialize the Measurement instance\n\naddBus!(system; label = \"Bus 1\", type = 3)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.1)\n\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.5)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 0.1)\n\n@wattmeter(label = \"Wattmeter ?\")\naddWattmeter!(system, device; bus = \"Bus 2\", active = -0.11, variance = 1e-3)\naddWattmeter!(system, device; from = \"Branch 1\", active = 0.09, variance = 1e-4)\naddWattmeter!(system, device; to = \"Branch 1\", active = -0.12, variance = 1e-4, status = 0)\n\nanalysis = dcStateEstimation(system, device) # <- Build DCStateEstimation for the model\nsolve!(system, analysis)\n\nupdateWattmeter!(system, device; label = \"Wattmeter 1\", status = 0)\nupdateWattmeter!(system, device; label = \"Wattmeter 2\", active = 0.1, noise = false)\nupdateWattmeter!(system, device; label = \"Wattmeter 3\", status = 1)\n\n# <- No need for re-build; we have already updated the existing DCStateEstimation instance\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"note: Info\nThis concept removes the need to rebuild both the Measurement and the DCStateEstimation from the beginning when implementing changes to the existing measurement set. In the scenario of employing the WLS model, JuliaGrid can reuse the symbolic factorizations of LU or LDLt, provided that the nonzero pattern of the gain matrix remains unchanged.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"manual/dcStateEstimation/#Reusing-Weighted-Least-Squares-Matrix-Factorization","page":"DC State Estimation","title":"Reusing Weighted Least-Squares Matrix Factorization","text":"","category":"section"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Drawing from the preceding example, our focus now shifts to finding a solution involving modifications that entail adjusting the measurement value of the Wattmeter 2. It is important to note that these adjustments do not impact the variance or status of the measurement device, which can affect the gain matrix. To resolve this updated system, users can simply execute the solve! function:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nupdateWattmeter!(system, device, analysis; label = \"Wattmeter 2\", active = 0.091)\n\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"note: Info\nIn this scenario, JuliaGrid will recognize instances where the user has not modified parameters that impact the gain matrix. Consequently, JuliaGrid will leverage the previously performed gain matrix factorization, resulting in a significantly faster solution compared to recomputing the factorization.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"manual/dcStateEstimation/#DCSEPowerAnalysisManual","page":"DC State Estimation","title":"Power Analysis","text":"","category":"section"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"After obtaining the solution from the DC state estimation, calculating powers related to buses and branches is facilitated by using the power! function. For instance, let us consider the model for which we obtained the DC state estimation solution:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", type = 3, conductance = 1e-3)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.2)\naddBus!(system; label = \"Bus 3\", type = 1, active = 0.4)\n\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.5)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 3\", reactance = 0.2)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.3)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 3.2)\n\naddWattmeter!(system, device; bus = \"Bus 1\", active = 0.6, variance = 1e-3)\naddWattmeter!(system, device; bus = \"Bus 3\", active = -0.4, variance = 1e-2)\naddWattmeter!(system, device; from = \"Branch 1\", active = 0.18, variance = 1e-4)\naddWattmeter!(system, device; to = \"Branch 2\", active = -0.42, variance = 1e-4)\n\nanalysis = dcStateEstimation(system, device)\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"We can compute active powers using the following function:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"power!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"For example, active power injections corresponding to buses are:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"print(system.bus.label, analysis.power.injection.active)","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"note: Info\nTo better understand the powers associated with buses, and branches that are calculated by the power! function, we suggest referring to the tutorials on.","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"manual/dcStateEstimation/#Print-Results-in-the-REPL-2","page":"DC State Estimation","title":"Print Results in the REPL","text":"","category":"section"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Users can utilize any of the print functions outlined in the Print API related to the DC analysis. For example, to print state estimation data related to wattmeters, we can use:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"@power(MW, pu, pu)\nprintWattmeterData(system, device, analysis)\n@default(unit) # hide","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"manual/dcStateEstimation/#Save-Results-to-a-CSV-File","page":"DC State Estimation","title":"Save Results to a CSV File","text":"","category":"section"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"For CSV output, users should first generate a simple table with style = false, and then save it to a CSV file:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"using CSV\n\nio = IOBuffer()\nprintWattmeterData(system, device, analysis, io; style = false)\nCSV.write(\"bus.csv\", CSV.File(take!(io); delim = \"|\"))","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"manual/dcStateEstimation/#Active-Power-Injection","page":"DC State Estimation","title":"Active Power Injection","text":"","category":"section"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"To calculate active power injection associated with a specific bus, the function can be used:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"active = injectionPower(system, analysis; label = \"Bus 1\")","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"manual/dcStateEstimation/#Active-Power-Injection-from-Generators","page":"DC State Estimation","title":"Active Power Injection from Generators","text":"","category":"section"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"To calculate active power injection from the generators at a specific bus, the function can be used:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"active = supplyPower(system, analysis; label = \"Bus 1\")","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"","category":"page"},{"location":"manual/dcStateEstimation/#Active-Power-Flow","page":"DC State Estimation","title":"Active Power Flow","text":"","category":"section"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"Similarly, we can compute the active power flow at both the from-bus and to-bus ends of the specific branch by utilizing the provided functions below:","category":"page"},{"location":"manual/dcStateEstimation/","page":"DC State Estimation","title":"DC State Estimation","text":"active = fromPower(system, analysis; label = \"Branch 1\")\nactive = toPower(system, analysis; label = \"Branch 1\")","category":"page"},{"location":"tutorials/acPowerFlow/#ACPowerFlowTutorials","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"JuliaGrid uses standard network components and the Unified Branch Model for power flow analysis, allowing load profiles, generator capacities, voltage specifications, contingency analysis, and planning to be defined efficiently.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To begin, let us generate the PowerSystem type, as illustrated by the following example:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n@labels(Integer)\n\n@power(MW, MVAr, MVA)\n@voltage(pu, deg, V)\n\nsystem = powerSystem()\n\naddBus!(system; label = 1, type = 3)\naddBus!(system; label = 2, type = 1, active = 21.7, reactive = 12.7)\naddBus!(system; label = 3, type = 1, active = 11.2, reactive = -3.0)\naddBus!(system; label = 4, type = 2, conductance = 2.1, susceptance = 1.2)\n\naddBranch!(system; from = 1, to = 2, resistance = 0.02, reactance = 0.06)\naddBranch!(system; from = 1, to = 3, resistance = 0.05, reactance = 0.21)\naddBranch!(system; from = 2, to = 3, resistance = 0.13, reactance = 0.26)\naddBranch!(system; from = 3, to = 4, reactance = 0.17, susceptance = 0.2, conductance = 1e-4)\n\naddGenerator!(system; bus = 1)\naddGenerator!(system; bus = 3, active = 40.0, reactive = 42.4)\nnothing #hide","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To review, we can conceptualize the bus/branch model as the graph denoted by mathcalG = (mathcalN mathcalE), where we have the set of buses mathcalN = 1 dots n, and the set of branches mathcalE subseteq mathcalN times mathcalN within the power system:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝒩 = collect(keys(system.bus.label))\nℰ = hcat([𝒩[system.branch.layout.from] 𝒩[system.branch.layout.to]])","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"ukw: Notation\nIn this section, when referring to a vector mathbfa, we use the notation mathbfa = a_i or mathbfa = a_ij, where a_i represents the element associated with bus i in mathcalN, and a_ij represents the element associated with branch (ij) in mathcalE.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#FlowNodalNetworkEquationsTutorials","page":"AC Power Flow","title":"Nodal Network Equations","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"As previously demonstrated in the section on the Nodal Network Equations, we observe the system of equations:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" mathbfbar I = mathbfY mathbfbar V","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The complex current injection at the bus i in mathcalN is defined as:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" barI_i = cfracS_i^*barV_i^*","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Thus, for any given bus i in mathcalN, we can express it as:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" cfracS_i^*barV_i^* = sum_j = 1^n Y_ij bar V_j","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The complex power injection denoted by S_i consists of both the active power P_i and reactive power Q_i. This relationship can be represented as follows:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" cfracP_i - textjQ_ibarV_i = sum_j = 1^n Y_ij bar V_j","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Recognizing that Y_ij = G_ij + textjB_ij, barV_i = V_i texte^textjtheta_i, barV_j = V_j texte^textjtheta_j, and by defining theta_ij = theta_i - theta_j, we can break down the above equation into its real and imaginary parts, resulting in two equations that describe bus i in mathcalN as follows:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n P_i =V_isumlimits_j=1^n (G_ijcostheta_ij+B_ijsintheta_ij)V_j\n Q_i =V_isumlimits_j=1^n (G_ijsintheta_ij-B_ijcostheta_ij)V_j\n\tendaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"As demonstrated by the above equations, the bus i in mathcalN contains four unknown variables: the active power injection P_i, reactive power injection Q_i, bus voltage magnitude V_i, and bus voltage angle theta_i.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To solve these equations, it is necessary to specify two known variables. Although any two variables can be selected mathematically, the choice is determined by the devices that are connected to a particular bus. The standard options are listed in the table below, and these options are used to define the bus types [9].","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Bus Type Label Known Unknown\nDemand 1 P_i, Q_i V_i, theta_i\nGenerator 2 P_i, V_i Q_i, theta_i\nSlack 3 V_i, theta_i P_i, Q_i","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Consequently, JuliaGrid operates with sets mathcalN_textpq and mathcalN_textpv that contain demand and generator buses, respectively, and exactly one slack bus in the set mathcalN_textsb. The bus types are stored in the variable:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"system.bus.layout.type","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"It should be noted that JuliaGrid cannot handle systems with multiple slack buses. Additionally, when using functions such as newtonRaphson, fastNewtonRaphsonBX, fastNewtonRaphsonXB, and gaussSeidel, the bus type can be modified as discussed in the section on Bus Type Modification.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Furthermore, active power injections P_i and reactive power injections Q_i can be expressed as:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n \tP_i = P_textpi - P_textdi \n Q_i = Q_textpi - Q_textdi\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"where P_textdi and Q_textdi denote the active and reactive power demanded at the bus i in mathcalN, while P_textpi and Q_textpi correspond to the active and reactive power produced by the generators at the bus i in mathcalN.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To provide a more comprehensive understanding, it is important to note that each bus i in mathcalN has the capacity to host multiple generators. This scenario can be conceptualized by introducing the set mathcalS_i, which encompasses all generators connected to bus i in mathcalN. With this perspective, we can calculate the values of P_textpi and Q_textpi as follows:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n \tP_textpi = sum_k in mathcalS_i P_textgk\n Q_textpi = sum_k in mathcalS_i Q_textgk\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"where P_textgk and Q_textgk represent the active and reactive power outputs of the k-th generator within the set mathcalS_i.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"As a way to summarize, the power injection vectors, represented as mathbfP = P_i and mathbfQ = Q_i can be computed based on the following variables and expressions:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐏 = system.bus.supply.active - system.bus.demand.active\n𝐐 = system.bus.supply.reactive - system.bus.demand.reactive","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Positive active or reactive power values, P_i 0 or Q_i 0, signify that power is being supplied into the power system from the specific bus. This indicates that the generators connected to this bus are producing more power than what the connected load is consuming. Conversely, negative values, P_i 0 or Q_i 0, indicate that the bus is drawing in active or reactive power from the power system. This suggests that the load's demand is exceeding the output from the generators.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#NewtonRaphsonMethodTutorials","page":"AC Power Flow","title":"Newton-Raphson Method","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The Newton-Raphson method is commonly used in AC power flow calculations due to its quadratic rate of convergence. It provides an accurate approximation of the roots of the system of nonlinear equations:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" mathbff(mathbfx) = mathbf0","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"This, in turn, allows for the determination of unknown voltage magnitudes and angles of buses, represented by the state vector mathbf x = mathbf x_texta mathbf x_textm^T. The state vector comprises two components:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"mathbf x_texta in mathbbR^n-1, which holds the bus voltage angles of demand and generator buses, represented by mathbf x_texta = theta_i, where i in mathcalN_textpq cup mathcalN_textpv,\nmathbf x_textm in mathbbR^n_textpq, which holds the bus voltage magnitudes of demand buses, represented by mathbf x_textm = V_i, where i in mathcalN_textpq, and n_textpq = mathcalN_textpq.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Knowing the voltage magnitudes and angles for certain types of buses is a consequence of the structure of the state vector mathbf x. Specifically, the voltage magnitude and angle at the slack bus are known, as well as the voltage magnitude at generator buses.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"As detailed in the Nodal Network Equations section of this manual, the expressions for active and reactive power injection are as follows:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n P_i =V_isumlimits_j=1^n (G_ijcostheta_ij+B_ijsintheta_ij)V_j\n Q_i =V_isumlimits_j=1^n (G_ijsintheta_ij-B_ijcostheta_ij)V_j\n\tendaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Using the above equations, we can define the active power injection function for demand and generator buses:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" f_P_i(mathbf x) = V_isumlimits_j=1^n (G_ijcostheta_ij+B_ijsintheta_ij)V_j - P_i = 0\n forall i in mathcalN_textpq cup mathcalN_textpv","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"and the reactive power injection function for demand buses:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" f_Q_i(mathbf x) = V_isumlimits_j=1^n (G_ijsintheta_ij-B_ijcostheta_ij)V_j - Q_i = 0\n forall i in mathcalN_textpq","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The active and reactive mismatches, often denoted as Delta P_i(mathbf x) and Delta Q_i(mathbf x), respectively, are defined as the functions f_P_i(mathbf x) and f_Q_i(mathbf x). The first terms on the right-hand side represent power injections at a bus, while the second term is constant and is obtained based on the active and reactive powers of the generators that supply a bus and active and reactive powers demanded by consumers at the same bus. Therefore, the Newton-Raphson method solves the system of nonlinear equations:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" mathbff(x) =\n beginbmatrix\n mathbff_textP(mathbf x) mathbff_textQ(mathbf x)\n endbmatrix = mathbf 0","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"where the first n - 1 equations correspond to demand and generator buses, and the last n_textpq equations correspond to demand buses.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#Initialization","page":"AC Power Flow","title":"Initialization","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To compute the voltage magnitudes and angles of buses using the Newton-Raphson method in JuliaGrid, you must first execute the acModel! function to set up the system, followed by initializing the Newton-Raphson method using the newtonRaphson function. The following code snippet demonstrates this process:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"acModel!(system)\nanalysis = newtonRaphson(system)\nnothing # hide","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"This results in the creation of the starting vectors of bus voltage magnitudes mathbfV^(0) and angles bmTheta^(0), as shown below:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐕⁽⁰⁾ = analysis.voltage.magnitude\n𝚯⁽⁰⁾ = analysis.voltage.angle","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Here, we utilize a \"flat start\" approach in our method. It is important to keep in mind that when dealing with initial conditions in this manner, the Newton-Raphson method may encounter difficulties.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#Iterative-Process","page":"AC Power Flow","title":"Iterative Process","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To implement the Newton-Raphson method, the iterative approach based on the Taylor series expansion, JuliaGrid provides the mismatch! and solve! functions. These functions are utilized to carry out the Newton-Raphson method iteratively until a stopping criterion is reached, as demonstrated in the following code snippet:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"for iteration = 1:100\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The mismatch! function calculates the mismatch in active power injection for demand and generator buses and the mismatch in reactive power injection for demand buses at each iteration nu = 1 2 dots. The equations used for these computations are:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" f_P_i(mathbf x^(nu-1)) = V_i^(nu-1)sumlimits_j=1^n (G_ijcostheta_ij^(nu-1)+B_ijsintheta_ij^(nu-1))V_j^(nu-1) - P_i\n forall i in mathcalN_textpq cup mathcalN_textpv","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"as well as the reactive power injection mismatch for demand buses:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" f_Q_i(mathbf x^(nu-1)) = V_i^(nu)sumlimits_j=1^n (G_ijsintheta_ij^(nu-1)-B_ijcostheta_ij^(nu-1))V_j^(nu-1) - Q_i\n forall i in mathcalN_textpq","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The resulting vector from these calculations is stored in the mismatch variable of the ACPowerFlow abstract type and can be accessed through the following line of code:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐟 = analysis.method.mismatch","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"In addition to computing the mismatches in active and reactive power injection, the mismatch! function also returns the maximum absolute values of these mismatches. These maximum values are used as termination criteria for the iteration loop if both are less than a predefined stopping criterion epsilon:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" max f_P_i(mathbf x^(nu-1)) forall i in mathcalN_textpq cup mathcalN_textpv epsilon \n max f_Q_i(mathbf x^(nu-1)) forall i in mathcalN_textpq epsilon","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Next, the function solve! computes the increments of bus voltage angle and magnitude at each iteration using:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" mathbfDelta mathbfx^(nu-1) = -mathbfJ(mathbfx^(nu-1))^-1 mathbff(mathbfx^(nu-1))","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"where mathbfDelta mathbfx = mathbf Delta mathbf x_texta mathbf Delta mathbf x_textm^T consists of the vector of bus voltage angle increments mathbf Delta mathbf x_texta in mathbbR^n-1 and bus voltage magnitude increments mathbf Delta mathbf x_textm in mathbbR^n_textpq, and mathbfJ(mathbfx) in mathbbR^n_textu times n_textu is the Jacobian matrix, n_textu = n + n_textpq - 1.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"tip: Tip\nBy default, JuliaGrid uses LU factorization as the primary method for factorizing the Jacobian matrix mathbfJ = mathbfLmathbfU, aiming to compute the increments. Nevertheless, users have the flexibility to opt for QR factorization as an alternative method.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"These values are stored in the ACPowerFlow abstract type and can be accessed after each iteration:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝚫𝐱 = analysis.method.increment\n𝐉 = analysis.method.jacobian\n𝐋 = analysis.method.factorization.L\n𝐔 = analysis.method.factorization.U","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The JuliaGrid implementation of the AC power flow follows a specific order to store the increment mathbfDelta mathbfx and mismatch mathbff(x) vectors. The first n-1 elements of both vectors correspond to the demand and generator buses in the same order as they appear in the input data. The first n-1 elements of the increment vector mathbfDelta mathbfx correspond to the voltage angle increments mathbf Delta mathbf x_texta, while the first n-1 elements of the mismatch vector mathbff(x) correspond to the mismatch in active power injections mathbff_textP(mathbf x).","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The last n_textpq elements of the increment mathbfDelta mathbfx and mismatch mathbff(x) vectors correspond to the demand buses in the order they appear in the input data. For the increment vector mathbfDelta mathbfx, it matches the bus voltage magnitude increments mathbf Delta mathbf x_textm, while for the mismatch vector mathbff(x), it matches the mismatch in reactive power injections mathbff_textQ(mathbf x).","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"These specified orders dictate the row and column order of the Jacobian matrix mathbfJ(mathbfx).","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Finally, the function solve! adds the computed increment term to the previous solution to obtain a new solution:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" mathbf x^(nu) = mathbf x^(nu-1) + mathbf Delta mathbf x^(nu-1)","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The bus voltage magnitudes mathbfV = V_i and angles bmTheta = theta_i are then updated based on the obtained solution mathbf x. It is important to note that only the voltage magnitudes related to demand buses and angles related to demand and generator buses are updated; not all values are updated. Therefore, the final solution obtained by JuliaGrid is stored in the following vectors:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐕 = analysis.voltage.magnitude\n𝚯 = analysis.voltage.angle","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#Jacobian-Matrix","page":"AC Power Flow","title":"Jacobian Matrix","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To complete the tutorial on the Newton-Raphson method, we will now describe the Jacobian matrix and provide the equations involved in its evolution. Without loss of generality, we assume that the slack bus is the first bus, followed by the set of demand buses and the set of generator buses:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n mathcalN_textsb = 1 \n mathcalN_textpq = 2 dots m \n mathcalN_textpv = m + 1dots n\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"where mathcalN = mathcalN_textsb cup mathcalN_textpq cup mathcalN_textpv. Therefore, we can express:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n mathbf x_texta = theta_2dotstheta_n^T mathbf Delta mathbf x_texta = Delta theta_2dotsDelta theta_n^T \n mathbf x_textm = V_2dotsV_m^T mathbf Delta mathbf x_textm = Delta V_2dotsDelta V_m^T\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The Jacobian matrix mathbfJ(x^(nu)) in mathbbR^n_textu times n_textu is:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" mathbfJ(x^(nu))=\n left\n beginarraycccccc\n cfracmathrm partialf_P_2(mathbf x^(nu)) mathrm partial theta_2 cdots \n cfracmathrm partialf_P_2(mathbf x^(nu))mathrm partial theta_n \n cfracmathrm partialf_P_2(mathbf x^(nu))mathrm partial V_2 cdots \n cfracmathrm partialf_P_2(mathbf x^(nu))mathrm partial V_m\n vdots \n cfracmathrm partialf_P_n(mathbf x^(nu)) mathrm partial theta_2 cdots \n cfracmathrm partialf_P_n(mathbf x^(nu))mathrm partial theta_n \n cfracmathrm partialf_P_n(mathbf x^(nu))mathrm partial V_2 cdots \n cfracmathrm partialf_P_n(mathbf x^(nu))mathrm partial V_m 10pt\n hline \n cfracmathrm partialf_Q_2(mathbf x^(nu)) mathrm partial theta_2 cdots \n cfracmathrm partialf_Q_2(mathbf x^(nu))mathrm partial theta_n \n cfracmathrm partialf_Q_2(mathbf x^(nu))mathrm partial V_2 cdots \n cfracmathrm partialf_Q_2(mathbf x^(nu))mathrm partial V_m\n vdots \n cfracmathrm partialf_Q_m(mathbf x^(nu)) mathrm partial theta_2 cdots \n cfracmathrm partialf_Q_m(mathbf x^(nu))mathrm partial theta_n \n cfracmathrm partialf_Q_m(mathbf x^(nu))mathrm partial V_2 cdots \n cfracmathrm partialf_Q_m(mathbf x^(nu))mathrm partial V_m\n endarray\n right","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The Jacobian matrix can be expressed using four block matrices:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"\tmathbfJ(x^(nu)) =\n beginbmatrix\n mathbfJ_11(x^(nu)) mathbfJ_12(x^(nu)) mathbfJ_21(x^(nu)) \n\t mathbfJ_22(x^(nu))\n endbmatrix","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"where diagonal elements of the Jacobian sub-matrices are defined as follows:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n cfracmathrm partialf_P_i(mathbf x^(nu)) mathrm partial theta_i =\n V_i^(nu)sumlimits_j=1^n (-G_ijsintheta_ij^(nu)+B_ijcostheta_ij^(nu))V_j^(nu) - B_ii(V_i^(nu))^2\n cfracmathrm partialf_P_i(mathbf x^(nu))mathrm partial V_i^(nu) =\n sumlimits_j=1^n (G_ijcostheta_ij^(nu)+B_ijsintheta_ij^(nu))V_j^(nu) + G_iiV_i^(nu)\n cfracmathrm partialf_Q_i(mathbf x^(nu)) mathrm partial theta_i =\n V_i^(nu) sumlimits_j=1^n (G_ijcostheta_ij^(nu)+B_ijsintheta_ij^(nu))V_j^(nu) - G_ii(V_i^(nu))^2\n cfracmathrm partialf_Q_i(mathbf x^(nu))mathrm partial V_i =\n sumlimits_j=1^n (G_ijsintheta_ij^(nu)-B_ijcostheta_ij^(nu))V_j^(nu) - B_iiV_i^(nu)\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"while non-diagonal elements of the Jacobian sub-matrices are:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n cfracmathrm partialf_P_i(mathbf x^(nu))mathrm partial theta_j =\n (G_ijsintheta_ij^(nu)-B_ijcostheta_ij^(nu))V_i^(nu)V_j^(nu)\n cfracmathrm partialf_P_i(mathbf x^(nu))mathrm partial V_j^(nu) =\n (G_ijcostheta_ij^(nu)+B_ijsintheta_ij^(nu))V_i^(nu)\n cfracmathrm partialf_Q_i(mathbf x^(nu))mathrm partial theta_j =\n -(G_ijcostheta_ij^(nu) + B_ijsintheta_ij^(nu))V_i^(nu)V_j^(nu)\n cfracmathrm partialf_Q_i(mathbf x^(nu))mathrmpartial V_j =\n (G_ijsintheta_ij^(nu)-B_ijcostheta_ij^(nu))V_i^(nu)\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#FastNewtonRaphsonMethodTutorials","page":"AC Power Flow","title":"Fast Newton-Raphson Method","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Although the fast Newton-Raphson method may converge more slowly than the traditional Newton-Raphson method, the shorter solution time for the updates often compensates for this slower convergence, resulting in a shorter overall solution time. This is particularly true for systems that are not heavily loaded, where a shorter overall solution time is almost always achieved. It is important to note that if the algorithm converges, it will converge to a correct solution [6].","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The fast Newton-Raphson method involves decoupling the power flow equations. Namely, the Newton-Raphson method is based on the equations:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginbmatrix\n mathbfJ_11(x) mathbfJ_12(x) mathbfJ_21(x) \n\t mathbfJ_22(x)\n endbmatrix\n beginbmatrix\n mathbf Delta mathbf x_texta mathbf Delta mathbf x_textm\n endbmatrix\t+\n beginbmatrix\n mathbff_textP(mathbf x) mathbff_textQ(mathbf x)\n endbmatrix = mathbf 0","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"where the iteration index has been omitted for simplicity. However, in transmission grids, there exists a strong coupling between active powers and voltage angles, as well as between reactive powers and voltage magnitudes. To achieve decoupling, two conditions must be satisfied: first, the resistance values r_ij of the branches must be small compared to their reactance values x_ij, and second, the angle differences must be small, i.e., theta_ij approx 0 [10]. Therefore, starting from the above equation, we have:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginbmatrix\n mathbfJ_11(x) mathbf0 mathbf0 mathbfJ_22(x)\n endbmatrix\n beginbmatrix\n mathbf Delta mathbf x_texta mathbf Delta mathbf x_textm\n endbmatrix\t+\n beginbmatrix\n mathbff_textP(mathbf x) mathbff_textQ(mathbf x)\n endbmatrix = mathbf 0","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"which gives the decoupled system as follows:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n mathbff_textP(mathbf x) = -mathbfJ_11(x) mathbf Delta mathbf x_texta \n mathbff_textQ(mathbf x) = -mathbfJ_22(x) mathbf Delta mathbf x_textm\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To examine the problem, it is helpful to express it as:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n f_P_2(mathbf x) = -Delta theta_2cfracmathrm partialf_P_2(mathbf x) mathrm partial theta_2 - cdots -\n Delta theta_n cfracmathrm partialf_P_2(mathbf x)mathrm partial theta_n \n vdots \n f_P_n(mathbf x) = -Delta theta_2cfracmathrm partialf_P_n(mathbf x) mathrm partial theta_2 - cdots -\n Delta theta_n cfracmathrm partialf_P_i(mathbf x)mathrm partial theta_n\n f_Q_2(mathbf x) = - Delta V_2 cfracmathrm partialf_Q_2(mathbf x)mathrm partial V_2 - cdots -\n Delta V_n_textpq cfracmathrm partialf_Q_2(mathbf x)mathrm partial V_m\n vdots \n f_Q_m(mathbf x) = - Delta V_2 cfracmathrm partialf_Q_m(mathbf x)mathrm partial V_2 - cdots -\n Delta V_m cfracmathrm partialf_Q_m(mathbf x)mathrm partial V_m\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Firstly, the second part of the expressions is expanded as follows:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n f_Q_2(mathbf x) =\n -cfracDelta V_2V_2V_2 cfracmathrm partialf_Q_2(mathbf x)mathrm partial V_2 - cdots -\n cfracDelta V_mV_m V_m\n cfracmathrm partialf_Q_2(mathbf x)mathrm partial V_m\n vdots \n f_Q_m(mathbf x) =\n - cfracDelta V_2V_2V_2 cfracmathrm partialf_Q_m(mathbf x)mathrm partial V_2 - cdots -\n cfracDelta V_mV_m V_m\n cfracmathrm partialf_Q_m(mathbf x)mathrm partial V_m\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Next, the Jacobian elements are derived. To achieve this, we can use the expressions defined for the Newton-Raphson method. For demand buses, the above expansions are applied as:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n cfracmathrm partialf_P_i(mathbf x) mathrm partial theta_i =\n V_isumlimits_j=1^n (-G_ijsintheta_ij+B_ijcostheta_ij)V_j - B_iiV_i^2\n cfracmathrm partialf_P_i(mathbf x)mathrm partial theta_j =\n (G_ijsintheta_ij-B_ijcostheta_ij)V_iV_j\n V_i cfracmathrm partialf_Q_i(mathbf x)mathrm partial V_i =\n V_isumlimits_j=1^n (G_ijsintheta_ij-B_ijcostheta_ij)V_j - B_iiV_i^2\n V_j cfracmathrm partialf_Q_i(mathbf x)mathrmpartial V_j =\n (G_ijsintheta_ij-B_ijcostheta_ij) V_i V_j\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"As the definition of reactive power is given by the equation:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" Q_i =V_isumlimits_j=1^n (G_ijsintheta_ij-B_ijcostheta_ij)V_j","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"the Jacobian elements can be expressed in the following manner:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n cfracmathrm partialf_P_i(mathbf x) mathrm partial theta_i =\n -Q_i - B_iiV_i^2\n cfracmathrm partialf_P_i(mathbf x)mathrm partial theta_j =\n (G_ijsintheta_ij-B_ijcostheta_ij) V_i V_j\n V_i cfracmathrm partialf_Q_i(mathbf x)mathrm partial V_i =\n Q_i - B_ii V_i^2\n V_j cfracmathrm partialf_Q_i(mathbf x)mathrmpartial V_j =\n (G_ijsintheta_ij - B_ijcostheta_ij) V_i V_j\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The decoupled model is established through the following approximations:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n sin(theta_ij) approx 0 \n cos(theta_ij) approx 1 \n Q_i B_iiV_i^2\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Thus, when the approximations are made, the Jacobian elements are simplified, resulting in the decoupled model where the Jacobian elements are:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n cfracmathrm partialf_P_i(mathbf x) mathrm partial theta_i = -B_iiV_i^2\n cfracmathrm partialf_P_i(mathbf x) mathrm partial theta_j = -B_ijV_iV_j\n V_i cfracmathrm partialf_Q_i(mathbf x) mathrm partial V_i = -B_iiV_i^2\n V_j cfracmathrm partialf_Q_i(mathbf x)mathrmpartial V_j = -B_ijV_iV_j\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Thus, the initial system of equations becomes:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n f_P_2(mathbf x) = B_22 Delta theta_2 V_2^2 + cdots + B_2n Delta theta_n V_2V_n \n vdots \n f_P_n(mathbf x) = B_n2 Delta theta_2 V_2V_n + cdots + B_nn Delta theta_n V_n^2 \n f_Q_2(mathbf x) = B_22 cfracDelta V_2V_2 V_2^2 + cdots + B_2m cfracDelta V_mV_m V_2V_m \n vdots \n f_Q_m(mathbf x) = B_m2 cfracDelta V_2V_2 V_2V_m + cdots + B_mm cfracDelta V_mV_m V_m^2\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Using V_j approx 1, wherein V_i^2 = V_iV_j j=i, the first part of the equations can be simplified to:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n f_P_2(mathbf x) = B_22 Delta theta_2 V_2 + cdots + B_2n Delta theta_n V_2\n vdots \n f_P_n(mathbf x) = B_n2 Delta theta_2 V_n + cdots + B_nn Delta theta_n V_n\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Similarly, the second part of the equations can be simplified to:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n f_Q_2(mathbf x) = B_22 V_2 Delta V_2 + cdots + B_2m V_2 Delta V_m\n \n vdots \n f_Q_m(mathbf x) = B_m2 V_m Delta V_2 + cdots + B_mm V_m Delta V_m\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The fast Newton-Raphson method is ultimately based on the system of equations presented below:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n cfracf_P_2(mathbf x)V_2 = B_22 Delta theta_2 + cdots + B_2n Delta theta_n \n vdots \n cfracf_P_n(mathbf x)V_n = B_n2 Delta theta_2 + cdots + B_nn Delta theta_n \n cfracf_Q_2(mathbf x)V_2 = B_22 Delta V_2 + cdots + B_2m Delta V_m \n vdots \n cfracf_Q_m(mathbf x)V_m = B_m2 Delta V_2 + cdots +\n B_mm Delta V_m\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"This system can be written as:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n mathbfh_textP(mathbf x) = mathbfB_1 mathbf Delta mathbf x_texta \n mathbfh_textQ(mathbf x) = mathbfB_2 mathbf Delta mathbf x_textm\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"One of the main advantages of this approach is that the Jacobian matrices mathbfB_1 and mathbfB_2 are constant and need only be formed once. Furthermore, this method can be used to define both the XB and BX versions of the fast Newton-Raphson method.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#XB-Version","page":"AC Power Flow","title":"XB Version","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The matrix mathbfB_1 is formed by neglecting the resistance r_ij, shunt susceptance Im y_textshi , charging susceptance Im y_textsij , and transformer tap ratio magnitude tau_ij. The matrix mathbfB_2 is constructed by disregarding the transformer phase shift angle phi_ij. This approach corresponds to the standard fast Newton-Raphson method and is known to exhibit exceptional convergence properties in typical scenarios [10].","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To initialize the XB version of the fast Newton-Raphson method, one can utilize the following code snippet:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"acModel!(system)\nanalysis = fastNewtonRaphsonXB(system)\nnothing # hide","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#BX-Version","page":"AC Power Flow","title":"BX Version","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The matrix mathbfB_1 ignores the shunt susceptanceIm y_textshi , charging susceptance Im y_textsij , and transformer tap ratio magnitude tau_ij. The matrix mathbfB_2 ignores the resistance r_ij and transformer phase shift angle phi_ij. In usual cases, the iteration count for the BX version is comparable to the XB scheme. However, for systems with high r_ijx_ij ratios, the BX scheme requires considerably fewer iterations than the XB scheme to solve the power flow [10].","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To initialize the BX version of the fast Newton-Raphson method, you can use the following code:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"acModel!(system)\nanalysis = fastNewtonRaphsonBX(system)\nnothing # hide","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#Initialization-2","page":"AC Power Flow","title":"Initialization","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"When a user creates the fast Newton-Raphson method in JuliaGrid, the Jacobian matrices mathbfB_1 and mathbfB_2 are formed to correspond to the active and reactive power equations, respectively:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐁₁ = analysis.method.active.jacobian\n𝐁₂ = analysis.method.reactive.jacobian","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Additionally, during this stage, JuliaGrid generates the starting vectors for bus voltage magnitudes mathbfV^(0) and angles bmTheta^(0) as demonstrated below:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐕⁽⁰⁾ = analysis.voltage.magnitude\n𝚯⁽⁰⁾ = analysis.voltage.angle","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#Iterative-Process-2","page":"AC Power Flow","title":"Iterative Process","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"JuliaGrid offers the mismatch! and solve! functions to implement the fast Newton-Raphson method iterations. These functions are used iteratively until a stopping criterion is met, as shown in the code snippet below:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"for iteration = 1:100\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The functions mathbff_textP(mathbf x) and mathbff_textQ(mathbf x) remain free of approximations, with only the calculation of the state variable increments affected [6]. As a result, we still use the following equations to compute the mismatches:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n f_P_i(mathbf x) = V_isumlimits_j=1^n (G_ijcostheta_ij+B_ijsintheta_ij)V_j - P_i = 0\n forall i in mathcalN_textpq cup mathcalN_textpv\n f_Q_i(mathbf x) = V_isumlimits_j=1^n (G_ijsintheta_ij-B_ijcostheta_ij)V_j - Q_i = 0\n forall i in mathcalN_textpq\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Therefore, the mismatch! function calculates the mismatch in active power injection for demand and generator buses and the mismatch in reactive power injection for demand buses at each iteration nu = 1 2 dots:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n h_P_i(mathbf x^(nu-1)) =\n sumlimits_j=1^n (G_ijcostheta_ij^(nu-1)+B_ijsintheta_ij^(nu-1))V_j^(nu-1) - cfracP_iV_i^(nu-1)\n forall i in mathcalN_textpq cup mathcalN_textpv \n h_Q_i(mathbf x^(nu-1)) =\n sumlimits_j=1^n (G_ijsintheta_ij^(nu-1)-B_ijcostheta_ij^(nu-1))V_j^(nu-1) - cfracQ_iV_i^(nu-1)\n forall i in mathcalN_textpq\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The resulting vectors from these calculations are stored in the ACPowerFlow abstract type and can be accessed through the following:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐡ₚ = analysis.method.active.increment\n𝐡ₒ = analysis.method.reactive.increment","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"In addition to computing the mismatches in active and reactive power injection, the mismatch! function also returns the maximum absolute values of these mismatches. These maximum values are used as termination criteria for the iteration loop if both are less than a predefined stopping criterion epsilon:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" max h_P_i(mathbf x^(nu)) forall i in mathcalN_textpq cup mathcalN_textpv epsilon \n max h_Q_i(mathbf x^(nu)) forall i in mathcalN_textpq epsilon","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Next, the function solve! computes the bus voltage angle increments:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" mathbf Delta mathbf x_texta^(nu-1) = mathbfB_1^-1 mathbfh_textP(mathbf x^(nu-1))","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To obtain the voltage angle increments, JuliaGrid initially performs LU factorization on the Jacobian matrix mathbfB_1 = mathbfL_1mathbfU_1. This factorization is executed only once and is utilized in each iteration of the algorithm:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐋₁ = analysis.method.active.factorization.L\n𝐔₁ = analysis.method.active.factorization.U","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"tip: Tip\nBy default, JuliaGrid uses LU factorization as the primary method for factorizing Jacobian matrix. Nevertheless, users have the flexibility to opt for QR factorization as an alternative method.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The vector of increments that corresponds to the active power equations can be accessed using:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝚫𝐱ₐ = analysis.method.active.increment","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The solution is then updated as follows:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" mathbf x_texta^(nu) = mathbf x_texta^(nu-1) + mathbf Delta mathbf x_texta^(nu-1)","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"It is important to note that only the voltage angles related to demand and generator buses are updated, while the vector of bus voltage angles of all buses is stored:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝚯 = analysis.voltage.angle","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"After calculating the update for voltage angles, to calculate the magnitude updates the fast Newton-Raphson method then solves the equation:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" mathbf Delta mathbf x_textm^(nu-1) = mathbfB_2^-1 mathbfh_textQ(mathbf x^(nu))","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Similarly to the previous instance, JuliaGrid initially executes LU factorization on the Jacobian matrix mathbfB_2 = mathbfL_2mathbfU_2. However, it provides the flexibility for users to opt for QR factorization instead. This factorization occurs only once and is utilized in each iteration of the fast Newton-Raphson algorithm:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐋₂ = analysis.method.reactive.factorization.L\n𝐔₂ = analysis.method.reactive.factorization.U","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The vector of increments that corresponds to the reactive power equations can be accessed using:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝚫𝐱ₘ = analysis.method.active.increment","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Finally, the solution is updated as follows:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" mathbf x_textm^(nu) = mathbf x_textm^(nu-1) + mathbf Delta mathbf x_textm^(nu-1)","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Again, it is important to note that only the voltage magnitudes of demand buses are updated, while the vector of bus voltage magnitude for all buses is stored:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐕 = analysis.voltage.magnitude","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#GaussSeidelMethodTutorials","page":"AC Power Flow","title":"Gauss-Seidel Method","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"As elaborated in the Nodal Network Equations section of this manual, each bus is associated with the balance equation expressed as:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" sum_j = 1^n Y_ij bar V_j = cfracP_i - textjQ_ibarV_i forall i in mathcalN","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"In its expanded form, this can be written as:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n Y_11 barV_1 + cdots+ Y_1nbarV_n = fracP_1 - jQ_1barV_1^* \n vdots \n Y_n1 barV_1 + cdots+ Y_nnbarV_n = fracP_n - jQ_nbarV_n^*\n\tendaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"While the Gauss-Seidel method directly solves the system of equations, it suffers from very slow convergence, which increases almost linearly with the system size, necessitating numerous iterations to obtain the desired solution [11]. Moreover, the convergence time of the Gauss-Seidel method increases significantly for large-scale systems and can face convergence issues for systems with high active power transfers. Nevertheless, power flow programs utilize both the Gauss-Seidel and Newton-Raphson methods in a complementary manner. Specifically, the Gauss-Seidel method is employed to obtain a quick approximate solution from a \"flat start\", while the Newton-Raphson method is utilized to obtain the final accurate solution [8].","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The Gauss-Seidel method is usually applied to a system of n complex equations, where one represents the slack bus. Consequently, one equation can be eliminated, resulting in a power flow problem with n-1 equations.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#Initialization-3","page":"AC Power Flow","title":"Initialization","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"JuliaGrid provides a way to utilize the Gauss-Seidel method for solving the AC power flow problem and determining the magnitudes and angles of bus voltages. To use this method, we need to execute the acModel! function first to set up the system and then initialize the Gauss-Seidel method using the gaussSeidel function. The code snippet below demonstrates this process:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"acModel!(system)\nanalysis = gaussSeidel(system)\nnothing # hide","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"This results in the creation of the starting vectors of bus voltage magnitudes mathbfV^(0) and angles bmTheta^(0), as shown below:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐕⁽⁰⁾ = analysis.voltage.magnitude\n𝚯⁽⁰⁾ = analysis.voltage.angle","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#Iterative-Process-3","page":"AC Power Flow","title":"Iterative Process","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"JuliaGrid offers the mismatch! and solve! functions to implement the Gauss-Seidel method iterations. These functions are used iteratively until a stopping criterion is met, as shown in the code snippet below:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"for iteration = 1:300\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"In contrast to the Newton-Raphson and fast Newton-Raphson methods, the Gauss-Seidel method does not require the calculation of the mismatch in active and reactive power injection at each iteration. Instead, the mismatch! function is used solely to verify the convergence criteria. At each iteration nu = 1 2 dots, we calculate the active power injection mismatch for demand and generator buses, as shown below:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" f_P_i(mathbf x^(nu-1)) = RebarV_i^(nu - 1) barI_i^*(nu - 1) - P_i forall i in mathcalN_textpq cup mathcalN_textpv","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"We also compute the reactive power injection mismatch for demand buses, given by:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" f_Q_i(mathbf x^(nu-1)) = ImbarV_i^(nu - 1) barI_i^*(nu - 1) - Q_i forall i in mathcalN_textpq","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"However, these mismatches are not stored, as they are only used to obtain the maximum absolute values of these mismatches. The maximum values of these mismatches are used as termination criteria for the iteration loop if both are less than a predefined stopping criterion epsilon, as shown below:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" max f_P_i(mathbf x^(nu-1)) forall i in mathcalN_textpq cup mathcalN_textpv epsilon \n max f_Q_i(mathbf x^(nu-1)) forall i in mathcalN_textpq epsilon","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"After initializing complex bus voltages barV_i^(0) for all buses in the power system, the function solve! proceeds to compute the voltages for demand buses using the Gauss-Seidel method:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" barV_i^(nu) =\n cfrac1Y_ii Bigg(cfracP_i - jQ_ibarV_i^*(nu-1) -\n sumlimits_substackj = 1^i - 1 Y_ijbarV_j^(nu) -\n sumlimits_substackj = i + 1^n Y_ijbarV_j^(nu-1)Bigg)\n forall i in mathcalN_textpq","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The next step is to determine the solution for generator buses in two stages: first, the reactive power injection is calculated, and then the bus complex voltage is updated using the following equations:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" beginaligned\n Q_i^(nu) =\n -Im left barV_i^*(nu) sumlimits_j=1^n Y_ijbarV_j^(nu)right forall i in mathcalN_textpv \n barV_i^(nu ) =\n cfrac1Y_ii Bigg(cfracP_i - jQ_i^(nu)barV_i^*(nu )-\n sumlimits_substackj = 1j neq i^n Y_ijbarV_j^(nu) Bigg) forall i in mathcalN_textpv\n endaligned","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The obtained voltage magnitude may not be equal to the magnitude specified for the generator bus, so a voltage correction step is necessary:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" barV_i^(nu) = V_i^(0) cfracbarV_i^(nu)V_i^(nu) forall i in mathcalN_textpv","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"JuliaGrid stores the final results in vectors that contain all bus voltage magnitudes and angles:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐕 = analysis.voltage.magnitude\n𝚯 = analysis.voltage.angle","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#ACPowerAnalysisTutorials","page":"AC Power Flow","title":"Power Analysis","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Once the computation of voltage magnitudes and angles at each bus is completed, various electrical quantities can be determined. JuliaGrid offers the power! function, which enables the calculation of powers associated with buses, branches, and generators. Here is an example code snippet demonstrating its usage:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"power!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The function stores the computed powers in the rectangular coordinate system. It calculates the following powers related to buses, branches, and generators:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Bus Active Reactive\nInjections mathbfP = P_i mathbfQ = Q_i\nGenerator injections mathbfP_textp = P_textpi mathbfQ_textp = Q_textpi\nShunt elements mathbfP_textsh = P_textshi mathbfQ_textsh = Q_textshi","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Branch Active Reactive\nFrom-bus end flows mathbfP_texti = P_ij mathbfQ_texti = Q_ij\nTo-bus end flows mathbfP_textj = P_ji mathbfQ_textj = Q_ji\nShunt elements mathbfP_texts = P_textsij mathbfP_texts = P_textsij\nSeries elements mathbfP_textl = P_textlij mathbfQ_textl = Q_textlij","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Generator Active Reactive\nOutputs mathbfP_textg = P_textgi mathbfQ_textg = Q_textgi","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"note: Info\nFor a clear comprehension of the equations, symbols presented in this section, as well as for a better grasp of power directions, please refer to the Unified Branch Model.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#Power-Injections","page":"AC Power Flow","title":"Power Injections","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Active and reactive power injections are stored as the vectors mathbfP = P_i and mathbfQ = Q_i, respectively, and can be retrieved using the following commands:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐏 = analysis.power.injection.active\n𝐐 = analysis.power.injection.reactive","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#GeneratorPowerInjectionsManual","page":"AC Power Flow","title":"Generator Power Injections","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The power! function in JuliaGrid also computes the active and reactive power injections from the generators at each bus. The active power supplied by the generators to the buses can be calculated by summing the given generator active powers in the input data, except for the slack bus, which can be determined as:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" P_textpi = P_i + P_textdi i in mathcalN_textsb","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"where P_textdi represents the active power demanded by consumers at the slack bus. The active power injections from the generators at each bus are stored as the vector, denoted by mathbfP_textp = P_textpi, can be obtained using:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐏ₚ = analysis.power.supply.active","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The calculation of reactive power injection from the generators at generator or slack buses can be achieved using the subsequent equation:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" Q_textpi = Q_i + Q_textdi forall i in mathcalN_textpv cup mathcalN_textsb","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"where Q_textdi represents the reactive power demanded by consumers at the corresponding bus. Further, the reactive power injected by the generators at buses from mathcalN_textpq can be calculated by summing the given generator reactive powers in the input data. The vector of these reactive power injections by the generators to the buses, denoted by mathbfQ_textp = Q_textpi, can be retrieved using the following command:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐐ₚ = analysis.power.supply.reactive","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#Power-at-Bus-Shunt-Elements","page":"AC Power Flow","title":"Power at Bus Shunt Elements","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Active and reactive powers associated with the shunt elements at each bus are represented by the vectors mathbfP_textsh = P_textshi and mathbfQ_textsh = Q_textshi. To retrieve these powers in JuliaGrid, use the following commands:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐏ₛₕ = analysis.power.shunt.active\n𝐐ₛₕ = analysis.power.shunt.reactive","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#Power-Flows","page":"AC Power Flow","title":"Power Flows","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The resulting active and reactive power flows at each from-bus end are stored as the vectors mathbfP_texti = P_ij and mathbfQ_texti = Q_ij respectively, and can be retrieved using the following commands:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐏ᵢ = analysis.power.from.active\n𝐐ᵢ = analysis.power.from.reactive","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The vectors of active and reactive power flows at the to-bus end are stored as mathbfP_textj = P_ji and mathbfQ_textj = Q_ji, respectively, and can be retrieved using the following code:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐏ⱼ = analysis.power.to.active\n𝐐ⱼ = analysis.power.to.reactive","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#Power-at-Branch-Shunt-Elements","page":"AC Power Flow","title":"Power at Branch Shunt Elements","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Active and reactive powers associated with the branch shunt elements at each branch are represented by the vectors mathbfP_texts = P_textsij and mathbfQ_texts = Q_textsij. We can retrieve these values using the following code:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐏ₛ = analysis.power.charging.active\n𝐐ₛ = analysis.power.charging.reactive","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#Power-at-Branch-Series-Elements","page":"AC Power Flow","title":"Power at Branch Series Elements","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Active and reactive powers associated with the branch series element at each branch are represented by the vectors mathbfP_textl = P_textlij and mathbfQ_textl = Q_textlij. We can retrieve these values using the following code:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐏ₗ = analysis.power.series.active\n𝐐ₗ = analysis.power.series.reactive","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#GeneratorPowerOutputsManual","page":"AC Power Flow","title":"Generator Power Outputs","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To obtain the output active powers of each generator connected to bus i in mathcalN_textpq cup mathcalN_textpv, the given active power in the input data is utilized. For the generator connected to the slack bus, the output active power is determined using the equation:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" P_textgi = P_i + P_textdi i in mathcalN_textsb","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"In the case of multiple generators connected to the slack bus, the first generator in the input data is assigned the obtained value of P_textgi. Then, this amount of power is reduced by the output active power of the other generators.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To retrieve the vector of active power outputs of generators, denoted as mathbfP_textg = P_textgi, i in mathcalS, where the set mathcalS represents the set of generators, users can utilize the following command:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐏ₒ = analysis.power.generator.active","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The output reactive powers of each generator located at the bus is obtained as:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":" Q_textgi = Q_i + Q_textdi i in mathcalN","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"If there are multiple generators at the same bus, the reactive power is allocated proportionally among the generators based on their reactive power capabilities.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To retrieve the vector of reactive power outputs of generators, denoted as mathbfQ_textg = Q_textgi, i in mathcalS, users can utilize:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐐ₒ = analysis.power.generator.reactive","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#ACCurrentAnalysisTutorials","page":"AC Power Flow","title":"Current Analysis","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"JuliaGrid offers the current! function, which enables the calculation of currents associated with buses and branches. Here is an example code snippet demonstrating its usage:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"current!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"The function stores the computed currents in the polar coordinate system. It calculates the following currents related to buses and branches:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Bus Magnitude Angle\nInjections mathbfI = I_i bmpsi = psi_i","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Branch Magnitude Angle\nFrom-bus end flows mathbfI_texti = I_ij bmpsi_texti = psi_ij\nTo-bus end flows mathbfI_textj = I_ji bmpsi_textj = psi_ji\nSeries elements mathbfI_textl = I_textlij bmpsi_textl = psi_textlij","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"note: Info\nFor a clear comprehension of the equations, symbols presented in this section, as well as for a better grasp of power directions, please refer to the Unified Branch Model.","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#Current-Injections","page":"AC Power Flow","title":"Current Injections","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"In JuliaGrid, complex current injections are stored in the vector of magnitudes denoted as mathbfI = I_i and the vector of angles represented as bmpsi = psi_i. You can retrieve them using the following commands:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐈 = analysis.current.injection.magnitude\n𝛙 = analysis.current.injection.angle","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#Current-Flows","page":"AC Power Flow","title":"Current Flows","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To obtain the vectors of magnitudes mathbfI_texti = I_ij and angles bmpsi_texti = psi_ij for the resulting complex current flows, you can use the following commands:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐈ᵢ = analysis.current.from.magnitude\n𝛙ᵢ = analysis.current.from.angle","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"Similarly, we can obtain the vectors of magnitudes mathbfI_textj = I_ji and angles bmpsi_textj = psi_ji of the resulting complex current flows using the following code:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐈ⱼ = analysis.current.to.magnitude\n𝛙ⱼ = analysis.current.to.angle","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"","category":"page"},{"location":"tutorials/acPowerFlow/#Current-at-Branch-Series-Elements","page":"AC Power Flow","title":"Current at Branch Series Elements","text":"","category":"section"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"To obtain the vectors of magnitudes mathbfI_textl = I_textlij and angles bmpsi_textl = psi_textlij of the resulting complex current flows, one can use the following code:","category":"page"},{"location":"tutorials/acPowerFlow/","page":"AC Power Flow","title":"AC Power Flow","text":"𝐈ₗ = analysis.current.series.magnitude\n𝛙ₗ = analysis.current.series.angle","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/#DCOptimalPowerFlowTutorials","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"section"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"To begin, let us generate the PowerSystem type, as illustrated by the following example:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"using JuliaGrid # hide\nusing JuMP, HiGHS\n@default(template) # hide\n@default(unit) # hide\n\n@labels(Integer)\n\nsystem = powerSystem()\n\naddBus!(system; label = 1, type = 3, angle = 0.17)\naddBus!(system; label = 2, type = 2, active = 0.1, conductance = 0.04)\naddBus!(system; label = 3, type = 1, active = 0.05)\n\n@branch(minDiffAngle = -pi, maxDiffAngle = pi)\naddBranch!(system; label = 1, from = 1, to = 2, reactance = 0.05, maxFromBus = 0.15)\naddBranch!(system; label = 2, from = 1, to = 3, reactance = 0.01, maxFromBus = 0.10)\naddBranch!(system; label = 3, from = 2, to = 3, reactance = 0.01, maxFromBus = 0.25)\n\n@generator(minActive = 0.0)\naddGenerator!(system; label = 1, bus = 1, active = 3.2, maxActive = 0.5)\naddGenerator!(system; label = 2, bus = 2, active = 0.2, maxActive = 0.3)\n\ncost!(system; label = 1, active = 2, polynomial = [1100.2; 500; 80])\ncost!(system; label = 2, active = 1, piecewise = [10.85 12.3; 14.77 16.8; 18 18.1])\nnothing # hide","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"To review, we can conceptualize the bus/branch model as the graph denoted by mathcalG = (mathcalN mathcalE), where we have the set of buses mathcalN = 1 dots n, and the set of branches mathcalE subseteq mathcalN times mathcalN within the power system:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"𝒩 = collect(keys(system.bus.label))\nℰ = [𝒩[system.branch.layout.from] 𝒩[system.branch.layout.to]]","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Moreover, we identify the set of generators as mathcalS = 1 dots n_textg within the power system:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"𝒮 = collect(keys(system.generator.label))","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"ukw: Notation\nHere, when referring to a vector mathbfa, we use the notation mathbfa = a_i or mathbfa = a_ij, where a_i represents the element related with bus i in mathcalN or generator i in mathcalS, while a_ij denotes the element related with branch (ij) in mathcalE.","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/#DCOptimalPowerFlowModelTutorials","page":"DC Optimal Power Flow","title":"Optimal Power Flow Model","text":"","category":"section"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"In the DC optimal power flow, the active power outputs of the generators mathbf P_textg = P_textgi, i in mathcalS, are represented as linear functions of the bus voltage angles bmTheta = theta_i, i in mathcalN. Thus, the optimization variables in this model are the active power outputs of the generators and the bus voltage angles.","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The DC optimal power flow model has the form:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"beginaligned\n textminimize sum_i in mathcalS f_i(P_textgi) \n textsubjectto theta_i - theta_texts = 0 i in mathcalN_textsb 3pt\n h_P_i(mathbf P_textg bmTheta) = 0 forall i in mathcalN 3pt\n theta_ij^textmin leq theta_i - theta_j leq theta_ij^textmax forall (ij) in mathcalE 3pt\n P_ij^textmin leq h_P_ij(theta_i theta_j) leq P_ij^textmax forall (ij) in mathcalE 3pt\n P_textgi^textmin leq P_textgi leq P_textgi^textmax forall i in mathcalS\nendaligned","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Essentially, the DC optimal power flow is focused on the minimization of the objective function related to the costs associated with the active power output of generators, all while ensuring the satisfaction of various constraints. This optimization task holds a crucial role in the efficient and timely management of electrical power systems. However, it is important to note that the solutions provided by the DC optimal power flow are approximate in nature.","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/#Build-Optimal-Power-Flow-Model","page":"DC Optimal Power Flow","title":"Build Optimal Power Flow Model","text":"","category":"section"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"To build the DC optimal power flow model, we must first load the power system and establish the DC model using:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"dcModel!(system)\nnothing # hide","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Afterward, the DC optimal power flow model is created using the dcOptimalPowerFlow function:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"analysis = dcOptimalPowerFlow(system, HiGHS.Optimizer; active = \"Pg\", angle = \"θ\")\nnothing # hide","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/#Optimization-Variables","page":"DC Optimal Power Flow","title":"Optimization Variables","text":"","category":"section"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Hence, the variables in this model encompass the active power outputs of the generators denoted as mathbfP_textg = P_textgi, where i in mathcalS, and the bus voltage angles represented by bmTheta = theta_i, where i in mathcalN. You can access these variables using the following:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"𝐏ₒ = analysis.method.variable.active\n𝚯 = analysis.method.variable.angle","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/#Objective-Function","page":"DC Optimal Power Flow","title":"Objective Function","text":"","category":"section"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The objective function represents the sum of the active power cost functions f_i(P_textgi), i in mathcalS, for each generator, where these cost functions can be polynomial or linear piecewise functions. It is important to note that only polynomial cost functions up to the second degree are included in the objective function. If higher-degree polynomials are present, they will be excluded from the objective function by JuliaGrid.","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/#Polynomial-Active-Power-Cost-Function","page":"DC Optimal Power Flow","title":"Polynomial Active Power Cost Function","text":"","category":"section"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The DC optimal power flow in JuliaGrid allows the cost function f_i(P_textgi) to be represented as a polynomial of up to the second degree, making it possible to express the cost function as linear or quadratic. The possible representations are as follows:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"beginaligned\n f_i(P_textgi) = a_1P_textgi + a_0 \n f_i(P_textgi) = a_2 P_textgi^2 + a_1P_textgi + a_0\nendaligned","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Furthermore, it is worth noting that the function can be given simply as a constant with only the coefficient a_0, which implies that the cost of the generator remains constant regardless of the active power outputs. In conclusion, as illustrated in Figure 1, typical scenarios involve linear or quadratic cost functions, resulting in a best-case scenario for a linear optimization problem and a worst-case scenario for a quadratic optimization problem.","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"\n
Figure 1: The polynomial cost functions of generator active power output.
\n ","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"When utilizing the cost! function within JuliaGrid, employing the polynomial keyword results in the polynomial being constructed with coefficients ordered from the highest degree to the lowest. For instance, in the provided case study, we created a quadratic polynomial represented as:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"beginaligned\n f_1(P_textg1) = 11002 P_textg1^2 + 500 P_textg1 + 80\nendaligned","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"To access these coefficients, users can utilize the variable:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"f₁ = system.generator.cost.active.polynomial[1]","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/#Linear-Piecewise-Active-Power-Cost-Function","page":"DC Optimal Power Flow","title":"Linear Piecewise Active Power Cost Function","text":"","category":"section"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The DC optimal power flow in JuliaGrid offers another option for defining cost functions by using linear piecewise functions as approximations of the polynomial functions, as depicted in Figure 2.","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"\n
Figure 2: The linear piecewise cost functions of active power output.
\n ","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"To define linear piecewise functions in JuliaGrid, users can utilize the cost! function with the piecewise keyword. The linear piecewise function is constructed using a matrix where each row defines a single point. The first column holds the generator's active power output, while the second column corresponds to the associated cost value. For example, in the provided case study, a linear piecewise function is created and can be accessed as follows:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"f₂ = system.generator.cost.active.piecewise[2]","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Similar to how convex linear piecewise functions are treated in the AC Optimal Power Flow, JuliaGrid adopts a constrained cost variable method for the linear piecewise functions. In this method, the piecewise linear cost function is converted into a series of linear inequality constraints for each segment, which are defined by two adjacent points along the line, along with a helper variable specific to the piecewise function. However, for linear piecewise functions that have only one segment defined by two points, JuliaGrid simplifies it into a standard linear function without requiring a helper variable.","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Consequently, for a piecewise cost function denoted as f_i(P_textgi) with k segments (where k 1), the j-th segment, defined by the points P_textgij f_i(P_textgij) and P_textgij+1 f_i(P_textgij+1), is characterized by the following inequality constraints:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"cfracf_i(P_textgij+1) - f_i(P_textgij)P_textgij+1 - P_textgij(P_textgi - P_textgij) + f_i(P_textgij) leq H_i i in mathcalS j = 1dotsk","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"where H_i represents the helper variable. To finalize this method, we simply need to include the helper variable H_i in the objective function. This approach efficiently handles linear piecewise cost functions, providing the flexibility to capture nonlinear characteristics while still benefiting from the advantages of linear optimization techniques.","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"As an example, in the provided case study, the helper variable is defined as follows:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"H₂ = analysis.method.variable.actwise[2]","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Lastly, the set of constraints introduced by the linear piecewise cost function is displayed as follows:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(analysis.method.constraint.piecewise.active)","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/#Objective-Function-2","page":"DC Optimal Power Flow","title":"Objective Function","text":"","category":"section"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"As previously explained, the objective function relies on the defined polynomial or linear piecewise cost functions and represents the sum of these costs. In the provided example, the objective function that must be minimized to obtain the optimal values for the active power output of the generators and the bus voltage angles can be accessed using the following code:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"JuMP.objective_function(analysis.method.jump)","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/#Constraint-Functions","page":"DC Optimal Power Flow","title":"Constraint Functions","text":"","category":"section"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"In the following section, we will examine the various constraints defined within the DC optimal power flow model.","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/#Slack-Bus-Constraint","page":"DC Optimal Power Flow","title":"Slack Bus Constraint","text":"","category":"section"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The first equality constraint is linked to the slack bus, where the bus voltage angle denoted as theta_i is fixed to a constant value theta_texts. It can be expressed as follows:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"theta_i - theta_texts = 0 i in mathcalN_textsb","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"where the set mathcalN_textsb contains the index of the slack bus. To access the equality constraint from the model, we can utilize the variable:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(analysis.method.constraint.slack.angle)","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/#Bus-Active-Power-Balance-Constraints","page":"DC Optimal Power Flow","title":"Bus Active Power Balance Constraints","text":"","category":"section"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The second equality constraint in the optimization problem is associated with the active power balance equation:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"h_P_i(mathbf P_textg bmTheta) = 0 forall i in mathcalN","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"As elaborated in the Nodal Network Equations section, we can express the equation as follows:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"h_P_i(mathbf P_textg bmTheta) = sum_k in mathcalS_i P_textgk - sum_k = 1^n B_ik theta_k - P_textdi - P_textshi - P_texttri","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"In this equation, the set mathcalS_i subseteq mathcalS encompasses all generators connected to bus i in mathcalN, and P_textgk represents the active power output of the k-th generator within the set mathcalS_i. More precisely, the variable P_textgk represents the optimization variable, as well as the bus voltage angle theta_k.","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The constant terms in these equations are determined by the active power demand at bus P_textdi, the active power demanded by the shunt element P_textshi, and power related to the shift angle of the phase transformers P_texttri. The values representing these constant terms mathbfP_textd = P_textdi, mathbfP_textsh = P_textshi, and mathbfP_texttr = P_texttri, i in mathcalN, can be accessed:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"𝐏ₒ = system.bus.demand.active\n𝐏ₛₕ = system.bus.shunt.conductance\n𝐏ₜᵣ = system.model.dc.shiftPower","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"To retrieve constraints from the model, we can use:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(analysis.method.constraint.balance.active)","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/#Bus-Voltage-Angle-Difference-Constraints","page":"DC Optimal Power Flow","title":"Bus Voltage Angle Difference Constraints","text":"","category":"section"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The inequality constraint related to the minimum and maximum bus voltage angle difference between the from-bus and to-bus ends of each branch is defined as follows:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"theta_ij^textmin leq theta_i - theta_j leq theta_ij^textmax forall (ij) in mathcalE","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"where theta_ij^textmin represents the minimum, while theta_ij^textmax represents the maximum of the angle difference between adjacent buses. The values representing the voltage angle difference, denoted as bmTheta_textlm = theta_ij^textmin theta_ij^textmax, (ij) in mathcalE, are provided as follows:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"𝚯ₗₘ = [system.branch.voltage.minDiffAngle system.branch.voltage.maxDiffAngle]","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"To retrieve constraints from the model, we can use:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(analysis.method.constraint.voltage.angle)","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/#Branch-Active-Power-Flow-Constraints","page":"DC Optimal Power Flow","title":"Branch Active Power Flow Constraints","text":"","category":"section"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The inequality constraint related to active power flow is used to represent thermal limits on power transmission. This constraint is defined as follows:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"P_ij^textmin leq h_P_ij(theta_i theta_j) leq P_ij^textmax forall (ij) in mathcalE","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The branch flow limits at the from-bus, denoted as mathbfP_textf = P_ij^textmin P_ij^textmax , can be retrieved as follows:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"𝐏ₒ = [system.branch.flow.minFromBus system.branch.flow.maxFromBus]","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The active power flow at branch (ij) in mathcalE can be derived using the Branch Network Equations and is given by:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"h_P_ij(theta_i theta_j) = frac1tau_ij x_ij (theta_i - theta_j - phi_ij)","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"To retrieve constraints from the model, we can use:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(analysis.method.constraint.flow.active)","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/#Generator-Active-Power-Capability-Constraints","page":"DC Optimal Power Flow","title":"Generator Active Power Capability Constraints","text":"","category":"section"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The inequality constraints associated with the minimum and maximum active power outputs of the generators are defined as follows:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"P_textgi^textmin leq P_textgi leq P_textgi^textmax forall i in mathcalS","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"In this representation, the lower and upper bounds are determined by the vector mathbfP_textm = P_textgi^textmin P_textgi^textmax, i in mathcalS. We can access these bounds using the following variable:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"𝐏ₘ = [system.generator.capability.minActive system.generator.capability.maxActive]","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"To retrieve constraints from the model, we can use:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"print(analysis.method.constraint.capability.active)","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/#DCOptimalPowerFlowSolutionTutorials","page":"DC Optimal Power Flow","title":"Optimal Power Flow Solution","text":"","category":"section"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"To acquire the output active power of generators and the bus voltage angles, the user must invoke the function:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"JuMP.set_silent(analysis.method.jump) # hide\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Therefore, to get the vector of output active power of generators mathbfP_textg = P_textgi, i in mathcalS, we can use:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"𝐏ₒ = analysis.power.generator.active","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Further, the resulting bus voltage angles bmTheta = theta_i, i in mathcalN, are saved in the vector as follows:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"𝚯 = analysis.voltage.angle","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/#DCOptimalPowerAnalysisTutorials","page":"DC Optimal Power Flow","title":"Power Analysis","text":"","category":"section"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"After obtaining the solution from the DC optimal power flow, we can calculate the powers related to buses and branches using the power! function:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"power!(system, analysis)\nnothing # hide","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"note: Info\nFor a clear comprehension of the equations, symbols provided below, as well as for a better grasp of power directions, please refer to the Unified Branch Model.","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/#Power-Injections","page":"DC Optimal Power Flow","title":"Power Injections","text":"","category":"section"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Active power injections are stored as the vector mathbfP = P_i, and can be retrieved using the following commands:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"𝐏 = analysis.power.injection.active","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/#Generator-Power-Injections","page":"DC Optimal Power Flow","title":"Generator Power Injections","text":"","category":"section"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The active power supplied by generators to the buses can be calculated by summing the active power outputs of the generators obtained from the optimal DC power flow. This can be expressed as:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":" P_textpi = sum_k=1^n_textgi P_textgk forall i in mathcalN","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Here, P_textgk represents the active power output of the k-th generator connected to bus i in mathcalN, and n_textgi denotes the total number of generators connected to the same bus. We can obtain the vector of active powers injected by generators into the buses, denoted as mathbfP_textp = P_textpi, using the following command:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"𝐏ₚ = analysis.power.supply.active","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/#Power-Flows","page":"DC Optimal Power Flow","title":"Power Flows","text":"","category":"section"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"The resulting from-bus active power flows are stored as the vector mathbfP_texti = P_ij, which can be retrieved using:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"𝐏ᵢ = analysis.power.from.active","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"Similarly, the resulting to-bus active power flows are stored as the vector mathbfP_textj = P_ji, which can be retrieved using:","category":"page"},{"location":"tutorials/dcOptimalPowerFlow/","page":"DC Optimal Power Flow","title":"DC Optimal Power Flow","text":"𝐏ⱼ = analysis.power.to.active","category":"page"},{"location":"manual/pmuStateEstimation/#PMUStateEstimationManual","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To perform linear state estimation solely based on PMU data, the initial requirement is to have the PowerSystem type configured with the AC model, along with the Measurement type storing measurement data. Subsequently, we can formulate either the weighted least-squares (WLS) or the least absolute value (LAV) PMU state estimation model encapsulated within the type PMUStateEstimation using:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"pmuStateEstimation,\npmuLavStateEstimation.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"For resolving the PMU state estimation problem and obtaining bus voltage magnitudes and angles, utilize the following function:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"solve!.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"After executing the function solve!, where the user employs the WLS method, the user has the ability to check if the measurement set contains outliers throughout bad data analysis and remove those measurements using:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"residualTest!.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Moreover, before the creating PMUStateEstimation type, users can initiate an optimal PMU placement algorithm to determine the minimal set of PMUs required for an observable system:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"pmuPlacement.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"After obtaining the PMU state estimation solution, JuliaGrid offers post-processing analysis functions for calculating powers and currents associated with buses and branches:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"power!,\ncurrent!.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Additionally, specialized functions are available for calculating specific types of powers or currents for individual buses or branches.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#OptimalPMUPlacementManual","page":"PMU State Estimation","title":"Optimal PMU Placement","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Let us define the PowerSystem type and perform the AC power flow analysis solely for generating data to artificially create measurement values:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.5)\naddBus!(system; label = \"Bus 2\", type = 1, reactive = 0.05)\naddBus!(system; label = \"Bus 3\", type = 1, active = 0.5)\n\n@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.01)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.04)\n\n@generator(reactive = 0.1)\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 3.2)\naddGenerator!(system; label = \"Generator 2\", bus = \"Bus 2\", active = 2.1)\n\nanalysis = newtonRaphson(system)\nfor iteration = 1:10\n mismatch!(system, analysis)\n solve!(system, analysis)\nend\nnothing # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#Optimal-Solution","page":"PMU State Estimation","title":"Optimal Solution","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Upon defining the PowerSystem type, JuliaGrid provides the possibility to determine the minimal number of PMUs required for system observability using the pmuPlacement function:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"using GLPK\n\nplacement = pmuPlacement(system, GLPK.Optimizer)\nnothing # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The placement variable contains data regarding the optimal placement of measurements. In this instance, installing a PMU at Bus 2 renders the system observable:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"placement.bus","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"This PMU installed at Bus 2 will measure the bus voltage phasor at the corresponding bus and all current phasors at the branches incident to Bus 2 located at the from-bus or to-bus ends:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"placement.from\nplacement.to","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"note: Info\nWe suggest that readers refer to the tutorial on Optimal PMU Placement for insights into the implementation.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#Measurement-Data","page":"PMU State Estimation","title":"Measurement Data","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Utilizing PMU placement and AC power flow data, which serves as the source for measurement values in this scenario, we can construct the Measurement type as follows:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"device = measurement()\n\n@pmu(label = \"PMU ? (!)\")\nfor (bus, idx) in placement.bus\n Vᵢ, θᵢ = analysis.voltage.magnitude[idx], analysis.voltage.angle[idx]\n addPmu!(system, device; bus = bus, magnitude = Vᵢ, angle = θᵢ)\nend\nfor branch in keys(placement.from)\n Iᵢⱼ, ψᵢⱼ = fromCurrent(system, analysis; label = branch)\n addPmu!(system, device; from = branch, magnitude = Iᵢⱼ, angle = ψᵢⱼ)\nend\nfor branch in keys(placement.to)\n Iⱼᵢ, ψⱼᵢ = toCurrent(system, analysis; label = branch)\n addPmu!(system, device; to = branch, magnitude = Iⱼᵢ, angle = ψⱼᵢ)\nend\nnothing # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"For example, we can observe the obtained set of measurement values:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"print(device.pmu.label, device.pmu.magnitude.mean, device.pmu.angle.mean)","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#PMUWLSStateEstimationSolutionManual","page":"PMU State Estimation","title":"Weighted Least-Squares Estimator","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Let us continue with the previous example, where we defined the PowerSystem and Measurement types. To establish the PMU state estimation model, we will use the pmuStateEstimation function:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"analysis = pmuStateEstimation(system, device)\nnothing # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"tip: Tip\nHere, the user triggers LU factorization as the default method for solving the PMU state estimation problem. However, the user also has the option to select alternative factorization methods such as LDLt or QR:analysis = pmuStateEstimation(system, device, QR)","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To obtain the bus voltage magnitudes and angles, the solve! function can be invoked as shown:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"solve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Upon obtaining the solution, access the bus voltage magnitudes and angles using:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"note: Info\nWe recommend that readers refer to the tutorial on PMU State Estimation for insights into the implementation.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#Correlated-Measurement-Errors","page":"PMU State Estimation","title":"Correlated Measurement Errors","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"In the above approach, we assume that measurement errors from a single PMU are uncorrelated. This assumption leads to the covariance matrix and its inverse matrix (i.e., precision matrix) maintaining a diagonal form:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"analysis.method.precision","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"While this approach is suitable for many scenarios, linear PMU state estimation relies on transforming from polar to rectangular coordinate systems. Consequently, measurement errors from a single PMU become correlated due to this transformation. This correlation results in the covariance matrix, and hence the precision matrix, no longer maintaining a diagonal form but instead becoming a block diagonal matrix.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To accommodate this, users have the option to consider correlation when adding each PMU to the Measurement type. For instance, let us add a new PMU while considering correlation:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"addPmu!(system, device; bus = \"Bus 3\", magnitude = 1.01, angle = -0.005, correlated = true)\nnothing # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Following this, we recreate the WLS state estimation model:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"analysis = pmuStateEstimation(system, device)\nnothing # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Upon inspection, it becomes evident that the precision matrix no longer maintains a diagonal structure:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"analysis.method.precision","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Subsequently, we can address this new scenario and observe the solution:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"solve!(system, analysis)\nprint(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#Alternative-Formulation","page":"PMU State Estimation","title":"Alternative Formulation","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The resolution of the WLS state estimation problem using the conventional method typically progresses smoothly. However, it is widely acknowledged that in certain situations common to real-world systems, this method can be vulnerable to numerical instabilities. Such conditions might impede the algorithm from finding a satisfactory solution. In such cases, users may opt for an alternative formulation of the WLS state estimation, namely, employing an approach called orthogonal factorization [5, Sec. 3.2].","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"This approach is suitable when measurement errors are uncorrelated, and the precision matrix remains diagonal. Therefore, as a preliminary step, we need to eliminate the correlation, as we did previously:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"updatePmu!(system, device; label = \"PMU 5 (Bus 3)\", correlated = false)\nnothing # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Subsequently, by specifying the Orthogonal argument in the pmuStateEstimation function, JuliaGrid implements a more robust approach to obtain the WLS estimator, which proves particularly beneficial when substantial differences exist among measurement variances:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"analysis = pmuStateEstimation(system, device, Orthogonal)\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#Print-Results-in-the-REPL","page":"PMU State Estimation","title":"Print Results in the REPL","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Users have the option to print the results in the REPL using any units that have been configured, such as:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"@voltage(pu, deg, V)\nprintBusData(system, analysis)\n@default(unit) # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Next, users can easily customize the print results for specific buses, for example:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"printBusData(system, analysis; label = \"Bus 1\", header = true)\nprintBusData(system, analysis; label = \"Bus 2\")\nprintBusData(system, analysis; label = \"Bus 3\", footer = true)","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#Save-Results-to-a-File","page":"PMU State Estimation","title":"Save Results to a File","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Users can also redirect print output to a file. For example, data can be saved in a text file as follows:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"open(\"bus.txt\", \"w\") do file\n printBusData(system, analysis, file)\nend","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"tip: Tip\nWe also provide functions to print or save state estimation results, such as estimated values and residuals. For more details, users can consult the Power and Current Analysis section of this manual.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#PMUBadDataDetectionManual","page":"PMU State Estimation","title":"Bad Data Processing","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"After acquiring the WLS solution using the solve! function, users can conduct bad data analysis employing the largest normalized residual test. Continuing with our defined power system and measurement set, let us introduce a new phasor measurement. Upon proceeding to find the solution for this updated state:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"addPmu!(system, device; bus = \"Bus 3\", magnitude = 3.2, angle = 0.0, noise = false)\n\nanalysis = pmuStateEstimation(system, device)\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Following the solution acquisition, we can verify the presence of erroneous data. Detection of such data is determined by the threshold keyword. If the largest normalized residual's value exceeds the threshold, the measurement will be identified as bad data and consequently removed from the PMU state estimation model:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"outlier = residualTest!(system, device, analysis; threshold = 4.0)\nnothing # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Users can examine the data obtained from the bad data analysis:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"outlier.detect\noutlier.maxNormalizedResidual\noutlier.label","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Hence, upon detecting bad data, the detect variable will hold true. The maxNormalizedResidual variable retains the value of the largest normalized residual, while the label contains the label of the measurement identified as bad data. JuliaGrid will mark the respective phasor measurement as out-of-service within the Measurement type.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Moreover, JuliaGrid will adjust the coefficient matrix and mean vector within the PMUStateEstimation type based on measurements now designated as out-of-service. To optimize the algorithm's efficiency, JuliaGrid resets non-zero elements to zero in the coefficient matrix and mean vector, effectively removing the impact of the corresponding measurement on the solution:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"analysis.method.mean\nanalysis.method.coefficient","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"After removing bad data, a new estimate can be computed without considering this specific phasor measurement:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"solve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"note: Info\nWe suggest that readers refer to the tutorial on Bad Data Processing for insights into the implementation.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#PMULAVtateEstimationSolutionManual","page":"PMU State Estimation","title":"Least Absolute Value Estimator","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The LAV method presents an alternative estimation technique known for its increased robustness compared to WLS. While the WLS method relies on specific assumptions regarding measurement errors, robust estimators like LAV are designed to maintain unbiasedness even in the presence of various types of measurement errors and outliers. This characteristic often eliminates the need for extensive bad data processing procedures [5, Ch. 6]. However, it is important to note that achieving robustness typically involves increased computational complexity.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To obtain an LAV estimator, users need to employ one of the solvers listed in the JuMP documentation. In many common scenarios, the Ipopt solver proves sufficient to obtain a solution:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"using Ipopt\nusing JuMP # hide\n\nanalysis = pmuLavStateEstimation(system, device, Ipopt.Optimizer)\nJuMP.set_silent(analysis.method.jump) # hide\nnothing # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#Setup-Starting-Primal-Values","page":"PMU State Estimation","title":"Setup Starting Primal Values","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"In JuliaGrid, the assignment of starting primal values for optimization variables takes place when the solve! function is executed. Starting primal values are determined based on the voltage fields within the PMUStateEstimation type. By default, these values are initially established using the initial bus voltage magnitudes and angles from PowerSystem type:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Users have the flexibility to customize these values according to their requirements, and they will be utilized as the starting primal values when executing the solve! function. It is important to note that JuliaGrid utilizes the provided data to set starting primal values in the rectangular coordinate system.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#Solution","page":"PMU State Estimation","title":"Solution","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To solve the formulated LAV state estimation model, simply execute the following function:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"solve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Upon obtaining the solution, access the bus voltage magnitudes and angles using:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"print(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)\nnothing # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"note: Info\nWe suggest that readers refer to the tutorial on Least Absolute Value Estimation for insights into the implementation.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#PMUMeasurementsAlterationManual","page":"PMU State Estimation","title":"Measurement Set Update","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"After establishing the Measurement type using the measurement function, users gain the capability to incorporate new measurement devices or update existing ones.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Once updates are completed, users can seamlessly progress towards generating the PMUStateEstimation type using the pmuStateEstimation or pmuLavStateEstimation function. Ultimately, resolving the PMU state estimation is achieved through the utilization of the solve! function:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\ndevice = measurement() # <- Initialize the Measurement instance\n\naddBus!(system; label = \"Bus 1\", type = 3)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.1, reactive = 0.01)\naddBus!(system; label = \"Bus 3\", type = 1, active = 2.5, reactive = 0.2)\n\n@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.03)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 3.2, reactive = 0.3)\n\n@pmu(label = \"PMU ?\")\naddPmu!(system, device; bus = \"Bus 1\", magnitude = 1.0, angle = 0.0)\naddPmu!(system, device; bus = \"Bus 2\", magnitude = 0.98, angle = -0.023)\naddPmu!(system, device; from = \"Branch 2\", magnitude = 0.5, angle = -0.05)\n\nanalysis = pmuStateEstimation(system, device) # <- Build PMUStateEstimation for the model\nsolve!(system, analysis)\n\naddPmu!(system, device; to = \"Branch 2\", magnitude = 0.5, angle = 3.1)\nupdatePmu!(system, device; label = \"PMU 1\", varianceMagnitude = 1e-8)\nupdatePmu!(system, device; label = \"PMU 3\", statusMagnitude = 0, statusAngle = 0)\n\nanalysis = pmuStateEstimation(system, device) # <- Build PMUStateEstimation for new model\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"note: Info\nThis concept removes the need to restart and recreate the Measurement type from the beginning when implementing changes to the existing measurement set.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#PMUStateEstimationUpdateManual","page":"PMU State Estimation","title":"State Estimation Update","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"An advanced methodology involves users establishing the PMUStateEstimation type using pmuStateEstimation or pmuLavStateEstimation just once. After this initial setup, users can seamlessly modify existing measurement devices without the need to recreate the PMUStateEstimation type.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"This advancement extends beyond the previous scenario where recreating the Measurement type was unnecessary, to now include the scenario where PMUStateEstimation also does not need to be recreated.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"tip: Tip\nThe addition of new measurements after the creation of PMUStateEstimation is not practical in terms of reusing the PMUStateEstimation type. Instead, we recommend that users create a final set of measurements and then utilize update functions to manage devices, either putting them in-service or out-of-service throughout the process.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"We can modify the prior example to achieve the same model without establishing PMUStateEstimation twice:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\ndevice = measurement() # <- Initialize the Measurement instance\n\naddBus!(system; label = \"Bus 1\", type = 3)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.1, reactive = 0.01)\naddBus!(system; label = \"Bus 3\", type = 1, active = 2.5, reactive = 0.2)\n\n@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.03)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 3.2, reactive = 0.3)\n\n@pmu(label = \"PMU ?\")\naddPmu!(system, device; bus = \"Bus 1\", magnitude = 1.0, angle = 0.0)\naddPmu!(system, device; bus = \"Bus 2\", magnitude = 0.98, angle = -0.023)\naddPmu!(system, device; from = \"Branch 2\", magnitude = 0.5, angle = -0.05)\naddPmu!(system, device; to = \"Branch 2\", magnitude = 0.5, angle = 3.1, statusAngle = 0)\n\nanalysis = pmuStateEstimation(system, device) # <- Build PMUStateEstimation for the model\nsolve!(system, analysis)\n\nupdatePmu!(system, device, analysis; label = \"PMU 1\", varianceMagnitude = 1e-8)\nupdatePmu!(system, device, analysis; label = \"PMU 3\", statusMagnitude = 0, statusAngle = 0)\nupdatePmu!(system, device, analysis; label = \"PMU 4\", statusAngle = 1)\n\n# <- No need for re-build; we have already updated the existing PMUStateEstimation instance\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"note: Info\nThis concept removes the need to rebuild both the Measurement and the PMUStateEstimation from the beginning when implementing changes to the existing measurement set. In the scenario of employing the WLS model, JuliaGrid can reuse the symbolic factorizations of LU or LDLt, provided that the nonzero pattern of the gain matrix remains unchanged.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#PMUSEPowerCurrentAnalysisManual","page":"PMU State Estimation","title":"Power and Current Analysis","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"After obtaining the solution from the PMU state estimation, we can calculate various electrical quantities related to buses and branches using the power! and current! functions. For instance, let us consider the model for which we obtained the PMU state estimation solution:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", type = 3, susceptance = 0.002)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.1, reactive = 0.01)\naddBus!(system; label = \"Bus 3\", type = 1, active = 2.5, reactive = 0.2)\n\n@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.04)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 3\", reactance = 0.05)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.03)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 3.2, reactive = 0.3)\n\naddPmu!(system, device; bus = \"Bus 1\", magnitude = 1.0, angle = 0.0)\naddPmu!(system, device; bus = \"Bus 2\", magnitude = 0.97, angle = -0.051)\naddPmu!(system, device; from = \"Branch 2\", magnitude = 1.66, angle = -0.15)\naddPmu!(system, device; to = \"Branch 2\", magnitude = 1.67, angle = 2.96)\n\nanalysis = pmuStateEstimation(system, device)\nsolve!(system, analysis)","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"We can now utilize the provided functions to compute powers and currents:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"power!(system, analysis)\ncurrent!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"For instance, if we want to show the active power injections and the from-bus current magnitudes, we can employ the following code:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"print(system.bus.label, analysis.power.injection.active)\nprint(system.branch.label, analysis.current.from.magnitude)","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"note: Info\nTo better understand the powers and currents associated with buses and branches that are calculated by the power! and current! functions, we suggest referring to the tutorials on PMU State Estimation.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#Print-Results-in-the-REPL-2","page":"PMU State Estimation","title":"Print Results in the REPL","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Users can utilize any of the print functions outlined in the Print API. For example, to print state estimation data related to PMUs, we can use:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"@voltage(pu, deg, V)\nshow = Dict(\"Voltage Angle\" => false, \"Current Angle\" => false)\nprintPmuData(system, device, analysis; show)\n@default(unit) # hide","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#Save-Results-to-a-CSV-File","page":"PMU State Estimation","title":"Save Results to a CSV File","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"For CSV output, users should first generate a simple table with style = false, and then save it to a CSV file:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"using CSV\n\nio = IOBuffer()\nprintPmuData(system, device, analysis, io; style = false)\nCSV.write(\"bus.csv\", CSV.File(take!(io); delim = \"|\"))","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#Active-and-Reactive-Power-Injection","page":"PMU State Estimation","title":"Active and Reactive Power Injection","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To calculate the active and reactive power injection associated with a specific bus, the function can be used:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"active, reactive = injectionPower(system, analysis; label = \"Bus 1\")","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#Active-and-Reactive-Power-Injection-from-Generators","page":"PMU State Estimation","title":"Active and Reactive Power Injection from Generators","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To calculate the active and reactive power injection from the generators at a specific bus, the function can be used:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"active, reactive = supplyPower(system, analysis; label = \"Bus 1\")","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#Active-and-Reactive-Power-at-Shunt-Element","page":"PMU State Estimation","title":"Active and Reactive Power at Shunt Element","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To calculate the active and reactive power associated with shunt element at a specific bus, the function can be used:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"active, reactive = shuntPower(system, analysis; label = \"Bus 1\")","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#Active-and-Reactive-Power-Flow","page":"PMU State Estimation","title":"Active and Reactive Power Flow","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Similarly, we can compute the active and reactive power flow at both the from-bus and to-bus ends of the specific branch by utilizing the provided functions below:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"active, reactive = fromPower(system, analysis; label = \"Branch 2\")\nactive, reactive = toPower(system, analysis; label = \"Branch 2\")","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#Active-and-Reactive-Power-at-Charging-Admittances","page":"PMU State Estimation","title":"Active and Reactive Power at Charging Admittances","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To calculate the active and reactive power linked with branch charging admittances of the particular branch, the function can be used:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"active, reactive = chargingPower(system, analysis; label = \"Branch 1\")","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"Active powers indicate active losses within the branch's charging admittances. Moreover, charging admittances injected reactive powers into the power system due to their capacitive nature, as denoted by a negative sign.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#Active-and-Reactive-Power-at-Series-Impedance","page":"PMU State Estimation","title":"Active and Reactive Power at Series Impedance","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To calculate the active and reactive power across the series impedance of the branch, the function can be used:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"active, reactive = seriesPower(system, analysis; label = \"Branch 2\")","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"The active power also considers active losses originating from the series resistance of the branch, while the reactive power represents reactive losses resulting from the impedance's inductive characteristics.","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#Current-Injection","page":"PMU State Estimation","title":"Current Injection","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To calculate the current injection associated with a specific bus, the function can be used:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"magnitude, angle = injectionCurrent(system, analysis; label = \"Bus 1\")","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#Current-Flow","page":"PMU State Estimation","title":"Current Flow","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"We can compute the current flow at both the from-bus and to-bus ends of the specific branch by utilizing the provided functions below:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"magnitude, angle = fromCurrent(system, analysis; label = \"Branch 2\")\nmagnitude, angle = toCurrent(system, analysis; label = \"Branch 2\")","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"","category":"page"},{"location":"manual/pmuStateEstimation/#Current-Through-Series-Impedance","page":"PMU State Estimation","title":"Current Through Series Impedance","text":"","category":"section"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"To calculate the current passing through the series impedance of the branch in the direction from the from-bus end to the to-bus end, we can use the following function:","category":"page"},{"location":"manual/pmuStateEstimation/","page":"PMU State Estimation","title":"PMU State Estimation","text":"magnitude, angle = seriesCurrent(system, analysis; label = \"Branch 2\")","category":"page"},{"location":"manual/dcPowerFlow/#DCPowerFlowManual","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"section"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"To perform the DC power flow, we first need to have the PowerSystem type that has been created with the DC model. Following that, we can construct the power flow model encapsulated within the DCPowerFlow type by employing the following function:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"dcPowerFlow.","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"To solve the DC power flow problem and acquire bus voltage angles, make use of the following function:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"solve!.","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"After obtaining the solution for DC power flow, JuliaGrid offers a post-processing analysis function to compute active powers associated with buses, branches, and generators:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"power!.","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"Additionally, specialized functions are available for calculating specific types of powers for individual buses, branches, or generators.","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"manual/dcPowerFlow/#DCBusTypeModificationManual","page":"DC Power Flow","title":"Bus Type Modification","text":"","category":"section"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"During the initialization process, the designated slack bus, which is initially set, undergoes examination and can be altered using the dcPowerFlow function. Here is an example:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"system = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3)\naddBus!(system; label = \"Bus 2\", type = 2)\naddBus!(system; label = \"Bus 3\", type = 2)\n\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.01)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 3\")\n\ndcModel!(system)\nanalysis = dcPowerFlow(system)","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"In this example, the slack bus (type = 3) corresponds to the Bus 1. However, this bus does not have an in-service generator connected to it. JuliaGrid considers this a mistake and attempts to assign a new slack bus from the available generator buses (type = 2) that have connected in-service generators. In this particular example, the Bus 3 will become the new slack bus. As a result, we can observe the updated array of bus types:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3)\naddBus!(system; label = \"Bus 2\", type = 2, active = 0.1)\naddBus!(system; label = \"Bus 3\", type = 2, active = 0.05)\n\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 3\", reactance = 0.01)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.01)\n\naddGenerator!(system; bus = \"Bus 3\", active = 3.2)\n\ndcModel!(system)\nanalysis = dcPowerFlow(system)","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"print(system.bus.label, system.bus.layout.type)","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"note: Info\nThe bus that is defined as the slack bus (type = 3) but lacks a connected in-service generator will have its type changed to the demand bus (type = 1). Meanwhile, the first generator bus (type = 2) with an in-service generator connected to it will be assigned as the new slack bus (type = 3).","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"manual/dcPowerFlow/#DCPowerFlowSolutionManual","page":"DC Power Flow","title":"Power Flow Solution","text":"","category":"section"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"To solve the DC power flow problem using JuliaGrid, we start by creating the PowerSystem type and defining the DC model with the dcModel! function. Here is an example:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.1)\naddBus!(system; label = \"Bus 3\", type = 1, active = 0.05)\n\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 3\", reactance = 0.01)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.01)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 3.2)\n\ndcModel!(system)\nnothing # hide","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"The dcPowerFlow function can be used to establish the DC power flow problem:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"analysis = dcPowerFlow(system)\nnothing # hide","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"tip: Tip\nHere, the user triggers LU factorization as the default method for solving the DC power flow problem. However, the user also has the option to select alternative factorization methods such as LDLt or QR, for instance:analysis = dcPowerFlow(system, LDLt)","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"To obtain the bus voltage angles, we can call the solve! function as follows:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"solve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"Once the solution is obtained, the bus voltage angles can be accessed using:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"print(system.bus.label, analysis.voltage.angle)\nnothing # hide","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"note: Info\nFor implementation insights, we suggest referring to the tutorial on DC Power Flow Analysis.","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"manual/dcPowerFlow/#Print-Results-in-the-REPL","page":"DC Power Flow","title":"Print Results in the REPL","text":"","category":"section"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"Users have the option to print the results in the REPL using any units that have been configured, such as:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"@voltage(pu, deg, V)\nprintBusData(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"Next, users can easily customize the print results for specific buses, for example:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"printBusData(system, analysis; label = \"Bus 1\", header = true)\nprintBusData(system, analysis; label = \"Bus 2\")\nprintBusData(system, analysis; label = \"Bus 3\", footer = true)","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"manual/dcPowerFlow/#Save-Results-to-a-File","page":"DC Power Flow","title":"Save Results to a File","text":"","category":"section"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"Users can also redirect print output to a file. For example, data can be saved in a text file as follows:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"open(\"bus.txt\", \"w\") do file\n printBusData(system, analysis, file)\nend","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"manual/dcPowerFlow/#Save-Results-to-a-CSV-File","page":"DC Power Flow","title":"Save Results to a CSV File","text":"","category":"section"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"For CSV output, users should first generate a simple table with style = false, and then save it to a CSV file:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"using CSV\n\nio = IOBuffer()\nprintBusData(system, analysis, io; style = false)\nCSV.write(\"bus.csv\", CSV.File(take!(io); delim = \"|\"))","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"manual/dcPowerFlow/#DCPowerSystemAlterationManual","page":"DC Power Flow","title":"Power System Update","text":"","category":"section"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"After establishing the PowerSystem type using the powerSystem function and configuring the DC model with dcModel!, users gain the capability to incorporate new branches and generators. Furthermore, they can adjust buses, branches, and generators.","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"Once updates are completed, users can progress towards generating the DCPowerFlow type using the dcPowerFlow function. Ultimately, resolving the DC power flow is achieved through the utilization of the solve! function:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem() # <- Initialize the PowerSystem instance\n\naddBus!(system; label = \"Bus 1\", type = 3)\naddBus!(system; label = \"Bus 2\", type = 2, active = 2.1)\n\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 3.2)\n\ndcModel!(system)\nanalysis = dcPowerFlow(system) # <- Build DCPowerFlow for the defined power system\nsolve!(system, analysis)\n\nupdateBus!(system; label = \"Bus 2\", active = 0.4)\n\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 2\", reactance = 1)\nupdateBranch!(system; label = \"Branch 1\", status = 0)\n\naddGenerator!(system; label = \"Generator 2\", bus = \"Bus 2\", active = 1.5)\nupdateGenerator!(system; label = \"Generator 1\", active = 1.9)\n\nanalysis = dcPowerFlow(system) # <- Build DCPowerFlow for the updated power system\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"note: Info\nThis concept removes the need to restart and recreate the PowerSystem within the dc field from the beginning when implementing changes to the existing power system.","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"manual/dcPowerFlow/#DCPowerFlowUpdateManual","page":"DC Power Flow","title":"Power Flow Update","text":"","category":"section"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"An advanced methodology involves users establishing the DCPowerFlow type using dcPowerFlow just once. After this initial setup, users can integrate new branches and generators, and also have the capability to modify buses, branches, and generators, all without the need to recreate the DCPowerFlow type.","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"This advancement extends beyond the previous scenario where recreating the PowerSystem and DC model was unnecessary, to now include the scenario where DCPowerFlow also does not need to be recreated. Such efficiency can be particularly advantageous in cases where JuliaGrid can reuse nodal matrix factorization.","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"By modifying the previous example, we observe that we now create the DCPowerFlow type only once:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem() # <- Initialize the PowerSystem instance\n\naddBus!(system; label = \"Bus 1\", type = 3)\naddBus!(system; label = \"Bus 2\", type = 2, active = 2.1)\n\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 3.2)\n\ndcModel!(system)\nanalysis = dcPowerFlow(system) # <- Build DCPowerFlow for the defined power system\nsolve!(system, analysis)\n\nupdateBus!(system, analysis; label = \"Bus 2\", active = 0.4)\n\naddBranch!(system, analysis; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 2\", reactance = 1)\nupdateBranch!(system, analysis; label = \"Branch 1\", status = 0)\n\naddGenerator!(system, analysis; label = \"Generator 2\", bus = \"Bus 2\", active = 1.5)\nupdateGenerator!(system, analysis; label = \"Generator 1\", active = 1.9)\n\n# <- No need for re-build; we have already updated the existing DCPowerFlow instance\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"note: Info\nThis concept removes the need to restart and recreate both the PowerSystem within the dc field and the DCPowerFlow from the beginning when implementing changes to the existing power system. Additionally, JuliaGrid can reuse symbolic factorizations of LU or LDLt, as long as the nonzero pattern of the nodal matrix remains consistent between power system configurations.","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"manual/dcPowerFlow/#Reusing-Matrix-Factorization","page":"DC Power Flow","title":"Reusing Matrix Factorization","text":"","category":"section"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"Drawing from the preceding example, our focus now shifts to finding a solution involving modifications that entail adjusting the active power demand at Bus 2, introducing a new generator at Bus 2, and fine-tuning the output power of Generator 1. It is important to note that these adjustments do not impact the branches, leaving the nodal matrix unchanged. To resolve this updated system, users can simply execute the solve! function:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"\nupdateBus!(system, analysis; label = \"Bus 2\", active = 0.2)\naddGenerator!(system, analysis; label = \"Generator 3\", bus = \"Bus 2\", active = 0.3)\nupdateGenerator!(system, analysis; label = \"Generator 1\", active = 2.1)\n\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"note: Info\nIn this scenario, JuliaGrid will recognize instances where the user has not modified branch parameters affecting the nodal matrix. Consequently, JuliaGrid will leverage the previously performed nodal matrix factorization, resulting in a significantly faster solution compared to recomputing the factorization.","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"manual/dcPowerFlow/#Limitations","page":"DC Power Flow","title":"Limitations","text":"","category":"section"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"The dcPowerFlow function oversees bus type validations, as detailed in the Bus Type Modification section. Consequently, if a user intends to change the slack bus or leaves an existing slack bus without a generator, proceeding directly to the solve! function is not feasible.","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"In these instances, JuliaGrid will raise an error:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"updateGenerator!(system, analysis; label = \"Generator 1\", status = 0)","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"Now, the user must execute the dcPowerFlow function instead of attempting to reuse the DCPowerFlow type:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"updateGenerator!(system; label = \"Generator 1\", status = 0)\n\nanalysis = dcPowerFlow(system)\nsolve!(system, analysis)","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"note: Info\nAfter creating the PowerSystem and DCPowerFlow types, users can add or modify buses, branches, and generators before directly using the solve! function. JuliaGrid automatically executes the necessary functions when adjustments lead to a valid solution. However, if modifications are incompatible, like changing the slack bus, JuliaGrid raises an error to prevent misleading outcomes, ensuring accuracy.","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"manual/dcPowerFlow/#DCPowerAnalysisManual","page":"DC Power Flow","title":"Power Analysis","text":"","category":"section"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"After obtaining the solution, we can calculate powers related to buses, branches, and generators using the power! function. For example, let us consider the power system for which we obtained the DC power flow solution:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\n\naddBus!(system; label = \"Bus 1\", type = 3)\naddBus!(system; label = \"Bus 2\", type = 1, active = 0.1)\naddBus!(system; label = \"Bus 3\", type = 1, active = 0.05)\n\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.05)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 3\", reactance = 0.01)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.01)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 3.2)\n\nanalysis = dcPowerFlow(system)\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"Now we can calculate the active powers using the following function:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"power!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"Next, let us convert the base power unit to megavolt-amperes (MVA):","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"@base(system, MVA, V)\nnothing # hide","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"Finally, here are the calculated active power values in megawatts (MW) corresponding to buses and branches:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"print(system.bus.label, system.base.power.value * analysis.power.injection.active)\nprint(system.branch.label, system.base.power.value * analysis.power.from.active)","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"note: Info\nTo better understand the powers associated with buses, branches, and generators that are calculated by the power! function, we suggest referring to the tutorials on DC Power Flow Analysis.","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"manual/dcPowerFlow/#Print-Results-in-the-REPL-2","page":"DC Power Flow","title":"Print Results in the REPL","text":"","category":"section"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"Users can utilize any of the print functions outlined in the Print Power System Data or Print Power System Summary. For example, users have the option to print the results in the REPL using any units that have been configured:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"@power(MW, pu, pu)\nprintBranchData(system, analysis)\n@default(unit) # hide\nnothing # hide","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"manual/dcPowerFlow/#Active-Power-Injection","page":"DC Power Flow","title":"Active Power Injection","text":"","category":"section"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"To calculate active power injection associated with a specific bus, the function can be used:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"active = injectionPower(system, analysis; label = \"Bus 1\")","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"manual/dcPowerFlow/#Active-Power-Injection-from-Generators","page":"DC Power Flow","title":"Active Power Injection from Generators","text":"","category":"section"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"To calculate active power injection from the generators at a specific bus, the function can be used:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"active = supplyPower(system, analysis; label = \"Bus 1\")","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"manual/dcPowerFlow/#Active-Power-Flow","page":"DC Power Flow","title":"Active Power Flow","text":"","category":"section"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"Similarly, we can compute the active power flow at both the from-bus and to-bus ends of the specific branch by utilizing the provided functions below:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"active = fromPower(system, analysis; label = \"Branch 2\")\nactive = toPower(system, analysis; label = \"Branch 2\")","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"","category":"page"},{"location":"manual/dcPowerFlow/#Generator-Active-Power-Output","page":"DC Power Flow","title":"Generator Active Power Output","text":"","category":"section"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"Finally, we can compute the active power output of a particular generator using the function:","category":"page"},{"location":"manual/dcPowerFlow/","page":"DC Power Flow","title":"DC Power Flow","text":"active = generatorPower(system, analysis; label = \"Generator 1\")\n@voltage(pu, pu, V) # hide\n@power(pu, pu, pu) # hide","category":"page"},{"location":"tutorials/measurementModel/#MeasurementModelTutorials","page":"Measurement Model","title":"Measurement Model","text":"","category":"section"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Let us begin by examining a power system. To do that, we will construct one as shown below:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = 1)\naddBus!(system; label = 2)\naddBus!(system; label = 3)\n\n@branch(reactance = 0.03)\naddBranch!(system; label = 1, from = 1, to = 2)\naddBranch!(system; label = 2, from = 1, to = 3)\naddBranch!(system; label = 3, from = 2, to = 3)\nnothing # hide","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"To review, we can conceptualize the bus/branch model as the graph denoted by mathcalG = (mathcalN mathcalE), where we have the set of buses mathcalN = 1 dots n, and the set of branches mathcalE subseteq mathcalN times mathcalN within the power system:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"𝒩 = collect(keys(system.bus.label))\nℰ = [𝒩[system.branch.layout.from] 𝒩[system.branch.layout.to]]","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Our goal is to monitor the power system, and this process involves collecting measurement data for various electrical quantities distributed throughout the power system.","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"tutorials/measurementModel/#Power-System-Monitoring","page":"Measurement Model","title":"Power System Monitoring","text":"","category":"section"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Measurement data is obtained through two main technologies: SCADA (Supervisory Control and Data Acquisition) and WAMS (Wide Area Measurement System). These technologies enable the collection of a wide range of measurements distributed throughout the power system. This extensive dataset allows us to employ state estimation algorithms to obtain the present state of the power system, in contrast to power flow algorithms, which are typically used for offline analyses. To commence, we will represent the entire set of measurement devices as mathcalM.","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"SCADA provides legacy measurements with low sampling rates, making them unsuitable for capturing real-time system dynamics. It provides a snapshot of the power system's state, with delays measured in seconds and minutes. These legacy measurement devices, subsets of the set mathcalM, include:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"a set of voltmeters mathcalV for measuring bus voltage magnitudes,\na set of ammeters mathcalI for measuring branch current magnitudes,\na set of wattmeters mathcalP for active power injection and flow measurements,\na set of varmeters mathcalQ for reactive power injection and flow measurements.","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In contrast, WAMS technology utilizes PMUs (Phasor Measurement Units) to provide data with high sampling rates, typically ranging between 10 and 20 ms, facilitating real-time monitoring of the system. Therefore, PMUs expand the set mathcalM as follows:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"a set of PMUs barmathcalP for bus voltage and branch current phasor measurements.","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"ukw: Notation\nIn this section, when referring to a vector mathbfa, we use the notation mathbfa = a_i, where a_i represents the element associated measurement i in mathcalM.","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"tutorials/measurementModel/#Measurement-Model","page":"Measurement Model","title":"Measurement Model","text":"","category":"section"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"The measurement model, as defined by the set mathcalM, can be expressed as a system of equations [12]:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":" mathbfz=mathbfh(mathbf x) + mathbfu","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"where mathbf x=x_1dotsx_n^T is the vector of state variables, mathbfh(mathbfx)= h_1(mathbfx), dots, h_k(mathbfx)^T is the vector of measurement functions, mathbfz = z_1dotsz_k^mathrmT is the vector of measurement values, and mathbfu = u_1dotsu_k^mathrmT is the vector of measurement errors. In the context of transmission grids, this model is often an overdetermined system of equations (ks) [13, Sec. 2.1].","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"These errors are assumed to follow a Gaussian distribution with a zero-mean and covariance matrix bm Sigma. The diagonal elements of bm Sigma correspond to the measurement variances mathbfv = v_1dotsv_k^T, while the off-diagonal elements represent the covariances between the measurement errors mathbfw = w_1dotsw_k^T. These covariances exist only if PMUs are observed in rectangular coordinates and correlation is required.","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"tutorials/measurementModel/#Gaussian-Probability-Density-Function","page":"Measurement Model","title":"Gaussian Probability Density Function","text":"","category":"section"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Each legacy measurement and each magnitude or angle measurement from PMUs is associated with a measured value z_i, a measurement error u_i, and a measurement function h_i(mathbfx). Assuming that measurement errors u_i follow a zero mean Gaussian distribution, the probability density function associated with the i-th measurement is proportional to:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":" mathcalN(z_imathbfxv_i) propto expBiggcfracz_i-h_i(mathbfx)^22v_iBigg","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"where v_i is the measurement variance defined by the measurement error u_i, and the measurement function h_i(mathbfx) connects the vector of state variables mathbfx to the value of the i-th measurement.","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"tutorials/measurementModel/#Artificial-Generation-of-Measurement-Values","page":"Measurement Model","title":"Artificial Generation of Measurement Values","text":"","category":"section"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"When defining the system of equations, it is essential to have measurement values represented by mathbfz. In JuliaGrid, users have the option to either directly specify measurement values or artificially generate the vector mathbfz. The artificial generation process involves setting the keyword noise = true, which introduces white Gaussian noise with variances v_1 dots v_k added to the provided values e_1 dots e_k, typically representing the exact values of the respective electrical quantities:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":" epsilon_i sim mathcalN(0v_i) 5pt\n z_i = e_i + epsilon_i","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"tutorials/measurementModel/#Voltmeters","page":"Measurement Model","title":"Voltmeters","text":"","category":"section"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"A voltmeter V_i in mathcalV measures the bus voltage magnitude at bus i in mathcalN. Let us introduce two voltmeters that measure voltage magnitudes at the first and third bus. For the first voltmeter, we directly pass the measurement value, while for the second voltmeter, we generate the measurement value artificially:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addVoltmeter!(system, device; label = \"V₁\", bus = 1, magnitude = 1.1, variance = 1e-3)\naddVoltmeter!(system, device; label = \"V₃\", bus = 3, magnitude = 1.0, noise = true)\nnothing # hide","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Consequently, we establish the set of voltmeters mathcalV subset mathcalM:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"𝒱 = collect(keys(device.voltmeter.label))","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"This set of voltmeters defines vectors of measurement values denoted as mathbfz_mathcalV = z_i and variances denoted as mathbfv_mathcalV = v_i, where i in mathcalV, and can be accessed through the following variables:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"𝐳ᵥ = device.voltmeter.magnitude.mean\n𝐯ᵥ = device.voltmeter.magnitude.variance","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"tutorials/measurementModel/#Ammeters","page":"Measurement Model","title":"Ammeters","text":"","category":"section"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"An ammeter I_ij in mathcalI measures the magnitude of branch current at the from-bus end of the branch (ij) in mathcalE. Let us add this type of ammeter at the first branch between buses 1 and 2:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addAmmeter!(system, device; label = \"I₁₂\", from = 1, magnitude = 0.3, variance = 1e-3)\nnothing # hide","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Additionally, an ammeter can measure the branch current magnitude at the to-bus end of the branch (ij) in mathcalE, denoted as I_ji in mathcalI. For example, we can include this type of ammeter at the same branch:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addAmmeter!(system, device; label = \"I₂₁\", to = 1, magnitude = 0.2, variance = 1e-3)\nnothing # hide","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Consequently, we establish the set of ammeters mathcalI subset mathcalM:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"ℐ = collect(keys(device.ammeter.label))","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"This set of ammeters defines vectors of measurement values denoted as mathbfz_mathcalI = z_i and variances denoted as mathbfv_mathcalI = v_i, where i in mathcalI, and can be accessed through the following variables:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"𝐳ₒ = device.ammeter.magnitude.mean\n𝐯ₒ = device.ammeter.magnitude.variance","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"tutorials/measurementModel/#Wattmeters","page":"Measurement Model","title":"Wattmeters","text":"","category":"section"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"A wattmeter P_i in mathcalP measures the active power injection at bus i in mathcalN. Hence, let us add it to the second bus:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addWattmeter!(system, device; label = \"P₂\", bus = 2, active = 0.1, variance = 1e-4)\nnothing # hide","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Next, a wattmeter denoted as P_ij in mathcalP measures the active power flow at the from-bus end of the branch (ij) in mathcalE. Let us add this type of wattmeter at the second branch:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addWattmeter!(system, device; label = \"P₁₃\", from = 2, active = 0.2, variance = 1e-3)\nnothing # hide","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Moreover, a wattmeter can also measure the active power flow at the to-bus end of the branch (ij) in mathcalE, denoted as P_ji in mathcalP. For example, we can include this type of wattmeter at the same branch:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addWattmeter!(system, device; label = \"P₃₁\", to = 2, active = 0.3, variance = 1e-3)\nnothing # hide","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Consequently, we establish the set of wattmeters mathcalP subset mathcalM:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"𝒫 = collect(keys(device.wattmeter.label))","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"This set of wattmeters defines vectors of measurement values denoted as mathbfz_mathcalP = z_i and variances denoted as mathbfv_mathcalP = v_i, where i in mathcalP, and can be accessed through the following variables:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"𝐳ₚ = device.wattmeter.active.mean\n𝐯ₚ = device.wattmeter.active.variance","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"tutorials/measurementModel/#Varmeters","page":"Measurement Model","title":"Varmeters","text":"","category":"section"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"A varmeter Q_i in mathcalQ measures the reactive power injection at bus i in mathcalN. Hence, let us add it to the first bus:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addVarmeter!(system, device; label = \"Q₁\", bus = 1, reactive = 0.01, variance = 1e-2)\nnothing # hide","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Next, a varmeter denoted as Q_ij in mathcalQ measures the reactive power flow at the from-bus end of the branch (ij) in mathcalE. Let us add this type of varmeter at the first branch:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addVarmeter!(system, device; label = \"Q₁₂\", from = 1, reactive = 0.02, variance = 1e-3)\nnothing # hide","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Moreover, a varmeter can also measure the reactive power flow at the to-bus end of the branch (ij) in mathcalE, denoted as Q_ji in mathcalQ. For example, we can include this type of varmeter at the same branch:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addVarmeter!(system, device; label = \"Q₂₁\", to = 1, reactive = 0.03, noise = true)\nnothing # hide","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Consequently, we establish the set of varmeters mathcalQ subset mathcalM:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"𝒬 = collect(keys(device.varmeter.label))","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"This set of varmeters defines vectors of measurement values denoted as mathbfz_mathcalQ = z_i and variances denoted as mathbfv_mathcalQ = v_i, where i in mathcalQ, and can be accessed through the following variables:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"𝐳ₒ = device.varmeter.reactive.mean\n𝐯ₒ = device.varmeter.reactive.variance","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"tutorials/measurementModel/#PMUs","page":"Measurement Model","title":"PMUs","text":"","category":"section"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"PMUs measure voltage and current phasors in the polar coordinate system, thus each PMU output is represented by magnitude and angle along with corresponding variances [14, Sec. 5.6]. When installed on buses, they measure bus voltage phasors, while on branches, they measure current phasors.","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"A PMU (V_i theta_i) in barmathcalP measures the voltage phasor at bus i in mathcalN. Let us integrate this type of PMU at the first bus:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addPmu!(system, device; label = \"V₁, θ₁\", bus = 1, magnitude = 1, angle = 0, noise = true)\nnothing # hide","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Next, a PMU (I_ij psi_ij) in barmathcalP measures the branch current magnitude at the from-bus end of the branch (ij) in mathcalE. Let us add this type of PMU at the first branch:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addPmu!(system, device; label = \"I₁₂, ψ₁₂\", from = 1, magnitude = 0.2, angle = -0.1)\nnothing # hide","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Moreover, a PMU can measure the branch current magnitude at the to-bus end of the branch (ij) in mathcalE, denoted as (I_ji psi_ji) in barmathcalP. For example, let us include this type of PMU at the same branch:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addPmu!(system, device; label = \"I₂₁, ψ₂₁\", to = 1, magnitude = 0.3, angle = -0.2)\nnothing # hide","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Consequently, we establish the set of PMUs barmathcalP subset mathcalM:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"𝒫̄ = collect(keys(device.pmu.label))","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"This set of PMUs establishes vectors representing measurement magnitudes and angles mathbfz_barmathcalP = z_i z_j, along with their corresponding variances mathbfv_barmathcalP = v_i v_j, where (i j) in barmathcalP. These values can be accessed as:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"pmu = device.pmu;\n\n𝐳ₚ = collect(Iterators.flatten(zip(pmu.magnitude.mean, pmu.angle.mean)))\n𝐯ₚ = collect(Iterators.flatten(zip(pmu.magnitude.variance, pmu.angle.variance)))","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"note: Info\nPMUs can be handled in state estimation algorithms according to our definition in polar coordinate systems. However, they can also be processed in rectangular coordinates, where we observe the real and imaginary parts of the phasor measurements rather than magnitude and angle. Further details can be found in tutorials that describe specific state estimation analyses.","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"tutorials/measurementModel/#State-Estimation","page":"Measurement Model","title":"State Estimation","text":"","category":"section"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"After establishing the measurement model, which includes specifying measurement values, variances, the locations of measurement devices, and known power system network parameters, the subsequent step involves the process of state estimation. State estimation is a component of energy management systems and typically encompasses network topology processing, observability analysis, state estimation algorithms, and bad data analysis.","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"The primary goal of state estimation algorithms is to determine state variables, often associated with bus voltages. Therefore, by representing the vector of state variables as mathbfx and the vector of noisy measurement values as mathbfz, we can effectively describe the state estimation problem using the following conditional probability equation:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":" \t\tp(mathbfxmathbfz)= cfracp(mathbfzmathbfx)p(mathbfx)p(mathbfz)","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"If we assume that the prior probability distribution p(mathbfx) is uniform and that p(mathbfz) does not depend on mathbfx, the maximum a posteriori solution simplifies to the maximum likelihood solution, as shown below [15]:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"\thatmathbfx = mathrmargmax_mathbfxp(mathbfxmathbfz) =\n\tmathrmargmax_mathbfxp(mathbfzmathbfx) = mathrmargmax_mathbfxmathcalL(mathbfzmathbfx)","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"We can find this solution by maximizing the likelihood function mathcalL(mathbfzmathbfx), which is defined based on the likelihoods of k independent measurements:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"\thatmathbf x = mathrmarg max_mathbfxmathcalL(mathbfzmathbfx)=\n\tmathrmarg max_mathbfx prod_i=1^k mathcalN(z_imathbfxv_i)","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"It can be demonstrated that the solution to the maximum a posteriori problem can be obtained by solving the following optimization problem, commonly referred to as the weighted least-squares problem [9, Sec. 9.3]:","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"\thatmathbf x = mathrmargmin_mathbfx sum_i=1^kcfracz_i-h_i(mathbf x)^2v_i","category":"page"},{"location":"tutorials/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"The state estimate, denoted as hatmathbf x, resulting from the solution to the above optimization problem, is known as the weighted least-squares estimator. Both the maximum likelihood and weighted least-squares estimators are equivalent to the maximum a posteriori solution [15, Sec. 8.6].","category":"page"},{"location":"manual/measurementModel/#MeasurementModelManual","page":"Measurement Model","title":"Measurement Model","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"The JuliaGrid supports the type Measurement to preserve measurement data, with the following fields: voltmeter, ammeter, wattmeter, varmeter, and pmu. These fields contain information pertaining to measurements such as bus voltage magnitude, branch current magnitude, active power flow and injection, reactive power flow and injection measurements, and measurements of bus voltage and branch current phasors.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"The type Measurement can be created using a function:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"measurement.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"JuliaGrid supports two modes for populating the Measurement type: using built-in functions or using HDF5 files.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"To work with HDF5 files, JuliaGrid provides the function:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"saveMeasurement.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Once the Measurement type has been established, we can incorporate voltmeters, ammeters, wattmeters, varmeters, and phasor measurement units (PMUs) using the following functions:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"addVoltmeter!,\naddAmmeter!,\naddWattmeter!,\naddVarmeter!,\naddPmu!.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Also, JuliaGrid provides macros @voltmeter, @ambmeter, @wattmeter, @varmeter, and @pmu to define templates that aid in creating measurement devices. These templates help avoid entering the same parameters repeatedly.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"note: Info\nIt is important to note that measurement devices associated with branches can only be incorporated if the branch is in-service. This reflects JuliaGrid's approach to mimic a network topology processor, where logical data analysis configures the energized components of the power system.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Moreover, it is feasible to modify the parameters of measurement devices. When these functions are executed, all relevant fields within the Measurement type will be automatically updated. These functions include:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"updateVoltmeter!,\nupdateAmmeter!,\nupdateWattmeter!,\nupdateVarmeter!,\nupdatePmu!.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"tip: Tip\nThe functions for updating measurement devices serve a dual purpose. While their primary function is to modify the Measurement type, they are also designed to accept various analysis models like AC or DC state estimation models. When feasible, these functions not only modify the Measurement type but also adapt the analysis model, often resulting in improved computational efficiency. Detailed instructions on utilizing this feature can be found in dedicated manuals for specific analyses.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Finally, the user has the capability to randomly alter the measurement set by activating or deactivating devices through the following function:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"status!.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Furthermore, we provide users with the ability to modify each specific measurement set by utilizing the functions:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"statusVoltmeter!,\nstatusAmmeter!,\nstatusWattmeter!,\nstatusVarmeter!,\nstatusPmu!.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#BuildMeasurementModelManual","page":"Measurement Model","title":"Build Model","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"The measurement function generates the Measurement type and requires a string-formatted path to HDF5 files as input. Alternatively, the Measurement can be created without any initial data by initializing it as empty, allowing the user to construct the measurements from scratch.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#HDF5-File","page":"Measurement Model","title":"HDF5 File","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In order to use the HDF5 file as input to create the Measurement type, it is necessary to have saved the data using the saveMeasurement function beforehand. Let us say we saved the measurements as measurements14.h5 in the directory C:\\hdf5. Then, the following code can be used to construct the Measurement type:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"device = measurement(\"C:/hdf5/measurements14.h5\")","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Model-from-Scratch","page":"Measurement Model","title":"Model from Scratch","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"To start building a model from the ground up, the initial step involves constructing a power system, which facilitates the addition of measurement devices to buses or branches. As an illustration:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid # hide\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12)\n\naddVoltmeter!(system, device; bus = \"Bus 1\", magnitude = 1.0, variance = 1e-3)\naddWattmeter!(system, device; from = \"Branch 1\", active = 0.2, variance = 1e-4, noise = true)","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In this context, we have created the voltmeter responsible for measuring the bus voltage magnitude at Bus 1, with associated mean and variance values expressed in per-units:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"[device.voltmeter.magnitude.mean device.voltmeter.magnitude.variance]","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Furthermore, we have established the wattmeter to measure the active power flow at the from-bus end of Branch 1, with corresponding mean and variance values also expressed in per-units:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"[device.wattmeter.active.mean device.wattmeter.active.variance]","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"tip: Tip\nThe measurement values (i.e., means) can be generated by adding white Gaussian noise with specified variance values to perturb the original values. This can be achieved by setting noise = true within the functions used for adding devices.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#SaveMeasurementModelManual","page":"Measurement Model","title":"Save Model","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Once the Measurement type has been created using one of the methods outlined in Build Model, the current data can be stored in the HDF5 file by using saveMeasurement function:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"saveMeasurement(device; path = \"C:/hdf5/measurement.h5\")","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"All electrical quantities saved in the HDF5 file are in per-units and radians.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#AddVoltmeterManual","page":"Measurement Model","title":"Add Voltmeter","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"We have the option to add voltmeters to a loaded measurement type or to one created from scratch. As an example, we can initiate the Measurement type and then incorporate voltmeters by utilizing the addVoltmeter! function:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid # hide\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\")\n\naddVoltmeter!(system, device; bus = \"Bus 1\", magnitude = 0.9, variance = 1e-4)\naddVoltmeter!(system, device; bus = \"Bus 1\", magnitude = 1.0, variance = 1e-3, noise = true)","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In this example, we have established two voltmeters designed to measure the bus voltage magnitude at Bus 1. In the case of the second voltmeter, the measurement value is generated internally by introducing white Gaussian noise with the variance added to the magnitude value. As a result, we obtain the following data:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"[device.voltmeter.magnitude.mean device.voltmeter.magnitude.variance]","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"note: Info\nWe recommend reading the documentation for the addVoltmeter! function, where we have provided a list of the keywords that can be used.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Customizing-Input-Units-for-Keywords","page":"Measurement Model","title":"Customizing Input Units for Keywords","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"By default, the magnitude and variance keywords are expected to be provided in per-units (pu). However, users have the flexibility to specify these values in volts (V) if they prefer. For instance, consider the following example:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid # hide\n\n@voltage(kV, rad, V)\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 135e3)\n\naddVoltmeter!(system, device; bus = \"Bus 1\", magnitude = 121.5, variance = 0.0135)\naddVoltmeter!(system, device; bus = \"Bus 1\", magnitude = 135, variance = 0.135, noise = true)","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In this example, we have chosen to specify magnitude and variance in kilovolts (kV). It is important to note that even though we have used kilovolts as the input units, these keywords will still be stored in the per-units:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"[device.voltmeter.magnitude.mean device.voltmeter.magnitude.variance]","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Print-Data-in-the-REPL","page":"Measurement Model","title":"Print Data in the REPL","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Users have the option to print the voltmeter data in the REPL using any units that have been configured:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"printVoltmeterData(system, device)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#AddAmmeterManual","page":"Measurement Model","title":"Add Ammeter","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Users can introduce ammeters into either an existing measurement type or one that they create from the ground up by making use of the addAmmeter! function, as demonstrated in the following example:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid # hide\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12)\n\naddAmmeter!(system, device; from = \"Branch 1\", magnitude = 0.8, variance = 1e-3)\naddAmmeter!(system, device; to = \"Branch 1\", magnitude = 0.9, variance = 1e-1, noise = true)","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In this scenario, we have established one ammeter to measure the branch current magnitude at the from-bus end of Branch 1, as indicated by the use of the from keyword. Similarly, we have added an ammeter to measure the branch current magnitude at the to-bus end of the branch by utilizing the to keyword.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"For the first ammeter, we assume that the measurement value is already known, defined by the magnitude. In contrast, for the second ammeter, the measurement value is generated by adding white Gaussian noise with the variance to the magnitude value. These actions result in the following outcomes:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"[device.ammeter.magnitude.mean device.ammeter.magnitude.variance]","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"note: Info\nWe recommend reading the documentation for the addAmmeter! function, where we have provided a list of the keywords that can be used.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Customizing-Input-Units-for-Keywords-2","page":"Measurement Model","title":"Customizing Input Units for Keywords","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"By default, the magnitude and variance keywords are expected to be provided in per-unit (pu). However, users have the flexibility to express these values in amperes (A) if they prefer. Take a look at the following example:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid # hide\n@default(unit) # hide\n@current(A, rad)\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 135e3)\naddBus!(system; label = \"Bus 2\", base = 135e3)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12)\n\naddAmmeter!(system, device; from = \"Branch 1\", magnitude = 342.13, variance = 0.428)\naddAmmeter!(system, device; to = \"Branch 1\", magnitude = 385, variance = 42.8, noise = true)","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In this example, we have opted to specify the magnitude and variance in amperes (A). It is worth noting that, despite using amperes as the input units, these keywords will still be stored in the per-unit system:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"[device.ammeter.magnitude.mean device.ammeter.magnitude.variance]","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Print-Data-in-the-REPL-2","page":"Measurement Model","title":"Print Data in the REPL","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Users have the option to print the ammeter data in the REPL using any units that have been configured:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"printAmmeterData(system, device)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#AddWattmeterManual","page":"Measurement Model","title":"Add Wattmeter","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Users can include wattmeters in either an existing measurement type or one that they create from scratch by utilizing the addWattmeter! function, as demonstrated in the following example:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid # hide\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12)\n\naddWattmeter!(system, device; bus = \"Bus 1\", active = 0.6, variance = 1e-3)\naddWattmeter!(system, device; from = \"Branch 1\", active = 0.3, variance = 1e-2)\naddWattmeter!(system, device; to = \"Branch 1\", active = 0.1, variance = 1e-3, noise = true)","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In this scenario, one wattmeter has been added to measure the active power injection at Bus 1, as indicated by the use of the bus keyword. Additionally, two wattmeters have been introduced to measure the active power flow on both sides of Branch 1 using the from and to keywords.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"For the first and second wattmeters, we assume that the measurement values are already known, defined by the active. In contrast, for the third wattmeter, the measurement value is generated by adding white Gaussian noise with the variance to the active value. As a result, the measurement data is as follows:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"[device.wattmeter.active.mean device.wattmeter.active.variance]","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"note: Info\nWe recommend reading the documentation for the addWattmeter! function, where we have provided a list of the keywords that can be used.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Customizing-Input-Units-for-Keywords-3","page":"Measurement Model","title":"Customizing Input Units for Keywords","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"By default, the active and variance keywords are expected to be provided in per-unit (pu) values. However, users have the option to express these values in watts (W) if they prefer, as demonstrated in the following example:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid # hide\n@default(unit) # hide\n@power(MW, pu, pu)\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12)\n\naddWattmeter!(system, device; bus = \"Bus 1\", active = 60, variance = 1e-1)\naddWattmeter!(system, device; from = \"Branch 1\", active = 30, variance = 1)\naddWattmeter!(system, device; to = \"Branch 1\", active = 10, variance = 1e-1, noise = true)","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In this example, we have chosen to specify the active and variance in megawatts (MW), but even though we have used megawatts as the input units, these keywords will still be stored in the per-unit system:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"[device.wattmeter.active.mean device.wattmeter.active.variance]","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Print-Data-in-the-REPL-3","page":"Measurement Model","title":"Print Data in the REPL","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Users have the option to print the wattmeter data in the REPL using any units that have been configured:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"printWattmeterData(system, device)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#AddVarmeterManual","page":"Measurement Model","title":"Add Varmeter","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"To include varmeters, the same approach as described in the Add Wattmeter section can be applied, but here, we make use of the addVarmeter! function, as demonstrated in the following example:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid # hide\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12)\n\naddVarmeter!(system, device; bus = \"Bus 1\", reactive = 0.2, variance = 1e-3)\naddVarmeter!(system, device; from = \"Branch 1\", reactive = 0.1, variance = 1e-2)\naddVarmeter!(system, device; to = \"Branch 1\", reactive = 0.05, variance = 1e-3, noise = true)","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In this context, one varmeter has been added to measure the reactive power injection at Bus 1, as indicated by the use of the bus keyword. Additionally, two varmeters have been introduced to measure the reactive power flow on both sides of Branch 1 using the from and to keywords. As a result, the following outcomes are observed:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"[device.varmeter.reactive.mean device.varmeter.reactive.variance]","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"note: Info\nWe recommend reading the documentation for the addVarmeter! function, where we have provided a list of the keywords that can be used.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Customizing-Input-Units-for-Keywords-4","page":"Measurement Model","title":"Customizing Input Units for Keywords","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Just as we explained for the previous device, users have the flexibility to select units different from per-units. In this case, they can opt for megavolt-ampere reactive (MVAr), as illustrated in the following example:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid # hide\n@default(unit) # hide\n@power(pu, MVAr, pu)\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12)\n\naddVarmeter!(system, device; bus = \"Bus 1\", reactive = 20, variance = 1e-1)\naddVarmeter!(system, device; from = \"Branch 1\", reactive = 10, variance = 1)\naddVarmeter!(system, device; to = \"Branch 1\", reactive = 5, variance = 1e-1, noise = true)","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"JuliaGrid will still store the values in the per-unit system:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"[device.varmeter.reactive.mean device.varmeter.reactive.variance]","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Print-Data-in-the-REPL-4","page":"Measurement Model","title":"Print Data in the REPL","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Users have the option to print the varmeter data in the REPL using any units that have been configured:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"printVarmeterData(system, device)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#AddPMUManual","page":"Measurement Model","title":"Add PMU","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Users have the capability to incorporate PMUs into either an existing measurement type or create one from scratch by utilizing the addPmu! function, as demonstrated in the following example:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid # hide\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12)\n\naddPmu!(system, device; bus = \"Bus 1\", magnitude = 1.1, angle = 0.1, varianceMagnitude = 0.1)\naddPmu!(system, device; from = \"Branch 1\", magnitude = 1.0, angle = -0.2, noise = true)\naddPmu!(system, device; to = \"Branch 1\", magnitude = 0.9, angle = 0.0, varianceAngle = 0.001)","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"note: Info\nWhile the typical understanding of a PMU encompasses a device that measures the bus voltage phasor and all branch current phasors incident to the bus, we have chosen to deconstruct this concept to offer users increased flexibility. As a result, our approach yields PMUs that measure individual phasors, each described with magnitude and angle, along with corresponding variances, all presented in the polar coordinate system.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In this context, one PMU has been added to measure the bus voltage phasor at Bus 1, as indicated by the use of the bus keyword. Additionally, two PMUs have been introduced to measure the branch current phasors on both sides of Branch 1 using the from and to keywords.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"For the first and third PMUs, we assume that the measurement values are already known, defined by the magnitude and angle keywords. However, for the second PMU, we generate the measurement value by adding white Gaussian noise with varianceMagnitude and varianceAngle to the magnitude and angle values, respectively. It is important to note that when we omit specifying variance values, we rely on their default settings, both of which are equal to 1e-5. As a result, we observe the following outcomes:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"[device.pmu.magnitude.mean device.pmu.magnitude.variance]\n[device.pmu.angle.mean device.pmu.angle.variance]","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"note: Info\nWe recommend reading the documentation for the addPmu! function, where we have provided a list of the keywords that can be used.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Coordinate-Systems-and-Correlated-Measurement-Errors","page":"Measurement Model","title":"Coordinate Systems and Correlated Measurement Errors","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"When users add PMUs, the incorporation of these measurements into the state estimation model is always in the rectangular coordinate system. In this scenario, the real and imaginary components of the phasor measurements become correlated, although typically these correlations are disregarded [1]. However, if users want to consider these error correlations, the keyword correlated = true is provided for support.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Further, in the AC state estimation model, users have the flexibility to integrate PMU outputs in the polar coordinate system by specifying polar = true.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"For example, let us add PMUs:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid # hide\n\naddPmu!(system, device; bus = \"Bus 2\", magnitude = 0.9, angle = 0, correlated = true)\naddPmu!(system, device; bus = \"Bus 2\", magnitude = 0.9, angle = 0, polar = true)","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In the case of linear state estimation using PMUs only, both PMUs will be integrated into the rectangular coordinate system because the polar keyword is only related to AC state estimation. The treatment of the first PMU assumes error correlation between the real and imaginary parts. Conversely, the treatment of the second PMU assumes no correlation, as it defaults to correlated = false.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Next, in AC state estimation, the first PMU measurement will be integrated into the rectangular coordinate system where correlation between the real and imaginary parts exists. The second PMU will be integrated in the polar coordinate system.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"tip: Tip\nIt is noteworthy that expressing current phasor measurements in polar coordinates can lead to ill-conditioned problems due to small current magnitudes, whereas using rectangular representation can resolve this issue.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Customizing-Input-Units-for-Keywords-5","page":"Measurement Model","title":"Customizing Input Units for Keywords","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"By default, the magnitude and varianceMagnitude keywords are expected to be provided in per-unit (pu), while the angle and varianceAngle keywords are expected to be provided in radians (rad). However, users have the flexibility to express these values in different units, such as volts (V) and degrees (deg) if the PMU is set to a bus, or amperes (A) and degrees (deg) if the PMU is set to a branch. This flexibility is demonstrated in the following:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid # hide\n@default(unit) # hide\n@voltage(kV, deg, V)\n@current(A, deg)\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", base = 135e3)\naddBus!(system; label = \"Bus 2\", base = 135e3)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12)\n\naddPmu!(system, device; bus = \"Bus 1\", magnitude = 148.5, angle = 5.73, varianceAngle = 0.06)\naddPmu!(system, device; from = \"Branch 1\", magnitude = 167.35, angle = -11.46, noise = true)\naddPmu!(system, device; to = \"Branch 1\", magnitude = 150.61, angle = 0.0)","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In this example, we have opted to specify kilovolts (kV) and degrees (deg) for the PMU located at Bus 1, and amperes (A) and degrees (deg) for the PMUs located at Branch 1. It is important to note that regardless of the units used, the values will still be stored in per-units and radians:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"[device.pmu.magnitude.mean device.pmu.magnitude.variance]\n[device.pmu.angle.mean device.pmu.angle.variance]","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Print-Data-in-the-REPL-5","page":"Measurement Model","title":"Print Data in the REPL","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Users have the option to print the PMU data in the REPL using any units that have been configured:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"printPmuData(system, device)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#AddTemplatesMeasurementManual","page":"Measurement Model","title":"Add Templates","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"The functions addVoltmeter!, addAmmeter!, addWattmeter!, addVarmeter!, and addPmu! are employed to introduce measurement devices. In cases where specific keywords are not explicitly defined, default values are automatically assigned to certain parameters.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Default-Keyword-Values","page":"Measurement Model","title":"Default Keyword Values","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"When utilizing the addVoltmeter! function, the default variance is set to variance = 1e-2 per-unit, and the voltmeter's operational status is automatically assumed to be in-service, as indicated by the setting of status = 1.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Similarly, for the addAmmeter! function, the default variances are established at variance = 1e-2 per-unit, and the operational statuses are configured to status = 1. This means that if a user places an ammeter at either the from-bus or to-bus end of a branch, the default settings are identical. However, as we will explain in the following subsection, users have the flexibility to fine-tune these default values, differentiating between the two locations.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In alignment with ammeters, the addWattmeter! and addVarmeter! functions feature default variances set at variance = 1e-2 per-unit, and statuses are automatically assigned as status = 1, regardless of whether the wattmeter or varmeter is placed at the bus, the from-bus end, or the to-bus end. Users have the ability to customize these default values, making distinctions between the three positions of the measurement devices.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"For the addPmu! function, variances for both magnitude and angle measurements are standardized to varianceMagnitude = 1e-5 and varianceAngle = 1e-5 in per-units. Likewise, operational statuses are uniformly set to statusMagnitude = 1 and statusAngle = 1, regardless of whether the PMU is positioned on the bus, the from-bus end, or the to-bus end. Once more, users retain the option to tailor these default values to their specific needs, allowing for distinctions between these three locations of the measurement devices. Additionally, the coordinate system utilized for AC state estimation is consistently configured with polar = false, while correlation in the rectangular system is disabled with correlated = false.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Across all measurement devices, the method for generating measurement means is established as noise = false.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#ChangeKeywordsMeasurementManual","page":"Measurement Model","title":"Change Default Keyword Values","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In JuliaGrid, users have the flexibility to customize default values and assign personalized settings using the @voltmeter, @ammeter, @wattmeter, @varmeter, and @pmu macros. These macros create voltmeter, ammeter, wattmeter, varmeter, and pmu templates that are employed each time functions for adding measurement devices are called. Here is an example of creating these templates with tailored default values:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid # hide\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12)\n\n@voltmeter(variance = 1e-4, noise = true)\naddVoltmeter!(system, device; label = \"Voltmeter 1\", bus = \"Bus 1\", magnitude = 1.0)\n\n@ammeter(varianceFrom = 1e-3, varianceTo = 1e-4, statusTo = 0)\naddAmmeter!(system, device; label = \"Ammeter 1\", from = \"Branch 1\", magnitude = 1.1)\naddAmmeter!(system, device; label = \"Ammeter 2\", to = \"Branch 1\", magnitude = 0.9)\n\n@wattmeter(varianceBus = 1e-3, statusFrom = 0, noise = true)\naddWattmeter!(system, device; label = \"Wattmeter 1\", bus = \"Bus 1\", active = 0.6)\naddWattmeter!(system, device; label = \"Wattmeter 2\", from = \"Branch 1\", active = 0.3)\naddWattmeter!(system, device; label = \"Wattmeter 3\", to = \"Branch 1\", active = 0.1)\n\n@varmeter(varianceFrom = 1e-3, varianceTo = 1e-3, statusBus = 0)\naddVarmeter!(system, device; label = \"Varmeter 1\", bus = \"Bus 1\", reactive = 0.2)\naddVarmeter!(system, device; label = \"Varmeter 2\", from = \"Branch 1\", reactive = 0.1)\naddVarmeter!(system, device; label = \"Varmeter 3\", to = \"Branch 1\", reactive = 0.05)\n\n@pmu(varianceMagnitudeBus = 1e-4, statusAngleBus = 0, varianceAngleFrom = 1e-3)\naddPmu!(system, device; label = \"PMU 1\", bus = \"Bus 1\", magnitude = 1.1, angle = -0.1)\naddPmu!(system, device; label = \"PMU 2\", from = \"Branch 1\", magnitude = 1.0, angle = -0.2)\naddPmu!(system, device; label = \"PMU 3\", to = \"Branch 1\", magnitude = 0.9, angle = 0.0)","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"For instance, when adding a wattmeter to the bus, the varianceBus = 1e-3 will be applied, or if it is added to the from-bus end of the branch, these wattmeters will be set as out-of-service according to statusFrom = 0.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Similarly, when adding a PMU to the bus, the variance of the bus voltage magnitude will be defined in accordance with varianceMagnitudeBus = 1e-4, while the bus voltage angle measurements will be configured as out-of-service based on the statusAngleBus = 0.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"It is important to note that changing input units will also impact the templates accordingly.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Multiple-Templates","page":"Measurement Model","title":"Multiple Templates","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In the case of calling the macros multiple times, the provided keywords and values will be combined into a single template for the corresponding measurement device.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Reset-Templates","page":"Measurement Model","title":"Reset Templates","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"To reset the measurement device templates to their default settings, users can utilize the following macros:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"@default(voltmeter)\n@default(ammeter)\n@default(wattmeter)\n@default(varmeter)\n@default(pmu)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Additionally, users can reset all templates using the macro:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"@default(template)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#LabelsMeasurementManual","page":"Measurement Model","title":"Labels","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"JuliaGrid necessitates a unique label for each voltmeter, ammeter, wattmeter, varmeter, or pmu. These labels are stored in order dictionaries, functioning as pairs of strings and integers. The string signifies the distinct label for the particular device, while the integer tracks the internal numbering of measurement devices.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In all the previous examples, with the exception of the last one, we relied on automatic labeling by omitting the label keyword. This allowed JuliaGrid to independently assign unique labels to measurement devices. In such cases, JuliaGrid utilizes a sequential set of increasing integers for labeling the devices. The last example demonstrates the user labeling approach.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"tip: Tip\nString labels improve readability, but in larger models, the overhead from using strings can become substantial. To reduce memory usage, users can configure ordered dictionaries to accept and store integers as labels:@labels(Integers)","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Integer-Based-Labeling","page":"Measurement Model","title":"Integer-Based Labeling","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Let us take a look at the following illustration:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n@labels(Integers)\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = 1)\naddBus!(system; label = 2)\naddBranch!(system; label = 1, from = 1, to = 2, reactance = 0.12)\n\naddVoltmeter!(system, device; label = 1, bus = 1, magnitude = 1.0)\n\naddAmmeter!(system, device; label = 1, from = 1, magnitude = 1.1)\naddAmmeter!(system, device; label = 2, to = 1, magnitude = 0.9)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In this example, we use the macro @labels to specify that labels will be stored as integers. It is essential to run this macro; otherwise, even if integers are used in subsequent functions, they will be stored as strings.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Automated-Labeling-Using-Templates","page":"Measurement Model","title":"Automated Labeling Using Templates","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Furthermore, users can create labels using templates and include the symbol ? to insert an incremental set of integers at any position. In addition, users have the option to use the symbol ! to insert the location of the measurement device into the label. For example:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12)\n\n@voltmeter(label = \"Voltmeter ?\")\naddVoltmeter!(system, device; bus = \"Bus 1\", magnitude = 1.0)\naddVoltmeter!(system, device; bus = \"Bus 2\", magnitude = 0.9)\n\n@ammeter(label = \"!\")\naddAmmeter!(system, device; from = \"Branch 1\", magnitude = 1.1)\naddAmmeter!(system, device; to = \"Branch 1\", magnitude = 0.9)\n\n@wattmeter(label = \"Wattmeter ?: !\")\naddWattmeter!(system, device; bus = \"Bus 1\", active = 0.6)\naddWattmeter!(system, device; from = \"Branch 1\", active = 0.3)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"To illustrate, the voltmeter labels are defined with incremental integers as follows:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"device.voltmeter.label","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Moreover, for ammeter labels, location information is employed:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"device.ammeter.label","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Lastly, for wattmeters, a combination of both approaches is used:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"device.wattmeter.label","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Retrieving-Labels","page":"Measurement Model","title":"Retrieving Labels","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Let us explore how to retrieve stored labels. Consider the following model:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid # hide\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\")\naddBus!(system; label = \"Bus 2\")\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.12)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 2\", to = \"Bus 1\", reactance = 0.14)\n\naddWattmeter!(system, device; label = \"Wattmeter 2\", bus = \"Bus 2\", active = 0.6)\naddWattmeter!(system, device; label = \"Wattmeter 1\", bus = \"Bus 1\", active = 0.2)\naddWattmeter!(system, device; label = \"Wattmeter 4\", from = \"Branch 1\", active = 0.3)\naddWattmeter!(system, device; label = \"Wattmeter 3\", to = \"Branch 1\", active = 0.1)\naddWattmeter!(system, device; label = \"Wattmeter 5\", from = \"Branch 2\", active = 0.1)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"To access the wattmeter labels, we can use the variable:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"device.wattmeter.label","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"If we need to obtain only labels, we can use the following code:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"label = collect(keys(device.wattmeter.label))","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"To isolate the wattmeters positioned either at the buses or at the ends of branches (from-bus or to-bus), users can achieve this using the following code:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"label[device.wattmeter.layout.bus]\nlabel[device.wattmeter.layout.from]\nlabel[device.wattmeter.layout.to]","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Furthermore, when using the addWattmeter! function, the labels for the keywords bus, from, and to are stored internally as numerical values. To retrieve bus labels, we can follow this procedure:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"label = collect(keys(system.bus.label));\nlabel[device.wattmeter.layout.index[device.wattmeter.layout.bus]]","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Similarly, to obtain labels for branches, we can use the following code:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"label = collect(keys(system.branch.label));\n\nlabel[device.wattmeter.layout.index[device.wattmeter.layout.from]]\nlabel[device.wattmeter.layout.index[device.wattmeter.layout.to]]","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"This procedure is applicable to all measurement devices, including voltmeters, ammeters, varmeters, and PMUs.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"tip: Tip\nJuliaGrid offers the capability to print labels alongside various types of data. For instance, users can use the following code to print labels in combination with specific data:print(device.wattmeter.label, device.wattmeter.active.mean)","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Loading-and-Saving-Labels","page":"Measurement Model","title":"Loading and Saving Labels","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"When saving the measurements to an HDF5 file, the label type (strings or integers) will match the type chosen during system setup. Likewise, when loading data from an HDF5 file, the label type will be preserved as saved, regardless of what is set by the @labels macro.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#AddDeviceGroupsManual","page":"Measurement Model","title":"Add Multiple Devices","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Users have the option to add measurement devices with data generated from one of the AC analyses, specifically, using results obtained from either AC power flow or AC optimal power flow. To do this, users simply need to provide the AC type as an argument to one of the functions responsible for adding measurement devices:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.5, magnitude = 0.9, angle = 0.0)\naddBus!(system; label = \"Bus 2\", type = 1, reactive = 0.05, magnitude = 1.1, angle = -0.1)\naddBus!(system; label = \"Bus 3\", type = 1, active = 0.5, magnitude = 1.0, angle = -0.2)\n\n@branch(resistance = 0.03, susceptance = 0.02)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.5)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 3\", reactance = 0.1)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.2)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 0.2)\naddGenerator!(system; label = \"Generator 2\", bus = \"Bus 2\", active = 1.2)\n\nanalysis = newtonRaphson(system)\nfor iteration = 1:100\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\npower!(system, analysis)\ncurrent!(system, analysis)\n\n@voltmeter(label = \"!\", noise = true)\naddVoltmeter!(system, device, analysis; variance = 1e-3)\n\n@ammeter(label = \"!\")\naddAmmeter!(system, device, analysis; varianceFrom = 1e-3, statusTo = 0, noise = true)\n\n@wattmeter(label = \"!\")\naddWattmeter!(system, device, analysis; varianceBus = 1e-3, statusFrom = 0)\n\n@varmeter(label = \"!\")\naddVarmeter!(system, device, analysis; varianceFrom = 1e-3, statusBus = 0)\n\n@pmu(label = \"!\", polar = true)\naddPmu!(system, device, analysis; varianceMagnitudeBus = 1e-3)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In this example, we incorporate voltmeters to all buses and ammeters to all branches on both ends of each branch. We set noise = true once in the template and once directly in the function, which means that measurement values are generated by adding white Gaussian noise with specified variances to perturb the values obtained from the AC power flow analysis.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"For wattmeters, varmeters, and PMUs added to all buses and branches, we rely on the default setting of noise = false to obtain measurement values that match precisely with those obtained from the AC power flow analysis. Additionally, when including PMUs in the AC state estimation model, we opt for the polar coordinate system by setting polar = true.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"note: Info\nIt is important to note that JuliaGrid follows a specific order: it first adds bus measurements, then branch measurements. For branches, it adds measurement located at the from-bus end, and immediately after, measurement at the to-bus end. This process is repeated for all in-service branches.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Users have the option to employ an alternative method for adding groups of measurements, utilizing functions that add measurements individually. This approach may offer a more straightforward process. For example, to add wattmeters similarly to the procedure outlined above, we can employ the following:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Pᵢ = analysis.power.injection.active\nfor (label, idx) in system.bus.label\n addWattmeter!(system, device; bus = label, active = Pᵢ[idx], variance = 1e-3)\nend\n\nPᵢⱼ = analysis.power.from.active\nPⱼᵢ = analysis.power.to.active\nfor (label, idx) in system.branch.label\n addWattmeter!(system, device; from = label, active = Pᵢⱼ[idx], status = 0)\n addWattmeter!(system, device; to = label, active = Pⱼᵢ[idx])\nend\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#UpdateMeasurementDevicesManual","page":"Measurement Model","title":"Update Devices","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"After the addition of measurement devices to the Measurement type, users possess the flexibility to modify all parameters as defined in the function that added these measurement devices.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#UpdateVoltmeterManual","page":"Measurement Model","title":"Update Voltmeter","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Users have the flexibility to modify all parameters as defined within the addVoltmeter! function. For illustration, let us continue with the example from the Add Device Groups section:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"updateVoltmeter!(system, device; label = \"Bus 2\", magnitude = 0.9, noise = false)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In this example, we update the measurement value of the voltmeter located at Bus 2, and this measurement is now generated without the inclusion of white Gaussian noise.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#UpdateAmmeterManual","page":"Measurement Model","title":"Update Ammeter","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Similarly, users have the flexibility to modify all parameters defined within the addAmmeter! function. Using the same example from the Add Device Groups section, for example, we have:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"updateAmmeter!(system, device; label = \"From Branch 2\", magnitude = 1.2, variance = 1e-4)\nupdateAmmeter!(system, device; label = \"To Branch 2\", status = 0)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In this example, we make adjustments to the measurement and variance values of the ammeter located at Branch 2, specifically at the from-bus end. Next, we deactivate the ammeter at the same branch on the to-bus end.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#UpdateWattmeterManual","page":"Measurement Model","title":"Update Wattmeter","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Following the same logic, users can modify all parameters defined within the addWattmeter! function:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"updateWattmeter!(system, device; label = \"Bus 1\", active = 1.2, variance = 1e-4)\nupdateWattmeter!(system, device; label = \"To Branch 1\", variance = 1e-6)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In this case, we modify the measurement and variance values for the wattmeter located at Bus 1. The wattmeter at Branch 1 on the to-bus end retains its measurement value, while only the measurement variance is adjusted.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#UpdateVarmeterManual","page":"Measurement Model","title":"Update Varmeter","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Following the same logic, users can modify all parameters defined within the addVarmeter! function:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"updateVarmeter!(system, device; label = \"Bus 1\", reactive = 1.2)\nupdateVarmeter!(system, device; label = \"Bus 2\", status = 0)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In this instance, we make adjustments to the measurement value of the varmeter located at Bus 1, while utilizing a previously defined variance. Furthermore, we deactivate the varmeter at Bus 2 and designate it as out-of-service.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#UpdatePMUrManual","page":"Measurement Model","title":"Update PMU","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Finally, users can modify all PMU parameters defined within the addPmu! function:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"updatePmu!(system, device; label = \"Bus 1\", magnitude = 1.05, noise = true)\nupdatePmu!(system, device; label = \"From Branch 1\", varianceAngle = 1e-6, polar = false)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In this example, we adjust the magnitude measurement value of the PMU located at Bus 1. Now, this measurement is generated by adding white Gaussian noise with specified variance value to perturb the magnitude value, while keeping the bus angle voltage value unchanged. For the PMU placed at Branch 1 on the from-bus end, we retain the existing measurement values and only adjust the variance of the angle measurement. Additionally, we choose to include this measurement in the rectangular coordinate system for the AC state estimation.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#MeasurementSetManual","page":"Measurement Model","title":"Measurement Set","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Once measurement devices are integrated into the Measurement type, we empower users to create measurement sets in a randomized manner. To be more precise, users can manipulate the status of devices, activating or deactivating them according to specific settings. To illustrate this feature, let us first create a measurement set using the following example:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"using JuliaGrid # hide\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\ndevice = measurement()\n\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.5, magnitude = 0.9, angle = 0.0)\naddBus!(system; label = \"Bus 2\", type = 1, reactive = 0.05, magnitude = 1.1, angle = -0.1)\naddBus!(system; label = \"Bus 3\", type = 1, active = 0.5, magnitude = 1.0, angle = -0.2)\n\n@branch(resistance = 0.03, susceptance = 0.02)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", reactance = 0.5)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 3\", reactance = 0.1)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 3\", reactance = 0.2)\n\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 0.2)\naddGenerator!(system; label = \"Generator 2\", bus = \"Bus 2\", active = 1.2)\n\nanalysis = newtonRaphson(system)\nfor iteration = 1:100\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\npower!(system, analysis)\ncurrent!(system, analysis)\n\naddVoltmeter!(system, device, analysis)\naddAmmeter!(system, device, analysis)\naddPmu!(system, device, analysis)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Activating-Devices","page":"Measurement Model","title":"Activating Devices","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"As a starting point, we create the measurement set where all devices are set to in-service mode based on default settings. In this instance, we generate the measurement set comprising 3 voltmeters, 6 ammeters, and 9 PMUs.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Subsequently, we offer users the ability to manipulate the status of in-service devices using the status! function. For example, within this set, if we wish to have only 12 out of the total 18 devices in-service while the rest are out-of-service, we can accomplish this as follows:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"status!(system, device; inservice = 12)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Upon executing this function, 12 devices will be randomly selected to be in-service, while the remaining 6 will be set to out-of-service.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Furthermore, users can fine-tune the manipulation of specific measurements. Let us say we want to activate only 2 ammeters while deactivating the remaining ammeters:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"statusAmmeter!(system, device; inservice = 2)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"This action will result in 2 ammeters being in-service and 4 being out-of-service.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Users also have the option to further refine these actions by specifying devices at particular locations within the power system. For instance, we can enable 3 PMUs at buses to measure bus voltage phasors while deactivating all PMUs at branches that measure current phasors:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"statusPmu!(system, device; inserviceBus = 3, inserviceFrom = 0, inserviceTo = 0)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"The outcome will be that 3 PMUs are set to in-service at buses for voltage phasor measurements, while all PMUs at branches measuring current phasors will be in out-of-service mode.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Deactivating-Devices","page":"Measurement Model","title":"Deactivating Devices","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Likewise, we empower users to specify the number of devices to be set as out-of-service rather than defining the number of in-service devices. For instance, if the intention is to deactivate just 2 devices from the total measurement set, it can be achieved as follows:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"status!(system, device; outservice = 2)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"In this scenario 2 devices will be randomly deactivated, while the rest will remain in in-service status. Similar to the previous approach, users can apply this to specific devices or employ fine-tuning as needed.","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"","category":"page"},{"location":"manual/measurementModel/#Activating-Devices-Using-Redundancy","page":"Measurement Model","title":"Activating Devices Using Redundancy","text":"","category":"section"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Furthermore, users can take advantage of redundancy, which represents the ratio between measurement devices and state variables. For example, if we wish to have the number of measurement devices be 1.2 times greater than the number of state variables, we can utilize the following command:","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"status!(system, device; redundancy = 1.2)\nnothing # hide","category":"page"},{"location":"manual/measurementModel/","page":"Measurement Model","title":"Measurement Model","text":"Considering that the number of state variables is 5 (excluding the voltage angle related to the slack bus), using a redundancy value of 1.2 will result in 6 devices being set to in-service, while the remainder will be deactivated. As before, users can target specific devices or adjust settings as needed.","category":"page"},{"location":"background/bibliography/#Bibliography","page":"Bibliography","title":"Bibliography","text":"","category":"section"},{"location":"background/bibliography/","page":"Bibliography","title":"Bibliography","text":"A. Gomez-Exposito, A. Abur, P. Rousseaux, A. de la Villa Jaen and C. Gomez-Quiles. On the use of PMUs in power system state estimation. In: 17th power system computation conference (2011).\n\n\n\nG. N. Korres. Observability analysis based on Echelon form of a reduced dimensional Jacobian matrix. IEEE Transactions on Power Systems 26, 2572–2573 (2011).\n\n\n\nM. Zhou, V. A. Centeno, J. S. Thorp and A. G. Phadke. An alternative for including phasor measurements in state estimators. IEEE transactions on power systems 21, 1930–1937 (2006).\n\n\n\nG. Korres and N. Manousakis. State estimation and observability analysis for phasor measurement unit measured systems. IET generation, transmission & distribution 6, 902–913 (2012).\n\n\n\nA. Abur and A. G. Exposito. Power system state estimation: theory and implementation (CRC press, 2004).\n\n\n\nG. Andersson. Power system analysis. EEH-Power Systems Laboratory, ETH Zurich, Lecture Notes, 227–0526 (2012).\n\n\n\nJ. J. Grainger and W. D. Stevenson. Power system analysis (McGraw-Hill, 1994).\n\n\n\nR. D. Zimmerman and C. E. Murillo-Sánchez. Matpower 6.0 users manual. Power Systems Engineering Research Center 9 (2016).\n\n\n\nA. J. Wood, B. F. Wollenberg and G. B. Sheblé. Power generation, operation, and control (John Wiley & Sons, 2013).\n\n\n\nR. A. Van Amerongen. A general-purpose version of the fast decoupled load flow. IEEE Transactions on Power Systems 4, 760–770 (1989).\n\n\n\nD. P. Chassin, P. R. Armstrong, D. G. Chavarrı́a-Miranda and R. T. Guttromson. Gauss-Seidel accelerated: implementing flow solvers on field programmable gate arrays. In: 2006 IEEE Power Engineering Society General Meeting (IEEE, 2006); p. 5–pp.\n\n\n\nF. C. Schweppe and D. B. Rom. Power system static-state estimation, Part II: Approximate model. IEEE Transactions on Power Apparatus and Systems, 125–130 (1970).\n\n\n\nA. Monticelli. State estimation in electric power systems: a generalized approach (Springer Science & Business Media, 2012).\n\n\n\nA. G. Phadke and J. S. Thorp. Synchronized phasor measurements and their applications. Vol. 1 no. 2017 (Springer, 2008).\n\n\n\nD. Barber. Bayesian reasoning and machine learning (Cambridge University Press, 2012).\n\n\n\nI. ISO. and B. OIML. Guide to the Expression of Uncertainty in Measurement (Aenor, 1993).\n\n\n\nY. Weng, Q. Li, R. Negi and M. Ilić. Semidefinite programming for power system state estimation. In: 2012 IEEE Power and Energy Society General Meeting (IEEE, 2012); pp. 1–8.\n\n\n\nP. C. Hansen, V. Pereyra and G. Scherer. Least squares data fitting with applications (JHU Press, 2013).\n\n\n\nG. N. Korres. A distributed multiarea state estimation. IEEE Transactions on Power Systems 26, 73–84 (2010).\n\n\n\nM. Cosovic, M. Delalic, D. Raca and D. Vukobratovic. Observability analysis for large-scale power systems using factor graphs. IEEE Transactions on Power Systems 36, 4791–4799 (2021).\n\n\n\nH. Horisberger. Observability analysis for power systems with measurement deficiencies. IFAC Proceedings Volumes 18, 51–58 (1985).\n\n\n\nN. M. Manousakis and G. N. Korres. Observability analysis for power systems including conventional and phasor measurements. IET Conference Proceedings, 158-158(1) (2010).\n\n\n\nB. Gou. Optimal placement of PMUs by integer linear programming. IEEE Transactions on power systems 23, 1525–1526 (2008).\n\n\n\nB. Xu and A. Abur. Observability analysis and measurement placement for systems with PMUs. In: IEEE PES Power Systems Conference and Exposition, 2004. (IEEE, 2004); pp. 943–946.\n\n\n\n","category":"page"},{"location":"manual/acOptimalPowerFlow/#ACOptimalPowerFlowManual","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuliaGrid utilizes the JuMP package to construct optimal power flow models, allowing users to manipulate these models using the standard functions provided by JuMP. As a result, JuliaGrid supports popular solvers mentioned in the JuMP documentation to solve the optimization problem.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To perform the AC optimal power flow, we first need to have the PowerSystem type that has been created with the AC model. After that, create the ACOptimalPowerFlow type to establish the AC optimal power flow framework using the function:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"acOptimalPowerFlow.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To solve the AC optimal power flow problem and acquire bus voltage magnitudes and angles, and generator active and reactive power outputs, make use of the following function:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"solve!.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"After obtaining the AC optimal power flow solution, JuliaGrid offers post-processing analysis functions to calculate powers and currents associated with buses and branches:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"power!,\ncurrent!.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Additionally, specialized functions are available for calculating specific types of powers or currents for individual buses, branches, or generators.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#ACOptimalPowerFlowModelManual","page":"AC Optimal Power Flow","title":"Optimal Power Flow Model","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To set up the AC optimal power flow, we begin by creating the model. To illustrate this, consider the following:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"using JuliaGrid # hide\nusing JuMP, Ipopt\n@default(unit) # hide\n@default(template) # hide\n\nsystem = powerSystem()\n\n@bus(minMagnitude = 0.95, maxMagnitude = 1.05)\naddBus!(system; label = \"Bus 1\", type = 3, active = 0.1, angle = -0.1)\naddBus!(system; label = \"Bus 2\", reactive = 0.01, magnitude = 1.1)\n\n@branch(minDiffAngle = -pi, maxDiffAngle = pi, reactance = 0.5, type = 2)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", maxFromBus = 0.15)\n\n@generator(maxActive = 0.5, minReactive = -0.1, maxReactive = 0.1, status = 0)\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 0.4, reactive = 0.2)\naddGenerator!(system; label = \"Generator 2\", bus = \"Bus 2\", active = 0.2, reactive = 0.1)\n\ncost!(system; label = \"Generator 1\", active = 2, polynomial = [800.0; 200.0; 80.0])\ncost!(system; label = \"Generator 2\", active = 1, piecewise = [10.8 12.3; 14.7 16.8; 18 18.1])\n\ncost!(system; label = \"Generator 1\", reactive = 2, polynomial = [2.0])\ncost!(system; label = \"Generator 2\", reactive = 1, piecewise = [2.0 4.0; 6.0 8.0])\n\nacModel!(system)\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Next, the acOptimalPowerFlow function is utilized to formulate the AC optimal power flow problem:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"analysis = acOptimalPowerFlow(system, Ipopt.Optimizer)\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#ACOptimizationVariablesManual","page":"AC Optimal Power Flow","title":"Optimization Variables","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"In the AC optimal power flow model, the active and reactive power outputs of the generators are expressed as nonlinear functions of the bus voltage magnitudes and angles. As a result, the variables in this model include the active and reactive power outputs of the generators, as well as the bus voltage magnitudes and angles:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuMP.all_variables(analysis.method.jump)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"It is important to note that this is not a comprehensive set of optimization variables. When the cost function is defined as a linear piecewise function comprising multiple segments, as illustrated in the case of the active power output cost for Generator 2, JuliaGrid automatically generates helper optimization variables named actwise and reactwise, and formulates a set of linear constraints to effectively address these cost functions. For the sake of simplicity, we initially assume that Generator 2 is out-of-service. Consequently, the helper variable is not included in the set of optimization variables. However, as we progress through this manual, we will activate the generator, introducing the helper variable and additional constraints to the optimization model.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"It is worth emphasizing that in instances where a linear piecewise cost function consists of only a single segment, as demonstrated by the reactive power output cost of Generator 2, the function is modeled as a standard linear function, obviating the need for additional helper optimization variables.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Please be aware that JuliaGrid maintains references to all variables, which are categorized into six fields:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"fieldnames(typeof(analysis.method.variable))","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Variable-Names","page":"AC Optimal Power Flow","title":"Variable Names","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Users have the option to define custom variable names for printing and writing equations, which can help present them in a more compact form. For example:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"analysis = acOptimalPowerFlow(system, Ipopt.Optimizer; magnitude = \"V\", angle = \"θ\")\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Add-Variables","page":"AC Optimal Power Flow","title":"Add Variables","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The user has the ability to easily add new variables to the defined AC optimal power flow model by using the @variable macro from the JuMP package:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuMP.@variable(analysis.method.jump, newVariable)\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"We can verify that the new variable is included in the defined model by using the function:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuMP.is_valid(analysis.method.jump, newVariable)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Delete-Variables","page":"AC Optimal Power Flow","title":"Delete Variables","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The variable can be deleted, but this operation is only applicable if the objective function is either affine or quadratic. To achieve this, we can utilize the delete function provided by the JuMP, as demonstrated below:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuMP.delete(analysis.method.jump, newVariable)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"After deletion, the variable is no longer part of the model:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuMP.is_valid(analysis.method.jump, newVariable)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#DCConstraintFunctionsManual","page":"AC Optimal Power Flow","title":"Constraint Functions","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuliaGrid keeps track of all the references to internally formed constraints in the constraint field of the ACOptimalPowerFlow type. These constraints are divided into six fields:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"fieldnames(typeof(analysis.method.constraint))","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"note: Info\nWe suggest that readers refer to the tutorial on AC Optimal Power Flow for insights into the implementation.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Slack-Bus-Constraint","page":"AC Optimal Power Flow","title":"Slack Bus Constraint","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The slack field contains a reference to the equality constraint associated with the fixed bus voltage angle value of the slack bus. This constraint is set within the addBus! function using the angle keyword:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(system.bus.label, analysis.method.constraint.slack.angle)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Users have the flexibility to modify this constraint by changing which bus serves as the slack bus and by adjusting the value of the bus angle. This can be achieved using the updateBus! function, for example:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"updateBus!(system, analysis; label = \"Bus 1\", type = 1)\nupdateBus!(system, analysis; label = \"Bus 2\", type = 3, angle = -0.2)\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Subsequently, the updated slack constraint can be inspected as follows:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(system.bus.label, analysis.method.constraint.slack.angle)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Bus-Power-Balance-Constraints","page":"AC Optimal Power Flow","title":"Bus Power Balance Constraints","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The balance field contains references to the equality constraints associated with the active and reactive power balance equations defined for each bus. These constraints ensure that the total active and reactive power injected by the generators matches the total active and reactive power demanded at each bus.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The constant term in the active power balance equations is determined by the active keyword within the addBus! function, which defines the active power demanded at the bus. We can access the references to the active power balance constraints using the following code snippet:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(system.bus.label, analysis.method.constraint.balance.active)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Similarly, the constant term in the reactive power balance equations is determined by the reactive keyword within the addBus! function, which defines the reactive power demanded at the bus. We can access the references to the reactive power balance constraints using the following code snippet:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(system.bus.label, analysis.method.constraint.balance.reactive)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"During the execution of functions that add or update power system components, these constraints are automatically adjusted to reflect the current configuration of the power system, for example:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"updateBus!(system, analysis; label = \"Bus 2\", active = 0.5)\nupdateBranch!(system, analysis; label = \"Branch 1\", reactance = 0.25)\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The updated set of active power balance constraints can be examined as follows:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(system.bus.label, analysis.method.constraint.balance.active)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Bus-Voltage-Constraints","page":"AC Optimal Power Flow","title":"Bus Voltage Constraints","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The voltage field contains references to the inequality constraints associated with the voltage magnitude and voltage angle difference limits. These constraints ensure that the bus voltage magnitudes and the angle differences between the from-bus and to-bus ends of each branch are within specified limits.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The minimum and maximum bus voltage magnitude limits are set using the minMagnitude and maxMagnitude keywords within the addBus! function. The constraints associated with these limits can be accessed using:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(system.bus.label, analysis.method.constraint.voltage.magnitude)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The minimum and maximum voltage angle difference limits between the from-bus and to-bus ends of each branch are set using the minDiffAngle and maxDiffAngle keywords within the addBranch! function. The constraints associated with these limits can be accessed using the following code snippet:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(system.branch.label, analysis.method.constraint.voltage.angle)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"note: Info\nPlease note that if the limit constraints are set to minDiffAngle = -2π and maxDiffAngle = 2π for the corresponding branch, JuliGrid will omit the corresponding inequality constraint.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Additionally, by employing the updateBus! and updateBranch! functions, the user has the ability to modify these specific constraints:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"updateBus!(system, analysis; label = \"Bus 1\", minMagnitude = 1.0, maxMagnitude = 1.0)\nupdateBranch!(system, analysis; label = \"Branch 1\", minDiffAngle = -1.7, maxDiffAngle = 1.7)\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Subsequently, the updated set of constraints can be examined as follows:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(system.bus.label, analysis.method.constraint.voltage.magnitude)\nprint(system.branch.label, analysis.method.constraint.voltage.angle)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#ACBranchFlowConstraintsManual","page":"AC Optimal Power Flow","title":"Branch Flow Constraints","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The flow field contains references to the inequality constraints associated with the apparent power flow, active power flow, or current flow magnitude limits at the from-bus and to-bus ends of each branch. The type to which one of the constraints will be applied is defined according to the type keyword within the addBranch! function:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"type = 1 for the apparent power flow,\ntype = 2 for the active power flow,\ntype = 3 for the current flow magnitude.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"These limits are specified using the minFromBus, maxFromBus, minToBus and maxToBus keywords within the addBranch! function. By default, these limit keywords are associated with apparent power (type = 1).","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"However, in the example, we configured it to use active power flow by setting type = 2. To access the flow constraints of branches at the from-bus end, we can utilize the following code snippet:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(system.branch.label, analysis.method.constraint.flow.from)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"note: Info\nIf the branch flow limits are set to minFromBus = 0.0 and maxFromBus = 0.0 for the corresponding branch, JuliGrid will omit the corresponding inequality constraint at the from-bus end of the branch. The same applies to the to-bus end if minToBus = 0.0 and maxToBus = 0.0 are set.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Additionally, by employing the updateBranch! function, we have the ability to modify these specific constraints:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"updateBranch!(system, analysis; label = \"Branch 1\", minFromBus = -0.15, maxToBus = 0.15)\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The updated set of flow constraints can be examined as follows:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(system.branch.label, analysis.method.constraint.flow.from)\nprint(system.branch.label, analysis.method.constraint.flow.to)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"tip: Tip\nIn typical scenarios, minFromBus is equal to minToBus, and maxFromBus is equal to maxToBus. However, we allow these values to be defined separately for greater flexibility, enabling, among other things, the option to apply constraints on only one side of the branch.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Generator-Power-Capability-Constraints","page":"AC Optimal Power Flow","title":"Generator Power Capability Constraints","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The capability field contains references to the inequality constraints associated with the minimum and maximum active and reactive power outputs of the generators.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The constraints associated with the minimum and maximum active power output limits of the generators are defined using the minActive and maxActive keywords within the addGenerator! function. To access the constraints associated with these limits, we can use the following code snippet:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(system.generator.label, analysis.method.constraint.capability.active)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Similarly, the constraints associated with the minimum and maximum reactive power output limits of the generators are specified using the minReactive and maxReactive keywords within the addGenerator! function. To access these constraints, we can use the following code snippet:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(system.generator.label, analysis.method.constraint.capability.reactive)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"As demonstrated, the active and reactive power outputs of Generator 1 and Generator 2 are currently fixed at zero due to previous actions that set these generators out-of-service. However, we can modify these specific constraints by utilizing the updateGenerator! function, as shown below:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"updateGenerator!(system, analysis; label = \"Generator 1\", status = 1)\nupdateGenerator!(system, analysis; label = \"Generator 2\", status = 1, minActive = 0.1)\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Subsequently, the updated set of constraints can be examined as follows:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(system.generator.label, analysis.method.constraint.capability.active)\nprint(system.generator.label, analysis.method.constraint.capability.reactive)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"note: Info\nThis representation may not fully capture the generator's power output behavior due to the tradeoff between active and reactive power outputs. JuliaGrid can incorporate this tradeoff in its optimization model. For more information, see the tutorial on Power Capability Constraints.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Power-Piecewise-Constraints","page":"AC Optimal Power Flow","title":"Power Piecewise Constraints","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"In the context of cost modeling, the piecewise field acts as a reference to the inequality constraints associated with linear piecewise cost functions. These constraints are established using the cost! function, with active = 1 or reactive = 1 specified when working with linear piecewise cost functions that consist of multiple segments.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"In our example, only the active power cost of Generator 2 is modeled as a linear piecewise function with two segments, and JuliaGrid takes care of setting up the appropriate inequality constraints for each segment:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(system.generator.label, analysis.method.constraint.piecewise.active)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"It is worth noting that these constraints can also be automatically updated using the cost! function. Readers can find more details in the section discussing the objective function.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"As mentioned at the beginning, linear piecewise cost functions with multiple segments will also introduce helper variables that are added to the objective function. In this specific example, the helper variable is:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"analysis.method.variable.actwise[2]","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Add-Constraints","page":"AC Optimal Power Flow","title":"Add Constraints","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Users can effortlessly introduce additional constraints into the defined AC optimal power flow model by utilizing the addBranch! or addGenerator! functions. Specifically, if a user wishes to include a new branch or generator in an already defined PowerSystem and ACOptimalPowerFlow type:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"addBranch!(system, analysis; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 2\", reactance = 1)\naddGenerator!(system, analysis; label = \"Generator 3\", bus = \"Bus 2\", active = 2, status = 1)\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"This will affect all constraints related to branches and generators, but it will also update balance constraints to configure the optimization model to match the current state of the power system. For example, we can observe the following updated constraints:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(system.branch.label, analysis.method.constraint.voltage.angle)\nprint(system.generator.label, analysis.method.constraint.capability.active)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Add-User-Defined-Constraints","page":"AC Optimal Power Flow","title":"Add User-Defined Constraints","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Users also have the option to include their custom constraints within the established AC optimal power flow model by employing the @constraint macro. For example, the addition of a new constraint can be achieved as follows:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuMP.@constraint(analysis.method.jump, 0.0 <= analysis.method.variable.active[3] <= 0.3)\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Delete-Constraints","page":"AC Optimal Power Flow","title":"Delete Constraints","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To delete a constraint, users can make use of the delete function from the JuMP package. When handling constraints that have been internally created, users can refer to the constraint references stored in the constraint field of the ACOptimalPowerFlow type.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"For example, if the intention is to eliminate constraints related to the capability of Generator 3, we can use:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuMP.delete(analysis.method.jump, analysis.method.constraint.capability.active[3])\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"note: Info\nIn the event that a user deletes a constraint and subsequently executes a function that updates bus, branch, or generator parameters, and if the deleted constraint is affected by these functions, JuliaGrid will automatically reinstate that constraint. Users should exercise caution when deleting constraints, as this action is considered potentially harmful since it operates independently of power system data.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#ACObjectiveFunctionManual","page":"AC Optimal Power Flow","title":"Objective Function","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The objective function of the AC optimal power flow is formulated using polynomial and linear piecewise cost functions associated with the generators, defined using the cost! functions.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"In the provided example, the objective function to be minimized in order to obtain optimal values for the active and reactive power outputs of the generators, as well as the bus voltage magnitudes and angles, is as follows:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuMP.objective_function(analysis.method.jump)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuliaGrid also stores the objective function in a separate variable, which can be accessed by referring to the variable analysis.objective. In this variable, the objective function is organized in a way that separates the quadratic and nonlinear components of the objective function.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Update-Objective-Function","page":"AC Optimal Power Flow","title":"Update Objective Function","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"By utilizing the cost! functions, users have the flexibility to modify the objective function by adjusting polynomial or linear piecewise coefficients or by changing the type of polynomial or linear piecewise function employed. For example, consider Generator 1, which employs a quadratic polynomial cost function for active power. We can redefine the cost function for this generator as a cubic polynomial and thereby define a nonlinear objective function:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"cost!(system, analysis; label = \"Generator 1\", active = 2, polynomial = [631; 257; 40; 5.0])\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"This leads to an updated objective function, which can be examined as follows:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuMP.objective_function(analysis.method.jump)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#User-Defined-Objective-Function","page":"AC Optimal Power Flow","title":"User-Defined Objective Function","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Users can modify the objective function using the set_objective_function function from the JuMP package. This operation is considered destructive because it is independent of power system data; however, in certain scenarios, it may be more straightforward than using the cost! function for updates. Moreover, using this methodology, users can combine a defined function with a newly defined expression.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"In this context, we can utilize the saved objective function within the objective field of the ACOptimalPowerFlow type. For example, we can easily eliminate nonlinear parts and alter the quadratic component of the objective:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"expr = 5.0 * analysis.method.variable.active[1] * analysis.method.variable.active[1]\nJuMP.set_objective_function(analysis.method.jump, analysis.method.objective.quadratic - expr)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"We can now observe the updated objective function as follows:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuMP.objective_function(analysis.method.jump)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#ACSetupPrimalStartingValuesManual","page":"AC Optimal Power Flow","title":"Setup Starting Values","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"In JuliaGrid, the assignment of starting primal and dual values for optimization variables and constraints takes place when the solve! function is executed.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Starting-Primal-Values","page":"AC Optimal Power Flow","title":"Starting Primal Values","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Starting primal values are determined based on the generator and voltage fields within the ACOptimalPowerFlow type. By default, these values are initially established using the active and reactive power outputs of the generators and the initial bus voltage magnitudes and angles:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"generator = analysis.power.generator;\nprint(system.generator.label, generator.active, generator.reactive)\nprint(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Users have the flexibility to adjust these values according to their specifications, which will then be used as the starting primal values when executing the solve! function.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Using-AC-Power-Flow","page":"AC Optimal Power Flow","title":"Using AC Power Flow","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"In this perspective, users have the capability to conduct the AC power flow analysis and leverage the resulting solution to configure starting primal values. Here is an illustration of how this can be achieved:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"flow = newtonRaphson(system)\nfor iteration = 1:100\n stopping = mismatch!(system, flow)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, flow)\nend","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"After obtaining the solution, we can calculate the active and reactive power outputs of the generators and utilize the bus voltage magnitudes and angles to set the starting values. In this case, the generator and voltage fields of the ACOptimalPowerFlow type can be employed to store the new starting values:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"for (key, idx) in system.generator.label\n active, reactive = generatorPower(system, flow; label = key)\n analysis.power.generator.active[idx] = active\n analysis.power.generator.reactive[idx] = reactive\nend\n\nfor i = 1:system.bus.number\n analysis.voltage.magnitude[i] = flow.voltage.magnitude[i]\n analysis.voltage.angle[i] = flow.voltage.angle[i]\nend","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Starting-Dual-Values","page":"AC Optimal Power Flow","title":"Starting Dual Values","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Dual variables, often referred to as Lagrange multipliers or Kuhn-Tucker multipliers, represent the shadow prices or marginal costs associated with constraints. The assignment of initial dual values occurs when the solve! function is executed. Initially, the starting dual values are unknown, but users can access and manually set them. For example:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"analysis.method.dual.balance.active[1] = 0.4\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#ACOptimalPowerFlowSolutionManual","page":"AC Optimal Power Flow","title":"Optimal Power Flow Solution","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To establish the AC optimal power flow problem, we can utilize the acOptimalPowerFlow function. After setting up the problem, we can use the solve! function to compute the optimal values for the active and reactive power outputs of the generators and the bus voltage magnitudes angles. Also, to turn off the solver output within the REPL, we use the set_silent function before calling solve! function. Here is an example:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuMP.set_silent(analysis.method.jump)\nsolve!(system, analysis)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuMP.set_silent(analysis.method.jump)\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"By executing this function, we will obtain the solution with the optimal values for the active and reactive power outputs of the generators, as well as the bus voltage magnitudes and angles.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"generator = analysis.power.generator;\nprint(system.generator.label, generator.active, generator.reactive)\nprint(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Objective-Value","page":"AC Optimal Power Flow","title":"Objective Value","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To obtain the objective value of the optimal power flow solution, we can use the objective_value function:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"JuMP.objective_value(analysis.method.jump)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Dual-Variables","page":"AC Optimal Power Flow","title":"Dual Variables","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The values of the dual variables are stored in the dual field of the ACOptimalPowerFlow type. For example:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"analysis.method.dual.balance.active[1]","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Print-Results-in-the-REPL","page":"AC Optimal Power Flow","title":"Print Results in the REPL","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Users can utilize the functions printBusData and printGeneratorData to display results. Additionally, the functions listed in the Print Constraint Data section allow users to print constraint data related to buses, branches, or generators in the desired units. For example:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"@power(MW, MVAr, pu)\nshow = Dict(\"Active Power Balance\" => false)\nprintBusConstraint(system, analysis; show)\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Next, users can easily customize the print results for specific constraint, for example:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"printBusConstraint(system, analysis; label = \"Bus 1\", header = true)\nprintBusConstraint(system, analysis; label = \"Bus 2\", footer = true)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Save-Results-to-a-File","page":"AC Optimal Power Flow","title":"Save Results to a File","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Users can also redirect print output to a file. For example, data can be saved in a text file as follows:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"open(\"bus.txt\", \"w\") do file\n printBusConstraint(system, analysis, file)\nend","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Save-Results-to-a-CSV-File","page":"AC Optimal Power Flow","title":"Save Results to a CSV File","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"For CSV output, users should first generate a simple table with style = false, and then save it to a CSV file:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"using CSV\n\nio = IOBuffer()\nprintBusConstraint(system, analysis, io; style = false)\nCSV.write(\"constraint.csv\", CSV.File(take!(io); delim = \"|\"))","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Primal-and-Dual-Warm-Start","page":"AC Optimal Power Flow","title":"Primal and Dual Warm Start","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Utilizing the ACOptimalPowerFlow type and proceeding directly to the solver offers the advantage of a \"warm start\". In this scenario, the starting primal and dual values for the subsequent solving step correspond to the solution obtained from the previous step.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Primal-Variables","page":"AC Optimal Power Flow","title":"Primal Variables","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"In the previous example, the following solution was obtained, representing the values of the primal variables:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(system.generator.label, generator.active, generator.reactive)\nprint(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Dual-Variables-2","page":"AC Optimal Power Flow","title":"Dual Variables","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"We also obtained all dual values. Here, we list only the dual variables for one type of constraint as an example:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(system.generator.label, analysis.method.dual.capability.reactive)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Modify-Optimal-Power-Flow","page":"AC Optimal Power Flow","title":"Modify Optimal Power Flow","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Now, let us introduce changes to the power system from the previous example:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"updateGenerator!(system, analysis; label = \"Generator 2\", maxActive = 0.08)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Next, we want to solve this modified optimal power flow problem. If we use solve! at this point, the primal and dual starting values will be set to the previously obtained values:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"solve!(system, analysis)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"As a result, we obtain a new solution:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(system.generator.label, generator.active, generator.reactive)\nprint(system.bus.label, analysis.voltage.magnitude, analysis.voltage.angle)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Reset-Primal-and-Dual-Values","page":"AC Optimal Power Flow","title":"Reset Primal and Dual Values","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Users retain the flexibility to reset initial primal values to their default configurations at any juncture. This can be accomplished by utilizing the active and reactive power outputs of the generators and the initial bus voltage magnitudes and angles extracted from the PowerSystem type, employing the startingPrimal! function:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"startingPrimal!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The primal starting values will now be identical to those that would be obtained if the acOptimalPowerFlow function were executed after all the updates have been applied.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Using the startingDual! function, users can clear all dual variable values, resetting them to their default state:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"startingDual!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#ACOptimalPowerCurrentAnalysisManual","page":"AC Optimal Power Flow","title":"Power and Current Analysis","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"After obtaining the solution from the AC optimal power flow, we can calculate various electrical quantities related to buses and branches using the power! and current! functions. For instance, let us consider the power system for which we obtained the AC optimal power flow solution:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"using JuliaGrid, JuMP # hide\nusing Ipopt\n\n@default(unit) # hide\n@default(template) # hide\nsystem = powerSystem()\n\n@bus(minMagnitude = 0.9, maxMagnitude = 1.1)\naddBus!(system; label = \"Bus 1\", type = 3, magnitude = 1.05, angle = 0.17)\naddBus!(system; label = \"Bus 2\", active = 0.1, reactive = 0.01, conductance = 0.04)\naddBus!(system; label = \"Bus 3\", active = 0.05, reactive = 0.02)\n\n@branch(resistance = 0.5, reactance = 1.0, conductance = 1e-4, susceptance = 0.01)\naddBranch!(system; label = \"Branch 1\", from = \"Bus 1\", to = \"Bus 2\", maxFromBus = 0.15)\naddBranch!(system; label = \"Branch 2\", from = \"Bus 1\", to = \"Bus 3\", maxFromBus = 0.10)\naddBranch!(system; label = \"Branch 3\", from = \"Bus 2\", to = \"Bus 3\", maxFromBus = 0.25)\n\n@generator(maxActive = 0.5, minReactive = -0.1, maxReactive = 0.1)\naddGenerator!(system; label = \"Generator 1\", bus = \"Bus 1\", active = 3.2, reactive = 0.5)\naddGenerator!(system; label = \"Generator 2\", bus = \"Bus 2\", active = 0.2, reactive = 0.1)\n\ncost!(system; label = \"Generator 1\", active = 2, polynomial = [1100.2; 500; 80])\ncost!(system; label = \"Generator 2\", active = 1, piecewise = [10.8 12.3; 14.7 16.8; 18 18.1])\n\nanalysis = acOptimalPowerFlow(system, Ipopt.Optimizer)\nJuMP.set_silent(analysis.method.jump) # hide\nsolve!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"We can now utilize the following functions to calculate powers and currents:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"power!(system, analysis)\ncurrent!(system, analysis)\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"For instance, if we want to show the active power injections and the from-bus current magnitudes, we can employ:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"print(system.bus.label, analysis.power.injection.active)\nprint(system.branch.label, analysis.current.from.magnitude)","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"note: Info\nTo better understand the powers and current associated with buses and branches that are calculated by the power! and current! functions, we suggest referring to the tutorials on AC Optimal Power Flow.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Print-Results-in-the-REPL-2","page":"AC Optimal Power Flow","title":"Print Results in the REPL","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Users can utilize any of the print functions outlined in the Print Power System Data or Print Power System Summary. For example, to create a bus data with the desired units, users can use the following function:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"@voltage(pu, deg, V)\n@power(MW, MVAr, pu)\nshow = Dict(\"Power Generation\" => false, \"Current Injection\" => false)\nprintBusData(system, analysis; show)\n@default(unit) # hide\nnothing # hide","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Active-and-Reactive-Power-Injection","page":"AC Optimal Power Flow","title":"Active and Reactive Power Injection","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To calculate the active and reactive power injection associated with a specific bus, the function can be used:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"active, reactive = injectionPower(system, analysis; label = \"Bus 1\")","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Active-and-Reactive-Power-Injection-from-Generators","page":"AC Optimal Power Flow","title":"Active and Reactive Power Injection from Generators","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To calculate the active and reactive power injection from the generators at a specific bus, the function can be used:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"active, reactive = supplyPower(system, analysis; label = \"Bus 2\")","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Active-and-Reactive-Power-at-Shunt-Element","page":"AC Optimal Power Flow","title":"Active and Reactive Power at Shunt Element","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To calculate the active and reactive power associated with shunt element at a specific bus, the function can be used:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"active, reactive = shuntPower(system, analysis; label = \"Bus 2\")","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Active-and-Reactive-Power-Flow","page":"AC Optimal Power Flow","title":"Active and Reactive Power Flow","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Similarly, we can compute the active and reactive power flow at both the from-bus and to-bus ends of the specific branch by utilizing the provided functions below:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"active, reactive = fromPower(system, analysis; label = \"Branch 2\")\nactive, reactive = toPower(system, analysis; label = \"Branch 2\")","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Active-and-Reactive-Power-at-Charging-Admittances","page":"AC Optimal Power Flow","title":"Active and Reactive Power at Charging Admittances","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To calculate the total active and reactive power linked with branch charging admittances of the particular branch, the function can be used:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"active, reactive = chargingPower(system, analysis; label = \"Branch 1\")","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"Active powers indicate active losses within the branch's charging admittances. Moreover, charging admittances injected reactive powers into the power system due to their capacitive nature, as denoted by a negative sign.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Active-and-Reactive-Power-at-Series-Impedance","page":"AC Optimal Power Flow","title":"Active and Reactive Power at Series Impedance","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To calculate the active and reactive power across the series impedance of the branch, the function can be used:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"active, reactive = seriesPower(system, analysis; label = \"Branch 2\")","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"The active power also considers active losses originating from the series resistance of the branch, while the reactive power represents reactive losses resulting from the impedance's inductive characteristics.","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Current-Injection","page":"AC Optimal Power Flow","title":"Current Injection","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To calculate the current injection associated with a specific bus, the function can be used:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"magnitude, angle = injectionCurrent(system, analysis; label = \"Bus 1\")","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Current-Flow","page":"AC Optimal Power Flow","title":"Current Flow","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"We can compute the current flow at both the from-bus and to-bus ends of the specific branch by using:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"magnitude, angle = fromCurrent(system, analysis; label = \"Branch 2\")\nmagnitude, angle = toCurrent(system, analysis; label = \"Branch 2\")","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"","category":"page"},{"location":"manual/acOptimalPowerFlow/#Current-Through-Series-Impedance","page":"AC Optimal Power Flow","title":"Current Through Series Impedance","text":"","category":"section"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"To calculate the current passing through the series impedance of the branch in the direction from the from-bus end to the to-bus end, we can use the following function:","category":"page"},{"location":"manual/acOptimalPowerFlow/","page":"AC Optimal Power Flow","title":"AC Optimal Power Flow","text":"magnitude, angle = seriesCurrent(system, analysis; label = \"Branch 2\")","category":"page"},{"location":"api/setupPrint/#setupPrintAPI","page":"Setup and Print","title":"Setup and Print","text":"","category":"section"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"For further information on this topic, please see the Power System Model or Measurement Model sections of the Manual. Please note that when using macros, they modify variables within the current scope. Print functions can be used to print results to the REPL, or users can redirect the output to print results to a text file, for example.","category":"page"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"To load power system model API functionalities into the current scope, utilize the following command:","category":"page"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"using JuliaGrid","category":"page"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"","category":"page"},{"location":"api/setupPrint/#Base-Units","page":"Setup and Print","title":"Base Units","text":"","category":"section"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"@base","category":"page"},{"location":"api/setupPrint/#Input-Units","page":"Setup and Print","title":"Input Units","text":"","category":"section"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"@power\n@voltage\n@current\n@parameter","category":"page"},{"location":"api/setupPrint/#Label-Types","page":"Setup and Print","title":"Label Types","text":"","category":"section"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"@labels","category":"page"},{"location":"api/setupPrint/#Default-Settings","page":"Setup and Print","title":"Default Settings","text":"","category":"section"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"@default","category":"page"},{"location":"api/setupPrint/#Print-Power-System-Data","page":"Setup and Print","title":"Print Power System Data","text":"","category":"section"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"printBusData\nprintBranchData\nprintGeneratorData","category":"page"},{"location":"api/setupPrint/#Print-Power-System-Summary","page":"Setup and Print","title":"Print Power System Summary","text":"","category":"section"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"printBusSummary\nprintBranchSummary\nprintGeneratorSummary","category":"page"},{"location":"api/setupPrint/#Print-Measurement-Data","page":"Setup and Print","title":"Print Measurement Data","text":"","category":"section"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"printVoltmeterData\nprintAmmeterData\nprintWattmeterData\nprintVarmeterData\nprintPmuData","category":"page"},{"location":"api/setupPrint/#Print-Constraint-Data","page":"Setup and Print","title":"Print Constraint Data","text":"","category":"section"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"printBusConstraint\nprintBranchConstraint\nprintGeneratorConstraint","category":"page"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"","category":"page"},{"location":"api/setupPrint/#Base-Units-2","page":"Setup and Print","title":"Base Units","text":"","category":"section"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"@base","category":"page"},{"location":"api/setupPrint/#JuliaGrid.@base","page":"Setup and Print","title":"JuliaGrid.@base","text":"@base(system::PowerSystem, power, voltage)\n\nBy default, the units for base power and base voltages are set to volt-ampere (VA) and volt (V), but you can modify the prefixes using the macro.\n\nPrefixes must be specified according to the SI prefixes and should be included with the unit of power (VA) or unit of voltage (V). Keep in mind that the macro must be used after creating the composite type PowerSystem.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\n@base(system, MVA, kV)\n\n\n\n\n\n","category":"macro"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"","category":"page"},{"location":"api/setupPrint/#Input-Units-2","page":"Setup and Print","title":"Input Units","text":"","category":"section"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"@power\n@voltage\n@current\n@parameter","category":"page"},{"location":"api/setupPrint/#JuliaGrid.@power","page":"Setup and Print","title":"JuliaGrid.@power","text":"@power(active, reactive, apparent)\n\nJuliaGrid stores all data related with powers in per-units, and these cannot be altered. However, the power units of the built-in functions used to add or modified power system elements can be modified using the macro.\n\nPrefixes must be specified according to the SI prefixes and should be included with the unit of active power (W), reactive power (VAr), or apparent power (VA). Also, it is a possible to combine SI units with/without prefixes with per-units (pu).\n\nChanging the unit of active power is reflected in the following quantities:\n\naddBus!, updateBus!, @bus: active, conductance;\naddBranch!, updateBranch!, @branch: if type = 2: minFromBus, maxFromBus, minToBus, maxToBus;\naddGenerator!, updateGenerator!, @generator: active, minActive, maxActive, lowActive, upActive, loadFollowing, reserve10min, reserve30min;\ncost!: if active: piecewise, polynomial;\naddWattmeter!, updateWattmeter!: active, variance;\n@wattmeter: , varianceBus, varianceFrom, varianceTo.\n\nChanging the unit of reactive power unit is reflected in the following quantities:\n\naddBus!, updateBus!, @bus: reactive, susceptance;\naddGenerator!, updateGenerator!, @generator: reactive, minReactive, maxReactive, minLowReactive, maxLowReactive, minUpReactive, maxUpReactive, reactiveRamp;\ncost!: if reactive: piecewise, polynomial;\naddVarmeter!, updateVarmeter!: reactive, variance;\n@varmeter: varianceBus, varianceFrom, varianceTo.\n\nChanging the unit of apparent power unit is reflected in the following quantities:\n\naddBranch!, updateBranch!, @branch: if type = 1: minFromBus, maxFromBus, minToBus, maxToBus.\n\nExample\n\n@power(MW, kVAr, VA)\n\n\n\n\n\n","category":"macro"},{"location":"api/setupPrint/#JuliaGrid.@voltage","page":"Setup and Print","title":"JuliaGrid.@voltage","text":"@voltage(magnitude, angle, base)\n\nJuliaGrid stores all data related with voltages in per-units and radians, and these cannot be altered. However, the voltage magnitude and angle units of the built-in functions used to add or modified power system elements can be modified using the macro.\n\nThe prefixes must adhere to the SI prefixes and should be specified along with the unit of voltage, either magnitude (V) or base (V). Alternatively, the unit of voltage magnitude can be expressed in per-unit (pu). The unit of voltage angle should be in radians (rad) or degrees (deg).\n\nChanging the unit of voltage magnitude is reflected in the following quantities:\n\naddBus!, updateBus!, @bus: magnitude, minMagnitude, maxMagnitude;\naddGenerator!, updateGenerator!, @generator: magnitude;\naddVoltmeter!, updateVoltmeter!, @voltmeter: magnitude, variance;\naddPmu!, updatePmu!: if bus: magnitude, varianceMagnitude;\n@pmu: varianceMagnitudeBus.\n\nChanging the unit of voltage angle is reflected in the following quantities:\n\naddBus!, updateBus!, @bus: angle;\naddBranch!, updateBranch!, @branch: shiftAngle, minDiffAngle, maxDiffAngle;\naddPmu!, updatePmu!: if bus: angle, varianceAngle;\n@pmu: varianceAngleBus.\n\nChanging the unit prefix of voltage base is reflected in the following quantity:\n\naddBus!, updateBus!, @bus: base.\n\nExample\n\n@voltage(pu, deg, kV)\n\n\n\n\n\n","category":"macro"},{"location":"api/setupPrint/#JuliaGrid.@current","page":"Setup and Print","title":"JuliaGrid.@current","text":"@current(magnitude, angle)\n\nJuliaGrid stores all data related with currents in per-units and radians, and these cannot be altered. However, the current magnitude and angle units of the built-in functions used to add or modified measurement devices can be modified using the macro.\n\nThe prefixes must adhere to the SI prefixes and should be specified along with the unit of current magnitude (V). Alternatively, the unit of current magnitude can be expressed in per-unit (pu). The unit of current angle should be in radians (rad) or degrees (deg).\n\nChanging the unit of current magnitude is reflected in the following quantities:\n\naddBranch!, updateBranch!, @branch: if type = 3: minFromBus, maxFromBus, minToBus, maxToBus.\naddAmmeter!, updateAmmeter!: magnitude, variance;\n@ammeter: varianceFrom, varianceTo;\naddPmu!, updatePmu!: if from or to: magnitude, varianceMagnitude;\n@pmu: varianceMagnitudeFrom, varianceMagnitudeTo.\n\nChanging the unit of current angle is reflected in the following quantities:\n\naddPmu!, updatePmu!: if from or to: angle, varianceAngle;\n@pmu: varianceAngleFrom, varianceAngleTo.\n\nExample\n\n@current(pu, deg)\n\n\n\n\n\n","category":"macro"},{"location":"api/setupPrint/#JuliaGrid.@parameter","page":"Setup and Print","title":"JuliaGrid.@parameter","text":"@parameter(impedance, admittance)\n\nJuliaGrid stores all data related with impedances and admittancies in per-units, and these cannot be altered. However, units of impedance and admittance of the built-in functions used to add or modified power system elements can be modified using the macro.\n\nPrefixes must be specified according to the SI prefixes and should be included with the unit of impedance (Ω) or unit of admittance (S). The second option is to define the units in per-unit (pu).\n\nIn the case where impedance and admittance are being used in SI units (Ω and S) and these units are related to the transformer, the assignment must be based on the primary side of the transformer.\n\nChanging the units of impedance is reflected in the following quantities in specific functions:\n\naddBranch!, updateBranch!, @branch: resistance, reactance.\n\nChanging the units of admittance is reflected in the following quantities:\n\naddBranch!, updateBranch!, @branch: conductance, susceptance.\n\nExample\n\n@parameter(Ω, pu)\n\n\n\n\n\n","category":"macro"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"","category":"page"},{"location":"api/setupPrint/#Label-Types-2","page":"Setup and Print","title":"Label Types","text":"","category":"section"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"@labels","category":"page"},{"location":"api/setupPrint/#JuliaGrid.@labels","page":"Setup and Print","title":"JuliaGrid.@labels","text":"@labels(type)\n\nJuliaGrid keeps all labels in ordered dictionaries as Strings. Users have the option to use Integers instead, which can be a more efficient way to store labels, particularly for large-scale systems.\n\nExample\n\n@labels(Integer)\n\n\n\n\n\n","category":"macro"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"","category":"page"},{"location":"api/setupPrint/#Default-Settings-2","page":"Setup and Print","title":"Default Settings","text":"","category":"section"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"@default","category":"page"},{"location":"api/setupPrint/#JuliaGrid.@default","page":"Setup and Print","title":"JuliaGrid.@default","text":"@default(mode)\n\nThe macro is designed to reset various settings to their default values.\n\nThe mode argument can take on the following values:\n\nunit: Resets all units to their default settings.\npower: Sets active, reactive, and apparent power to per-units.\nvoltage: Sets voltage magnitude to per-unit and voltage angle to radian.\nparameter: Sets impedance and admittance to per-units.\ntemplate: Resets bus, branch, generator, voltmeter, ammeter, wattmeter, varmeter, and pmu templates to their default settings.\nbus: Resets the bus template to its default settings.\nbranch: Resets the branch template to its default settings.\ngenerator: Resets the generator template to its default settings.\nvoltmeter: Resets the voltmeter template to its default settings.\nammeter: Resets the ammeter template to its default settings.\nwattmeter: Resets the wattmeter template to its default settings.\nvarmeter: Resets the varmeter template to its default settings.\npmu: Resets the pmu template to its default settings.\n\nExample\n\n@default(unit)\n\n\n\n\n\n","category":"macro"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"","category":"page"},{"location":"api/setupPrint/#PrintPowerSystemDataAPI","page":"Setup and Print","title":"Print Power System Data","text":"","category":"section"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"printBusData\nprintBranchData\nprintGeneratorData","category":"page"},{"location":"api/setupPrint/#JuliaGrid.printBusData","page":"Setup and Print","title":"JuliaGrid.printBusData","text":"printBusData(system::PowerSystem, analysis::Analysis, [io::IO];\n label, fmt, width, show, delimiter, title, header, footer, repeat, style)\n\nThe function prints voltages, powers, and currents related to buses. Optionally, an IO may be passed as the last argument to redirect the output.\n\nKeywords\n\nThe following keywords control the printed data:\n\nlabel: Prints only the data for the corresponding bus.\nfmt: Specifies the preferred numeric formats or alignments for the columns.\nwidth: Specifies the preferred widths for the columns.\nshow: Toggles the printing of the columns.\ndelimiter: Sets the column delimiter.\ntitle: Toggles the printing of the table title.\nheader: Toggles the printing of the header.\nfooter: Toggles the printing of the footer.\nrepeat: Prints the header again after a specified number of lines have been printed.\nstyle: Prints either a stylish table or a simple table suitable for easy export.\n\ncompat: Julia 1.10\nThe function printBusData requires Julia 1.10 or later.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\npower!(system, analysis)\n\n# Print data for all buses\nfmt = Dict(\"Power Demand\" => \"%.2f\", \"Voltage Magnitude\" => \"%.2f\", \"Label\" => \"%s\")\nshow = Dict(\"Power Injection\" => false, \"Power Generation Reactive\" => false)\nprintBusData(system, analysis; fmt, show, repeat = 10)\n\n# Print data for specific buses\ndelimiter = \" \"\nwidth = Dict(\"Voltage\" => 9, \"Power Injection Active\" => 9)\nprintBusData(system, analysis; label = 2, delimiter, width, title = true, header = true)\nprintBusData(system, analysis; label = 10, delimiter, width)\nprintBusData(system, analysis; label = 12, delimiter, width)\nprintBusData(system, analysis; label = 14, delimiter, width, footer = true)\n\n\n\n\n\n","category":"function"},{"location":"api/setupPrint/#JuliaGrid.printBranchData","page":"Setup and Print","title":"JuliaGrid.printBranchData","text":"printBranchData(system::PowerSystem, analysis::Analysis, [io::IO];\n label, fmt, width, show, delimiter, title, header, footer, repeat, style)\n\nThe function prints powers and currents related to branches. Optionally, an IO may be passed as the last argument to redirect the output.\n\nKeywords\n\nThe following keywords control the printed data:\n\nlabel: Prints only the data for the corresponding branch.\nfmt: Specifies the preferred numeric formats or alignments for the columns.\nwidth: Specifies the preferred widths for the columns.\nshow: Toggles the printing of the columns.\ndelimiter: Sets the column delimiter.\ntitle: Toggles the printing of the table title.\nheader: Toggles the printing of the header.\nfooter: Toggles the printing of the footer.\nrepeat: Prints the header again after a specified number of lines have been printed.\nstyle: Prints either a stylish table or a simple table suitable for easy export.\n\ncompat: Julia 1.10\nThe function printBranchData requires Julia 1.10 or later.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\npower!(system, analysis)\n\n# Print data for all branches\nfmt = Dict(\"Shunt Power\" => \"%.2f\", \"Series Power Reactive\" => \"%.2f\")\nshow = Dict(\"From-Bus Power\" => false, \"To-Bus Power Reactive\" => false)\nprintBranchData(system, analysis; fmt, show, repeat = 11, title = false)\n\n# Print data for specific branches\ndelimiter = \" \"\nwidth = Dict(\"From-Bus Power\" => 9, \"To-Bus Power Active\" => 9)\nprintBranchData(system, analysis; label = 2, delimiter, width, header = true)\nprintBranchData(system, analysis; label = 10, delimiter, width)\nprintBranchData(system, analysis; label = 12, delimiter, width)\nprintBranchData(system, analysis; label = 14, delimiter, width, footer = true)\n\n\n\n\n\n","category":"function"},{"location":"api/setupPrint/#JuliaGrid.printGeneratorData","page":"Setup and Print","title":"JuliaGrid.printGeneratorData","text":"printGeneratorData(system::PowerSystem, analysis::Analysis, [io::IO];\n label, fmt, width, show, delimiter, title, header, footer, repeat, style)\n\nThe function prints powers related to generators. Optionally, an IO may be passed as the last argument to redirect the output.\n\nKeywords\n\nThe following keywords control the printed data:\n\nlabel: Prints only the data for the corresponding generator.\nfmt: Specifies the preferred numeric formats or alignments for the columns.\nwidth: Specifies the preferred widths for the columns.\nshow: Toggles the printing of the columns.\ndelimiter: Sets the column delimiter.\ntitle: Toggles the printing of the table title.\nheader: Toggles the printing of the header.\nfooter: Toggles the printing of the footer.\nrepeat: Prints the header again after a specified number of lines have been printed.\nstyle: Prints either a stylish table or a simple table suitable for easy export.\n\ncompat: Julia 1.10\nThe function printGeneratorData requires Julia 1.10 or later.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\npower!(system, analysis)\n\n# Print data for all generators\nfmt = Dict(\"Power Output Active\" => \"%.2f\")\nshow = Dict(\"Power Output Reactive\" => false)\nprintGeneratorData(system, analysis; fmt, show, title = false)\n\n# Print data for specific generators\ndelimiter = \" \"\nwidth = Dict(\"Power Output Active\" => 7)\nprintGeneratorData(system, analysis; label = 1, delimiter, width, header = true)\nprintGeneratorData(system, analysis; label = 4, delimiter, width)\nprintGeneratorData(system, analysis; label = 5, delimiter, width, footer = true)\n\n\n\n\n\n","category":"function"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"","category":"page"},{"location":"api/setupPrint/#PrintPowerSystemSummaryAPI","page":"Setup and Print","title":"Print Power System Summary","text":"","category":"section"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"printBusSummary\nprintBranchSummary\nprintGeneratorSummary","category":"page"},{"location":"api/setupPrint/#JuliaGrid.printBusSummary","page":"Setup and Print","title":"JuliaGrid.printBusSummary","text":"printBusSummary(system::PowerSystem, analysis::Analysis, [io::IO];\n fmt, width, show, delimiter, title, header, footer, style)\n\nThe function prints a summary of the electrical quantities related to buses. Optionally, an IO may be passed as the last argument to redirect the output.\n\nKeywords\n\nThe following keywords control the printed data:\n\nfmt: Specifies the preferred numeric formats or alignments for the columns.\nwidth: Specifies the preferred widths for the columns.\nshow: Toggles the printing of the columns.\ndelimiter: Sets the column delimiter.\ntitle: Toggles the printing of the table title.\nheader: Toggles the printing of the header.\nfooter: Toggles the printing of the footer.\nstyle: Prints either a stylish table or a simple table suitable for easy export.\n\ncompat: Julia 1.10\nThe function printBusSummary requires Julia 1.10 or later.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\npower!(system, analysis)\n\nshow = Dict(\"In-Use\" => false)\nprintBusSummary(system, analysis; show, delimiter = \" \", title = false)\n\n\n\n\n\n","category":"function"},{"location":"api/setupPrint/#JuliaGrid.printBranchSummary","page":"Setup and Print","title":"JuliaGrid.printBranchSummary","text":"printBranchSummary(system::PowerSystem, analysis::Analysis, [io::IO];\n fmt, width, show, delimiter, title, header, footer, style))\n\nThe function prints a summary of the electrical quantities related to branches. Optionally, an IO may be passed as the last argument to redirect the output.\n\nKeywords\n\nThe following keywords control the printed data:\n\nfmt: Specifies the preferred numeric formats or alignments for the columns.\nwidth: Specifies the preferred widths for the columns.\nshow: Toggles the printing of the columns.\ndelimiter: Sets the column delimiter.\ntitle: Toggles the printing of the table title.\nheader: Toggles the printing of the header.\nfooter: Toggles the printing of the footer.\nstyle: Prints either a stylish table or a simple table suitable for easy export.\n\ncompat: Julia 1.10\nThe function printBranchSummary requires Julia 1.10 or later.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\npower!(system, analysis)\n\nshow = Dict(\"Total\" => false)\nprintBranchSummary(system, analysis; show, delimiter = \" \", title = false)\n\n\n\n\n\n","category":"function"},{"location":"api/setupPrint/#JuliaGrid.printGeneratorSummary","page":"Setup and Print","title":"JuliaGrid.printGeneratorSummary","text":"printGeneratorSummary(system::PowerSystem, analysis::Analysis, [io::IO];\n fmt, width, show, delimiter, title, header, footer, style)\n\nThe function prints a summary of the electrical quantities related to generators. Optionally, an IO may be passed as the last argument to redirect the output.\n\nKeywords\n\nThe following keywords control the printed data:\n\nfmt: Specifies the preferred numeric formats or alignments for the columns.\nwidth: Specifies the preferred widths for the columns.\nshow: Toggles the printing of the columns.\ndelimiter: Sets the column delimiter.\ntitle: Toggles the printing of the table title.\nheader: Toggles the printing of the header.\nfooter: Toggles the printing of the footer.\nstyle: Prints either a stylish table or a simple table suitable for easy export.\n\ncompat: Julia 1.10\nThe function printGeneratorSummary requires Julia 1.10 or later.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\n\nanalysis = newtonRaphson(system)\nfor i = 1:10\n stopping = mismatch!(system, analysis)\n if all(stopping .< 1e-8)\n break\n end\n solve!(system, analysis)\nend\npower!(system, analysis)\n\nshow = Dict(\"Minimum\" => false)\nprintGeneratorSummary(system, analysis; show, delimiter = \" \", title = false)\n\n\n\n\n\n","category":"function"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"","category":"page"},{"location":"api/setupPrint/#Print-Measurement-Data-2","page":"Setup and Print","title":"Print Measurement Data","text":"","category":"section"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"printVoltmeterData\nprintAmmeterData\nprintWattmeterData\nprintVarmeterData\nprintPmuData","category":"page"},{"location":"api/setupPrint/#JuliaGrid.printVoltmeterData","page":"Setup and Print","title":"JuliaGrid.printVoltmeterData","text":"printVoltmeterData(system::PowerSystem, device::Measurement, [analysis::Analysis],\n [io::IO]; label, fmt, width, show, delimiter, title, header, footer, repeat, style)\n\nThe function prints data related to voltmeters. Optionally, an IO may be passed as the last argument to redirect the output. Users can also omit the Analysis type to print only data related to the Measurement type.\n\nKeywords\n\nThe following keywords control the printed data:\n\nlabel: Prints only the data for the corresponding voltmeter.\nfmt: Specifies the preferred numeric formats or alignments for the columns.\nwidth: Specifies the preferred widths for the columns.\nshow: Toggles the printing of the columns.\ndelimiter: Sets the column delimiter.\ntitle: Toggles the printing of the table title.\nheader: Toggles the printing of the header.\nfooter: Toggles the printing of the footer.\nrepeat: Prints the header again after a specified number of lines have been printed.\nstyle: Prints either a stylish table or a simple table suitable for easy export.\n\ncompat: Julia 1.10\nThe function printBusData requires Julia 1.10 or later.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = gaussNewton(system, device)\nfor iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n break\n end\nend\npower!(system, analysis)\n\n# Print data for all voltmeters\nfmt = Dict(\"Voltage Magnitude\" => \"%.2f\", \"Voltage Magnitude Estimate\" => \"%.6f\")\nshow = Dict(\"Voltage Magnitude Residual\" => false)\nprintVoltmeterData(system, device, analysis; fmt, show, delimiter = \" \", repeat = 10)\n\n# Print data for specific voltmeters\nwidth = Dict(\"Voltage Magnitude Estimate\" => 11)\nprintVoltmeterData(system, device, analysis; label = 1, width, header = true)\nprintVoltmeterData(system, device, analysis; label = 6, width)\nprintVoltmeterData(system, device, analysis; label = 8, width, footer = true)\n\n\n\n\n\n","category":"function"},{"location":"api/setupPrint/#JuliaGrid.printAmmeterData","page":"Setup and Print","title":"JuliaGrid.printAmmeterData","text":"printAmmeterData(system::PowerSystem, device::Measurement, [analysis::Analysis],\n [io::IO]; label, fmt, width, show, delimiter, title, header, footer, repeat, style)\n\nThe function prints data related to ammeters. Optionally, an IO may be passed as the last argument to redirect the output. Users can also omit the Analysis type to print only data related to the Measurement type.\n\nKeywords\n\nThe following keywords control the printed data:\n\nlabel: Prints only the data for the corresponding ammeter.\nfmt: Specifies the preferred numeric formats or alignments for the columns.\nwidth: Specifies the preferred widths for the columns.\nshow: Toggles the printing of the columns.\ndelimiter: Sets the column delimiter.\ntitle: Toggles the printing of the table title.\nheader: Toggles the printing of the header.\nfooter: Toggles the printing of the footer.\nrepeat: Prints the header again after a specified number of lines have been printed.\nstyle: Prints either a stylish table or a simple table suitable for easy export.\n\ncompat: Julia 1.10\nThe function printBusData requires Julia 1.10 or later.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = gaussNewton(system, device)\nfor iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n break\n end\nend\ncurrent!(system, analysis)\n\n# Print data for all ammeters\nfmt = Dict(\"Current Magnitude\" => \"%.2f\", \"Current Magnitude Estimate\" => \"%.6f\")\nshow = Dict(\"Current Magnitude Residual\" => false)\nprintAmmeterData(system, device, analysis; fmt, show, delimiter = \" \", repeat = 10)\n\n# Print data for specific ammeters\nwidth = Dict(\"Current Magnitude\" => 10)\nprintAmmeterData(system, device, analysis; label = \"From 1\", width, header = true)\nprintAmmeterData(system, device, analysis; label = \"From 4\", width)\nprintAmmeterData(system, device, analysis; label = \"From 6\", width, footer = true)\n\n\n\n\n\n","category":"function"},{"location":"api/setupPrint/#JuliaGrid.printWattmeterData","page":"Setup and Print","title":"JuliaGrid.printWattmeterData","text":"printWattmeterData(system::PowerSystem, device::Measurement, [analysis::Analysis],\n [io::IO]; label, fmt, width, show, delimiter, title, header, footer, repeat, style)\n\nThe function prints data related to wattmeters. Optionally, an IO may be passed as the last argument to redirect the output. Users can also omit the Analysis type to print only data related to the Measurement type.\n\nKeywords\n\nThe following keywords control the printed data:\n\nlabel: Prints only the data for the corresponding wattmeter.\nfmt: Specifies the preferred numeric formats or alignments for the columns.\nwidth: Specifies the preferred widths for the columns.\nshow: Toggles the printing of the columns.\ndelimiter: Sets the column delimiter.\ntitle: Toggles the printing of the table title.\nheader: Toggles the printing of the header.\nfooter: Toggles the printing of the footer.\nrepeat: Prints the header again after a specified number of lines have been printed.\nstyle: Prints either a stylish table or a simple table suitable for easy export.\n\ncompat: Julia 1.10\nThe function printBusData requires Julia 1.10 or later.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = gaussNewton(system, device)\nfor iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n break\n end\nend\npower!(system, analysis)\n\n# Print data for all wattmeters\nfmt = Dict(\"Active Power\" => \"%.2f\", \"Active Power Estimate\" => \"%.6f\")\nshow = Dict(\"Active Power Status\" => false)\nprintWattmeterData(system, device, analysis; fmt, show, delimiter = \" \", repeat = 14)\n\n# Print data for specific wattmeters\nwidth = Dict(\"Active Power Residual\" => 11)\nprintWattmeterData(system, device, analysis; label = 2, width, header = true)\nprintWattmeterData(system, device, analysis; label = 5, width)\nprintWattmeterData(system, device, analysis; label = 9, width, footer = true)\n\n\n\n\n\n","category":"function"},{"location":"api/setupPrint/#JuliaGrid.printVarmeterData","page":"Setup and Print","title":"JuliaGrid.printVarmeterData","text":"printVarmeterData(system::PowerSystem, device::Measurement, [analysis::Analysis],\n [io::IO]; label, fmt, width, show, delimiter, title, header, footer, repeat, style)\n\nThe function prints data related to varmeters. Optionally, an IO may be passed as the last argument to redirect the output. Users can also omit the Analysis type to print only data related to the Measurement type.\n\nKeywords\n\nThe following keywords control the printed data:\n\nlabel: Prints only the data for the corresponding varmeter.\nfmt: Specifies the preferred numeric formats or alignments for the columns.\nwidth: Specifies the preferred widths for the columns.\nshow: Toggles the printing of the columns.\ndelimiter: Sets the column delimiter.\ntitle: Toggles the printing of the table title.\nheader: Toggles the printing of the header.\nfooter: Toggles the printing of the footer.\nrepeat: Prints the header again after a specified number of lines have been printed.\nstyle: Prints either a stylish table or a simple table suitable for easy export.\n\ncompat: Julia 1.10\nThe function printBusData requires Julia 1.10 or later.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = gaussNewton(system, device)\nfor iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n break\n end\nend\npower!(system, analysis)\n\n# Print data for all wattmeters\nfmt = Dict(\"Reactive Power\" => \"%.2f\", \"Reactive Power Estimate\" => \"%.6f\")\nshow = Dict(\"Reactive Power Status\" => false)\nprintVarmeterData(system, device, analysis; fmt, show, delimiter = \" \", repeat = 14)\n\n# Print data for specific wattmeters\nwidth = Dict(\"Reactive Power Residual\" => 11)\nprintVarmeterData(system, device, analysis; label = 2, width, header = true)\nprintVarmeterData(system, device, analysis; label = 5, width)\nprintVarmeterData(system, device, analysis; label = 9, width, footer = true)\n\n\n\n\n\n","category":"function"},{"location":"api/setupPrint/#JuliaGrid.printPmuData","page":"Setup and Print","title":"JuliaGrid.printPmuData","text":"printPmuData(system::PowerSystem, device::Measurement, [analysis::Analysis],\n [io::IO]; label, fmt, width, show, delimiter, title, header, footer, repeat, style)\n\nThe function prints data related to PMUs. Optionally, an IO may be passed as the last argument to redirect the output. Users can also omit the Analysis type to print only data related to the Measurement type.\n\nKeywords\n\nThe following keywords control the printed data:\n\nlabel: Prints only the data for the corresponding PMU.\nfmt: Specifies the preferred numeric formats or alignments for the columns.\nwidth: Specifies the preferred widths for the columns.\nshow: Toggles the printing of the columns.\ndelimiter: Sets the column delimiter.\ntitle: Toggles the printing of the table title.\nheader: Toggles the printing of the header.\nfooter: Toggles the printing of the footer.\nrepeat: Prints the header again after a specified number of lines have been printed.\nstyle: Prints either a stylish table or a simple table suitable for easy export.\n\ncompat: Julia 1.10\nThe function printPmuData requires Julia 1.10 or later.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = gaussNewton(system, device)\nfor iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n break\n end\nend\ncurrent!(system, analysis)\n\n# Print data for all PMUs\nfmt = Dict(\"Current Magnitude\" => \"%.2f\", \"Current Magnitude Variance\" => \"%.5f\")\nshow = Dict(\"Current Angle\" => false, \"Current Magnitude Status\" => false)\nprintPmuData(system, device, analysis; fmt, show, delimiter = \" \", repeat = 10)\n\n# Print data for specific PMUs\nwidth = Dict(\"Current Magnitude\" => 10, \"Current Angle Status\" => 8)\nprintPmuData(system, device, analysis; label = \"From 1\", width, header = true)\nprintPmuData(system, device, analysis; label = \"From 4\", width)\nprintPmuData(system, device, analysis; label = \"From 6\", width, footer = true)\n\n\n\n\n\n","category":"function"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"","category":"page"},{"location":"api/setupPrint/#PrintConstraintDataAPI","page":"Setup and Print","title":"Print Constraint Data","text":"","category":"section"},{"location":"api/setupPrint/","page":"Setup and Print","title":"Setup and Print","text":"printBusConstraint\nprintBranchConstraint\nprintGeneratorConstraint","category":"page"},{"location":"api/setupPrint/#JuliaGrid.printBusConstraint","page":"Setup and Print","title":"JuliaGrid.printBusConstraint","text":"printBusConstraint(system::PowerSystem, analysis::OptimalPowerFlow, [io::IO];\n label, fmt, width, show, delimiter, title, header, footer, repeat, style)\n\nThe function prints constraint data related to buses. Optionally, an IO may be passed as the last argument to redirect the output.\n\nKeywords\n\nThe following keywords control the printed data:\n\nlabel: Prints only the data for the corresponding bus.\nfmt: Specifies the preferred numeric formats or alignments for the columns.\nwidth: Specifies the preferred widths for the columns.\nshow: Toggles the printing of the columns.\ndelimiter: Sets the column delimiter.\ntitle: Toggles the printing of the table title.\nheader: Toggles the printing of the header.\nfooter: Toggles the printing of the footer.\nrepeat: Prints the header again after a specified number of lines have been printed.\nstyle: Prints either a stylish table or a simple table suitable for easy export.\n\ncompat: Julia 1.10\nThe function printBusConstraint requires Julia 1.10 or later.\n\nExample\n\nusing Ipopt\n\nsystem = powerSystem(\"case14.h5\")\n\nanalysis = acOptimalPowerFlow(system, Ipopt.Optimizer)\nsolve!(system, analysis)\n\n# Print data for all buses\nfmt = Dict(\"Active Power Balance\" => \"%.2e\", \"Reactive Power Balance Dual\" => \"%.4e\")\nshow = Dict(\"Voltage Magnitude\" => false, \"Reactive Power Balance Solution\" => false)\nprintBusConstraint(system, analysis; fmt, show, repeat = 10)\n\n# Print data for specific buses\ndelimiter = \" \"\nwidth = Dict(\"Voltage Magnitude\" => 8, \"Active Power Balance Solution\" => 12)\nprintBusConstraint(system, analysis; label = 2, delimiter, width, header = true)\nprintBusConstraint(system, analysis; label = 10, delimiter, width)\nprintBusConstraint(system, analysis; label = 14, delimiter, width, footer = true)\n\n\n\n\n\n","category":"function"},{"location":"api/setupPrint/#JuliaGrid.printBranchConstraint","page":"Setup and Print","title":"JuliaGrid.printBranchConstraint","text":"printBranchConstraint(system::PowerSystem, analysis::OptimalPowerFlow, [io::IO];\n label, fmt, width, show, delimiter, title, header, footer, repeat, style)\n\nThe function prints constraint data related to branches. Optionally, an IO may be passed as the last argument to redirect the output.\n\nKeywords\n\nThe following keywords control the printed data:\n\nlabel: Prints only the data for the corresponding branch.\nfmt: Specifies the preferred numeric formats or alignments for the columns.\nwidth: Specifies the preferred widths for the columns.\nshow: Toggles the printing of the columns.\ndelimiter: Sets the column delimiter.\ntitle: Toggles the printing of the table title.\nheader: Toggles the printing of the header.\nfooter: Toggles the printing of the footer.\nrepeat: Prints the header again after a specified number of lines have been printed.\nstyle: Prints either a stylish table or a simple table suitable for easy export.\n\ncompat: Julia 1.10\nThe function printBranchConstraint requires Julia 1.10 or later.\n\nExample\n\nusing Ipopt\n\nsystem = powerSystem(\"case14.h5\")\nupdateBranch!(system; label = 3, minDiffAngle = 0.05, maxDiffAngle = 1.5)\nupdateBranch!(system; label = 4, minDiffAngle = 0.05, maxDiffAngle = 1.1)\nupdateBranch!(system; label = 4, maxFromBus = 0.4, maxToBus = 0.5)\nupdateBranch!(system; label = 9, minFromBus = 0.1, maxFromBus = 0.3)\n\nanalysis = acOptimalPowerFlow(system, Ipopt.Optimizer)\nsolve!(system, analysis)\n\n# Print data for all branches\nfmt = Dict(\"Voltage Angle Difference\" => \"%.2f\")\nshow = Dict(\"To-Bus Apparent Power Flow Dual\" => false)\nprintBranchConstraint(system, analysis; fmt, show, repeat = 2)\n\n# Print data for specific branches\ndelimiter = \" \"\nwidth = Dict(\"From-Bus Apparent Power Flow\" => 13, \"Voltage Angle Difference Dual\" => 12)\nprintBranchConstraint(system, analysis; label = 3, delimiter, width, header = true)\nprintBranchConstraint(system, analysis; label = 4, delimiter, width)\nprintBranchConstraint(system, analysis; label = 9, delimiter, width, footer = true)\n\n\n\n\n\n","category":"function"},{"location":"api/setupPrint/#JuliaGrid.printGeneratorConstraint","page":"Setup and Print","title":"JuliaGrid.printGeneratorConstraint","text":"printGeneratorConstraint(system::PowerSystem, analysis::OptimalPowerFlow, [io::IO];\n label, fmt, width, show, delimiter, title, header, footer, repeat, style)\n\nThe function prints constraint data related to generators. Optionally, an IO may be passed as the last argument to redirect the output.\n\nKeywords\n\nThe following keywords control the printed data:\n\nlabel: Prints only the data for the corresponding generator.\nfmt: Specifies the preferred numeric formats or alignments for the columns.\nwidth: Specifies the preferred widths for the columns.\nshow: Toggles the printing of the columns.\ndelimiter: Sets the column delimiter.\ntitle: Toggles the printing of the table title.\nheader: Toggles the printing of the header.\nfooter: Toggles the printing of the footer.\nrepeat: Prints the header again after a specified number of lines have been printed.\nstyle: Prints either a stylish table or a simple table suitable for easy export.\n\ncompat: Julia 1.10\nThe function printGeneratorConstraint requires Julia 1.10 or later.\n\nExample\n\nusing Ipopt\n\nsystem = powerSystem(\"case14.h5\")\n\nanalysis = acOptimalPowerFlow(system, Ipopt.Optimizer)\nsolve!(system, analysis)\n\n# Print data for all generators\nfmt = Dict(\"Active Power Capability\" => \"%.2f\")\nshow = Dict(\"Reactive Power Capability\" => false, \"Active Power Capability Dual\" => false)\nprintGeneratorConstraint(system, analysis; fmt, show, repeat = 3)\n\n# Print data for specific generators\ndelimiter = \" \"\nwidth = Dict(\"Active Power Capability\" => 11, \"Reactive Power Capability Dual\" => 10)\nprintGeneratorConstraint(system, analysis; label = 2, delimiter, width, header = true)\nprintGeneratorConstraint(system, analysis; label = 3, delimiter, width)\nprintGeneratorConstraint(system, analysis; label = 5, delimiter, width, footer = true)\n\n\n\n\n\n","category":"function"},{"location":"api/stateEstimation/#StateEstimationAPI","page":"State Estimation","title":"State Estimation","text":"","category":"section"},{"location":"api/stateEstimation/","page":"State Estimation","title":"State Estimation","text":"For further information on this topic, please see the AC State Estimation, PMU State Estimation or DC State Estimation sections of the Manual. Below, we have provided a list of functions that can be utilized for state estimation, observability analysis, or bad data processing.","category":"page"},{"location":"api/stateEstimation/","page":"State Estimation","title":"State Estimation","text":"To load state estimation API functionalities into the current scope, utilize the following command:","category":"page"},{"location":"api/stateEstimation/","page":"State Estimation","title":"State Estimation","text":"using JuliaGrid","category":"page"},{"location":"api/stateEstimation/","page":"State Estimation","title":"State Estimation","text":"","category":"page"},{"location":"api/stateEstimation/#Observability-Analysis","page":"State Estimation","title":"Observability Analysis","text":"","category":"section"},{"location":"api/stateEstimation/","page":"State Estimation","title":"State Estimation","text":"islandTopologicalFlow\nislandTopological\nrestorationGram!","category":"page"},{"location":"api/stateEstimation/#AC-State-Estimation","page":"State Estimation","title":"AC State Estimation","text":"","category":"section"},{"location":"api/stateEstimation/","page":"State Estimation","title":"State Estimation","text":"gaussNewton\nacLavStateEstimation\nsolve!","category":"page"},{"location":"api/stateEstimation/#PMU-State-Estimation","page":"State Estimation","title":"PMU State Estimation","text":"","category":"section"},{"location":"api/stateEstimation/","page":"State Estimation","title":"State Estimation","text":"pmuPlacement\npmuStateEstimation\npmuLavStateEstimation\nsolve!","category":"page"},{"location":"api/stateEstimation/#DC-State-Estimation","page":"State Estimation","title":"DC State Estimation","text":"","category":"section"},{"location":"api/stateEstimation/","page":"State Estimation","title":"State Estimation","text":"dcStateEstimation\ndcLavStateEstimation\nsolve!","category":"page"},{"location":"api/stateEstimation/#Bad-Data-Analysis","page":"State Estimation","title":"Bad Data Analysis","text":"","category":"section"},{"location":"api/stateEstimation/","page":"State Estimation","title":"State Estimation","text":"residualTest!","category":"page"},{"location":"api/stateEstimation/","page":"State Estimation","title":"State Estimation","text":"","category":"page"},{"location":"api/stateEstimation/#Observability-Analysis-2","page":"State Estimation","title":"Observability Analysis","text":"","category":"section"},{"location":"api/stateEstimation/","page":"State Estimation","title":"State Estimation","text":"islandTopologicalFlow(::PowerSystem, ::Measurement)\nislandTopological(::PowerSystem, ::Measurement)\nrestorationGram!(::PowerSystem, ::Measurement, ::Measurement, ::Island)","category":"page"},{"location":"api/stateEstimation/#JuliaGrid.islandTopologicalFlow-Tuple{PowerSystem, Measurement}","page":"State Estimation","title":"JuliaGrid.islandTopologicalFlow","text":"islandTopologicalFlow(system::PowerSystem, device::Measurement)\n\nThe function utilizes a topological approach to detect flow observable islands, resulting in the formation of disconnected and loop-free subgraphs. It is assumed that active and reactive power measurements are paired, indicating a standard observability analysis. In this analysis, islands formed by active power measurements correspond to those formed by reactive power measurements.\n\nArguments\n\nTo define flow observable islands, this function necessitates the composite types PowerSystem and Measurement.\n\nReturns\n\nThe function returns an Island type, containing information about the islands:\n\nisland: List enumerating observable islands with indices of buses.\nbus: Positions of buses in relation to each island.\ntie: Tie data associated with buses and branches.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nstatusWattmeter!(system, device; inservice = 15)\ndevice.varmeter.reactive.status = copy(device.wattmeter.active.status)\n\nislands = islandTopologicalFlow(system, device)\n\n\n\n\n\n","category":"method"},{"location":"api/stateEstimation/#JuliaGrid.islandTopological-Tuple{PowerSystem, Measurement}","page":"State Estimation","title":"JuliaGrid.islandTopological","text":"islandTopological(system::PowerSystem, meter::Measurement)\n\nThe function employs a topological method to identify maximal observable islands. Specifically, it employs active power measurements to pinpoint flow observable islands. Subsequently, these islands are merged based on the available injection measurements.\n\nIt is assumed that active and reactive power measurements are paired, indicating a standard observability analysis. In this analysis, islands formed by active power measurements correspond to those formed by reactive power measurements.\n\nArguments\n\nTo define flow observable islands, this function necessitates the composite types PowerSystem and Measurement.\n\nReturns\n\nThe function returns an Island type, containing information about the islands:\n\nisland: List enumerating observable islands with indices of buses.\nbus: Positions of buses in relation to each island.\ntie: Tie data associated with buses and branches.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nstatusWattmeter!(system, device; inservice = 15)\ndevice.varmeter.reactive.status = copy(device.wattmeter.active.status)\n\nislands = islandTopological(system, device)\n\n\n\n\n\n","category":"method"},{"location":"api/stateEstimation/#JuliaGrid.restorationGram!-Tuple{PowerSystem, Measurement, Measurement, Island}","page":"State Estimation","title":"JuliaGrid.restorationGram!","text":"restorationGram!(system::PowerSystem, device::Measurement, pseudo::Measurement,\n islands::Island; threshold)\n\nUpon identifying the islands, the function incorporates measurements from the available pseudo-measurements in the pseudo variable into the device variable to reinstate observability. This method relies on reduced coefficient matrices and the Gram matrix.\n\nIt is important to note that the device labels in the device and pseudo variables must be different to enable the function to successfully incorporate measurements from pseudo into the device set of measurements.\n\nKeyword\n\nThe keyword threshold defines the zero pivot threshold value, with a default value of 1e-5. More precisely, all computed pivots less than this value will be treated as zero pivots.\n\nUpdates\n\nThe function updates the device variable of the Measurement composite type.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\npseudo = measurement(\"pseudomeasurement14.h5\")\n\nstatusWattmeter!(system, device; inservice = 10)\nislands = islandTopological(system, device)\n\nrestorationGram!(system, device, pseudo, islands)\n\n\n\n\n\n","category":"method"},{"location":"api/stateEstimation/","page":"State Estimation","title":"State Estimation","text":"","category":"page"},{"location":"api/stateEstimation/#AC-State-Estimation-2","page":"State Estimation","title":"AC State Estimation","text":"","category":"section"},{"location":"api/stateEstimation/","page":"State Estimation","title":"State Estimation","text":"gaussNewton\nacLavStateEstimation\nsolve!(::PowerSystem, ::ACStateEstimation{NonlinearWLS{Normal}})","category":"page"},{"location":"api/stateEstimation/#JuliaGrid.gaussNewton","page":"State Estimation","title":"JuliaGrid.gaussNewton","text":"gaussNewton(system::PowerSystem, device::Measurement, [method = LU])\n\nThe function sets up the Gauss-Newton method to solve the nonlinear or AC state estimation model, where the vector of state variables is given in polar coordinates. The Gauss-Newton method throughout iterations provided WLS estimator.\n\nArguments\n\nThis function requires the PowerSystem and Measurement composite types to establish the nonlinear WLS state estimation framework.\n\nMoreover, the presence of the method parameter is not mandatory. To address the WLS state estimation method, users can opt to utilize factorization techniques to decompose the gain matrix, such as LU, QR, or LDLt especially when the gain matrix is symmetric. Opting for the Orthogonal method is advisable for a more robust solution in scenarios involving ill-conditioned data, particularly when substantial variations in variances are present.\n\nIf the user does not provide the method, the default method for solving the estimation model will be LU factorization.\n\nUpdates\n\nIf the AC model has not been created, the function will automatically trigger an update of the ac field within the PowerSystem composite type.\n\nReturns\n\nThe function returns an instance of the ACStateEstimation type, which includes the following fields:\n\nvoltage: The variable allocated to store the bus voltage magnitudes and angles.\npower: The variable allocated to store the active and reactive powers.\nmethod: The system model vectors and matrices.\n\nExamples\n\nSet up the AC state estimation model to be solved using the default LU factorization:\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = gaussNewton(system, device)\n\nSet up the AC state estimation model to be solved using the orthogonal method:\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = gaussNewton(system, device, Orthogonal)\n\n\n\n\n\n","category":"function"},{"location":"api/stateEstimation/#JuliaGrid.acLavStateEstimation","page":"State Estimation","title":"JuliaGrid.acLavStateEstimation","text":"acLavStateEstimation(system::PowerSystem, device::Measurement, optimizer)\n\nThe function sets up the LAV method to solve the nonlinear or AC state estimation model, where the vector of state variables is given in polar coordinates.\n\nArguments\n\nThis function requires the PowerSystem and Measurement composite types to establish the LAV state estimation model. The LAV method offers increased robustness compared to WLS, ensuring unbiasedness even in the presence of various measurement errors and outliers.\n\nUsers can employ the LAV method to find an estimator by choosing one of the available optimization solvers. Typically, Ipopt.Optimizer suffices for most scenarios.\n\nUpdates\n\nIf the AC model has not been created, the function will automatically trigger an update of the ac field within the PowerSystem composite type.\n\nReturns\n\nThe function returns an instance of the ACStateEstimation type, which includes the following fields:\n\nvoltage: The variable allocated to store the bus voltage magnitudes and angles.\npower: The variable allocated to store the active and reactive powers.\nmethod: The optimization model.\n\nExample\n\nusing Ipopt\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = acLavStateEstimation(system, device, Ipopt.Optimizer)\n\n\n\n\n\n","category":"function"},{"location":"api/stateEstimation/#JuliaGrid.solve!-Tuple{PowerSystem, ACStateEstimation{NonlinearWLS{Normal}}}","page":"State Estimation","title":"JuliaGrid.solve!","text":"solve!(system::PowerSystem, analysis::ACStateEstimation)\n\nBy computing the bus voltage magnitudes and angles, the function solves the AC state estimation model.\n\nUpdates\n\nThe resulting bus voltage magnitudes and angles are stored in the voltage field of the ACStateEstimation type.\n\nExamples\n\nSolving the AC state estimation model and obtaining the WLS estimator:\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = gaussNewton(system, device)\nfor iteration = 1:20\n stopping = solve!(system, analysis)\n if stopping < 1e-8\n break\n end\nend\n\nSolving the AC state estimation model and obtaining the LAV estimator:\n\nusing Ipopt\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = acLavStateEstimation(system, device, Ipopt.Optimizer)\nsolve!(system, analysis)\n\n\n\n\n\n","category":"method"},{"location":"api/stateEstimation/","page":"State Estimation","title":"State Estimation","text":"","category":"page"},{"location":"api/stateEstimation/#PMU-State-Estimation-2","page":"State Estimation","title":"PMU State Estimation","text":"","category":"section"},{"location":"api/stateEstimation/","page":"State Estimation","title":"State Estimation","text":"pmuPlacement\npmuStateEstimation\npmuLavStateEstimation\nsolve!(::PowerSystem, ::PMUStateEstimation{LinearWLS{Normal}})","category":"page"},{"location":"api/stateEstimation/#JuliaGrid.pmuPlacement","page":"State Estimation","title":"JuliaGrid.pmuPlacement","text":"pmuPlacement(system::PowerSystem, optimizer; bridge)\n\nThe function determines the optimal placement of PMUs through integer linear programming. Specifically, it identifies the minimum set of PMU locations required for effective power system state estimation, ensuring observability with the least number of PMUs.\n\nThe function accepts a PowerSystem composite type as input to establish the framework for finding the optimal PMU placement. If the ac field within the PowerSystem composite type is not yet created, the function automatically initiates an update process.\n\nAdditionally, the optimizer argument is a crucial component for formulating and solving the optimization problem. Typically, using the GLPK or HiGHS solver is sufficient. For more detailed information, please refer to the JuMP documenatation.\n\nKeyword\n\nThe bridge keyword enables users to manage the bridging mechanism within the JuMP package.\n\nReturns\n\nThe function returns an instance of the PlacementPMU type, containing variables such as:\n\nbus: Bus labels with indices marking the positions of PMUs at buses.\nfrom: Branch labels with indices marking the positions of PMUs at from-bus ends.\nto: Branch labels with indices marking the positions of PMUs at to-bus ends.\n\nNote that if the conventional understanding of a PMU involves a device measuring the bus voltage phasor and all branch current phasors incident to the bus, the result is saved only in the bus variable. However, if we consider that a PMU measures individual phasors, each described with magnitude and angle, then measurements are needed at each bus in the bus variable, and each branch with positions given according to from and to variables.\n\nExample\n\nusing GLPK, Ipopt\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement()\n\nanalysis = acOptimalPowerFlow(system, Ipopt.Optimizer)\nsolve!(system, analysis)\ncurrent!(system, analysis)\n\nplacement = pmuPlacement(system, GLPK.Optimizer)\n\n@pmu(label = \"PMU ?: !\")\nfor (bus, i) in placement.bus\n Vi, θi = analysis.voltage.magnitude[i], analysis.voltage.angle[i]\n addPmu!(system, device; bus = bus, magnitude = Vi, angle = θi)\nend\nfor branch in keys(placement.from)\n Iij, ψij = fromCurrent(system, analysis; label = branch)\n addPmu!(system, device; from = branch, magnitude = Iij, angle = ψij)\nend\nfor branch in keys(placement.to)\n Iji, ψji = toCurrent(system, analysis; label = branch)\n addPmu!(system, device; to = branch, magnitude = Iji, angle = ψji)\nend\n\n\n\n\n\n","category":"function"},{"location":"api/stateEstimation/#JuliaGrid.pmuStateEstimation","page":"State Estimation","title":"JuliaGrid.pmuStateEstimation","text":"pmuStateEstimation(system::PowerSystem, device::Measurement, [method = LU])\n\nThe function establishes the linear WLS model for state estimation with PMUs only. In this model, the vector of state variables contains bus voltages, given in rectangular coordinates.\n\nArguments\n\nThis function requires the PowerSystem and Measurement composite types to establish the WLS state estimation model.\n\nMoreover, the presence of the method parameter is not mandatory. To address the WLS state estimation method, users can opt to utilize factorization techniques to decompose the gain matrix, such as LU, QR, or LDLt especially when the gain matrix is symmetric. Opting for the Orthogonal method is advisable for a more robust solution in scenarios involving ill-conditioned data, particularly when substantial variations in variances are present.\n\nIf the user does not provide the method, the default method for solving the estimation model will be LU factorization.\n\nUpdates\n\nIf the AC model has not been created, the function will automatically trigger an update of the ac field within the PowerSystem composite type.\n\nReturns\n\nThe function returns an instance of the PMUStateEstimation abstract type, which includes the following fields:\n\nvoltage: The variable allocated to store the bus voltage magnitudes and angles.\npower: The variable allocated to store the active and reactive powers.\nmethod: The system model vectors and matrices.\n\nExamples\n\nSet up the PMU state estimation model to be solved using the default LU factorization:\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = pmuStateEstimation(system, device)\n\nSet up the PMU state estimation model to be solved using the orthogonal method:\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = pmuStateEstimation(system, device, Orthogonal)\n\n\n\n\n\n","category":"function"},{"location":"api/stateEstimation/#JuliaGrid.pmuLavStateEstimation","page":"State Estimation","title":"JuliaGrid.pmuLavStateEstimation","text":"pmuLavStateEstimation(system::PowerSystem, device::Measurement, optimizer)\n\nThe function establishes the LAV model for state estimation with PMUs only. In this model, the vector of state variables contains bus voltages, given in rectangular coordinates.\n\nArguments\n\nThis function requires the PowerSystem and Measurement composite types to establish the LAV state estimation model. The LAV method offers increased robustness compared to WLS, ensuring unbiasedness even in the presence of various measurement errors and outliers.\n\nUsers can employ the LAV method to find an estimator by choosing one of the available optimization solvers. Typically, Ipopt.Optimizer suffices for most scenarios.\n\nUpdates\n\nIf the AC model has not been created, the function will automatically trigger an update of the ac field within the PowerSystem composite type.\n\nReturns\n\nThe function returns an instance of the PMUStateEstimation abstract type, which includes the following fields:\n\nvoltage: The variable allocated to store the bus voltage magnitudes and angles.\npower: The variable allocated to store the active and reactive powers.\nmethod: The optimization model.\n\nExample\n\nusing Ipopt\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = pmuLavStateEstimation(system, device, Ipopt.Optimizer)\n\n\n\n\n\n","category":"function"},{"location":"api/stateEstimation/#JuliaGrid.solve!-Tuple{PowerSystem, PMUStateEstimation{LinearWLS{Normal}}}","page":"State Estimation","title":"JuliaGrid.solve!","text":"solve!(system::PowerSystem, analysis::PMUStateEstimation)\n\nBy computing the bus voltage magnitudes and angles, the function solves the PMU state estimation model.\n\nUpdates\n\nThe resulting bus voltage magnitudes and angles are stored in the voltage field of the PMUStateEstimation type.\n\nExamples\n\nSolving the PMU state estimation model and obtaining the WLS estimator:\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = pmuStateEstimation(system, device)\nsolve!(system, analysis)\n\nSolving the PMU state estimation model and obtaining the LAV estimator:\n\nusing Ipopt\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = pmuLavStateEstimation(system, device, Ipopt.Optimizer)\nsolve!(system, analysis)\n\n\n\n\n\n","category":"method"},{"location":"api/stateEstimation/","page":"State Estimation","title":"State Estimation","text":"","category":"page"},{"location":"api/stateEstimation/#DC-State-Estimation-2","page":"State Estimation","title":"DC State Estimation","text":"","category":"section"},{"location":"api/stateEstimation/","page":"State Estimation","title":"State Estimation","text":"dcStateEstimation\ndcLavStateEstimation\nsolve!(::PowerSystem, ::DCStateEstimation{LinearWLS{Normal}})","category":"page"},{"location":"api/stateEstimation/#JuliaGrid.dcStateEstimation","page":"State Estimation","title":"JuliaGrid.dcStateEstimation","text":"dcStateEstimation(system::PowerSystem, device::Measurement, [method = LU])\n\nThe function establishes the WLS model for DC state estimation, where the vector of state variables contains only bus voltage angles.\n\nArguments\n\nThis function requires the PowerSystem and Measurement composite types to establish the WLS state estimation model.\n\nMoreover, the presence of the method parameter is not mandatory. To address the WLS state estimation method, users can opt to utilize factorization techniques to decompose the gain matrix, such as LU, QR, or LDLt especially when the gain matrix is symmetric. Opting for the Orthogonal method is advisable for a more robust solution in scenarios involving ill-conditioned data, particularly when substantial variations in variances are present.\n\nIf the user does not provide the method, the default method for solving the estimation model will be LU factorization.\n\nUpdates\n\nIf the DC model was not created, the function will automatically initiate an update of the dc field within the PowerSystem composite type. Additionally, if the slack bus lacks an in-service generator, JuliaGrid considers it a mistake and defines a new slack bus as the first generator bus with an in-service generator in the bus type list.\n\nReturns\n\nThe function returns an instance of the DCStateEstimation type, which includes the following fields:\n\nvoltage: The variable allocated to store the bus voltage angles.\npower: The variable allocated to store the active powers.\nmethod: The system model vectors and matrices.\n\nExamples\n\nSet up the DC state estimation model to be solved using the default LU factorization:\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = dcStateEstimation(system, device)\n\nSet up the DC state estimation model to be solved using the orthogonal method:\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = dcStateEstimation(system, device, Orthogonal)\n\n\n\n\n\n","category":"function"},{"location":"api/stateEstimation/#JuliaGrid.dcLavStateEstimation","page":"State Estimation","title":"JuliaGrid.dcLavStateEstimation","text":"dcLavStateEstimation(system::PowerSystem, device::Measurement, optimizer)\n\nThe function establishes the LAV model for DC state estimation, where the vector of state variables contains only bus voltage angles.\n\nArguments\n\nThis function requires the PowerSystem and Measurement composite types to establish the LAV state estimation model. The LAV method offers increased robustness compared to WLS, ensuring unbiasedness even in the presence of various measurement errors and outliers.\n\nUsers can employ the LAV method to find an estimator by choosing one of the available optimization solvers. Typically, Ipopt.Optimizer suffices for most scenarios.\n\nUpdates\n\nIf the DC model was not created, the function will automatically initiate an update of the dc field within the PowerSystem composite type. Additionally, if the slack bus lacks an in-service generator, JuliaGrid considers it a mistake and defines a new slack bus as the first generator bus with an in-service generator in the bus type list.\n\nReturns\n\nThe function returns an instance of the DCStateEstimation abstract type, which includes the following fields:\n\nvoltage: The variable allocated to store the bus voltage angles.\npower: The variable allocated to store the active powers.\nmethod: The optimization model.\n\nExample\n\nusing Ipopt\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = dcLavStateEstimation(system, device, Ipopt.Optimizer)\n\n\n\n\n\n","category":"function"},{"location":"api/stateEstimation/#JuliaGrid.solve!-Tuple{PowerSystem, DCStateEstimation{LinearWLS{Normal}}}","page":"State Estimation","title":"JuliaGrid.solve!","text":"solve!(system::PowerSystem, analysis::DCStateEstimation)\n\nBy computing the bus voltage angles, the function solves the DC state estimation model.\n\nUpdates\n\nThe resulting bus voltage angles are stored in the voltage field of the DCStateEstimation type.\n\nExamples\n\nSolving the DC state estimation model and obtaining the WLS estimator:\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = dcStateEstimation(system, device)\nsolve!(system, analysis)\n\nSolving the DC state estimation model and obtaining the LAV estimator:\n\nusing Ipopt\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = dcLavStateEstimation(system, device, Ipopt.Optimizer)\nsolve!(system, analysis)\n\n\n\n\n\n","category":"method"},{"location":"api/stateEstimation/","page":"State Estimation","title":"State Estimation","text":"","category":"page"},{"location":"api/stateEstimation/#Bad-Data-Analysis-2","page":"State Estimation","title":"Bad Data Analysis","text":"","category":"section"},{"location":"api/stateEstimation/","page":"State Estimation","title":"State Estimation","text":"residualTest!","category":"page"},{"location":"api/stateEstimation/#JuliaGrid.residualTest!","page":"State Estimation","title":"JuliaGrid.residualTest!","text":"residualTest!(system::PowerSystem, device::Measurement, analysis::StateEstimation;\n threshold)\n\nThe function conducts bad data detection and identification using the largest normalized residual test, subsequently removing measurement outliers from the measurement set. It can be executed after obtaining WLS estimator.\n\nArguments\n\nThis function requires the types PowerSystem, Measurement, and StateEstimation. The abstract type StateEstimation can have the following subtypes:\n\nACStateEstimation: Conducts bad data analysis within AC state estimation.\nPMUStateEstimation: Conducts bad data analysis within PMU state estimation.\nDCStateEstimation: Conducts bad data analysis within DC state estimation.\n\nKeyword\n\nThe keyword threshold establishes the identification threshold. If the largest normalized residual surpasses this threshold, the measurement is flagged as bad data. The default threshold value is set to threshold = 3.0.\n\nUpdates\n\nIf bad data is detected, the function flags the corresponding measurement within the Measurement type as out-of-service.\n\nMoreover, for DCStateEstimation and PMUStateEstimation types, the function removes the corresponding measurement from the coefficient matrix and mean vector. This facilitates direct progress to the function that solves the state estimation problem.\n\nReturns\n\nThe function returns an instance of the BadData type, which includes:\n\ndetect: Returns true after the function's execution if bad data is detected.\nmaxNormalizedResidual: Denotes the value of the largest normalized residual.\nlabel: Signifies the label of the bad data.\nindex: Represents the index of the bad data.\n\nExample\n\nsystem = powerSystem(\"case14.h5\")\ndevice = measurement(\"measurement14.h5\")\n\nanalysis = dcStateEstimation(system, device)\nsolve!(system, analysis)\n\noutlier = residualTest!(system, device, analysis; threshold = 4.0)\nsolve!(system, analysis)\n\n\n\n\n\n","category":"function"}] +} diff --git a/v0.2.0/siteinfo.js b/v0.2.0/siteinfo.js new file mode 100644 index 000000000..057c824fd --- /dev/null +++ b/v0.2.0/siteinfo.js @@ -0,0 +1 @@ +var DOCUMENTER_CURRENT_VERSION = "v0.2.0"; diff --git a/v0.2.0/tutorials/acOptimalPowerFlow/index.html b/v0.2.0/tutorials/acOptimalPowerFlow/index.html new file mode 100644 index 000000000..0e55b7aeb --- /dev/null +++ b/v0.2.0/tutorials/acOptimalPowerFlow/index.html @@ -0,0 +1,158 @@ + +AC Optimal Power Flow · JuliaGrid

AC Optimal Power Flow

To begin, let us generate the PowerSystem type, as illustrated by the following example:

using JuMP, Ipopt
+
+@labels(Integer)
+
+system = powerSystem()
+
+@bus(minMagnitude = 0.95, maxMagnitude = 1.05)
+addBus!(system; label = 1, type = 3, active = 0.1, angle = -0.1)
+addBus!(system; label = 2, reactive = 0.01, magnitude = 1.1)
+
+@branch(minDiffAngle = -pi, maxDiffAngle = pi, reactance = 0.5, type = 2)
+addBranch!(system; label = 1, from = 1, to = 2, maxFromBus = 0.15, maxToBus = 0.15)
+
+@generator(maxActive = 0.5, minReactive = -0.1, maxReactive = 0.1)
+addGenerator!(system; label = 1, bus = 1, active = 0.4, reactive = 0.2)
+addGenerator!(system; label = 2, bus = 2, active = 0.2, reactive = 0.1)
+
+cost!(system; label = 1, active = 2, polynomial = [900.0; 500.0; 80.0; 5.0])
+cost!(system; label = 2, active = 1, piecewise =  [10.8 12.3; 14.7 16.8; 18 18.1])
+
+cost!(system; label = 1, reactive = 1, piecewise = [10.0 20.0; 20.0 40.0])
+cost!(system; label = 2, reactive = 2, polynomial = [2.0])

To review, we can conceptualize the bus/branch model as the graph denoted by $\mathcal{G} = (\mathcal{N}, \mathcal{E})$, where we have the set of buses $\mathcal{N} = \{1, \dots, n\}$, and the set of branches $\mathcal{E} \subseteq \mathcal{N} \times \mathcal{N}$ within the power system:

julia> 𝒩 = collect(keys(system.bus.label))2-element Vector{Int64}:
+ 1
+ 2
julia> ℰ = [𝒩[system.branch.layout.from] 𝒩[system.branch.layout.to]]1×2 Matrix{Int64}: + 1 2

Moreover, we identify the set of generators as $\mathcal{S} = \{1, \dots, n_\text{g}\}$ within the power system:

julia> 𝒮 = collect(keys(system.generator.label))2-element Vector{Int64}:
+ 1
+ 2

Notation

Here, when referring to a vector $\mathbf{a}$, we use the notation $\mathbf{a} = [a_{i}]$ or $\mathbf{a} = [a_{ij}]$, where $a_i$ represents the element related with bus $i \in \mathcal{N}$ or generator $i \in \mathcal{S}$, while $a_{ij}$ denotes the element related with branch $(i,j) \in \mathcal{E}$.


Optimal Power Flow Model

In the AC optimal power flow model, the active and reactive power outputs of the generators, denoted as $\mathbf {P}_{\text{g}} = [{P}_{\text{g}i}]$ and $\mathbf {Q}_{\text{g}} = [{Q}_{\text{g}i}]$, where $i \in \mathcal{S}$, are expressed as nonlinear functions of the bus voltage magnitudes and angles, denoted as $\mathbf {V} = [{V}_{i}]$ and $\bm{\Theta} = [{\theta}_{i}]$, where $i \in \mathcal{N}$. Consequently, the optimization variables encompass the active and reactive power outputs of the generators, as well as the bus voltage magnitudes and angles.

The AC optimal power flow problem can be formulated as follows:

\[\begin{aligned} + & {\text{minimize}} & & \sum_{i \in \mathcal{S}} \left [ f_i(P_{\text{g}i}) + f_i(Q_{\text{g}i}) \right ] \\ + & \text{subject\;to} & & \theta_i - \theta_{\text{s}} = 0,\;\;\; i \in \mathcal{N_{\text{sb}}} \\[5pt] + & & & h_{P_i}(\mathbf {P}_{\text{g}}, \mathbf {V}, \bm{\Theta}) = 0,\;\;\; \forall i \in \mathcal{N} \\ + & & & h_{Q_i}(\mathbf {Q}_{\text{g}}, \mathbf {V}, \bm{\Theta}) = 0,\;\;\; \forall i \in \mathcal{N} \\[5pt] + & & & V_{i}^\text{min} \leq V_i \leq V_{i}^\text{max},\;\;\; \forall i \in \mathcal{N} \\ + & & & \theta_{ij}^\text{min} \leq \theta_i - \theta_j \leq \theta_{ij}^\text{max},\;\;\; \forall (i,j) \in \mathcal{E} \\[5pt] + & & & F_{ij}^{\text{min}} \leq h_{ij}(\mathbf {V}, \bm{\Theta}) \leq F_{ij}^{\text{max}},\;\;\; \forall (i,j) \in \mathcal{E} \\ + & & & F_{ji}^{\text{min}} \leq h_{ji}(\mathbf {V}, \bm{\Theta}) \leq F_{ji}^{\text{max}},\;\;\; \forall (i,j) \in \mathcal{E} \\[5pt] + & & & P_{\text{g}i}^\text{min} \leq P_{\text{g}i} \leq P_{\text{g}i}^\text{max} ,\;\;\; \forall i \in \mathcal{S} \\ + & & & Q_{\text{g}i}^\text{min} \leq Q_{\text{g}i} \leq Q_{\text{g}i}^\text{max} ,\;\;\; \forall i \in \mathcal{S}. +\end{aligned}\]

In essence, the AC optimal power flow aims to minimize the objective function associated with the costs of generator's active and reactive power output while ensuring the fulfillment of all constraints. This optimization task plays a pivotal role in effectively managing electrical power systems. By striking a balance between cost reduction and constraint adherence, the AC optimal power flow contributes to efficient and reliable electricity supply in complex grid environments.


Build Optimal Power Flow Model

To build the AC optimal power flow model, we must first load the power system and establish the AC model:

acModel!(system)

Afterward, the AC optimal power flow model is created using the acOptimalPowerFlow function:

analysis = acOptimalPowerFlow(
+  system, Ipopt.Optimizer; active = "Pg", reactive = "Qg", magnitude = "V", angle = "θ"
+)

Optimization Variables

The variables within this model encompass the active and reactive power outputs of the generators, denoted as $\mathbf{P}_{\text{g}} = [{P}_{\text{g}i}]$ and $\mathbf{Q}_{\text{g}} = [{Q}_{\text{g}i}]$, where $i \in \mathcal{S}$, and the bus voltage magnitudes and angles represented by $\mathbf{V} = [V_{i}]$ and $\bm{\Theta} = [{\theta}_{i}]$, where $i \in \mathcal{N}$. We can access these variables using the following code:

julia> 𝐏ₒ = analysis.method.variable.active2-element Vector{VariableRef}:
+ Pg[1]
+ Pg[2]
julia> 𝐐ₒ = analysis.method.variable.reactive2-element Vector{VariableRef}: + Qg[1] + Qg[2]
julia> 𝐕 = analysis.method.variable.magnitude2-element Vector{VariableRef}: + V[1] + V[2]
julia> 𝚯 = analysis.method.variable.angle2-element Vector{VariableRef}: + θ[1] + θ[2]

Objective Function

The objective function represents the sum of the active and reactive power cost functions $f_i(P_{\text{g}i})$ and $f_i(Q_{\text{g}i})$, where $i \in \mathcal{S}$, for each generator, where these cost functions can be polynomial or linear piecewise. Typically, the AC optimal power flow focuses on minimizing the cost of active power outputs only, but for comprehensive analysis, we also consider the costs associated with reactive power outputs.


Polynomial Cost Function

In the following analysis, we will focus on the cost function of generating active power, denoted as $f_i(P_{\text{g}i})$. However, please note that the same analysis can be applied to the cost function $f_i(Q_{\text{g}i})$ for reactive power.

In the AC optimal power flow, the cost function $f_i(P_{\text{g}i})$ can be represented as an $n$-th degree polynomial:

\[f_i(P_{\text{g}i}) = \sum_{k=0}^n a_k P_{\text{g}i}^k.\]

Typically, cost functions are represented as linear, quadratic, or cubic, as shown in Figure 1:

\[\begin{aligned} + f_i(P_{\text{g}i}) &= a_1P_{\text{g}i} + a_0 \\ + f_i(P_{\text{g}i}) &= a_2 P_{\text{g}i}^2 + a_1P_{\text{g}i} + a_0 \\ + f_i(P_{\text{g}i}) &= a_3 P_{\text{g}i}^3 + a_2 P_{\text{g}i}^2 + a_1P_{\text{g}i} + a_0. \\ +\end{aligned}\]

+
Figure 1: The polynomial cost functions of generator active power output.

When using the cost! function in JuliaGrid and specifying the polynomial keyword, the polynomial is constructed with coefficients arranged in descending order of their degrees, from the highest degree to the lowest. For example, in the case study provided, we generated a cubic polynomial cost function for the active output power of Generator 1, which is represented as:

\[\begin{aligned} + f_1(P_{\text{g}1}) &= 900 P_{\text{g}1}^3 + 500 P_{\text{g}1}^2 + 80 P_{\text{g}1} + 5. +\end{aligned}\]

To access these coefficients, users can utilize the variable:

julia> f₁ = system.generator.cost.active.polynomial[1]4-element Vector{Float64}:
+ 900.0
+ 500.0
+  80.0
+   5.0

Linear Piecewise Cost Function

The second option for defining cost functions in the AC optimal power flow is to use linear piecewise functions as approximations of the polynomial functions, as illustrated in Figure 2.

+
Figure 2: The linear piecewise cost functions of generator active power output.

To define linear piecewise functions in JuliaGrid, users can utilize the cost! function with the piecewise keyword. The linear piecewise function is constructed using a matrix where each row defines a single point. The first column holds the generator's active or reactive power output, while the second column corresponds to the associated cost value. For example, in the provided case study, a linear piecewise function is created and can be accessed as follows:

julia> f₂ = system.generator.cost.active.piecewise[2]3×2 Matrix{Float64}:
+ 10.8  12.3
+ 14.7  16.8
+ 18.0  18.1

JuliaGrid handles convex linear piecewise functions using a constrained cost variable method. In this approach, the piecewise linear cost function is replaced by a helper variable and a set of linear inequality constraints for each segment of the function defined by two neighboring points along the line. However, for linear piecewise functions that have only one segment defined by two points, JuliaGrid transforms it into a standard linear function without introducing a helper variable.

Hence, for a piecewise cost function denoted as $f_i(P_{\text{g}i})$ with $k$ segments (where $k > 1$), the $j$-th segment, defined by the points $[P_{\text{g}i,j}, f_i(P_{\text{g}i,j})]$ and $[P_{\text{g}i,j+1}, f_i(P_{\text{g}i,j+1})]$, is characterized by the following inequality constraints:

\[\cfrac{f_i(P_{\text{g}i,j+1}) - f_i(P_{\text{g}i,j})}{P_{\text{g}i,j+1} - P_{\text{g}i,j}}(P_{\text{g}i} - P_{\text{g}i,j}) + f_i(P_{\text{g}i,j}) \leq H_i, \;\;\; i \in \mathcal{S}, \;\;\; j = 1,\dots,k,\]

where $H_i$ represents the helper variable. To finalize this method, we simply need to include the helper variable $H_i$ in the objective function. This approach efficiently handles linear piecewise cost functions, providing the flexibility to capture nonlinear characteristics while still benefiting from the advantages of linear optimization techniques.

As an example, in the provided case study, the helper variable is defined as follows:

julia> H₂ = analysis.method.variable.actwise[2]actwise[2]

Lastly, the set of constraints introduced by the linear piecewise cost function is displayed as follows:

julia> print(analysis.method.constraint.piecewise.active)1.1538461538461542 Pg[2] - actwise[2] ≤ 0.16153846153846452
+0.3939393939393941 Pg[2] - actwise[2] ≤ -11.009090909090908

Objective Function

As previously explained, the objective function relies on the defined polynomial or linear piecewise cost functions and represents the sum of these costs. In the provided example, the objective function that must be minimized to obtain the optimal values for the active and reactive power outputs of the generators and the bus voltage magnitudes and angles can be accessed using the following:

julia> JuMP.objective_function(analysis.method.jump)(500 Pg[1]² + 80 Pg[1] + 2 Qg[1] + actwise[2] + 7) + (900.0 * (Pg[1] ^ 3.0))

Constraint Functions

In the following section, we will examine the various constraints defined within the AC optimal power flow model.


Slack Bus Constraint

The first equality constraint is linked to the slack bus, where the bus voltage angle denoted as $\theta_i$ is fixed to a constant value $\theta_{\text{s}}$. It can be expressed as follows:

\[\theta_i - \theta_{\text{s}} = 0,\;\;\; i \in \mathcal{N_{\text{sb}}},\]

where the set $\mathcal{N}_{\text{sb}}$ contains the index of the slack bus. To access the equality constraint from the model, we can utilize the variable:

julia> print(analysis.method.constraint.slack.angle)θ[1] = -0.1

Bus Power Balance Constraints

The second equality constraint in the optimization problem is associated with the active power balance equation:

\[\begin{aligned} +h_{P_i}(\mathbf {P}_{\text{g}}, \mathbf {V}, \bm{\Theta}) = 0,\;\;\; \forall i \in \mathcal{N}. +\end{aligned}\]

As elaborated in the Bus Injections section, we can express the equation as follows:

\[h_{P_i}(\mathbf {P}_{\text{g}}, \mathbf {V}, \bm{\Theta}) = {V}_{i}\sum\limits_{j=1}^n (G_{ij}\cos\theta_{ij}+B_{ij}\sin\theta_{ij})V_j - \sum_{k \in \mathcal{S}_i} P_{\text{g}k} + P_{\text{d}i}.\]

In this equation, the set $\mathcal{S}_i \subseteq \mathcal{S}$ encompasses all generators connected to bus $i \in \mathcal{N}$, and $P_{\text{g}k}$ represents the active power output of the $k$-th generator within the set $\mathcal{S}_i$. More Precisely, the variable $P_{\text{g}k}$ represents the optimization variable, along with the bus voltage angles $\theta_{ij} = \theta_i - \theta_j$ and the bus voltage magnitudes $V_i$ and $V_j$.

The constant term is determined by the active power demand $P_{\text{d}i}$ at bus $i \in \mathcal{N}$. The values representing this constant term, denoted as $\mathbf{P}_{\text{d}} = [P_{\text{d}i}]$, $i, \in \mathcal{N}$, can be accessed using the following:

julia> 𝐏ₒ = system.bus.demand.active2-element Vector{Float64}:
+ 0.1
+ 0.0

We can access the references to the active power balance constraints using the following snippet:

julia> print(analysis.method.constraint.balance.active)Pg[1] - (V[1] * ((V[2] * ((2.0 * sin(θ[1] - θ[2])))))) - 0.1 = 0
+Pg[2] - (V[2] * ((V[1] * ((2.0 * sin(-θ[1] + θ[2])))))) - 0.0 = 0

Similarly, the next constraint in the optimization problem is associated with the reactive power balance equation:

\[\begin{aligned} +h_{Q_i}(\mathbf {Q}_{\text{g}}, \mathbf {V}, \bm{\Theta}) = 0,\;\;\; \forall i \in \mathcal{N}. +\end{aligned}\]

As elaborated in the Bus Injections section, we can express the equation as follows:

\[h_{Q_i}(\mathbf {Q}_{\text{g}}, \mathbf {V}, \bm{\Theta}) = {V}_{i}\sum\limits_{j=1}^n (G_{ij}\sin\theta_{ij}-B_{ij}\cos\theta_{ij})V_j - \sum_{k \in \mathcal{S}_i} Q_{\text{g}k} + Q_{\text{d}i}.\]

As mentioned earlier for active power, $Q_{\text{g}k}$ represents the reactive power output of the $k$-th generator within the set $\mathcal{S}_i$. The variable $Q_{\text{g}k}$ serves as an optimization variable, as well as the bus voltage angles $\theta_{ij} = \theta_i - \theta_j$, and the bus voltage magnitudes $V_i$ and $V_j$.

The constant term is determined by the reactive power demand $Q_{\text{d}i}$ at bus $i \in \mathcal{N}$. The values representing this constant term, denoted as $\mathbf{Q}_{\text{d}} = [Q_{\text{d}i}]$, $i, \in \mathcal{N}$, can be accessed using the following:

julia> 𝐐ₒ = system.bus.demand.reactive2-element Vector{Float64}:
+ 0.0
+ 0.01

We can access the references to the reactive power balance constraints using the following snippet:

julia> print(analysis.method.constraint.balance.reactive)Qg[1] - (V[1] * ((2 V[1]) + (V[2] * ( - (2.0 * cos(θ[1] - θ[2])))))) - 0.0 = 0
+Qg[2] - (V[2] * ((2 V[2]) + (V[1] * ( - (2.0 * cos(-θ[1] + θ[2])))))) - 0.01 = 0

Bus Voltage Constraints

The inequality constraints associated with the voltage magnitude ensure that the bus voltage magnitudes are within specified limits:

\[V_{i}^\text{min} \leq V_i \leq V_{i}^\text{max},\;\;\; \forall i \in \mathcal{N},\]

where $V_{i}^\text{min}$ represents the minimum voltage magnitude, and $V_{i}^\text{max}$ represents the maximum voltage magnitude for bus $i \in \mathcal{N}$. The values representing these voltage magnitude limits, denoted as $\mathbf{V}_{\text{lm}} = [V_{i}^\text{min}, V_{i}^\text{max}]$, $i \in \mathcal{N}$, can be accessed using the following:

julia> 𝐕ₗₘ = [system.bus.voltage.minMagnitude system.bus.voltage.maxMagnitude]2×2 Matrix{Float64}:
+ 0.95  1.05
+ 0.95  1.05

To retrieve this inequality constraint from the model, we can use the following:

julia> print(analysis.method.constraint.voltage.magnitude)V[1] ∈ [0.95, 1.05]
+V[2] ∈ [0.95, 1.05]

The inequality constraint related to the minimum and maximum bus voltage angle difference between the from-bus and to-bus ends of each branch is defined as follows:

\[\theta_{ij}^\text{min} \leq \theta_i - \theta_j \leq \theta_{ij}^\text{max},\;\;\; \forall (i,j) \in \mathcal{E},\]

where $\theta_{ij}^\text{min}$ represents the minimum, while $\theta_{ij}^\text{max}$ represents the maximum of the angle difference between adjacent buses. The values representing the voltage angle difference, denoted as $\bm{\Theta}_{\text{lm}} = [\theta_{ij}^\text{min}, \theta_{ij}^\text{max}]$, $(i,j) \in \mathcal{E}$, are provided as follows:

julia> 𝚯ₗₘ = [system.branch.voltage.minDiffAngle system.branch.voltage.maxDiffAngle]1×2 Matrix{Float64}:
+ -3.14159  3.14159

To retrieve this inequality constraint from the model, we can use the following:

julia> print(analysis.method.constraint.voltage.angle)θ[1] - θ[2] ∈ [-3.141592653589793, 3.141592653589793]

Branch Flow Constraints

The inequality constraints related to the branch flow ratings can be associated with the limits on apparent power flow, active power flow, or current magnitude at the from-bus and to-bus ends of each branch. The type of constraint applied is determined by the type keyword within the addBranch! function.

Specifically, type = 1 is used for apparent power flow, type = 2 for active power flow, and type = 3 for current magnitude. These constraints can be expressed using the equations $h_{ij}(\mathbf {V}, \bm{\Theta})$ and $h_{ji}(\mathbf {V}, \bm{\Theta})$, representing the rating constraints at the from-bus and to-bus ends of each branch, respectively:

\[\begin{aligned} + F_{ij}^{\text{min}} \leq h_{ij}(\mathbf {V}, \bm{\Theta}) \leq F_{ij}^{\text{max}},\;\;\; \forall (i,j) \in \mathcal{E} \\ + F_{ji}^{\text{min}} \leq h_{ji}(\mathbf {V}, \bm{\Theta}) \leq F_{ji}^{\text{max}},\;\;\; \forall (i,j) \in \mathcal{E}. +\end{aligned}\]

The branch flow limits at the from-bus and to-bus ends, denoted as $\mathbf{F}_{\text{f}} = [F_{ij}^\text{min}, F_{ij}^\text{max}]$ and $\mathbf{F}_{\text{t}} = [F_{ji}^\text{min}, F_{ji}^\text{max}]$, $(i,j) \in \mathcal{E}$, can be retrieved as follows:

julia> 𝐅ₒ = [system.branch.flow.minFromBus system.branch.flow.maxFromBus]1×2 Matrix{Float64}:
+ 0.0  0.15
julia> 𝐅ₜ = [system.branch.flow.minToBus system.branch.flow.maxToBus]1×2 Matrix{Float64}: + 0.0 0.15

By default, JuliaGrid employs the rating constraints linked with the apparent power flow (type = 1). This constraint at the from-bus is specified as:

\[ h_{ij}(\mathbf {V}, \bm{\Theta}) = \sqrt{ A_{ij} V_i^4 + B_{ij} V_i^2 V_j^2 - 2 [C_{ij} \cos(\theta_{ij} - \phi_{ij}) - D_{ij} \sin(\theta_{ij} - \phi_{ij})]V_i^3 V_j},\]

where:

\[ \begin{gathered} + A_{ij} = \cfrac{(g_{ij} + g_{\text{s}i})^2+(b_{ij}+b_{\text{s}i})^2}{\tau_{ij}^4}, \;\;\; B_{ij} = \cfrac{g_{ij}^2+b_{ij}^2}{\tau_{ij}^2} \\ + C_{ij} = \cfrac{g_{ij}(g_{ij}+g_{\text{s}i})+b_{ij}(b_{ij}+b_{\text{s}i})}{\tau_{ij}^3}, \;\;\; D_{ij} = \cfrac{g_{ij}b_{\text{s}i} - b_{ij}g_{\text{s}i}}{\tau_{ij}^3}. + \end{gathered}\]

Furthermore, this constraint at the to-bus is specified as:

\[ h_{ji}(\mathbf {V}, \bm{\Theta}) = \sqrt{ A_{ji} V_j^4 + B_{ji} V_i^2 V_j^2 - 2 [C_{ji} \cos(\theta_{ij} - \phi_{ij}) + D_{ij} \sin(\theta_{ij} - \phi_{ij})]V_i V_j^3 },\]

where:

\[ \begin{gathered} + A_{ji} = (g_{ij} + g_{\text{s}i})^2+(b_{ij}+b_{\text{s}i})^2, \;\;\; B_{ji} = \cfrac{g_{ij}^2+b_{ij}^2}{\tau_{ij}^2} \\ + C_{ji} = \cfrac{g_{ij}(g_{ij}+g_{\text{s}i})+b_{ij}(b_{ij}+b_{\text{s}i})}{\tau_{ij}}, \;\;\; D_{ji} = \cfrac{g_{ij}b_{\text{s}i} - b_{ij}g_{\text{s}i}}{\tau_{ij}}. + \end{gathered}\]


The second option is to define the limit keywords for active power flow constraints (type = 2) at the from-bus and to-bus ends of each branch:

\[ \begin{aligned} + h_{ij}(\mathbf {V}, \bm{\Theta}) &= + \cfrac{ g_{ij} + g_{\text{s}ij}}{\tau_{ij}^2} V_{i}^2 - + \cfrac{1}{\tau_{ij}} \left[g_{ij}\cos(\theta_{ij} - \phi_{ij}) + b_{ij}\sin(\theta_{ij} - \phi_{ij})\right]V_{i}V_{j} \\ + h_{ji}(\mathbf {V}, \bm{\Theta}) &= (g_{ij} + g_{\text{s}ij}) V_{j}^2 - + \cfrac{1}{\tau_{ij}} \left[g_{ij} \cos(\theta_{ij} - \phi_{ij}) - b_{ij} \sin(\theta_{ij}- \phi_{ij})\right] V_{i} V_j. + \end{aligned}\]

In our example, we have chosen to utilize this type of flow constraints. To access the flow constraints of branches at the from-bus end, you can use the following code snippet:

julia> print(analysis.method.constraint.flow.from) - ((V[1]*V[2]) * ((-2.0 * sin(θ[1] - θ[2])))) ∈ [0, 0.15]

Similarly, to access the to-bus end flow constraints of branches you can use the following code snippet:

julia> print(analysis.method.constraint.flow.to) - ((V[1]*V[2]) * ( - (-2.0 * sin(θ[1] - θ[2])))) ∈ [0, 0.15]

The last option involves defining the limit keywords for current magnitude constraints (type = 3) at the from-bus and to-bus ends of each branch. In this case, the constraints are implemented as follows:

\[ \begin{aligned} + h_{ij}(\mathbf {V}, \bm{\Theta}) &= \sqrt{A_{ij}V_i^2 + B_{ij}V_j^2 - 2[C_{ij} \cos(\theta_{ij} - \phi_{ij}) - D_{ij}\sin(\theta_{ij} - \phi_{ij})]V_iV_j} \\ + h_{ji}(\mathbf {V}, \bm{\Theta}) &= \sqrt{A_{ji}V_j^2 + B_{ji}V_i^2 - 2[C_{ji} \cos(\theta_{ij} - \phi_{ij}) + D_{ji}\sin(\theta_{ij} - \phi_{ij})]V_iV_j}. + \end{aligned}\]


Generator Power Capability Constraints

The next set of constraints pertains to the minimum and maximum limits of active and reactive power outputs of the generators. These constraints ensure that the power outputs of the generators remain within specified bounds:

\[P_{\text{g}i}^\text{min} \leq P_{\text{g}i} \leq P_{\text{g}i}^\text{max} ,\;\;\; \forall i \in \mathcal{S}.\]

In this representation, the lower and upper limits are determined by the vector $\mathbf{P}_{\text{m}} = [P_{\text{g}i}^\text{min}, P_{\text{g}i}^\text{max}]$, $i \in \mathcal{S}$. We can access these bounds using the following:

julia> 𝐏ₘ = [system.generator.capability.minActive, system.generator.capability.maxActive]2-element Vector{Vector{Float64}}:
+ [0.0, 0.0]
+ [0.5, 0.5]

To access these constraints, you can utilize the following snippet:

julia> print(analysis.method.constraint.capability.active)Pg[1] ∈ [0, 0.5]
+Pg[2] ∈ [0, 0.5]

Similarly, constraints related to the minimum and maximum limits of reactive power outputs of the generators ensure that the reactive powers remain within specified boundaries:

\[Q_{\text{g}i}^\text{min} \leq Q_{\text{g}i} \leq Q_{\text{g}i}^\text{max} ,\;\;\; \forall i \in \mathcal{S}.\]

Thus, the lower and upper limits are determined by the vector $\mathbf{Q}_{\text{m}} = [Q_{\text{g}i}^\text{min}, Q_{\text{g}i}^\text{max}]$, $i \in \mathcal{S}$. We can access these bounds using the following:

julia> 𝐐ₘ = [system.generator.capability.minReactive system.generator.capability.maxReactive]2×2 Matrix{Float64}:
+ -0.1  0.1
+ -0.1  0.1

To access these constraints, you can use the following snippet:

julia> print(analysis.method.constraint.capability.reactive)Qg[1] ∈ [-0.1, 0.1]
+Qg[2] ∈ [-0.1, 0.1]

These capability limits of the generators define the feasible region, represented as a gray area in Figure 3, which forms the solution space for the active and reactive output powers of the generators.

+
Figure 3: The feasible region created by the active and reactive power capability constraints.

However, this representation might not be the most accurate depiction of the generator's output power behavior. In reality, there exists a tradeoff between the active and reactive power outputs of the generators [8]. Specifically, when a generator operates at its maximum active power $P_{\text{g}i}^\text{max}$, it may not be able to produce the maximum $Q_{\text{g}i}^\text{max}$ or minimum $Q_{\text{g}i}^\text{min}$ reactive power. To capture this tradeoff, we introduce the ability to include additional upper and lower constraints on the feasible region, leading to its reduction as shown in Figure 4.

+
Figure 4: The feasible region created by the active and reactive power capability constraints with additional upper and lower constraints.

If a user wishes to incorporate the tradeoff between active and reactive power outputs into the optimization model, they can define the points shown in Figure 4 within the addGenerator! function using the following keywords:

KeywordCoordinate
lowActive$P_{\text{g}i}^\text{low}$
minLowReactive$Q_{\text{g}i,\text{low}}^\text{min}$
maxLowReactive$Q_{\text{g}i,\text{low}}^\text{max}$
upActive$P_{\text{g}i}^\text{up}$
minUpReactive$Q_{\text{g}i,\text{up}}^\text{min}$
maxUpReactive$Q_{\text{g}i,\text{up}}^\text{max}$

When using these points, JuliaGrid constructs two additional capability constraints per generator as follows:

\[\begin{aligned} + (Q_{\text{g}i,\text{low}}^\text{max} - Q_{\text{g}i,\text{up}}^\text{max})P_{\text{g}i} + (P_{\text{g}i}^\text{up} - P_{\text{g}i}^\text{low})Q_{\text{g}i} + \leq (Q_{\text{g}i,\text{low}}^\text{max} - Q_{\text{g}i,\text{up}}^\text{max})P_{\text{g}i}^\text{low} + (P_{\text{g}i}^\text{up} - P_{\text{g}i}^\text{low})Q_{\text{g}i,\text{low}}^\text{max} \\ + (Q_{\text{g}i,\text{up}}^\text{min} - Q_{\text{g}i,\text{low}}^\text{min})P_{\text{g}i} + (P_{\text{g}i}^\text{low} - P_{\text{g}i}^\text{up})Q_{\text{g}i} + \leq (Q_{\text{g}i,\text{up}}^\text{min} - Q_{\text{g}i,\text{low}}^\text{min})P_{\text{g}i}^\text{low} + (P_{\text{g}i}^\text{low} - P_{\text{g}i}^\text{up})Q_{\text{g}i,\text{low}}^\text{min}. +\end{aligned}\]

To ensure numerical stability, these constraints are normalized by introducing two scaling factors:

\[\begin{aligned} + s_1 = \sqrt{(Q_{\text{g}i,\text{low}}^\text{max} - Q_{\text{g}i,\text{up}}^\text{max})^2 + (P_{\text{g}i}^\text{up} - P_{\text{g}i}^\text{low})^2}\\ + s_2 = \sqrt{(Q_{\text{g}i,\text{up}}^\text{min} - Q_{\text{g}i,\text{low}}^\text{min})^2 + (P_{\text{g}i}^\text{low} - P_{\text{g}i}^\text{up})^2}. +\end{aligned}\]

When these constraints exist in the system, users can access them using the following variables:

analysis.method.constraint.capability.upper
+analysis.method.constraint.capability.lower

These additional capability constraints allow us to accurately represent the tradeoff between active and reactive power outputs of the generators while maintaining numerical stability.


Optimal Power Flow Solution

To obtain the optimal values of active and reactive power outputs for generators and the bus voltage magnitudes and angles, the user needs to invoke the following function:

solve!(system, analysis)

After solving the AC optimal power flow problem, you can retrieve the vectors of output active and reactive power for generators, denoted as $\mathbf{P}_{\text{g}} = [P_{\text{g}i}]$ and $\mathbf{Q}_{\text{g}} = [Q_{\text{g}i}]$, where $i \in \mathcal{S}$, using the following commands:

julia> 𝐏ₒ = analysis.power.generator.active2-element Vector{Float64}:
+ 0.09999999002060665
+ 9.979393357759393e-9
julia> 𝐐ₒ = analysis.power.generator.reactive2-element Vector{Float64}: + -0.0863265171095855 + 0.09999999755725082

Similarly, the resulting bus voltage magnitudes and angles, represented by $\mathbf{V} = [V_{i}]$ and $\bm{\Theta} = [\theta_{i}]$, where $i \in \mathcal{N}$, are stored in the vectors as follows:

julia> 𝐕 = analysis.voltage.magnitude2-element Vector{Float64}:
+ 1.0071411833198654
+ 1.0499983906951869
julia> 𝚯 = analysis.voltage.angle2-element Vector{Float64}: + -0.1 + -0.0999999952815312

By accessing these vectors, you can analyze and utilize the optimal power flow solution for further studies or operational decision-making in the power system.


Power Analysis

Once the computation of voltage magnitudes and angles at each bus is completed, various electrical quantities can be determined. JuliaGrid offers the power! function, which enables the calculation of powers associated with buses and branches. Here is an example code snippet demonstrating its usage:

power!(system, analysis)

The function stores the computed powers in the rectangular coordinate system. It calculates the following powers related to buses and branches:

BusActiveReactive
Injections$\mathbf{P} = [P_i]$$\mathbf{Q} = [Q_i]$
Generator injections$\mathbf{P}_{\text{p}} = [P_{\text{p}i}]$$\mathbf{Q}_{\text{p}} = [Q_{\text{p}i}]$
Shunt elements$\mathbf{P}_{\text{sh}} = [{P}_{\text{sh}i}]$$\mathbf{Q}_{\text{sh}} = [{Q}_{\text{sh}i}]$
BranchActiveReactive
From-bus end flows$\mathbf{P}_{\text{i}} = [P_{ij}]$$\mathbf{Q}_{\text{i}} = [Q_{ij}]$
To-bus end flows$\mathbf{P}_{\text{j}} = [P_{ji}]$$\mathbf{Q}_{\text{j}} = [Q_{ji}]$
Shunt elements$\mathbf{P}_{\text{s}} = [P_{\text{s}ij}]$$\mathbf{P}_{\text{s}} = [P_{\text{s}ij}]$
Series elements$\mathbf{P}_{\text{l}} = [P_{\text{l}ij}]$$\mathbf{Q}_{\text{l}} = [Q_{\text{l}ij}]$
Info

For a clear comprehension of the equations, symbols presented in this section, as well as for a better grasp of power directions, please refer to the Unified Branch Model.


Power Injections

Active and reactive power injections are stored as the vectors $\mathbf{P} = [P_i]$ and $\mathbf{Q} = [Q_i]$, respectively, and can be retrieved using the following commands:

julia> 𝐏 = analysis.power.injection.active2-element Vector{Float64}:
+ -9.979529558626354e-9
+  9.979529558626354e-9
julia> 𝐐 = analysis.power.injection.reactive2-element Vector{Float64}: + -0.08632651709953175 + 0.08999999754755438

Generator Power Injections

The power! function in JuliaGrid also provides the computation of active and reactive power injections from the generators at each bus. To calculate the active power supplied by generators to the buses, one can simply sum the active power outputs of the generators obtained from the AC optimal power flow. This can be represented as:

\[ P_{\text{p}i} = \sum_{k \in \mathcal{S}_i} P_{\text{g}k},\;\;\; \forall i \in \mathcal{N},\]

where the set $\mathcal{S}_i \subseteq \mathcal{S}$ encompasses all generators connected to bus $i \in \mathcal{N}$. The active power injections from the generators at each bus are stored as a vector denoted by $\mathbf{P}_{\text{p}} = [P_{\text{p}i}]$, and can be obtained using:

julia> 𝐏ₚ = analysis.power.supply.active2-element Vector{Float64}:
+ 0.09999999002060665
+ 9.979393357759393e-9

Similarly, we can obtain the reactive power supplied by generators to the buses:

\[ Q_{\text{p}i} = \sum_{k \in \mathcal{S}_i} Q_{\text{g}k},\;\;\; \forall i \in \mathcal{N}.\]

The vector of these reactive power injections by the generators to the buses, denoted by $\mathbf{Q}_{\text{p}} = [Q_{\text{p}i}]$, can be retrieved using the following command:

julia> 𝐐ₚ = analysis.power.supply.reactive2-element Vector{Float64}:
+ -0.0863265171095855
+  0.09999999755725082

Power at Bus Shunt Elements

Active and reactive powers associated with the shunt elements at each bus are represented by the vectors $\mathbf{P}_{\text{sh}} = [{P}_{\text{sh}i}]$ and $\mathbf{Q}_{\text{sh}} = [{Q}_{\text{sh}i}]$. To retrieve these powers in JuliaGrid, use the following commands:

julia> 𝐏ₛₕ = analysis.power.shunt.active2-element Vector{Float64}:
+ 0.0
+ 0.0
julia> 𝐐ₛₕ = analysis.power.shunt.reactive2-element Vector{Float64}: + -0.0 + -0.0

Power Flows

The resulting active and reactive power flows at each from-bus end are stored as the vectors $\mathbf{P}_{\text{i}} = [P_{ij}]$ and $\mathbf{Q}_{\text{i}} = [Q_{ij}],$ respectively, and can be retrieved using the following commands:

julia> 𝐏ᵢ = analysis.power.from.active1-element Vector{Float64}:
+ -9.979529558626354e-9
julia> 𝐐ᵢ = analysis.power.from.reactive1-element Vector{Float64}: + -0.08632651709953175

Similarly, the vectors of active and reactive power flows at the to-bus end are stored as $\mathbf{P}_{\text{j}} = [P_{ji}]$ and $\mathbf{Q}_{\text{j}} = [Q_{ji}]$, respectively, and can be retrieved using the following code:

julia> 𝐏ⱼ = analysis.power.to.active1-element Vector{Float64}:
+ 9.979529558626354e-9
julia> 𝐐ⱼ = analysis.power.to.reactive1-element Vector{Float64}: + 0.08999999754755438

Power at Branch Shunt Elements

Active and reactive powers associated with the branch shunt elements at each branch are represented by the vectors $\mathbf{P}_{\text{s}} = [P_{\text{s}ij}]$ and $\mathbf{Q}_{\text{s}} = [Q_{\text{s}ij}]$. We can retrieve these values using the following code:

julia> 𝐏ₛ = analysis.power.charging.active1-element Vector{Float64}:
+ 0.0
julia> 𝐐ₛ = analysis.power.charging.reactive1-element Vector{Float64}: + -0.0

Power at Branch Series Elements

Active and reactive powers associated with the branch series element at each branch are represented by the vectors $\mathbf{P}_{\text{l}} = [P_{\text{l}ij}]$ and $\mathbf{Q}_{\text{l}} = [Q_{\text{l}ij}]$. We can retrieve these values using the following code:

julia> 𝐏ₗ = analysis.power.series.active1-element Vector{Float64}:
+ 0.0
julia> 𝐐ₗ = analysis.power.series.reactive1-element Vector{Float64}: + 0.003673480448022624

Current Analysis

JuliaGrid offers the current! function, which enables the calculation of currents associated with buses and branches. Here is an example code snippet demonstrating its usage:

current!(system, analysis)

The function stores the computed currents in the polar coordinate system. It calculates the following currents related to buses and branches:

BusMagnitudeAngle
Injections$\mathbf{I} = [I_i]$$\bm{\psi} = [\psi_i]$
BranchMagnitudeAngle
From-bus end flows$\mathbf{I}_{\text{i}} = [I_{ij}]$$\bm{\psi}_{\text{i}} = [\psi_{ij}]$
To-bus end flows$\mathbf{I}_{\text{j}} = [I_{ji}]$$\bm{\psi}_{\text{j}} = [\psi_{ji}]$
Series elements$\mathbf{I}_{\text{l}} = [I_{\text{l}ij}]$$\bm{\psi}_{\text{l}} = [\psi_{\text{l}ij}]$
Info

For a clear comprehension of the equations, symbols presented in this section, as well as for a better grasp of power directions, please refer to the Unified Branch Model.


Current Injections

In JuliaGrid, complex current injections are stored in the vector of magnitudes denoted as $\mathbf{I} = [I_i]$ and the vector of angles represented as $\bm{\psi} = [\psi_i]$. You can retrieve them using the following commands:

julia> 𝐈 = analysis.current.injection.magnitude2-element Vector{Float64}:
+ 0.08571441475064301
+ 0.08571441475064301
julia> 𝛙 = analysis.current.injection.angle2-element Vector{Float64}: + 1.4707964423970301 + -1.6707962111927632

Current Flows

To obtain the vectors of magnitudes $\mathbf{I}_{\text{i}} = [I_{ij}]$ and angles $\bm{\psi}_{\text{i}} = [\psi_{ij}]$ for the resulting complex current flows, you can use the following commands:

julia> 𝐈ᵢ = analysis.current.from.magnitude1-element Vector{Float64}:
+ 0.08571441475064301
julia> 𝛙ᵢ = analysis.current.from.angle1-element Vector{Float64}: + 1.4707964423970301

Similarly, we can obtain the vectors of magnitudes $\mathbf{I}_{\text{j}} = [I_{ji}]$ and angles $\bm{\psi}_{\text{j}} = [\psi_{ji}]$ of the resulting complex current flows using the following code:

julia> 𝐈ⱼ = analysis.current.to.magnitude1-element Vector{Float64}:
+ 0.08571441475064301
julia> 𝛙ⱼ = analysis.current.to.angle1-element Vector{Float64}: + -1.6707962111927632

Current at Branch Series Elements

To obtain the vectors of magnitudes $\mathbf{I}_{\text{l}} = [I_{\text{l}ij}]$ and angles $\bm{\psi}_{\text{l}} = [\psi_{\text{l}ij}]$ of the resulting complex current flows, one can use the following code:

julia> 𝐈ₗ = analysis.current.series.magnitude1-element Vector{Float64}:
+ 0.08571441475064301
julia> 𝛙ₗ = analysis.current.series.angle1-element Vector{Float64}: + 1.4707964423970301
diff --git a/v0.2.0/tutorials/acPowerFlow/index.html b/v0.2.0/tutorials/acPowerFlow/index.html new file mode 100644 index 000000000..11f008f32 --- /dev/null +++ b/v0.2.0/tutorials/acPowerFlow/index.html @@ -0,0 +1,457 @@ + +AC Power Flow · JuliaGrid

AC Power Flow

JuliaGrid uses standard network components and the Unified Branch Model for power flow analysis, allowing load profiles, generator capacities, voltage specifications, contingency analysis, and planning to be defined efficiently.

To begin, let us generate the PowerSystem type, as illustrated by the following example:

@labels(Integer)
+
+@power(MW, MVAr, MVA)
+@voltage(pu, deg, V)
+
+system = powerSystem()
+
+addBus!(system; label = 1, type = 3)
+addBus!(system; label = 2, type = 1, active = 21.7, reactive = 12.7)
+addBus!(system; label = 3, type = 1, active = 11.2, reactive = -3.0)
+addBus!(system; label = 4, type = 2, conductance = 2.1, susceptance = 1.2)
+
+addBranch!(system; from = 1, to = 2, resistance = 0.02, reactance = 0.06)
+addBranch!(system; from = 1, to = 3, resistance = 0.05, reactance = 0.21)
+addBranch!(system; from = 2, to = 3, resistance = 0.13, reactance = 0.26)
+addBranch!(system; from = 3, to = 4, reactance = 0.17, susceptance = 0.2, conductance = 1e-4)
+
+addGenerator!(system; bus = 1)
+addGenerator!(system; bus = 3, active = 40.0, reactive = 42.4)

To review, we can conceptualize the bus/branch model as the graph denoted by $\mathcal{G} = (\mathcal{N}, \mathcal{E})$, where we have the set of buses $\mathcal{N} = \{1, \dots, n\}$, and the set of branches $\mathcal{E} \subseteq \mathcal{N} \times \mathcal{N}$ within the power system:

julia> 𝒩 = collect(keys(system.bus.label))4-element Vector{Int64}:
+ 1
+ 2
+ 3
+ 4
julia> ℰ = hcat([𝒩[system.branch.layout.from] 𝒩[system.branch.layout.to]])4×2 Matrix{Int64}: + 1 2 + 1 3 + 2 3 + 3 4

Notation

In this section, when referring to a vector $\mathbf{a}$, we use the notation $\mathbf{a} = [a_{i}]$ or $\mathbf{a} = [a_{ij}]$, where $a_i$ represents the element associated with bus $i \in \mathcal{N}$, and $a_{ij}$ represents the element associated with branch $(i,j) \in \mathcal{E}$.


Nodal Network Equations

As previously demonstrated in the section on the Nodal Network Equations, we observe the system of equations:

\[ \mathbf{\bar {I}} = \mathbf{Y} \mathbf{\bar {V}}.\]

The complex current injection at the bus $i \in \mathcal{N}$ is defined as:

\[ \bar{I}_{i} = \cfrac{S_{i}^*}{\bar{V}_{i}^*}.\]

Thus, for any given bus $i \in \mathcal{N}$, we can express it as:

\[ \cfrac{S_{i}^*}{\bar{V}_{i}^*} = \sum_{j = 1}^n Y_{ij} \bar {V}_j.\]

The complex power injection denoted by $S_i$ consists of both the active power $P_i$ and reactive power $Q_i$. This relationship can be represented as follows:

\[ \cfrac{P_i - \text{j}Q_i}{\bar{V}_{i}} = \sum_{j = 1}^n Y_{ij} \bar {V}_j.\]

Recognizing that $Y_{ij} = G_{ij} + \text{j}B_{ij}$, $\bar{V}_{i} = V_i \text{e}^{\text{j}\theta_{i}}$, $\bar{V}_{j} = V_j \text{e}^{\text{j}\theta_{j}}$, and by defining $\theta_{ij} = \theta_{i} - \theta_{j}$, we can break down the above equation into its real and imaginary parts, resulting in two equations that describe bus $i \in \mathcal{N}$ as follows:

\[ \begin{aligned} + {P}_{i} &={V}_{i}\sum\limits_{j=1}^n (G_{ij}\cos\theta_{ij}+B_{ij}\sin\theta_{ij})V_j\\ + {Q}_{i} &={V}_{i}\sum\limits_{j=1}^n (G_{ij}\sin\theta_{ij}-B_{ij}\cos\theta_{ij})V_j. + \end{aligned}\]

As demonstrated by the above equations, the bus $i \in \mathcal{N}$ contains four unknown variables: the active power injection ${P}_{i}$, reactive power injection ${Q}_{i}$, bus voltage magnitude ${V}_{i}$, and bus voltage angle ${\theta}_{i}$.

To solve these equations, it is necessary to specify two known variables. Although any two variables can be selected mathematically, the choice is determined by the devices that are connected to a particular bus. The standard options are listed in the table below, and these options are used to define the bus types [9].

Bus TypeLabelKnownUnknown
Demand1$P_{i}$, $Q_{i}$$V_{i}$, ${\theta_{i}}$
Generator2$P_{i}$, $V_{i}$$Q_{i}$, ${\theta_{i}}$
Slack3$V_{i}$, ${\theta_{i}}$$P_{i}$, $Q_{i}$

Consequently, JuliaGrid operates with sets $\mathcal{N}_{\text{pq}}$ and $\mathcal{N}_{\text{pv}}$ that contain demand and generator buses, respectively, and exactly one slack bus in the set $\mathcal{N}_{\text{sb}}$. The bus types are stored in the variable:

julia> system.bus.layout.type4-element Vector{Int8}:
+ 3
+ 1
+ 1
+ 2

It should be noted that JuliaGrid cannot handle systems with multiple slack buses. Additionally, when using functions such as newtonRaphson, fastNewtonRaphsonBX, fastNewtonRaphsonXB, and gaussSeidel, the bus type can be modified as discussed in the section on Bus Type Modification.

Furthermore, active power injections ${P}_{i}$ and reactive power injections ${Q}_{i}$ can be expressed as:

\[ \begin{aligned} + P_{i} &= P_{\text{p}i} - P_{\text{d}i} \\ + Q_{i} &= Q_{\text{p}i} - Q_{\text{d}i}, + \end{aligned}\]

where ${P}_{\text{d}i}$ and ${Q}_{\text{d}i}$ denote the active and reactive power demanded at the bus $i \in \mathcal{N}$, while ${P}_{\text{p}i}$ and ${Q}_{\text{p}i}$ correspond to the active and reactive power produced by the generators at the bus $i \in \mathcal{N}$.

To provide a more comprehensive understanding, it is important to note that each bus $i \in \mathcal{N}$ has the capacity to host multiple generators. This scenario can be conceptualized by introducing the set $\mathcal{S}_i$, which encompasses all generators connected to bus $i \in \mathcal{N}$. With this perspective, we can calculate the values of ${P}_{\text{p}i}$ and ${Q}_{\text{p}i}$ as follows:

\[ \begin{aligned} + P_{\text{p}i} &= \sum_{k \in \mathcal{S}_i} P_{\text{g}k}\\ + Q_{\text{p}i} &= \sum_{k \in \mathcal{S}_i} Q_{\text{g}k}, + \end{aligned}\]

where $P_{\text{g}k}$ and $Q_{\text{g}k}$ represent the active and reactive power outputs of the $k$-th generator within the set $\mathcal{S}_i$.

As a way to summarize, the power injection vectors, represented as $\mathbf{P} = [P_i]$ and $\mathbf{Q} = [Q_i]$ can be computed based on the following variables and expressions:

julia> 𝐏 = system.bus.supply.active - system.bus.demand.active4-element Vector{Float64}:
+  0.0
+ -0.217
+  0.28800000000000003
+  0.0
julia> 𝐐 = system.bus.supply.reactive - system.bus.demand.reactive4-element Vector{Float64}: + 0.0 + -0.127 + 0.454 + 0.0

Positive active or reactive power values, $P_i > 0$ or $Q_i > 0$, signify that power is being supplied into the power system from the specific bus. This indicates that the generators connected to this bus are producing more power than what the connected load is consuming. Conversely, negative values, $P_i < 0$ or $Q_i < 0$, indicate that the bus is drawing in active or reactive power from the power system. This suggests that the load's demand is exceeding the output from the generators.


Newton-Raphson Method

The Newton-Raphson method is commonly used in AC power flow calculations due to its quadratic rate of convergence. It provides an accurate approximation of the roots of the system of nonlinear equations:

\[ \mathbf{f}(\mathbf{x}) = \mathbf{0}.\]

This, in turn, allows for the determination of unknown voltage magnitudes and angles of buses, represented by the state vector $\mathbf x = [\mathbf x_\text{a}, \mathbf x_\text{m}]^T$. The state vector comprises two components:

  • $\mathbf x_\text{a} \in \mathbb{R}^{n-1}$, which holds the bus voltage angles of demand and generator buses, represented by $\mathbf x_\text{a} = [\theta_i]$, where $i \in \mathcal{N}_{\text{pq}} \cup \mathcal{N}_{\text{pv}}$,
  • $\mathbf x_\text{m} \in \mathbb{R}^{n_{\text{pq}}}$, which holds the bus voltage magnitudes of demand buses, represented by $\mathbf x_\text{m} = [V_i]$, where $i \in \mathcal{N}_{\text{pq}}$, and $n_{\text{pq}} = |\mathcal{N}_{\text{pq}}|$.

Knowing the voltage magnitudes and angles for certain types of buses is a consequence of the structure of the state vector $\mathbf x$. Specifically, the voltage magnitude and angle at the slack bus are known, as well as the voltage magnitude at generator buses.

As detailed in the Nodal Network Equations section of this manual, the expressions for active and reactive power injection are as follows:

\[ \begin{aligned} + {P}_{i} &={V}_{i}\sum\limits_{j=1}^n (G_{ij}\cos\theta_{ij}+B_{ij}\sin\theta_{ij})V_j\\ + {Q}_{i} &={V}_{i}\sum\limits_{j=1}^n (G_{ij}\sin\theta_{ij}-B_{ij}\cos\theta_{ij})V_j. + \end{aligned}\]

Using the above equations, we can define the active power injection function for demand and generator buses:

\[ f_{P_i}(\mathbf x) = {V}_{i}\sum\limits_{j=1}^n (G_{ij}\cos\theta_{ij}+B_{ij}\sin\theta_{ij})V_j - {P}_{i} = 0, + \;\;\; \forall i \in \mathcal{N}_{\text{pq}} \cup \mathcal{N}_{\text{pv}},\]

and the reactive power injection function for demand buses:

\[ f_{Q_i}(\mathbf x) = {V}_{i}\sum\limits_{j=1}^n (G_{ij}\sin\theta_{ij}-B_{ij}\cos\theta_{ij})V_j - {Q}_{i} = 0, + \;\;\; \forall i \in \mathcal{N}_{\text{pq}}.\]

The active and reactive mismatches, often denoted as $\Delta P_i(\mathbf x)$ and $\Delta Q_i(\mathbf x)$, respectively, are defined as the functions $f_{P_i}(\mathbf x)$ and $f_{Q_i}(\mathbf x)$. The first terms on the right-hand side represent power injections at a bus, while the second term is constant and is obtained based on the active and reactive powers of the generators that supply a bus and active and reactive powers demanded by consumers at the same bus. Therefore, the Newton-Raphson method solves the system of nonlinear equations:

\[ \mathbf{f(x)} = + \begin{bmatrix} + \mathbf{f}_{\text{P}}(\mathbf x) \\ \mathbf{f}_{\text{Q}}(\mathbf x) + \end{bmatrix} = \mathbf 0,\]

where the first $n - 1$ equations correspond to demand and generator buses, and the last $n_{\text{pq}}$ equations correspond to demand buses.


Initialization

To compute the voltage magnitudes and angles of buses using the Newton-Raphson method in JuliaGrid, you must first execute the acModel! function to set up the system, followed by initializing the Newton-Raphson method using the newtonRaphson function. The following code snippet demonstrates this process:

acModel!(system)
+analysis = newtonRaphson(system)

This results in the creation of the starting vectors of bus voltage magnitudes $\mathbf{V}^{(0)}$ and angles $\bm{\Theta}^{(0)}$, as shown below:

julia> 𝐕⁽⁰⁾ = analysis.voltage.magnitude4-element Vector{Float64}:
+ 1.0
+ 1.0
+ 1.0
+ 1.0
julia> 𝚯⁽⁰⁾ = analysis.voltage.angle4-element Vector{Float64}: + 0.0 + 0.0 + 0.0 + 0.0

Here, we utilize a "flat start" approach in our method. It is important to keep in mind that when dealing with initial conditions in this manner, the Newton-Raphson method may encounter difficulties.


Iterative Process

To implement the Newton-Raphson method, the iterative approach based on the Taylor series expansion, JuliaGrid provides the mismatch! and solve! functions. These functions are utilized to carry out the Newton-Raphson method iteratively until a stopping criterion is reached, as demonstrated in the following code snippet:

for iteration = 1:100
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end

The mismatch! function calculates the mismatch in active power injection for demand and generator buses and the mismatch in reactive power injection for demand buses at each iteration $\nu = \{1, 2, \dots\}$. The equations used for these computations are:

\[ f_{P_i}(\mathbf x^{(\nu-1)}) = {V}_{i}^{(\nu-1)}\sum\limits_{j=1}^n (G_{ij}\cos\theta_{ij}^{(\nu-1)}+B_{ij}\sin\theta_{ij}^{(\nu-1)}){V}_{j}^{(\nu-1)} - {P}_{i}, + \;\;\; \forall i \in \mathcal{N}_{\text{pq}} \cup \mathcal{N}_{\text{pv}},\]

as well as the reactive power injection mismatch for demand buses:

\[ f_{Q_i}(\mathbf x^{(\nu-1)}) = {V}_{i}^{(\nu)}\sum\limits_{j=1}^n (G_{ij}\sin\theta_{ij}^{(\nu-1)}-B_{ij}\cos\theta_{ij}^{(\nu-1)}){V}_{j}^{(\nu-1)} - {Q}_{i}, + \;\;\; \forall i \in \mathcal{N}_{\text{pq}}.\]

The resulting vector from these calculations is stored in the mismatch variable of the ACPowerFlow abstract type and can be accessed through the following line of code:

julia> 𝐟 = analysis.method.mismatch6-element Vector{Float64}:
+  1.5543122344752192e-15
+  4.579669976578771e-16
+ -1.810613397539215e-16
+  3.497202527569243e-15
+  1.1345091532888318e-15
+  0.0

In addition to computing the mismatches in active and reactive power injection, the mismatch! function also returns the maximum absolute values of these mismatches. These maximum values are used as termination criteria for the iteration loop if both are less than a predefined stopping criterion $\epsilon$:

\[ \max \{|f_{P_i}(\mathbf x^{(\nu-1)})|,\; \forall i \in \mathcal{N}_{\text{pq}} \cup \mathcal{N}_{\text{pv}} \} < \epsilon \\ + \max \{|f_{Q_i}(\mathbf x^{(\nu-1)})|,\; \forall i \in \mathcal{N}_{\text{pq}} \} < \epsilon.\]

Next, the function solve! computes the increments of bus voltage angle and magnitude at each iteration using:

\[ \mathbf{\Delta} \mathbf{x}^{(\nu-1)} = -\mathbf{J}(\mathbf{x}^{(\nu-1)})^{-1} \mathbf{f}(\mathbf{x}^{(\nu-1)}),\]

where $\mathbf{\Delta} \mathbf{x} = [\mathbf \Delta \mathbf x_\text{a}, \mathbf \Delta \mathbf x_\text{m}]^T$ consists of the vector of bus voltage angle increments $\mathbf \Delta \mathbf x_\text{a} \in \mathbb{R}^{n-1}$ and bus voltage magnitude increments $\mathbf \Delta \mathbf x_\text{m} \in \mathbb{R}^{n_{\text{pq}}}$, and $\mathbf{J}(\mathbf{x}) \in \mathbb{R}^{n_{\text{u}} \times n_{\text{u}}}$ is the Jacobian matrix, $n_{\text{u}} = n + n_{\text{pq}} - 1$.

Tip

By default, JuliaGrid uses LU factorization as the primary method for factorizing the Jacobian matrix $\mathbf{J} = \mathbf{L}\mathbf{U}$, aiming to compute the increments. Nevertheless, users have the flexibility to opt for QR factorization as an alternative method.

These values are stored in the ACPowerFlow abstract type and can be accessed after each iteration:

julia> 𝚫𝐱 = analysis.method.increment6-element Vector{Float64}:
+  7.92699879268019e-11
+ -3.5508852576600275e-10
+ -2.6233074858150384e-9
+  9.233062009151665e-10
+  5.1042499891742e-9
+  7.485907667424543e-9
julia> 𝐉 = analysis.method.jacobian6×6 SparseArrays.SparseMatrixCSC{Float64, Int64} with 28 stored entries: + 18.4159 -3.36093 ⋅ 6.36094 -1.56596 ⋅ + -3.38112 15.4035 -7.11439 -1.65565 3.10891 0.0233733 + ⋅ -7.11439 7.11439 ⋅ -0.0238268 0.0233733 + -6.83212 1.7057 ⋅ 18.0563 -3.08559 ⋅ + 1.66532 -2.81034 -0.025953 -3.36147 14.9752 -6.40723 + ⋅ 0.025953 -0.025953 ⋅ -6.53154 6.40723
julia> 𝐋 = analysis.method.factorization.L6×6 SparseArrays.SparseMatrixCSC{Float64, Int64} with 17 stored entries: + 1.0 ⋅ ⋅ ⋅ ⋅ ⋅ + -0.00400889 1.0 ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ 1.0 ⋅ ⋅ ⋅ + -0.465213 0.00308853 -0.177715 1.0 ⋅ ⋅ + ⋅ ⋅ -0.371291 0.0618339 1.0 ⋅ + -0.00178072 -0.444182 0.0918455 -0.346344 -0.203397 1.0
julia> 𝐔 = analysis.method.factorization.U6×6 SparseArrays.SparseMatrixCSC{Float64, Int64} with 17 stored entries: + 0.498347 0.00163724 ⋅ -0.498347 ⋅ -0.00166901 + ⋅ 0.493224 ⋅ 4.33681e-19 ⋅ -0.502794 + ⋅ ⋅ 0.619986 -0.113149 0.214146 -0.0527194 + ⋅ ⋅ ⋅ 0.250011 -0.0158957 0.092718 + ⋅ ⋅ ⋅ ⋅ 0.688866 -0.12927 + ⋅ ⋅ ⋅ ⋅ ⋅ 0.299378

The JuliaGrid implementation of the AC power flow follows a specific order to store the increment $\mathbf{\Delta} \mathbf{x}$ and mismatch $\mathbf{f(x)}$ vectors. The first $n-1$ elements of both vectors correspond to the demand and generator buses in the same order as they appear in the input data. The first $n-1$ elements of the increment vector $\mathbf{\Delta} \mathbf{x}$ correspond to the voltage angle increments $\mathbf \Delta \mathbf x_\text{a}$, while the first $n-1$ elements of the mismatch vector $\mathbf{f(x)}$ correspond to the mismatch in active power injections $\mathbf{f}_{\text{P}}(\mathbf x)$.

The last $n_{\text{pq}}$ elements of the increment $\mathbf{\Delta} \mathbf{x}$ and mismatch $\mathbf{f(x)}$ vectors correspond to the demand buses in the order they appear in the input data. For the increment vector $\mathbf{\Delta} \mathbf{x}$, it matches the bus voltage magnitude increments $\mathbf \Delta \mathbf x_\text{m}$, while for the mismatch vector $\mathbf{f(x)}$, it matches the mismatch in reactive power injections $\mathbf{f}_{\text{Q}}(\mathbf x)$.

These specified orders dictate the row and column order of the Jacobian matrix $\mathbf{J}(\mathbf{x})$.

Finally, the function solve! adds the computed increment term to the previous solution to obtain a new solution:

\[ \mathbf {x}^{(\nu)} = \mathbf {x}^{(\nu-1)} + \mathbf \Delta \mathbf {x}^{(\nu-1)}.\]

The bus voltage magnitudes $\mathbf{V} = [V_i]$ and angles $\bm{\Theta} = [\theta_i]$ are then updated based on the obtained solution $\mathbf {x}$. It is important to note that only the voltage magnitudes related to demand buses and angles related to demand and generator buses are updated; not all values are updated. Therefore, the final solution obtained by JuliaGrid is stored in the following vectors:

julia> 𝐕 = analysis.voltage.magnitude4-element Vector{Float64}:
+ 1.0
+ 1.0058448714519173
+ 1.0892355535521518
+ 1.1103697460384185
julia> 𝚯 = analysis.voltage.angle4-element Vector{Float64}: + 0.0 + -0.00644900951642222 + -0.00046072472071607 + -0.0041086656422506945

Jacobian Matrix

To complete the tutorial on the Newton-Raphson method, we will now describe the Jacobian matrix and provide the equations involved in its evolution. Without loss of generality, we assume that the slack bus is the first bus, followed by the set of demand buses and the set of generator buses:

\[ \begin{aligned} + \mathcal{N}_{\text{sb}} &= \{ 1 \} \\ + \mathcal{N}_{\text{pq}} &= \{2, \dots, m\} \\ + \mathcal{N}_{\text{pv}} &= \{m + 1,\dots, n\}, + \end{aligned}\]

where $\mathcal{N} = \mathcal{N}_{\text{sb}} \cup \mathcal{N}_{\text{pq}} \cup \mathcal{N}_{\text{pv}}$. Therefore, we can express:

\[ \begin{aligned} + \mathbf x_\text{a} &= [\theta_2,\dots,\theta_n]^T, \;\;\;\;\;\; \mathbf \Delta \mathbf x_\text{a} = [\Delta \theta_2,\dots,\Delta \theta_n]^T \\ + \mathbf x_\text{m} &= [V_2,\dots,V_{m}]^T, \;\;\; \mathbf \Delta \mathbf x_\text{m} = [\Delta V_2,\dots,\Delta V_{m}]^T. + \end{aligned}\]

The Jacobian matrix $\mathbf{J(x^{(\nu)})} \in \mathbb{R}^{n_{\text{u}} \times n_{\text{u}}}$ is:

\[ \mathbf{J(x^{(\nu)})}= + \left[ + \begin{array}{ccc|ccc} + \cfrac{\mathrm \partial{{f_{P_2}}(\mathbf x^{(\nu)})}} {\mathrm \partial \theta_2} & \cdots & + \cfrac{\mathrm \partial{{f_{P_2}}(\mathbf x^{(\nu)})}}{\mathrm \partial \theta_{n}} & + \cfrac{\mathrm \partial{{f_{P_2}}(\mathbf x^{(\nu)})}}{\mathrm \partial V_{2}} &\cdots & + \cfrac{\mathrm \partial{{f_{P_2}}(\mathbf x^{(\nu)})}}{\mathrm \partial V_{m}}\\ + \;\vdots & \\ + \cfrac{\mathrm \partial{{f_{P_n}}(\mathbf x^{(\nu)})}} {\mathrm \partial \theta_2} & \cdots & + \cfrac{\mathrm \partial{{f_{P_n}}(\mathbf x^{(\nu)})}}{\mathrm \partial \theta_{n}} & + \cfrac{\mathrm \partial{{f_{P_n}}(\mathbf x^{(\nu)})}}{\mathrm \partial V_{2}} &\cdots & + \cfrac{\mathrm \partial{{f_{P_n}}(\mathbf x^{(\nu)})}}{\mathrm \partial V_{m}} \\[10pt] + \hline \\ + \cfrac{\mathrm \partial{{f_{Q_2}}(\mathbf x^{(\nu)})}} {\mathrm \partial \theta_2} & \cdots & + \cfrac{\mathrm \partial{{f_{Q_2}}(\mathbf x^{(\nu)})}}{\mathrm \partial \theta_{n}} & + \cfrac{\mathrm \partial{{f_{Q_2}}(\mathbf x^{(\nu)})}}{\mathrm \partial V_{2}} &\cdots & + \cfrac{\mathrm \partial{{f_{Q_2}}(\mathbf x^{(\nu)})}}{\mathrm \partial V_{m}}\\ + \;\vdots & \\ + \cfrac{\mathrm \partial{{f_{Q_{m}}}(\mathbf x^{(\nu)})}} {\mathrm \partial \theta_2} & \cdots & + \cfrac{\mathrm \partial{{f_{Q_{m}}}(\mathbf x^{(\nu)})}}{\mathrm \partial \theta_{n}} & + \cfrac{\mathrm \partial{{f_{Q_{m}}}(\mathbf x^{(\nu)})}}{\mathrm \partial V_{2}} &\cdots & + \cfrac{\mathrm \partial{{f_{Q_{m}}}(\mathbf x^{(\nu)})}}{\mathrm \partial V_{m}} + \end{array} + \right].\]

The Jacobian matrix can be expressed using four block matrices:

\[ \mathbf{J(x^{(\nu)})} = + \begin{bmatrix} + \mathbf{J_{11}(x^{(\nu)})} &\mathbf{J_{12}(x^{(\nu)})} \\ \mathbf{J_{21}(x^{(\nu)})} & + \mathbf{J_{22}(x^{(\nu)})} + \end{bmatrix},\]

where diagonal elements of the Jacobian sub-matrices are defined as follows:

\[ \begin{aligned} + \cfrac{\mathrm \partial{{f_{P_i}}(\mathbf x^{(\nu)})}} {\mathrm \partial \theta_{i}} &= + {V}_{i}^{(\nu)}\sum\limits_{j=1}^n (-G_{ij}\sin\theta_{ij}^{(\nu)}+B_{ij}\cos\theta_{ij}^{(\nu)}){V}_{j}^{(\nu)} - B_{ii}({V}_{i}^{(\nu)})^2\\ + \cfrac{\mathrm \partial{{f_{P_i}}(\mathbf x^{(\nu)})}}{\mathrm \partial V_{i}^{(\nu)}} &= + \sum\limits_{j=1}^n (G_{ij}\cos\theta_{ij}^{(\nu)}+B_{ij}\sin\theta_{ij}^{(\nu)}){V}_{j}^{(\nu)} + G_{ii}{V}_{i}^{(\nu)}\\ + \cfrac{\mathrm \partial{{f_{Q_i}}(\mathbf x^{(\nu)})}} {\mathrm \partial \theta_{i}} &= + {V}_{i}^{(\nu)} \sum\limits_{j=1}^n (G_{ij}\cos\theta_{ij}^{(\nu)}+B_{ij}\sin\theta_{ij}^{(\nu)}){V}_{j}^{(\nu)} - G_{ii}({V}_{i}^{(\nu)})^2\\ + \cfrac{\mathrm \partial{{f_{Q_i}}(\mathbf x^{(\nu)})}}{\mathrm \partial V_{i}} &= + \sum\limits_{j=1}^n (G_{ij}\sin\theta_{ij}^{(\nu)}-B_{ij}\cos\theta_{ij}^{(\nu)}){V}_{j}^{(\nu)} - B_{ii}{V}_{i}^{(\nu)}, + \end{aligned}\]

while non-diagonal elements of the Jacobian sub-matrices are:

\[ \begin{aligned} + \cfrac{\mathrm \partial{{f_{P_i}}(\mathbf x^{(\nu)})}}{\mathrm \partial \theta_{j}} &= + (G_{ij}\sin\theta_{ij}^{(\nu)}-B_{ij}\cos\theta_{ij}^{(\nu)}){V}_{i}^{(\nu)}{V}_{j}^{(\nu)}\\ + \cfrac{\mathrm \partial{{f_{P_i}}(\mathbf x^{(\nu)})}}{\mathrm \partial V_{j}^{(\nu)}} &= + (G_{ij}\cos\theta_{ij}^{(\nu)}+B_{ij}\sin\theta_{ij}^{(\nu)}){V}_{i}^{(\nu)}\\ + \cfrac{\mathrm \partial{{f_{Q_i}}(\mathbf x^{(\nu)})}}{\mathrm \partial \theta_{j}} &= + -(G_{ij}\cos\theta_{ij}^{(\nu)} + B_{ij}\sin\theta_{ij}^{(\nu)}){V}_{i}^{(\nu)}{V}_{j}^{(\nu)}\\ + \cfrac{\mathrm \partial{{f_{Q_i}}(\mathbf x^{(\nu)})}}{\mathrm\partial V_{j}} &= + (G_{ij}\sin\theta_{ij}^{(\nu)}-B_{ij}\cos\theta_{ij}^{(\nu)}){V}_{i}^{(\nu)}. + \end{aligned}\]


Fast Newton-Raphson Method

Although the fast Newton-Raphson method may converge more slowly than the traditional Newton-Raphson method, the shorter solution time for the updates often compensates for this slower convergence, resulting in a shorter overall solution time. This is particularly true for systems that are not heavily loaded, where a shorter overall solution time is almost always achieved. It is important to note that if the algorithm converges, it will converge to a correct solution [6].

The fast Newton-Raphson method involves decoupling the power flow equations. Namely, the Newton-Raphson method is based on the equations:

\[ \begin{bmatrix} + \mathbf{J_{11}(x)} &\mathbf{J_{12}(x)} \\ \mathbf{J_{21}(x)} & + \mathbf{J_{22}(x)} + \end{bmatrix} + \begin{bmatrix} + \mathbf \Delta \mathbf x_\text{a} \\ \mathbf \Delta \mathbf x_\text{m} + \end{bmatrix} + + \begin{bmatrix} + \mathbf{f}_{\text{P}}(\mathbf x) \\ \mathbf{f}_{\text{Q}}(\mathbf x) + \end{bmatrix} = \mathbf 0,\]

where the iteration index has been omitted for simplicity. However, in transmission grids, there exists a strong coupling between active powers and voltage angles, as well as between reactive powers and voltage magnitudes. To achieve decoupling, two conditions must be satisfied: first, the resistance values $r_{ij}$ of the branches must be small compared to their reactance values $x_{ij}$, and second, the angle differences must be small, i.e., $\theta_{ij} \approx 0$ [10]. Therefore, starting from the above equation, we have:

\[ \begin{bmatrix} + \mathbf{J_{11}(x)} & \mathbf{0} \\ \mathbf{0} & \mathbf{J_{22}(x)} + \end{bmatrix} + \begin{bmatrix} + \mathbf \Delta \mathbf x_\text{a} \\ \mathbf \Delta \mathbf x_\text{m} + \end{bmatrix} + + \begin{bmatrix} + \mathbf{f}_{\text{P}}(\mathbf x) \\ \mathbf{f}_{\text{Q}}(\mathbf x) + \end{bmatrix} = \mathbf 0,\]

which gives the decoupled system as follows:

\[ \begin{aligned} + \mathbf{f}_{\text{P}}(\mathbf x) &= -\mathbf{J_{11}(x)} \mathbf \Delta \mathbf x_\text{a} \\ + \mathbf{f}_{\text{Q}}(\mathbf x) &= -\mathbf{J_{22}(x)} \mathbf \Delta \mathbf x_\text{m}. + \end{aligned}\]

To examine the problem, it is helpful to express it as:

\[ \begin{aligned} + {f}_{P_2}(\mathbf x) &= -\Delta \theta_2\cfrac{\mathrm \partial{{f_{P_2}}(\mathbf x)}} {\mathrm \partial \theta_2} - \cdots - + \Delta \theta_n \cfrac{\mathrm \partial{{f_{P_2}}(\mathbf x)}}{\mathrm \partial \theta_{n}} \\ + & \vdots \\ + {f}_{P_n}(\mathbf x) &= -\Delta \theta_2\cfrac{\mathrm \partial{{f_{P_n}}(\mathbf x)}} {\mathrm \partial \theta_2} - \cdots - + \Delta \theta_n \cfrac{\mathrm \partial{{f_{P_i}}(\mathbf x)}}{\mathrm \partial \theta_{n}}\\ + {f}_{Q_2}(\mathbf x) &= - \Delta V_2 \cfrac{\mathrm \partial{{f_{Q_2}}(\mathbf x)}}{\mathrm \partial V_{2}} - \cdots - + \Delta V_{n_{\text{pq}}} \cfrac{\mathrm \partial{{f_{Q_2}}(\mathbf x)}}{\mathrm \partial V_{m}}\\ + & \vdots \\ + {f}_{Q_{m}}(\mathbf x) &= - \Delta V_2 \cfrac{\mathrm \partial{{f_{Q_{m}}}(\mathbf x)}}{\mathrm \partial V_{2}} - \cdots - + \Delta V_{m} \cfrac{\mathrm \partial{{f_{Q_{m}}}(\mathbf x)}}{\mathrm \partial V_{m}}. + \end{aligned}\]

Firstly, the second part of the expressions is expanded as follows:

\[ \begin{aligned} + {f}_{Q_2}(\mathbf x) &= + -\cfrac{\Delta V_2}{V_2}V_2 \cfrac{\mathrm \partial{{f_{Q_2}}(\mathbf x)}}{\mathrm \partial V_{2}} - \cdots - + \cfrac{\Delta V_{m}}{V_{m}} V_{m} + \cfrac{\mathrm \partial{{f_{Q_2}}(\mathbf x)}}{\mathrm \partial V_{m}}\\ + & \vdots \\ + {f}_{Q_{m}}(\mathbf x) &= + - \cfrac{\Delta V_2}{V_2}V_2 \cfrac{\mathrm \partial{{f_{Q_{m}}}(\mathbf x)}}{\mathrm \partial V_{2}} - \cdots - + \cfrac{\Delta V_{m}}{V_{m}} V_{m} + \cfrac{\mathrm \partial{{f_{Q_{m}}}(\mathbf x)}}{\mathrm \partial V_{m}}. + \end{aligned}\]

Next, the Jacobian elements are derived. To achieve this, we can use the expressions defined for the Newton-Raphson method. For demand buses, the above expansions are applied as:

\[ \begin{aligned} + \cfrac{\mathrm \partial{{f_{P_i}}(\mathbf x)}} {\mathrm \partial \theta_{i}} &= + {V}_{i}\sum\limits_{j=1}^n (-G_{ij}\sin\theta_{ij}+B_{ij}\cos\theta_{ij}){V}_{j} - B_{ii}{V}_{i}^2\\ + \cfrac{\mathrm \partial{{f_{P_i}}(\mathbf x)}}{\mathrm \partial \theta_{j}} &= + (G_{ij}\sin\theta_{ij}-B_{ij}\cos\theta_{ij}){V}_{i}{V}_{j}\\ + V_i \cfrac{\mathrm \partial{{f_{Q_i}}(\mathbf x)}}{\mathrm \partial V_{i}} &= + V_i\sum\limits_{j=1}^n (G_{ij}\sin\theta_{ij}-B_{ij}\cos\theta_{ij}){V}_{j} - B_{ii}{V}_{i}^2\\ + V_j \cfrac{\mathrm \partial{{f_{Q_i}}(\mathbf x)}}{\mathrm\partial V_{j}} &= + (G_{ij}\sin\theta_{ij}-B_{ij}\cos\theta_{ij}) V_i V_j. + \end{aligned}\]

As the definition of reactive power is given by the equation:

\[ {Q}_{i} ={V}_{i}\sum\limits_{j=1}^n (G_{ij}\sin\theta_{ij}-B_{ij}\cos\theta_{ij})V_j,\]

the Jacobian elements can be expressed in the following manner:

\[ \begin{aligned} + \cfrac{\mathrm \partial{{f_{P_i}}(\mathbf x)}} {\mathrm \partial \theta_{i}} &= + -Q_i - B_{ii}{V}_{i}^2\\ + \cfrac{\mathrm \partial{{f_{P_i}}(\mathbf x)}}{\mathrm \partial \theta_{j}} &= + (G_{ij}\sin\theta_{ij}-B_{ij}\cos\theta_{ij}) V_i V_j\\ + V_i \cfrac{\mathrm \partial{{f_{Q_i}}(\mathbf x)}}{\mathrm \partial V_{i}} &= + Q_i - B_{ii} V_i^2\\ + V_j \cfrac{\mathrm \partial{{f_{Q_i}}(\mathbf x)}}{\mathrm\partial V_{j}} &= + (G_{ij}\sin\theta_{ij} - B_{ij}\cos\theta_{ij}) V_i V_j. + \end{aligned}\]

The decoupled model is established through the following approximations:

\[ \begin{aligned} + \sin(\theta_{ij}) \approx 0 \\ + \cos(\theta_{ij}) \approx 1 \\ + Q_i << B_{ii}V_i^2. + \end{aligned}\]

Thus, when the approximations are made, the Jacobian elements are simplified, resulting in the decoupled model where the Jacobian elements are:

\[ \begin{aligned} + \cfrac{\mathrm \partial{{f_{P_i}}(\mathbf x)}} {\mathrm \partial \theta_{i}} &= -B_{ii}{V}_{i}^2\\ + \cfrac{\mathrm \partial{{f_{P_i}}(\mathbf x)}} {\mathrm \partial \theta_{j}} &= -B_{ij}{V}_{i}{V}_{j}\\ + V_i \cfrac{\mathrm \partial{{f_{Q_i}}(\mathbf x)}} {\mathrm \partial V_{i}} &= -B_{ii}{V}_{i}^2\\ + V_j \cfrac{\mathrm \partial{{f_{Q_i}}(\mathbf x)}}{\mathrm\partial V_{j}} &= -B_{ij}{V}_{i}{V}_{j}. + \end{aligned}\]

Thus, the initial system of equations becomes:

\[ \begin{aligned} + {f}_{P_2}(\mathbf x) &= B_{22} \Delta \theta_2 {V}_{2}^2 + \cdots + B_{2n} \Delta \theta_n {V}_{2}{V}_{n} \\ + & \vdots \\ + {f}_{P_n}(\mathbf x) &= B_{n2} \Delta \theta_2 {V}_{2}{V}_{n} + \cdots + B_{nn} \Delta \theta_n {V}_{n}^2 \\ + {f}_{Q_2}(\mathbf x) &= B_{22} \cfrac{\Delta V_2}{V_2} {V}_{2}^2 + \cdots + B_{2m} \cfrac{\Delta V_{m}}{V_{m}} {V}_{2}V_{m} \\ + & \vdots \\ + {f}_{Q_{m}}(\mathbf x) &= B_{m2} \cfrac{\Delta V_2}{V_2} {V}_{2}V_{m} + \cdots + B_{mm} \cfrac{\Delta V_{m}}{V_{m}} V_{m}^2. + \end{aligned}\]

Using $V_j \approx 1$, wherein $V_i^2 = V_iV_j, j=i$, the first part of the equations can be simplified to:

\[ \begin{aligned} + {f}_{P_2}(\mathbf x) &= B_{22} \Delta \theta_2 {V}_{2} + \cdots + B_{2n} \Delta \theta_n {V}_{2}\\ + & \vdots \\ + {f}_{P_n}(\mathbf x) &= B_{n2} \Delta \theta_2 {V}_{n} + \cdots + B_{nn} \Delta \theta_n {V}_{n}. + \end{aligned}\]

Similarly, the second part of the equations can be simplified to:

\[ \begin{aligned} + {f}_{Q_2}(\mathbf x) &= B_{22} {V}_{2} \Delta V_2 + \cdots + B_{2m} V_2 \Delta V_{m} + \\ + & \vdots \\ + {f}_{Q_{m}}(\mathbf x) &= B_{m2} V_{m} \Delta V_2 + \cdots + B_{mm} V_{m} \Delta V_{m}. + \end{aligned}\]

The fast Newton-Raphson method is ultimately based on the system of equations presented below:

\[ \begin{aligned} + \cfrac{{f}_{P_2}(\mathbf x)}{{V}_{2}} &= B_{22} \Delta \theta_2 + \cdots + B_{2n} \Delta \theta_n \\ + & \vdots \\ + \cfrac{{f}_{P_n}(\mathbf x)}{{V}_{n}} &= B_{n2} \Delta \theta_2 + \cdots + B_{nn} \Delta \theta_n \\ + \cfrac{{f}_{Q_2}(\mathbf x)}{{V}_{2}} &= B_{22} \Delta V_2 + \cdots + B_{2m} \Delta V_{m} \\ + & \vdots \\ + \cfrac{{f}_{Q_{m}}(\mathbf x)}{V_{m}} &= B_{m2} \Delta V_2 + \cdots + + B_{mm} \Delta V_{m}. + \end{aligned}\]

This system can be written as:

\[ \begin{aligned} + \mathbf{h}_{\text{P}}(\mathbf x) &= \mathbf{B}_1 \mathbf \Delta \mathbf x_\text{a} \\ + \mathbf{h}_{\text{Q}}(\mathbf x) &= \mathbf{B}_2 \mathbf \Delta \mathbf x_\text{m}. + \end{aligned}\]

One of the main advantages of this approach is that the Jacobian matrices $\mathbf{B}_1$ and $\mathbf{B}_2$ are constant and need only be formed once. Furthermore, this method can be used to define both the XB and BX versions of the fast Newton-Raphson method.


XB Version

The matrix $\mathbf{B}_1$ is formed by neglecting the resistance $r_{ij}$, shunt susceptance $\Im \{ y_{\text{sh}i} \}$, charging susceptance $\Im \{ y_{\text{s}ij} \}$, and transformer tap ratio magnitude $\tau_{ij}$. The matrix $\mathbf{B}_2$ is constructed by disregarding the transformer phase shift angle $\phi_{ij}$. This approach corresponds to the standard fast Newton-Raphson method and is known to exhibit exceptional convergence properties in typical scenarios [10].

To initialize the XB version of the fast Newton-Raphson method, one can utilize the following code snippet:

acModel!(system)
+analysis = fastNewtonRaphsonXB(system)

BX Version

The matrix $\mathbf{B}_1$ ignores the shunt susceptance$\Im \{ y_{\text{sh}i} \}$, charging susceptance $\Im \{ y_{\text{s}ij} \}$, and transformer tap ratio magnitude $\tau_{ij}$. The matrix $\mathbf{B}_2$ ignores the resistance $r_{ij}$ and transformer phase shift angle $\phi_{ij}$. In usual cases, the iteration count for the BX version is comparable to the XB scheme. However, for systems with high $r_{ij}/x_{ij}$ ratios, the BX scheme requires considerably fewer iterations than the XB scheme to solve the power flow [10].

To initialize the BX version of the fast Newton-Raphson method, you can use the following code:

acModel!(system)
+analysis = fastNewtonRaphsonBX(system)

Initialization

When a user creates the fast Newton-Raphson method in JuliaGrid, the Jacobian matrices $\mathbf{B}_1$ and $\mathbf{B}_2$ are formed to correspond to the active and reactive power equations, respectively:

julia> 𝐁₁ = analysis.method.active.jacobian3×3 SparseArrays.SparseMatrixCSC{Float64, Int64} with 7 stored entries:
+ -18.0769     3.07692    ⋅
+   3.07692  -13.4657    5.88235
+    ⋅         5.88235  -5.88235
julia> 𝐁₂ = analysis.method.reactive.jacobian3×3 SparseArrays.SparseMatrixCSC{Float64, Int64} with 7 stored entries: + -20.5128 3.84615 ⋅ + 3.84615 -14.3904 5.88235 + ⋅ 5.88235 -5.77035

Additionally, during this stage, JuliaGrid generates the starting vectors for bus voltage magnitudes $\mathbf{V}^{(0)}$ and angles $\bm{\Theta}^{(0)}$ as demonstrated below:

julia> 𝐕⁽⁰⁾ = analysis.voltage.magnitude4-element Vector{Float64}:
+ 1.0
+ 1.0
+ 1.0
+ 1.0
julia> 𝚯⁽⁰⁾ = analysis.voltage.angle4-element Vector{Float64}: + 0.0 + 0.0 + 0.0 + 0.0

Iterative Process

JuliaGrid offers the mismatch! and solve! functions to implement the fast Newton-Raphson method iterations. These functions are used iteratively until a stopping criterion is met, as shown in the code snippet below:

for iteration = 1:100
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end

The functions $\mathbf{f}_{\text{P}}(\mathbf x)$ and $\mathbf{f}_{\text{Q}}(\mathbf x)$ remain free of approximations, with only the calculation of the state variable increments affected [6]. As a result, we still use the following equations to compute the mismatches:

\[ \begin{aligned} + f_{P_i}(\mathbf x) &= {V}_{i}\sum\limits_{j=1}^n (G_{ij}\cos\theta_{ij}+B_{ij}\sin\theta_{ij})V_j - {P}_{i} = 0, + \;\;\; \forall i \in \mathcal{N}_{\text{pq}} \cup \mathcal{N}_{\text{pv}}\\ + f_{Q_i}(\mathbf x) &= {V}_{i}\sum\limits_{j=1}^n (G_{ij}\sin\theta_{ij}-B_{ij}\cos\theta_{ij})V_j - {Q}_{i} = 0, + \;\;\; \forall i \in \mathcal{N}_{\text{pq}}. + \end{aligned}\]

Therefore, the mismatch! function calculates the mismatch in active power injection for demand and generator buses and the mismatch in reactive power injection for demand buses at each iteration $\nu = \{1, 2, \dots\}$:

\[ \begin{aligned} + h_{P_i}(\mathbf {x}^{(\nu-1)}) &= + \sum\limits_{j=1}^n (G_{ij}\cos\theta_{ij}^{(\nu-1)}+B_{ij}\sin\theta_{ij}^{(\nu-1)}){V}_{j}^{(\nu-1)} - \cfrac{{P}_{i}}{{V}_{i}^{(\nu-1)}}, + \;\;\; \forall i \in \mathcal{N}_{\text{pq}} \cup \mathcal{N}_{\text{pv}} \\ + h_{Q_i}(\mathbf {x}^{(\nu-1)}) &= + \sum\limits_{j=1}^n (G_{ij}\sin\theta_{ij}^{(\nu-1)}-B_{ij}\cos\theta_{ij}^{(\nu-1)}){V}_{j}^{(\nu-1)} - \cfrac{{Q}_{i}}{{V}_{i}^{(\nu-1)}}, + \;\;\; \forall i \in \mathcal{N}_{\text{pq}}. + \end{aligned}\]

The resulting vectors from these calculations are stored in the ACPowerFlow abstract type and can be accessed through the following:

julia> 𝐡ₚ = analysis.method.active.increment3-element Vector{Float64}:
+  1.0521034860626955e-9
+ -1.8809173701904967e-10
+ -2.280102039884849e-10
julia> 𝐡ₒ = analysis.method.reactive.increment3-element Vector{Float64}: + 9.293374091829092e-11 + 4.4771575718049794e-12 + 4.400285291193953e-12

In addition to computing the mismatches in active and reactive power injection, the mismatch! function also returns the maximum absolute values of these mismatches. These maximum values are used as termination criteria for the iteration loop if both are less than a predefined stopping criterion $\epsilon$:

\[ \max \{|h_{P_i}(\mathbf x^{(\nu)})|,\; \forall i \in \mathcal{N}_{\text{pq}} \cup \mathcal{N}_{\text{pv}} \} < \epsilon \\ + \max \{|h_{Q_i}(\mathbf x^{(\nu)})|,\; \forall i \in \mathcal{N}_{\text{pq}} \} < \epsilon.\]

Next, the function solve! computes the bus voltage angle increments:

\[ \mathbf \Delta \mathbf x_\text{a}^{(\nu-1)} = \mathbf{B}_1^{-1} \mathbf{h}_{\text{P}}(\mathbf x^{(\nu-1)}).\]

To obtain the voltage angle increments, JuliaGrid initially performs LU factorization on the Jacobian matrix $\mathbf{B}_1 = \mathbf{L}_1\mathbf{U}_1$. This factorization is executed only once and is utilized in each iteration of the algorithm:

julia> 𝐋₁ = analysis.method.active.factorization.L3×3 SparseArrays.SparseMatrixCSC{Float64, Int64} with 5 stored entries:
+  1.0         ⋅         ⋅
+   ⋅         1.0        ⋅
+ -0.524625  -0.160564  1.0
julia> 𝐔₁ = analysis.method.active.factorization.U3×3 SparseArrays.SparseMatrixCSC{Float64, Int64} with 5 stored entries: + -0.5 ⋅ 0.5 + ⋅ -0.854545 0.145455 + ⋅ ⋅ -0.314811
Tip

By default, JuliaGrid uses LU factorization as the primary method for factorizing Jacobian matrix. Nevertheless, users have the flexibility to opt for QR factorization as an alternative method.

The vector of increments that corresponds to the active power equations can be accessed using:

julia> 𝚫𝐱ₐ = analysis.method.active.increment3-element Vector{Float64}:
+  1.0521034860626955e-9
+ -1.8809173701904967e-10
+ -2.280102039884849e-10

The solution is then updated as follows:

\[ \mathbf x_\text{a}^{(\nu)} = \mathbf x_\text{a}^{(\nu-1)} + \mathbf \Delta \mathbf x_\text{a}^{(\nu-1)}.\]

It is important to note that only the voltage angles related to demand and generator buses are updated, while the vector of bus voltage angles of all buses is stored:

julia> 𝚯 = analysis.voltage.angle4-element Vector{Float64}:
+  0.0
+ -0.006449009470429831
+ -0.00046072472210989724
+ -0.004108665646915064

After calculating the update for voltage angles, to calculate the magnitude updates the fast Newton-Raphson method then solves the equation:

\[ \mathbf \Delta \mathbf x_\text{m}^{(\nu-1)} = \mathbf{B}_2^{-1} \mathbf{h}_{\text{Q}}(\mathbf x^{(\nu)}).\]

Similarly to the previous instance, JuliaGrid initially executes LU factorization on the Jacobian matrix $\mathbf{B}_2 = \mathbf{L}_2\mathbf{U}_2$. However, it provides the flexibility for users to opt for QR factorization instead. This factorization occurs only once and is utilized in each iteration of the fast Newton-Raphson algorithm:

julia> 𝐋₂ = analysis.method.reactive.factorization.L3×3 SparseArrays.SparseMatrixCSC{Float64, Int64} with 5 stored entries:
+  1.0         ⋅         ⋅
+   ⋅         1.0        ⋅
+ -0.492513  -0.189366  1.0
julia> 𝐔₂ = analysis.method.reactive.factorization.U3×3 SparseArrays.SparseMatrixCSC{Float64, Int64} with 5 stored entries: + -0.495194 ⋅ 0.504806 + ⋅ -0.842105 0.157895 + ⋅ ⋅ -0.318121

The vector of increments that corresponds to the reactive power equations can be accessed using:

julia> 𝚫𝐱ₘ = analysis.method.active.increment3-element Vector{Float64}:
+  1.0521034860626955e-9
+ -1.8809173701904967e-10
+ -2.280102039884849e-10

Finally, the solution is updated as follows:

\[ \mathbf x_\text{m}^{(\nu)} = \mathbf x_\text{m}^{(\nu-1)} + \mathbf \Delta \mathbf x_\text{m}^{(\nu-1)}.\]

Again, it is important to note that only the voltage magnitudes of demand buses are updated, while the vector of bus voltage magnitude for all buses is stored:

julia> 𝐕 = analysis.voltage.magnitude4-element Vector{Float64}:
+ 1.0
+ 1.005844871456561
+ 1.0892355535531821
+ 1.1103697460394555

Gauss-Seidel Method

As elaborated in the Nodal Network Equations section of this manual, each bus is associated with the balance equation expressed as:

\[ \sum_{j = 1}^n Y_{ij} \bar {V}_j = \cfrac{P_i - \text{j}Q_i}{\bar{V}_{i}}, \;\;\; \forall i \in \mathcal{N}.\]

In its expanded form, this can be written as:

\[ \begin{aligned} + Y_{11} & \bar{V}_{1} + \cdots+ Y_{1n}\bar{V}_{n} = \frac{{P}_{1} - j{Q}_{1}}{\bar{V}_{1}^*} \\ + \; \vdots & \\ + Y_{n1} & \bar{V}_{1} + \cdots+ Y_{nn}\bar{V}_{n} = \frac{{P}_{n} - j{Q}_{n}}{\bar{V}_{n}^*}. + \end{aligned}\]

While the Gauss-Seidel method directly solves the system of equations, it suffers from very slow convergence, which increases almost linearly with the system size, necessitating numerous iterations to obtain the desired solution [11]. Moreover, the convergence time of the Gauss-Seidel method increases significantly for large-scale systems and can face convergence issues for systems with high active power transfers. Nevertheless, power flow programs utilize both the Gauss-Seidel and Newton-Raphson methods in a complementary manner. Specifically, the Gauss-Seidel method is employed to obtain a quick approximate solution from a "flat start", while the Newton-Raphson method is utilized to obtain the final accurate solution [8].

The Gauss-Seidel method is usually applied to a system of $n$ complex equations, where one represents the slack bus. Consequently, one equation can be eliminated, resulting in a power flow problem with $n-1$ equations.


Initialization

JuliaGrid provides a way to utilize the Gauss-Seidel method for solving the AC power flow problem and determining the magnitudes and angles of bus voltages. To use this method, we need to execute the acModel! function first to set up the system and then initialize the Gauss-Seidel method using the gaussSeidel function. The code snippet below demonstrates this process:

acModel!(system)
+analysis = gaussSeidel(system)

This results in the creation of the starting vectors of bus voltage magnitudes $\mathbf{V}^{(0)}$ and angles $\bm{\Theta}^{(0)}$, as shown below:

julia> 𝐕⁽⁰⁾ = analysis.voltage.magnitude4-element Vector{Float64}:
+ 1.0
+ 1.0
+ 1.0
+ 1.0
julia> 𝚯⁽⁰⁾ = analysis.voltage.angle4-element Vector{Float64}: + 0.0 + 0.0 + 0.0 + 0.0

Iterative Process

JuliaGrid offers the mismatch! and solve! functions to implement the Gauss-Seidel method iterations. These functions are used iteratively until a stopping criterion is met, as shown in the code snippet below:

for iteration = 1:300
+    stopping = mismatch!(system, analysis)
+    if all(stopping .< 1e-8)
+        break
+    end
+    solve!(system, analysis)
+end

In contrast to the Newton-Raphson and fast Newton-Raphson methods, the Gauss-Seidel method does not require the calculation of the mismatch in active and reactive power injection at each iteration. Instead, the mismatch! function is used solely to verify the convergence criteria. At each iteration $\nu = \{1, 2, \dots\}$, we calculate the active power injection mismatch for demand and generator buses, as shown below:

\[ {f}_{P_i}(\mathbf x^{(\nu-1)}) = \Re\{\bar{V}_i^{(\nu - 1)} \bar{I}_i^{*(\nu - 1)}\} - P_i, \;\;\; \forall i \in \mathcal{N}_{\text{pq}} \cup \mathcal{N}_{\text{pv}}.\]

We also compute the reactive power injection mismatch for demand buses, given by:

\[ {f}_{Q_i}(\mathbf x^{(\nu-1)}) = \Im\{\bar{V}_i^{(\nu - 1)} \bar{I}_i^{*(\nu - 1)}\} - Q_i, \;\;\; \forall i \in \mathcal{N}_{\text{pq}}.\]

However, these mismatches are not stored, as they are only used to obtain the maximum absolute values of these mismatches. The maximum values of these mismatches are used as termination criteria for the iteration loop if both are less than a predefined stopping criterion $\epsilon$, as shown below:

\[ \max \{|{f}_{P_i}(\mathbf x^{(\nu-1)})|,\; \forall i \in \mathcal{N}_{\text{pq}} \cup \mathcal{N}_{\text{pv}} \} < \epsilon \\ + \max \{|{f}_{Q_i}(\mathbf x^{(\nu-1)})|,\; \forall i \in \mathcal{N}_{\text{pq}} \} < \epsilon.\]

After initializing complex bus voltages $\bar{V}_i^{(0)}$ for all buses in the power system, the function solve! proceeds to compute the voltages for demand buses using the Gauss-Seidel method:

\[ \bar{V}_{i}^{(\nu)} = + \cfrac{1}{{Y}_{ii}} \Bigg(\cfrac{{P}_{i} - j{Q}_{i}}{\bar{V}_{i}^{*(\nu-1)}} - + \sum\limits_{\substack{j = 1}}^{i - 1} {Y}_{ij}\bar{V}_{j}^{(\nu)} - + \sum\limits_{\substack{j = i + 1}}^{n} {Y}_{ij}\bar{V}_{j}^{(\nu-1)}\Bigg), + \;\;\; \forall i \in \mathcal{N}_{\text{pq}}.\]

The next step is to determine the solution for generator buses in two stages: first, the reactive power injection is calculated, and then the bus complex voltage is updated using the following equations:

\[ \begin{aligned} + Q_i^{(\nu)} &= + -\Im \left\{ \bar{V}_{i}^{*(\nu)} \sum\limits_{j=1}^n {Y}_{ij}\bar{V}_{j}^{(\nu)}\right\}, \;\;\; \forall i \in \mathcal{N}_{\text{pv}} \\ + \bar{V}_{i}^{(\nu )} &:= + \cfrac{1}{{Y}_{ii}} \Bigg(\cfrac{{P}_{i} - j{Q}_{i}^{(\nu)}}{\bar{V}_{i}^{*(\nu )}}- + \sum\limits_{\substack{j = 1,\;j \neq i}}^{n} {Y}_{ij}\bar{V}_{j}^{(\nu)} \Bigg), \;\;\; \forall i \in \mathcal{N}_{\text{pv}}. + \end{aligned}\]

The obtained voltage magnitude may not be equal to the magnitude specified for the generator bus, so a voltage correction step is necessary:

\[ \bar{V}_{i}^{(\nu)} := {V}_{i}^{(0)} \cfrac{\bar{V}_{i}^{(\nu)}}{{V}_{i}^{(\nu)}}, \;\;\; \forall i \in \mathcal{N}_{\text{pv}}.\]

JuliaGrid stores the final results in vectors that contain all bus voltage magnitudes and angles:

julia> 𝐕 = analysis.voltage.magnitude4-element Vector{Float64}:
+ 1.0
+ 1.005844871851792
+ 1.0892355545361385
+ 1.1103697470414973
julia> 𝚯 = analysis.voltage.angle4-element Vector{Float64}: + 0.0 + -0.006449009444866342 + -0.0004607248321877602 + -0.004108665753722359

Power Analysis

Once the computation of voltage magnitudes and angles at each bus is completed, various electrical quantities can be determined. JuliaGrid offers the power! function, which enables the calculation of powers associated with buses, branches, and generators. Here is an example code snippet demonstrating its usage:

power!(system, analysis)

The function stores the computed powers in the rectangular coordinate system. It calculates the following powers related to buses, branches, and generators:

BusActiveReactive
Injections$\mathbf{P} = [P_i]$$\mathbf{Q} = [Q_i]$
Generator injections$\mathbf{P}_{\text{p}} = [P_{\text{p}i}]$$\mathbf{Q}_{\text{p}} = [Q_{\text{p}i}]$
Shunt elements$\mathbf{P}_{\text{sh}} = [{P}_{\text{sh}i}]$$\mathbf{Q}_{\text{sh}} = [{Q}_{\text{sh}i}]$
BranchActiveReactive
From-bus end flows$\mathbf{P}_{\text{i}} = [P_{ij}]$$\mathbf{Q}_{\text{i}} = [Q_{ij}]$
To-bus end flows$\mathbf{P}_{\text{j}} = [P_{ji}]$$\mathbf{Q}_{\text{j}} = [Q_{ji}]$
Shunt elements$\mathbf{P}_{\text{s}} = [P_{\text{s}ij}]$$\mathbf{P}_{\text{s}} = [P_{\text{s}ij}]$
Series elements$\mathbf{P}_{\text{l}} = [P_{\text{l}ij}]$$\mathbf{Q}_{\text{l}} = [Q_{\text{l}ij}]$
GeneratorActiveReactive
Outputs$\mathbf{P}_{\text{g}} = [P_{\text{g}i}]$$\mathbf{Q}_{\text{g}} = [Q_{\text{g}i}]$
Info

For a clear comprehension of the equations, symbols presented in this section, as well as for a better grasp of power directions, please refer to the Unified Branch Model.


Power Injections

Active and reactive power injections are stored as the vectors $\mathbf{P} = [P_i]$ and $\mathbf{Q} = [Q_i]$, respectively, and can be retrieved using the following commands:

julia> 𝐏 = analysis.power.injection.active4-element Vector{Float64}:
+ -0.025304583936174074
+ -0.21699999730489078
+  0.28800000125457986
+ -2.4077102614260874e-18
julia> 𝐐 = analysis.power.injection.reactive4-element Vector{Float64}: + -0.5224650282662511 + -0.12699999649491905 + 0.4540000073996279 + 9.892532361792298e-21

Generator Power Injections

The power! function in JuliaGrid also computes the active and reactive power injections from the generators at each bus. The active power supplied by the generators to the buses can be calculated by summing the given generator active powers in the input data, except for the slack bus, which can be determined as:

\[ P_{\text{p}i} = P_i + P_{\text{d}i},\;\;\; i \in \mathcal{N}_{\text{sb}},\]

where $P_{\text{d}i}$ represents the active power demanded by consumers at the slack bus. The active power injections from the generators at each bus are stored as the vector, denoted by $\mathbf{P}_{\text{p}} = [P_{\text{p}i}]$, can be obtained using:

julia> 𝐏ₚ = analysis.power.supply.active4-element Vector{Float64}:
+ -0.025304583936174074
+  0.0
+  0.4
+  0.0

The calculation of reactive power injection from the generators at generator or slack buses can be achieved using the subsequent equation:

\[ Q_{\text{p}i} = Q_i + Q_{\text{d}i},\;\;\; \forall i \in \mathcal{N}_{\text{pv}} \cup \mathcal{N}_{\text{sb}},\]

where $Q_{\text{d}i}$ represents the reactive power demanded by consumers at the corresponding bus. Further, the reactive power injected by the generators at buses from $\mathcal{N}_{\text{pq}}$ can be calculated by summing the given generator reactive powers in the input data. The vector of these reactive power injections by the generators to the buses, denoted by $\mathbf{Q}_{\text{p}} = [Q_{\text{p}i}]$, can be retrieved using the following command:

julia> 𝐐ₚ = analysis.power.supply.reactive4-element Vector{Float64}:
+ -0.5224650282662511
+  0.0
+  0.424
+  0.0

Power at Bus Shunt Elements

Active and reactive powers associated with the shunt elements at each bus are represented by the vectors $\mathbf{P}_{\text{sh}} = [{P}_{\text{sh}i}]$ and $\mathbf{Q}_{\text{sh}} = [{Q}_{\text{sh}i}]$. To retrieve these powers in JuliaGrid, use the following commands:

julia> 𝐏ₛₕ = analysis.power.shunt.active4-element Vector{Float64}:
+ 0.0
+ 0.0
+ 0.0
+ 0.02589134047804497
julia> 𝐐ₛₕ = analysis.power.shunt.reactive4-element Vector{Float64}: + -0.0 + -0.0 + -0.0 + -0.014795051701739982

Power Flows

The resulting active and reactive power flows at each from-bus end are stored as the vectors $\mathbf{P}_{\text{i}} = [P_{ij}]$ and $\mathbf{Q}_{\text{i}} = [Q_{ij}],$ respectively, and can be retrieved using the following commands:

julia> 𝐏ᵢ = analysis.power.from.active4-element Vector{Float64}:
+  0.0681800941327122
+ -0.09348467806888605
+ -0.14919987912917734
+  0.026012308231465508
julia> 𝐐ᵢ = analysis.power.from.reactive4-element Vector{Float64}: + -0.11979262337047558 + -0.4026724048957746 + -0.24793254773638929 + -0.25400850645944056

The vectors of active and reactive power flows at the to-bus end are stored as $\mathbf{P}_{\text{j}} = [P_{ji}]$ and $\mathbf{Q}_{\text{j}} = [Q_{ji}]$, respectively, and can be retrieved using the following code:

julia> 𝐏ⱼ = analysis.power.to.active4-element Vector{Float64}:
+ -0.06780011817571369
+  0.10202890060379553
+  0.15995879241931948
+ -0.02589134047804497
julia> 𝐐ⱼ = analysis.power.to.reactive4-element Vector{Float64}: + 0.12093255124147115 + 0.4385581395423945 + 0.26945037431667357 + 0.014795051701739979

Power at Branch Shunt Elements

Active and reactive powers associated with the branch shunt elements at each branch are represented by the vectors $\mathbf{P}_{\text{s}} = [P_{\text{s}ij}]$ and $\mathbf{Q}_{\text{s}} = [Q_{\text{s}ij}]$. We can retrieve these values using the following code:

julia> 𝐏ₛ = analysis.power.charging.active4-element Vector{Float64}:
+ 0.0
+ 0.0
+ 0.0
+ 0.00012096775342053239
julia> 𝐐ₛ = analysis.power.charging.reactive4-element Vector{Float64}: + -0.0 + -0.0 + -0.0 + -0.2419355068410648

Power at Branch Series Elements

Active and reactive powers associated with the branch series element at each branch are represented by the vectors $\mathbf{P}_{\text{l}} = [P_{\text{l}ij}]$ and $\mathbf{Q}_{\text{l}} = [Q_{\text{l}ij}]$. We can retrieve these values using the following code:

julia> 𝐏ₗ = analysis.power.series.active4-element Vector{Float64}:
+  0.0003799759569985204
+  0.008544222534909472
+  0.010758913290142138
+ -1.0842021724855044e-19
julia> 𝐐ₗ = analysis.power.series.reactive4-element Vector{Float64}: + 0.001139927870995561 + 0.03588573464661977 + 0.021517826580284276 + 0.0027220520833633236

Generator Power Outputs

To obtain the output active powers of each generator connected to bus $i \in \mathcal{N}_{\text{pq}} \cup \mathcal{N}_{\text{pv}}$, the given active power in the input data is utilized. For the generator connected to the slack bus, the output active power is determined using the equation:

\[ P_{\text{g}i} = P_i + P_{\text{d}i},\;\;\; i \in \mathcal{N}_{\text{sb}}.\]

In the case of multiple generators connected to the slack bus, the first generator in the input data is assigned the obtained value of $P_{\text{g}i}$. Then, this amount of power is reduced by the output active power of the other generators.

To retrieve the vector of active power outputs of generators, denoted as $\mathbf{P}_{\text{g}} = [P_{\text{g}i}]$, $i \in \mathcal{S}$, where the set $\mathcal{S}$ represents the set of generators, users can utilize the following command:

julia> 𝐏ₒ = analysis.power.generator.active2-element Vector{Float64}:
+ -0.025304583936174074
+  0.4

The output reactive powers of each generator located at the bus is obtained as:

\[ Q_{\text{g}i} = Q_i + Q_{\text{d}i},\;\;\; i \in \mathcal{N}.\]

If there are multiple generators at the same bus, the reactive power is allocated proportionally among the generators based on their reactive power capabilities.

To retrieve the vector of reactive power outputs of generators, denoted as $\mathbf{Q}_{\text{g}} = [Q_{\text{g}i}]$, $i \in \mathcal{S}$, users can utilize:

julia> 𝐐ₒ = analysis.power.generator.reactive2-element Vector{Float64}:
+ -0.5224650282662511
+  0.4240000073996279

Current Analysis

JuliaGrid offers the current! function, which enables the calculation of currents associated with buses and branches. Here is an example code snippet demonstrating its usage:

current!(system, analysis)

The function stores the computed currents in the polar coordinate system. It calculates the following currents related to buses and branches:

BusMagnitudeAngle
Injections$\mathbf{I} = [I_i]$$\bm{\psi} = [\psi_i]$
BranchMagnitudeAngle
From-bus end flows$\mathbf{I}_{\text{i}} = [I_{ij}]$$\bm{\psi}_{\text{i}} = [\psi_{ij}]$
To-bus end flows$\mathbf{I}_{\text{j}} = [I_{ji}]$$\bm{\psi}_{\text{j}} = [\psi_{ji}]$
Series elements$\mathbf{I}_{\text{l}} = [I_{\text{l}ij}]$$\bm{\psi}_{\text{l}} = [\psi_{\text{l}ij}]$
Info

For a clear comprehension of the equations, symbols presented in this section, as well as for a better grasp of power directions, please refer to the Unified Branch Model.


Current Injections

In JuliaGrid, complex current injections are stored in the vector of magnitudes denoted as $\mathbf{I} = [I_i]$ and the vector of angles represented as $\bm{\psi} = [\psi_i]$. You can retrieve them using the following commands:

julia> 𝐈 = analysis.current.injection.magnitude4-element Vector{Float64}:
+ 0.5230774586325025
+ 0.24997084766089062
+ 0.4935966411616148
+ 2.168404344971009e-18
julia> 𝛙 = analysis.current.injection.angle4-element Vector{Float64}: + 1.619191576605966 + 2.605637769016233 + -1.0059543720614923 + 3.141592653589793

Current Flows

To obtain the vectors of magnitudes $\mathbf{I}_{\text{i}} = [I_{ij}]$ and angles $\bm{\psi}_{\text{i}} = [\psi_{ij}]$ for the resulting complex current flows, you can use the following commands:

julia> 𝐈ᵢ = analysis.current.from.magnitude4-element Vector{Float64}:
+ 0.1378361267952858
+ 0.41338172516233695
+ 0.28768189283066065
+ 0.23441849266339332
julia> 𝛙ᵢ = analysis.current.from.angle4-element Vector{Float64}: + 1.0533688181418361 + 1.7989158163819308 + 2.1060717428167246 + 1.4682841231815587

Similarly, we can obtain the vectors of magnitudes $\mathbf{I}_{\text{j}} = [I_{ji}]$ and angles $\bm{\psi}_{\text{j}} = [\psi_{ji}]$ of the resulting complex current flows using the following code:

julia> 𝐈ⱼ = analysis.current.to.magnitude4-element Vector{Float64}:
+ 0.1378361267952858
+ 0.41338172516233695
+ 0.28768189283066065
+ 0.026856261289684834
julia> 𝛙ⱼ = analysis.current.to.angle4-element Vector{Float64}: + -2.088223835447957 + -1.3426768372078626 + -1.0355209107730685 + -2.626555205096993

Current at Branch Series Elements

To obtain the vectors of magnitudes $\mathbf{I}_{\text{l}} = [I_{\text{l}ij}]$ and angles $\bm{\psi}_{\text{l}} = [\psi_{\text{l}ij}]$ of the resulting complex current flows, one can use the following code:

julia> 𝐈ₗ = analysis.current.series.magnitude4-element Vector{Float64}:
+ 0.13783612679528548
+ 0.41338172516233634
+ 0.2876818928306608
+ 0.12653881253831878
julia> 𝛙ₗ = analysis.current.series.angle4-element Vector{Float64}: + 1.0533688181418344 + 1.798915816381931 + 2.1060717428167246 + 1.3809084790963575
diff --git a/v0.2.0/tutorials/acStateEstimation/index.html b/v0.2.0/tutorials/acStateEstimation/index.html new file mode 100644 index 000000000..56fe1b723 --- /dev/null +++ b/v0.2.0/tutorials/acStateEstimation/index.html @@ -0,0 +1,561 @@ + +AC State Estimation · JuliaGrid

AC State Estimation

To initiate the process, let us construct the PowerSystem type and formulate the AC model:

system = powerSystem()
+
+addBus!(system; label = 1, type = 3, active = 0.5)
+addBus!(system; label = 2, type = 1, reactive = 0.3)
+addBus!(system; label = 3, type = 1, active = 0.5)
+
+@branch(resistance = 0.02, susceptance = 0.04)
+addBranch!(system; label = 1, from = 1, to = 2, reactance = 0.6)
+addBranch!(system; label = 2, from = 1, to = 3, reactance = 0.7)
+addBranch!(system; label = 3, from = 2, to = 3, reactance = 0.2)
+
+addGenerator!(system; label = 1, bus = 1, active = 3.2, reactive = 0.2)
+
+acModel!(system)

To review, we can conceptualize the bus/branch model as the graph denoted by $\mathcal{G} = (\mathcal{N}, \mathcal{E})$, where we have the set of buses $\mathcal{N} = \{1, \dots, n\}$, and the set of branches $\mathcal{E} \subseteq \mathcal{N} \times \mathcal{N}$ within the power system:

julia> 𝒩 = collect(keys(system.bus.label))3-element Vector{String}:
+ "1"
+ "2"
+ "3"
julia> ℰ = [𝒩[system.branch.layout.from] 𝒩[system.branch.layout.to]]3×2 Matrix{String}: + "1" "2" + "1" "3" + "2" "3"

Following that, we will introduce the Measurement type and incorporate a set of measurement devices $\mathcal{M}$ into the graph $\mathcal{G}$. The AC state estimation includes a set of voltmeters $\mathcal{V}$, ammeters $\mathcal{I}$, wattmeters $\mathcal{P}$, varmeters $\mathcal{Q}$, and PMUs $\bar{\mathcal{P}}$, with PMUs being able to integrate into AC state estimation in either rectangular coordinates or polar coordinates. This process of adding measurement devices will be carried out in the State Estimation Model section. Currently, we are only initializing the Measurement type at this stage:

device = measurement()

Notation

Here, when referring to a vector $\mathbf{a}$, we use the notation $\mathbf{a} = [a_{i}]$ or $\mathbf{a} = [a_{ij}]$, where $a_i$ represents the element related with bus $i \in \mathcal{N}$ or measurement $i \in \mathcal{M}$, while $a_{ij}$ denotes the element related with branch $(i,j) \in \mathcal{E}$.


State Estimation Model

In accordance with the AC Model, the AC state estimation treats bus voltages as state variables, which we denoted by $\mathbf x \equiv [\bm {\Theta}, \mathbf{V}]^T$. The state vector encompasses two components:

  • $\bm {\Theta} \in \mathbb{R}^{n-1}$, representing bus voltage angles,
  • $\mathbf {V} \in \mathbb{R}^n$, representing bus voltage magnitudes.

Consequently, the total number of state variables is $n_\text{u} = 2n-1$, accounting for the fact that the voltage angle for the slack bus is known.

Within the JuliaGrid framework for AC state estimation, the methodology encompasses bus voltage magnitudes, branch current magnitudes, active powers, reactive powers, and phasor measurements. These measurements contribute to the construction of a nonlinear system of equations:

\[ \mathbf{z}=\mathbf{h}(\mathbf {x}) + \mathbf{u}.\]

Here, $\mathbf{h}(\mathbf {x})= [h_1(\mathbf {x})$, $\dots$, $h_k(\mathbf {x})]^{{T}}$ represents the vector of nonlinear measurement functions, where $k$ is the number of measurements, $\mathbf{z} = [z_1,\dots,z_k]^{T}$ denotes the vector of measurement values, and $\mathbf{u} = [u_1,\dots,u_k]^T$ represents the vector of measurement errors. It is worth noting that the number of equations in the system is equal to $k = |\mathcal{V} \cup \mathcal{I} \cup \mathcal{P} \cup \mathcal{Q}| + 2|\bar{\mathcal{P}}|$.

These errors are assumed to follow a Gaussian distribution with a zero mean and covariance matrix $\bm \Sigma$. The diagonal elements of $\bm \Sigma$ correspond to the measurement variances $\mathbf{v} = [v_1,\dots,v_k]^T$, while the off-diagonal elements represent the covariances between the measurement errors $\mathbf{w} = [w_1,\dots,w_k]^{T}$. These covariances exist only if PMUs are observed in rectangular coordinates and correlation is required.

Hence, the nonlinear system of equations is structured according to the specific devices:

\[ \begin{bmatrix} + \mathbf{z}_\mathcal{V}\\[3pt] + \mathbf{z}_\mathcal{I}\\[3pt] + \mathbf{z}_\mathcal{P}\\[3pt] + \mathbf{z}_\mathcal{Q}\\[3pt] + \mathbf{z}_{\bar{\mathcal{P}}} + \end{bmatrix} = + \begin{bmatrix} + \mathbf{h}_\mathcal{V}(\mathbf {x})\\[3pt] + \mathbf{h}_\mathcal{I}(\mathbf {x})\\[3pt] + \mathbf{h}_\mathcal{P}(\mathbf {x})\\[3pt] + \mathbf{h}_\mathcal{Q}(\mathbf {x})\\[3pt] + \mathbf{h}_{\bar{\mathcal{P}}}(\mathbf {x}) + \end{bmatrix} + + \begin{bmatrix} + \mathbf{u}_\mathcal{V}\\[3pt] + \mathbf{u}_\mathcal{I}\\[3pt] + \mathbf{u}_\mathcal{P}\\[3pt] + \mathbf{u}_\mathcal{Q}\\[3pt] + \mathbf{u}_{\bar{\mathcal{P}}} + \end{bmatrix}\]

Please note that each error vector, denoted as $\mathbf{u}_i$, where $i \in \{\mathcal{V}, \mathcal{I}, \mathcal{P}, \mathcal{Q}\}$, is associated with the variance vector $\mathbf{v}_i$. However, for PMUs, the error vector $\mathbf{u}_{\bar{\mathcal{P}}}$, along with its variance vector $\mathbf{v}_{\bar{\mathcal{P}}}$, can also be associated with the covariance vector $\mathbf{w}_{\bar{\mathcal{P}}}$.

In summary, upon user definition of the measurement devices, each $i$-th legacy measurement device is linked to the measurement function $h_i(\mathbf {x})$, the corresponding measurement value $z_i$, and the measurement variance $v_i$. Meanwhile, each $i$-th PMU is associated with two measurement functions $h_{2i-1}(\mathbf x)$, $h_{2i}(\mathbf x)$, along with their respective measurement values $z_{2i-1}$, $z_{2i}$, as well as their variances $v_{2i-1}$, $v_{2i}$, and possibly covariances $w_{2i-1}$, $w_{2i}$.

Typically, the AC state estimator is obtained using the Gauss-Newton method or its variation, which involves constructing the Jacobian matrix. Therefore, in addition to the aforementioned elements, we also need Jacobian expressions corresponding to the measurement functions, which are also provided below.


Bus Voltage Magnitude Measurements

When introducing a voltmeter $V_i \in \mathcal{V}$ at bus $i \in \mathcal{N}$, users specify the measurement value, variance, and measurement function of vectors:

\[ \mathbf{z}_\mathcal{V} = [z_{V_i}], \;\;\; \mathbf{v}_\mathcal{V} = [v_{V_i}], \;\;\; \mathbf{h}_\mathcal{V}(\mathbf {x}) = [h_{V_{i}}(\mathbf {x})].\]

For example:

addVoltmeter!(system, device; label = "V₁", bus = 1, magnitude = 1.0, variance = 1e-3)

Here, the bus voltage magnitude measurement function is simply defined as:

\[ h_{V_{i}}(\mathbf {x}) = V_{i},\]

with the following Jacobian expression:

\[ \cfrac{\mathrm \partial{{h_{V_{i}}(\mathbf x)}}} {\mathrm \partial V_{i}}=1.\]


From-Bus End Current Magnitude Measurements

When introducing an ammeter at branch $(i,j) \in \mathcal{E}$, it can be placed at the from-bus end, denoted as $I_{ij} \in \mathcal{I}$, specifying the measurement value, variance, and measurement function of vectors:

\[ \mathbf{z}_\mathcal{I} = [z_{I_{ij}}], \;\;\; \mathbf{v}_\mathcal{I} = [v_{I_{ij}}], \;\;\; \mathbf{h}_\mathcal{I}(\mathbf {x}) = [h_{I_{ij}}(\mathbf {x})].\]

For example:

addAmmeter!(system, device; label = "I₁₂", from = 1, magnitude = 0.3, variance = 1e-2)

Here, following the guidelines outlined in the AC Model, the function defining the current magnitude at the from-bus end is expressed as:

\[ h_{I_{ij}}(\mathbf {x}) = \sqrt{A_{I_{ij}}V_i^2 + B_{I_{ij}}V_j^2 - 2[C_{I_{ij}} \cos(\theta_{ij} - \phi_{ij}) - D_{I_{ij}}\sin(\theta_{ij} - \phi_{ij})]V_iV_j},\]

where:

\[ \begin{gathered} + A_{I_{ij}} = \cfrac{(g_{ij} + g_{\text{s}i})^2+(b_{ij}+b_{\text{s}i})^2}{\tau_{ij}^4}, \;\;\; B_{I_{ij}} = \cfrac{g_{ij}^2+b_{ij}^2}{\tau_{ij}^2} \\ + C_{I_{ij}} = \cfrac{g_{ij}(g_{ij}+g_{\text{s}i})+b_{ij}(b_{ij}+b_{\text{s}i})}{\tau_{ij}^3}, \;\;\; D_{I_{ij}} = \cfrac{g_{ij}b_{\text{s}i} - b_{ij}g_{\text{s}i}}{\tau_{ij}^3}. + \end{gathered}\]

Jacobian expressions corresponding to the measurement function $h_{I_{ij}}(\mathbf x)$ are defined as follows:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{I_{ij}}(\mathbf x)}}{\mathrm \partial \theta_{i}} &=- + \cfrac{\mathrm \partial{h_{I_{ij}}(\mathbf x)}}{\mathrm \partial \theta_{j}} = + \cfrac{ [C_{I_{ij}}\sin(\theta_{ij} - \phi_{ij}) + D_{I_{ij}}\cos(\theta_{ij} - \phi_{ij})]V_i V_j}{h_{I_{ij}}(\mathbf x)} \\ + \cfrac{\mathrm \partial{h_{I_{ij}}(\mathbf x)}}{\mathrm \partial V_{i}} &= + \cfrac{A_{I_{ij}}V_i - [C_{I_{ij}}\cos(\theta_{ij} - \phi_{ij}) - D_{I_{ij}}\sin(\theta_{ij} - \phi_{ij})]V_j}{h_{I_{ij}}(\mathbf x)} \\ + \cfrac{\mathrm \partial{h_{I_{ij}}(\mathbf x)}}{\mathrm \partial V_{j}} &= + \cfrac{B_{I_{ij}}V_j - [C_{I_{ij}}\cos(\theta_{ij} - \phi_{ij}) - D_{I_{ij}}\sin(\theta_{ij} - \phi_{ij})]V_i}{h_{I_{ij}}(\mathbf x)} . + \end{aligned}\]


To-Bus End Current Magnitude Measurements

In addition to the scenario where we add ammeters at the from-bus end, an ammeter can also be positioned at the to-bus end, denoted as $I_{ji} \in \mathcal{I}$, specifying the measurement value, variance, and measurement function of vectors:

\[ \mathbf{z}_\mathcal{I} = [z_{I_{ji}}], \;\;\; \mathbf{v}_\mathcal{I} = [v_{I_{ji}}], \;\;\; \mathbf{h}_\mathcal{I}(\mathbf {x}) = [h_{I_{ji}}(\mathbf {x})].\]

For example:

addAmmeter!(system, device; label = "I₂₁", to = 1, magnitude = 0.3, variance = 1e-3)

Now, the measurement function is as follows:

\[ h_{I_{ji}}(\mathbf {x}) = \sqrt{A_{I_{ji}}V_i^2 + B_{I_{ji}}V_j^2 - 2[C_{I_{ji}} \cos(\theta_{ij} - \phi_{ij}) + D_{I_{ji}}\sin(\theta_{ij} - \phi_{ij})]V_iV_j},\]

where:

\[ \begin{gathered} + A_{I_{ji}} = \cfrac{g_{ij}^2+b_{ij}^2}{\tau_{ij}^2}, \;\;\; B_{I_{ji}} = (g_{ij} + g_{\text{s}i})^2+(b_{ij}+b_{\text{s}i})^2 \\ + C_{I_{ji}} = \cfrac{g_{ij}(g_{ij}+g_{\text{s}i})+b_{ij}(b_{ij}+b_{\text{s}i})}{\tau_{ij}}, \;\;\; D_{I_{ji}} = \cfrac{g_{ij}b_{\text{s}i} - b_{ij}g_{\text{s}i}}{\tau_{ij}}. + \end{gathered}\]

Jacobian expressions corresponding to the measurement function $h_{I_{ji}}(\mathbf x)$ are defined as follows:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{I_{ji}}(\mathbf x)}}{\mathrm \partial \theta_{i}} &=- + \cfrac{\mathrm \partial{h_{I_{ji}}(\mathbf x)}}{\mathrm \partial \theta_{j}} = + \cfrac{[C_{I_{ji}}\sin(\theta_{ij} - \phi_{ij}) - D_{I_{ji}}\cos(\theta_{ij}- \phi_{ij})]V_i V_j}{h_{I_{ji}}(\mathbf x)} \\ + \cfrac{\mathrm \partial{h_{I_{ji}}(\mathbf x)}}{\mathrm \partial V_{i}} &= + \cfrac{A_{I_{ji}}V_i - [C_{I_{ji}}\cos(\theta_{ij} - \phi_{ij}) + D_{I_{ji}}\sin(\theta_{ij} - \phi_{ij})]V_j}{h_{I_{ji}}(\mathbf x)} \\ + \cfrac{\mathrm \partial{h_{I_{ji}}(\mathbf x)}}{\mathrm \partial V_{j}} &= + \cfrac{B_{I_{ji}}V_j - [C_{I_{ji}}\cos(\theta_{ij} - \phi_{ij}) + D_{I_{ji}}\sin(\theta_{ij} - \phi_{ij})]V_i}{h_{I_{ji}}(\mathbf x)} . + \end{aligned}\]


Active Power Injection Measurements

When adding a wattmeter $P_i \in \mathcal{P}$ at bus $i \in \mathcal{N}$, users specify that the wattmeter measures active power injection and define measurement value, variance, and measurement function of vectors:

\[ \mathbf{z}_\mathcal{P} = [z_{P_{i}}], \;\;\; \mathbf{v}_\mathcal{P} = [v_{P_{i}}], \;\;\; \mathbf{h}_\mathcal{P}(\mathbf {x}) = [h_{P_{i}}(\mathbf {x})].\]

For example:

addWattmeter!(system, device; label = "P₃", bus = 3, active = -0.5, variance = 1e-3)

Here, utilizing the AC Model, we derive the function defining the active power injection as follows:

\[ h_{P_{i}}(\mathbf {x}) = {V}_{i}\sum\limits_{j \in \mathcal{N}_i} (G_{ij}\cos\theta_{ij} + B_{ij}\sin\theta_{ij}){V}_{j},\]

where $\mathcal{N}_i$ contains buses incident to bus $i$, including bus $i$, with the following Jacobian expressions:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{P_{i}}(\mathbf x)}}{\mathrm \partial \theta_{i}} &= + {V}_{i}\sum_{j \in \mathcal{N}_i} (-G_{ij}\sin\theta_{ij}+B_{ij}\cos\theta_{ij}){V}_{j} - B_{ii}V_i^2\\ + \cfrac{\mathrm \partial{h_{P_{i}}(\mathbf x)}}{\mathrm \partial \theta_{j}} &= + (G_{ij}\sin\theta_{ij}-B_{ij}\cos\theta_{ij}){V}_{i}{V}_{j} \\ + \cfrac{\mathrm \partial{h_{P_{i}}(\mathbf x)}}{\mathrm \partial V_{i}} &= + \sum_{j \in \mathcal{N}_i} (G_{ij}\cos\theta_{ij}+B_{ij} \sin\theta_{ij})V_{j} + G_{ii} V_i\\ + \cfrac{\mathrm \partial{h_{P_{i}}(\mathbf x)}}{\mathrm \partial V_{j}} &= + (G_{ij}\cos\theta_{ij}+B_{ij}\sin\theta_{ij}){V}_{i}. + \end{aligned}\]


From-Bus End Active Power Flow Measurements

Additionally, when introducing a wattmeter at branch $(i,j) \in \mathcal{E}$, users specify that the wattmeter measures active power flow. It can be positioned at the from-bus end, denoted as $P_{ij} \in \mathcal{P}$, specifying the measurement value, variance, and measurement function of vectors:

\[ \mathbf{z}_\mathcal{P} = [z_{P_{ij}}], \;\;\; \mathbf{v}_\mathcal{P} = [v_{P_{ij}}], \;\;\; \mathbf{h}_\mathcal{P}(\mathbf {x}) = [h_{P_{ij}}(\mathbf {x})].\]

For example:

addWattmeter!(system, device; label = "P₁₂", from = 1, active = 0.2, variance = 1e-4)

Here, the function describing active power flow at the from-bus end is defined as follows:

\[ h_{P_{ij}}(\mathbf {x}) = \cfrac{g_{ij} + g_{\text{s}i}}{\tau_{ij}^2} V_{i}^2 - \cfrac{1}{\tau_{ij}} \left[g_{ij}\cos(\theta_{ij} - \phi_{ij}) + b_{ij}\sin(\theta_{ij} - \phi_{ij})\right]V_{i}V_{j},\]

with the following Jacobian expressions:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{P_{ij}}(\mathbf x)}}{\mathrm \partial \theta_{i}} &=- + \cfrac{\mathrm \partial{h_{P_{ij}}(\mathbf x)}}{\mathrm \partial \theta_{j}} = + \cfrac{1}{\tau_{ij}} \left[g_{ij}\sin(\theta_{ij} - \phi_{ij}) - b_{ij}\cos(\theta_{ij} - \phi_{ij})\right] V_{i}V_{j} \\ + \cfrac{\mathrm \partial{h_{P_{ij}}(\mathbf x)}}{\mathrm \partial V_{i}} &= + 2\cfrac{g_{ij} + g_{\text{s}i}}{\tau_{ij}^2} V_{i} - + \cfrac{1}{\tau_{ij}} \left[g_{ij}\cos(\theta_{ij} - \phi_{ij}) + b_{ij}\sin(\theta_{ij} - \phi_{ij})\right] V_{j} \\ + \cfrac{\mathrm \partial{h_{P_{ij}}(\mathbf x)}}{\mathrm \partial V_{j}} &= - + \cfrac{1}{\tau_{ij}} \left[g_{ij} \cos(\theta_{ij} - \phi_{ij}) + b_{ij} \sin(\theta_{ij} - \phi_{ij})\right] V_{i}. + \end{aligned}\]


To-Bus End Active Power Flow Measurements

Similarly, a wattmeter can be placed at the to-bus end, denoted as $P_{ji} \in \mathcal{P}$, specifying the measurement value, variance, and measurement function of vectors:

\[ \mathbf{z}_\mathcal{P} = [z_{P_{ji}}], \;\;\; \mathbf{v}_\mathcal{P} = [v_{P_{ji}}], \;\;\; \mathbf{h}_\mathcal{P}(\mathbf {x}) = [h_{P_{ji}}(\mathbf {x})].\]

For example:

addWattmeter!(system, device; label = "P₂₁", to = 1, active = -0.2, variance = 1e-4)

Thus, the function describing active power flow at the to-bus end is defined as follows:

\[ h_{P_{ji}}(\mathbf {x}) = (g_{ij} + g_{\text{s}i}) V_{j}^2 - \cfrac{1}{\tau_{ij}} \left[g_{ij} \cos(\theta_{ij} - \phi_{ij}) - b_{ij} \sin(\theta_{ij}- \phi_{ij})\right] V_{i} V_j,\]

with the following Jacobian expressions:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{P_{ji}}(\mathbf x)}}{\mathrm \partial \theta_{i}} &= - + \cfrac{\mathrm \partial{h_{P_{ji}}(\mathbf x)}}{\mathrm \partial \theta_{j}} = + \cfrac{1}{\tau_{ij}} \left[g_{ij}\sin(\theta_{ij} - \phi_{ij}) + b_{ij}\cos(\theta_{ij} - \phi_{ij})\right] V_{i}V_{j} \\ + \cfrac{\mathrm \partial{h_{P_{ji}}(\mathbf x)}}{\mathrm \partial V_{i}} &= - + \cfrac{1}{\tau_{ij}} \left[g_{ij} \cos(\theta_{ij} - \phi_{ij}) - b_{ij} \sin(\theta_{ij} - \phi_{ij})\right] V_j \\ + \cfrac{\mathrm \partial{h_{P_{ji}}(\mathbf x)}}{\mathrm \partial V_{j}} &= 2(g_{ij} + g_{\text{s}i}) V_{j}- + \cfrac{1}{\tau_{ij}} \left[g_{ij} \cos(\theta_{ij} - \phi_{ij}) - b_{ij} \sin(\theta_{ij} - \phi_{ij})\right] V_{i}. + \end{aligned}\]


Reactive Power Injection Measurements

When adding a varmeter $Q_i \in \mathcal{Q}$ at bus $i \in \mathcal{N}$, users specify that the varmeter measures reactive power injection and define the measurement value, variance, and measurement function of vectors:

\[ \mathbf{z}_\mathcal{Q} = [z_{Q_{i}}], \;\;\; \mathbf{v}_\mathcal{Q} = [v_{Q_{i}}], \;\;\; \mathbf{h}_\mathcal{Q}(\mathbf {x}) = [h_{Q_{i}}(\mathbf {x})].\]

For example:

addVarmeter!(system, device; label = "Q₃", bus = 3, reactive = 0, variance = 1e-3)

Here, utilizing the AC Model, we derive the function defining the reactive power injection as follows:

\[ h_{Q_{i}}(\mathbf {x}) = {V}_{i}\sum\limits_{j \in \mathcal{N}_i} (G_{ij}\sin\theta_{ij} - B_{ij}\cos\theta_{ij}){V}_{j},\]

where $\mathcal{N}_i$ contains buses incident to bus $i$, including bus $i$, with the following Jacobian expressions:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{Q_{i}}(\mathbf x)}}{\mathrm \partial \theta_{i}} &= + {V}_{i}\sum_{j \in \mathcal{N}_i} (G_{ij}\cos\theta_{ij}+B_{ij}\sin\theta_{ij}){V}_{j} - G_{ii}V_i^2\\ + \cfrac{\mathrm \partial{h_{Q_{i}}(\mathbf x)}}{\mathrm \partial \theta_{j}} &= + -(G_{ij}\cos\theta_{ij}+B_{ij}\sin\theta_{ij}){V}_{i}{V}_{j} \\ + \cfrac{\mathrm \partial{h_{Q_{i}}(\mathbf x)}}{\mathrm \partial V_{i}} &= + \sum_{j \in \mathcal{N}_i} (G_{ij}\sin\theta_{ij}-B_{ij}\cos\theta_{ij}){V}_{j} - B_{ii}{V}_{i}\\ + \cfrac{\mathrm \partial{h_{Q_{i}}(\mathbf x)}}{\mathrm \partial V_{j}} &= + (G_{ij}\sin\theta_{ij}-B_{ij}\cos\theta_{ij}){V}_{i}. + \end{aligned}\]


From-Bus End Reactive Power Flow Measurements

Additionally, when introducing a varmeter at branch $(i,j) \in \mathcal{E}$, users specify that the varmeter measures reactive power flow. It can be positioned at the from-bus end, denoted as $Q_{ij} \in \mathcal{Q}$, with its measurement value, variance, and measurement function included in vectors:

\[ \mathbf{z}_\mathcal{Q} = [z_{Q_{ij}}], \;\;\; \mathbf{v}_\mathcal{Q} = [v_{Q_{ij}}], \;\;\; \mathbf{h}_\mathcal{Q}(\mathbf {x}) = [h_{Q_{ij}}(\mathbf {x})].\]

For example:

addVarmeter!(system, device; label = "Q₁₂", from = 1, reactive = 0.2, variance = 1e-4)

Here, the function describing reactive power flow at the from-bus end is defined as follows:

\[ h_{Q_{ij}}(\mathbf {x}) = -\cfrac{b_{ij} + b_{\text{s}i}}{\tau_{ij}^2} V_{i}^2 - \cfrac{1}{\tau_{ij}} \left[g_{ij}\sin(\theta_{ij} - \phi_{ij}) - b_{ij}\cos(\theta_{ij} - \phi_{ij})\right] V_{i}V_{j},\]

with the following Jacobian expressions:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{Q_{ij}}(\mathbf x)}}{\mathrm \partial \theta_{i}} &= - + \cfrac{\mathrm \partial{h_{Q_{ij}}(\mathbf x)}}{\mathrm \partial \theta_{j}} = - + \cfrac{1}{\tau_{ij}} \left[g_{ij}\cos(\theta_{ij} - \phi_{ij}) + b_{ij}\sin(\theta_{ij} - \phi_{ij})\right] V_{i}V_{j} \\ + \cfrac{\mathrm \partial{h_{Q_{ij}}(\mathbf x)}}{\mathrm \partial V_{i}} &= - + 2\cfrac{b_{ij} + b_{\text{s}i}}{\tau_{ij}^2} V_{i} - + \cfrac{1}{\tau_{ij}} \left[g_{ij}\sin(\theta_{ij} - \phi_{ij}) - b_{ij}\cos(\theta_{ij} - \phi_{ij})\right] V_{j}\\ + \cfrac{\mathrm \partial{h_{Q_{ij}}(\mathbf x)}}{\mathrm \partial V_{j}} &= - + \cfrac{1}{\tau_{ij}} \left[g_{ij}\sin(\theta_{ij} - \phi_{ij}) - b_{ij}\cos(\theta_{ij} - \phi_{ij})\right] V_{i}. + \end{aligned}\]


To-Bus End Reactive Power Flow Measurements

Similarly, a varmeter can be placed at the to-bus end, denoted as $Q_{ji} \in \mathcal{Q}$, with its own measurement value, variance, and measurement function included in vectors:

\[ \mathbf{z}_\mathcal{Q} = [z_{Q_{ji}}], \;\;\; \mathbf{v}_\mathcal{Q} = [v_{Q_{ji}}], \;\;\; \mathbf{h}_\mathcal{Q}(\mathbf {x}) = [h_{Q_{ji}}(\mathbf {x})].\]

For example:

addVarmeter!(system, device; label = "Q₂₁", to = 1, reactive = -0.2, variance = 1e-4)

Thus, the function describing reactive power flow at the to-bus end is defined as follows:

\[ h_{Q_{ji}}(\mathbf {x}) = -(b_{ij} + b_{\text{s}i}) V_{j}^2 + \cfrac{1}{\tau_{ij}} \left[g_{ij} \sin(\theta_{ij} - \phi_{ij}) + b_{ij} \cos(\theta_{ij} - \phi_{ij})\right] V_{i}V_{j},\]

with the following Jacobian expressions:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{Q_{ji}}(\mathbf x)}}{\mathrm \partial \theta_{i}} &= - + \cfrac{\mathrm \partial{h_{Q_{ji}}(\mathbf x)}}{\mathrm \partial \theta_{j}} = + \cfrac{1}{\tau_{ij}} \left[g_{ij}\cos(\theta_{ij} - \phi_{ij}) - b_{ij}\sin(\theta_{ij} - \phi_{ij})\right] V_{i}V_{j} \\ + \cfrac{\mathrm \partial{h_{Q_{ji}}(\mathbf x)}}{\mathrm \partial V_{i}} &= + \cfrac{1}{\tau_{ij}} \left[g_{ij} \sin(\theta_{ij} - \phi_{ij}) + b_{ij} \cos(\theta_{ij} - \phi_{ij})\right] V_{j}\\ + \cfrac{\mathrm \partial{h_{Q_{ji}}(\mathbf x)}}{\mathrm \partial V_{j}} &= - + 2(b_{ij} + b_{\text{s}i}) V_{j} + + \cfrac{1}{\tau_{ij}} \left[g_{ij} \sin(\theta_{ij} - \phi_{ij}) + b_{ij} \cos(\theta_{ij} - \phi_{ij})\right] V_{i}. + \end{aligned}\]


Rectangular Bus Voltage Phasor Measurements

When a PMU $(V_i, \theta_i) \in \bar{\mathcal{P}}$ is introduced at bus $i \in \mathcal{N}$, it will be incorporated into the AC state estimation model using rectangular coordinates by default. It will define the measurement values, variances, and measurement functions of vectors:

\[ \mathbf{z}_{\bar{\mathcal{P}}} = [z_{\Re(\bar{V}_{i})}, z_{\Im(\bar{V}_{i})}], \;\;\; \mathbf{v}_{\bar{\mathcal{P}}} = [v_{\Re(\bar{V}_{i})}, v_{\Im(\bar{V}_{i})}], \;\;\; \mathbf{h}_{\bar{\mathcal{P}}}(\mathbf {x}) = [h_{\Re(\bar{V}_{i})}(\mathbf {x}), h_{\Im(\bar{V}_{i})}(\mathbf {x})].\]

For example:

addPmu!(system, device; label = "V₂, θ₂", bus = 2, magnitude = 0.9, angle = -0.1,
+varianceMagnitude = 1e-5, varianceAngle = 1e-5)

Here, measurement values are obtained according to:

\[ \begin{aligned} + z_{\Re(\bar{V}_i)} = z_{V_i} \cos z_{\theta_i}\\ + z_{\Im(\bar{V}_i)} = z_{V_i} \sin z_{\theta_i}. + \end{aligned}\]

Utilizing the classical theory of propagation of uncertainty [16], the variances can be calculated as follows:

\[ \begin{aligned} + v_{\Re(\bar{V}_i)} &= + v_{V_i} \left[ \cfrac{\mathrm \partial} {\mathrm \partial z_{V_i}} (z_{V_i} \cos z_{\theta_i}) \right]^2 + + v_{\theta_i} \left[ \cfrac{\mathrm \partial} {\mathrm \partial z_{\theta_i}} (z_{V_i} \cos z_{\theta_i})\right]^2 = + v_{V_i} (\cos z_{\theta_i})^2 + v_{\theta_i} (z_{V_i} \sin z_{\theta_i})^2\\ + v_{\Im(\bar{V}_i)} &= + v_{V_i} \left[ \cfrac{\mathrm \partial} {\mathrm \partial z_{V_i}} (z_{V_i} \sin z_{\theta_i}) \right]^2 + + v_{\theta_i} \left[ \cfrac{\mathrm \partial} {\mathrm \partial z_{\theta_i}} (z_{V_i} \sin z_{\theta_i})\right]^2 = + v_{V_i} (\sin z_{\theta_i})^2 + v_{\theta_i} (z_{V_i} \cos z_{\theta_i})^2. + \end{aligned}\]

Lastly, the functions defining the bus voltage phasor measurement are:

\[ \begin{aligned} + h_{\Re(\bar{V}_{i})}(\mathbf {x}) = V_{i}\cos \theta_i\\ + h_{\Im(\bar{V}_{i})}(\mathbf {x}) = V_{i}\sin \theta_i. + \end{aligned}\]

Jacobian expressions corresponding to the measurement function $h_{\Re(\bar{V}_{i})}(\mathbf x)$ are defined as follows:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{\Re(\bar{V}_{i})}(\mathbf x)}}{\mathrm \partial \theta_{i}}=-V_{i}\sin \theta_i, \;\;\; + \cfrac{\mathrm \partial{h_{\Re(\bar{V}_{i})}(\mathbf x)}}{\mathrm \partial V_{i}}=\cos \theta_i, + \end{aligned}\]

while Jacobian expressions corresponding to the measurement function $h_{\Im(\bar{V}_{i})}(\mathbf x)$ are:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{\Im(\bar{V}_{i})}(\mathbf x)}}{\mathrm \partial \theta_{i}}=V_{i}\cos \theta_i,\;\;\; + \cfrac{\mathrm \partial{h_{\Im(\bar{V}_{i})}(\mathbf x)}}{\mathrm \partial V_{i}}=\sin \theta_i. + \end{aligned}\]

In the previous example, the user neglects the covariances between the real and imaginary parts of the measurement. However, if desired, the user can also include them in the state estimation model by specifying the covariances of the vector:

\[ \mathbf{w}_{\bar{\mathcal{P}}} = [w_{\Re(\bar{V}_{i})}, w_{\Im(\bar{V}_{i})}].\]

addPmu!(system, device; label = "V₃, θ₃", bus = 3, magnitude = 0.9, angle = -0.2,
+varianceMagnitude = 1e-5, varianceAngle = 1e-5, correlated = true)

Then, the covariances are obtained as follows:

\[ w_{\Re(\bar{V}_{i})} = w_{\Im(\bar{V}_{i})} = + v_{V_i} \cfrac{\mathrm \partial} {\mathrm \partial z_{V_i}} (z_{V_i} \cos z_{\theta_i}) + \cfrac{\mathrm \partial} {\mathrm \partial z_{V_i}} (z_{V_i} \sin z_{\theta_i}) + + v_{\theta_i} \cfrac{\mathrm \partial} {\mathrm \partial z_{\theta_i}} (z_{V_i} \cos z_{\theta_i}) + \cfrac{\mathrm \partial} {\mathrm \partial z_{\theta_i}} (z_{V_i} \sin z_{\theta_i}),\]

which results in the solution:

\[ w_{\Re(\bar{V}_{i})} = w_{\Im(\bar{V}_{i})} = \cos z_{\theta_i} \sin z_{\theta_i}(v_{V_i} - v_{\theta_i} z_{V_i}^2).\]


Polar Bus Voltage Phasor Measurements

If the user chooses to include phasor measurement $(V_i, \theta_i) \in \bar{\mathcal{P}}$ in polar coordinates in the AC state estimation model, the user will specify the measurement values, variances, and measurement functions of vectors:

\[ \mathbf{z}_{\bar{\mathcal{P}}} = [z_{V_i}, z_{\theta_i}], \;\;\; \mathbf{v}_{\bar{\mathcal{P}}} = [v_{V_i}, v_{\theta_i}], \;\;\; \mathbf{h}_{\bar{\mathcal{P}}}(\mathbf {x}) = [h_{V_{i}}(\mathbf {x}), h_{\theta_{i}}(\mathbf {x})].\]

For example:

addPmu!(system, device; label = "V₁, θ₁", bus = 1, magnitude = 1.0, angle = 0,
+varianceMagnitude = 1e-5, varianceAngle = 1e-6, polar = true)

Here, the functions defining the bus voltage phasor measurement are straightforward:

\[ \begin{aligned} + h_{V_{i}}(\mathbf {x}) = V_{i}\\ + h_{\theta_{i}}(\mathbf {x}) = \theta_{i}, + \end{aligned}\]

with the following Jacobian expressions:

\[ \begin{aligned} + \cfrac{\mathrm \partial{{h_{{V}_{i}}(\mathbf x)}}}{\mathrm \partial V_{i}}=1, \;\;\; + \cfrac{\mathrm \partial{{h_{\theta_i}(\mathbf x)}}}{\mathrm \partial \theta_{i}}=1. + \end{aligned}\]


Rectangular From-Bus End Current Phasor Measurements

When introducing a PMU at branch $(i,j) \in \mathcal{E}$, it can be placed at the from-bus end, denoted as $(I_{ij}, \psi_{ij}) \in \bar{\mathcal{P}}$, and it will be integrated into the AC state estimation model using rectangular coordinates by default. Incorporating current phasor measurements in the polar coordinate system is highly susceptible to ill-conditioned problems, especially when dealing with small values of current magnitudes. This is the reason why we typically include PMUs in the rectangular coordinate system by default.

Therefore, here we specify the measurement values, variances, and measurement functions of vectors:

\[ \mathbf{z}_{\bar{\mathcal{P}}} = [z_{\Re(\bar{I}_{ij})}, z_{\Im(\bar{I}_{ij})}], \;\;\; \mathbf{v}_{\bar{\mathcal{P}}} = [v_{\Re(\bar{I}_{ij})}, v_{\Im(\bar{I}_{ij})}], \;\;\; \mathbf{h}_{\bar{\mathcal{P}}}(\mathbf {x}) = [h_{\Re(\bar{I}_{ij})}(\mathbf {x}), h_{\Im(\bar{I}_{ij})}(\mathbf {x})].\]

For example:

addPmu!(system, device; label = "I₂₃, ψ₂₃", from = 3, magnitude = 0.3, angle = 0.4,
+varianceMagnitude = 1e-5, varianceAngle = 1e-4)

Here, measurement values are obtained according to:

\[ \begin{aligned} + z_{\Re(\bar{I}_{ij})} = z_{I_{ij}} \cos z_{\psi_{ij}}\\ + z_{\Im(\bar{I}_{ij})} = z_{I_{ij}} \sin z_{\psi_{ij}}. + \end{aligned}\]

Utilizing the classical theory of propagation of uncertainty [16], the variances can be calculated as follows:

\[ \begin{aligned} + v_{\Re(\bar{I}_{ij})} & = v_{I_{ij}} (\cos z_{\psi_{ij}})^2 + v_{\psi_{ij}} (z_{I_{ij}} \sin z_{\psi_{ij}})^2 \\ + v_{\Im(\bar{I}_{ij})} &= v_{I_{ij}} (\sin z_{\psi_{ij}})^2 + v_{\psi_{ij}} (z_{I_{ij}} \cos z_{\psi_{ij}})^2. + \end{aligned}\]

The functions defining the current phasor measurement at the from-bus end are:

\[ \begin{aligned} + h_{\Re(\bar{I}_{ij})}(\mathbf {x}) &= (A_{\psi_{ij}} \cos \theta_i - B_{\psi_{ij}} \sin \theta_i)V_i - [C_{\psi_{ij}} \cos (\theta_j + \phi_{ij}) - D_{\psi_{ij}} \sin (\theta_j + \phi_{ij})]V_j, \\ + h_{\Im(\bar{I}_{ij})}(\mathbf {x}) &= (A_{\psi_{ij}} \sin \theta_i + B_{\psi_{ij}} \cos \theta_i)V_i - [C_{\psi_{ij}} \sin (\theta_j + \phi_{ij}) + D_{\psi_{ij}} \cos (\theta_j + \phi_{ij})]V_j. + \end{aligned}\]

Jacobian expressions corresponding to the measurement function $h_{\Re(\bar{I}_{ij})}(\mathbf x)$ are defined as follows:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{\Re(\bar{I}_{ij})}(\mathbf x)}}{\mathrm \partial \theta_{i}} &= + -(A_{\psi_{ij}} \sin \theta_{i} + B_{\psi_{ij}} \cos \theta_{i})V_i\\ + \cfrac{\mathrm \partial{h_{\Re(\bar{I}_{ij})}(\mathbf x)}}{\mathrm \partial \theta_{j}} &= + [C_{\psi_{ij}} \sin(\theta_j + \phi_{ij}) + D_{\psi_{ij}} \cos(\theta_j + \phi_{ij})] V_j \\ + \cfrac{\mathrm \partial{h_{\Re(\bar{I}_{ij})}(\mathbf x)}}{\mathrm \partial V_{i}} &= + A_{\psi_{ij}} \cos \theta_{i} - B_{\psi_{ij}} \sin\theta_{i}\\ + \cfrac{\mathrm \partial{h_{\Re(\bar{I}_{ij})}(\mathbf x)}}{\mathrm \partial V_{j}} &= + -C_{\psi_{ij}} \cos(\theta_j + \phi_{ij}) + D_{\psi_{ij}} \sin(\theta_j + \phi_{ij}). + \end{aligned}\]

while Jacobian expressions corresponding to the measurement function $h_{\Im(\bar{I}_{ij})}(\mathbf x)$ are:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{\Im(\bar{I}_{ij})}(\mathbf x)}}{\mathrm \partial \theta_{i}} &= + (A_{\psi_{ij}} \cos \theta_{i} - B_{\psi_{ij}} \sin \theta_{i})V_i\\ + \cfrac{\mathrm \partial{h_{\Im(\bar{I}_{ij})}(\mathbf x)}}{\mathrm \partial \theta_{j}} &= + [-C_{\psi_{ij}} \cos(\theta_j + \phi_{ij}) + D_{\psi_{ij}} \sin(\theta_j + \phi_{ij})] V_j \\ + \cfrac{\mathrm \partial{h_{\Im(\bar{I}_{ij})}(\mathbf x)}}{\mathrm \partial V_{i}} &= + A_{\psi_{ij}} \sin \theta_{i} + B_{\psi_{ij}} \cos\theta_{i}\\ + \cfrac{\mathrm \partial{h_{\Im(\bar{I}_{ij})}(\mathbf x)}}{\mathrm \partial V_{j}} &= + -C_{\psi_{ij}} \sin(\theta_j + \phi_{ij}) - D_{\psi_{ij}} \cos(\theta_j + \phi_{ij}). + \end{aligned}\]

In the previous example, the user neglects the covariances between the real and imaginary parts of the measurement. However, if desired, the user can also include them in the state estimation model by specifying the covariances of the vector:

\[ \mathbf{w}_{\bar{\mathcal{P}}} = [w_{\Re(\bar{I}_{ij})}, w_{\Im(\bar{I}_{ij})}].\]

addPmu!(system, device; label = "I₁₃, ψ₁₃", from = 2, magnitude = 0.3, angle = -0.5,
+varianceMagnitude = 1e-4, varianceAngle = 1e-5, correlated = true)

Then, the covariances are obtained as follows:

\[ w_{\Re(\bar{I}_{ij})} = w_{\Im(\bar{I}_{ij})} = \sin z_{\psi_{ij}} \cos z_{\psi_{ij}}(v_{I_{ij}} - v_{\psi_{ij}} z_{I_{ij}}^2).\]


Polar From-Bus End Current Phasor Measurements

If the user chooses to include phasor measurement $(I_{ij}, \psi_{ij}) \in \bar{\mathcal{P}}$ in polar coordinates in the AC state estimation model, the user will specify the measurement values, variances, and measurement functions of vectors:

\[ \mathbf{z}_{\bar{\mathcal{P}}} = [z_{I_{ij}}, z_{\psi_{ij}}], \;\;\; \mathbf{v}_{\bar{\mathcal{P}}} = [v_{I_{ij}}, v_{\psi_{ij}}], \;\;\; \mathbf{h}_{\bar{\mathcal{P}}}(\mathbf {x}) = [h_{I_{ij}}(\mathbf {x}), h_{\psi_{ij}}(\mathbf {x})].\]

For example:

addPmu!(system, device; label = "I₁₂, ψ₁₂", from = 1, magnitude = 0.3, angle = -0.7,
+varianceMagnitude = 1e-5, varianceAngle = 1e-4, polar = true)

Here, the function associated with the branch current magnitude at the from-bus end remains identical to the one provided in From-Bus End Current Magnitude Measurements. However, the function defining the branch current angle measurement is expressed as:

\[ h_{\psi_{ij}}(\mathbf {x}) = \mathrm{atan}\Bigg[ + \cfrac{(A_{\psi_{ij}} \sin\theta_i + B_{\psi_{ij}} \cos\theta_i)V_i - [C_{\psi_{ij}} \sin(\theta_{j}+\phi_{ij}) + D_{\psi_{ij}}\cos(\theta_{j}+\phi_{ij})]V_j} + {(A_{\psi_{ij}} \cos\theta_i - B_{\psi_{ij}} \sin\theta_i)V_i - [C_{\psi_{ij}} \cos(\theta_{j}+\phi_{ij}) - D_{\psi_{ij}} \sin(\theta_{j}+\phi_{ij})]V_j} \Bigg],\]

where:

\[ A_{\psi_{ij}} = \cfrac{g_{ij} + g_{\text{s}i}}{\tau_{ij}^2}, \;\;\; B_{\psi_{ij}} = \cfrac{b_{ij}+b_{\text{s}i}}{\tau_{ij}^2}, \;\;\; + C_{\psi_{ij}} = \cfrac{g_{ij}}{\tau_{ij}}, \;\;\; D_{\psi_{ij}} = \cfrac{b_{ij}}{\tau_{ij}}.\]

Jacobian expressions associated with the branch current magnitude function $h_{I_{ij}}(\mathbf x)$ remains identical to the one provided in From-Bus End Current Magnitude Measurements. Further, Jacobian expressions corresponding to the measurement function $h_{\psi_{ij}}(\mathbf x)$ are defined as follows:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{\psi_{ij}}(\mathbf x)}}{\mathrm \partial \theta_{i}} &= + \cfrac{A_{I_{ij}} V_i^2- [C_{I_{ij}} \cos(\theta_{ij}- \phi_{ij}) - D_{I_{ij}} \sin (\theta_{ij} - \phi_{ij}) ]V_iV_j}{h_{{I}_{ij}}^2(\mathbf x)} \\ + \cfrac{\mathrm \partial{h_{\psi_{ij}}(\mathbf x)}}{\mathrm \partial \theta_{j}} &= + \cfrac{B_{I_{ij}} V_j^2 - [C_{I_{ij}} \cos (\theta_{ij} - \phi_{ij}) - D_{I_{ij}} \sin(\theta_{ij}- \phi_{ij})]V_iV_j}{h_{{I}_{ij}}^2(\mathbf x)} \\ + \cfrac{\mathrm \partial{h_{\psi_{ij}}(\mathbf x)}}{\mathrm \partial V_{i}} &= - + \cfrac{[C_{I_{ij}} \sin (\theta_{ij} - \phi_{ij}) + D_{I_{ij}} \cos(\theta_{ij}- \phi_{ij})]V_j }{h_{{I}_{ij}}^2(\mathbf x)}\\ + \cfrac{\mathrm \partial{h_{\psi_{ij}}(\mathbf x)}}{\mathrm \partial V_{j}} &= + \cfrac{[C_{I_{ij}} \sin (\theta_{ij} - \phi_{ij}) + D_{I_{ij}} \cos(\theta_{ij}- \phi_{ij})]V_i }{h_{{I}_{ij}}^2(\mathbf x)}. + \end{aligned}\]


Rectangular To-Bus End Current Phasor Measurements

When introducing a PMU at branch $(i,j) \in \mathcal{E}$, it can be placed at the to-bus end, denoted as $(I_{ji}, \psi_{ji}) \in \bar{\mathcal{P}}$, and it will be integrated into the AC state estimation model using rectangular coordinates by default. The user will specify the measurement values, variances, and measurement functions of vectors:

\[ \mathbf{z}_{\bar{\mathcal{P}}} = [z_{\Re(\bar{I}_{ji})}, z_{\Im(\bar{I}_{ji})}], \;\;\; \mathbf{v}_{\bar{\mathcal{P}}} = [v_{\Re(\bar{I}_{ji})}, v_{\Im(\bar{I}_{ji})}], \;\;\; \mathbf{h}_{\bar{\mathcal{P}}}(\mathbf {x}) = [h_{\Re(\bar{I}_{ji})}(\mathbf {x}), h_{\Im(\bar{I}_{ji})}(\mathbf {x})].\]

For example:

addPmu!(system, device; label = "I₃₂, ψ₃₂", to = 3, magnitude = 0.3, angle = -2.9,
+varianceMagnitude = 1e-5, varianceAngle = 1e-5)

Here, measurement values are obtained according to:

\[ \begin{aligned} + z_{\Re(\bar{I}_{ji})} = z_{I_{ji}} \cos z_{\psi_{ji}}\\ + z_{\Im(\bar{I}_{ji})} = z_{I_{ji}} \sin z_{\psi_{ji}}. + \end{aligned}\]

The variances can be calculated as follows:

\[ \begin{aligned} + v_{\Re(\bar{I}_{ji})} &= v_{I_{ji}} (\cos z_{\psi_{ji}})^2 + v_{\psi_{ji}} (z_{I_{ji}} \sin z_{\psi_{ji}})^2 \\ + v_{\Im(\bar{I}_{ji})} &= v_{I_{ji}} (\sin z_{\psi_{ji}})^2 + v_{\psi_{ji}} (z_{I_{ji}} \cos z_{\psi_{ji}})^2. + \end{aligned}\]

The functions defining the current phasor measurement at the to-bus end are:

\[ \begin{aligned} + h_{\Re(\bar{I}_{ji})}(\mathbf {x}) &= (A_{\psi_{ji}} \cos \theta_j - B_{\psi_{ji}} \sin \theta_j)V_j - [C_{\psi_{ji}} \cos (\theta_i - \phi_{ij}) - D_{\psi_{ji}} \sin (\theta_i + \phi_{ij})]V_i\\ + h_{\Im(\bar{I}_{ji})}(\mathbf {x}) &= (A_{\psi_{ji}} \sin \theta_j + B_{\psi_{ji}} \cos \theta_j)V_j - [C_{\psi_{ji}} \sin (\theta_i + \phi_{ij}) + D_{\psi_{ji}} \cos (\theta_i + \phi_{ij})]V_i. + \end{aligned}\]

Jacobian expressions corresponding to the measurement function $h_{\Re(\bar{I}_{ji})}(\mathbf x)$ are defined as follows:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{\Re(\bar{I}_{ji})}(\mathbf x)}}{\mathrm \partial \theta_{i}} &= + [C_{\psi_{ji}} \sin (\theta_{i} - \phi_{ij}) + D_{\psi_{ji}} \cos (\theta_{i} - \phi_{ij})]V_i\\ + \cfrac{\mathrm \partial{h_{\Re(\bar{I}_{ji})}(\mathbf x)}}{\mathrm \partial \theta_{j}} &= + -(A_{\psi_{ji}} \sin\theta_j + B_{\psi_{ji}} \cos \theta_j ) V_j \\ + \cfrac{\mathrm \partial{h_{\Re(\bar{I}_{ji})}(\mathbf x)}}{\mathrm \partial V_{i}} &= + - C_{\psi_{ji}} \cos (\theta_{i} - \phi_{ij}) + D_{\psi_{ji}} \sin(\theta_{i} - \phi_{ij})\\ + \cfrac{\mathrm \partial{h_{\Re(\bar{I}_{ji})}(\mathbf x)}}{\mathrm \partial V_{j}} &= + A_{\psi_{ji}} \cos \theta_j - B_{\psi_{ji}} \sin \theta_j. + \end{aligned}\]

while Jacobian expressions corresponding to the measurement function $h_{\Im(\bar{I}_{ji})}(\mathbf x)$ are:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{\Im(\bar{I}_{ji})}(\mathbf x)}}{\mathrm \partial \theta_{i}} &= + [-C_{\psi_{ji}} \cos (\theta_{i} - \phi_{ij}) + D_{\psi_{ji}} \sin (\theta_{i} - \phi_{ij})]V_i\\ + \cfrac{\mathrm \partial{h_{\Im(\bar{I}_{ji})}(\mathbf x)}}{\mathrm \partial \theta_{j}} &= + (A_{\psi_{ji}} \cos\theta_j - B_{\psi_{ji}} \sin \theta_j ) V_j \\ + \cfrac{\mathrm \partial{h_{\Im(\bar{I}_{ji})}(\mathbf x)}}{\mathrm \partial V_{i}} &= + - C_{\psi_{ji}} \sin (\theta_{i} - \phi_{ij}) - D_{\psi_{ji}} \cos(\theta_{i} - \phi_{ij})\\ + \cfrac{\mathrm \partial{h_{\Im(\bar{I}_{ji})}(\mathbf x)}}{\mathrm \partial V_{j}} &= + A_{\psi_{ji}} \sin \theta_j + B_{\psi_{ji}} \cos \theta_j. + \end{aligned}\]

As before, we are neglecting the covariances between the real and imaginary parts of the measurement. If desired, we can include them in the state estimation model by specifying the covariances of the vector:

\[ \mathbf{w}_{\bar{\mathcal{P}}} = [w_{\Re(\bar{I}_{ji})}, w_{\Im(\bar{I}_{ji})}].\]

addPmu!(system, device; label = "I₃₁, ψ₃₁", to = 2, magnitude = 0.3, angle = 2.5,
+varianceMagnitude = 1e-5, varianceAngle = 1e-5, correlated = true)

Then, the covariances are obtained as follows:

\[ w_{\Re(\bar{I}_{ji})} = w_{\Im(\bar{I}_{ji})} = \sin z_{\psi_{ji}} \cos z_{\psi_{ji}}(v_{I_{ji}} - v_{\psi_{ji}} z_{I_{ji}}^2).\]


Polar To-Bus End Current Phasor Measurements

If the user chooses to include phasor measurement $(I_{ji}, \psi_{ji}) \in \bar{\mathcal{P}}$ in polar coordinates in the AC state estimation model, the user will specify the measurement values, variances, and measurement functions of vectors:

\[ \mathbf{z}_{\bar{\mathcal{P}}} = [z_{I_{ji}}, z_{\psi_{ji}}], \;\;\; \mathbf{v}_{\bar{\mathcal{P}}} = [v_{I_{ji}}, v_{\psi_{ji}}], \;\;\; \mathbf{h}_{\bar{\mathcal{P}}}(\mathbf {x}) = [h_{I_{ji}}(\mathbf {x}), h_{\psi_{ji}}(\mathbf {x})].\]

For example:

addPmu!(system, device; label = "I₂₁, ψ₂₁", to = 1, magnitude = 0.3, angle = 2.3,
+varianceMagnitude = 1e-2, varianceAngle = 1e-3, polar = true)

Here, the function associated with the branch current magnitude at the to-bus end remains identical to the one provided in To-Bus End Current Magnitude Measurements. However, the function defining the branch current angle measurement is expressed as:

\[ h_{\psi_{ji}}(\mathbf {x}) = \mathrm{atan}\Bigg[ + \cfrac{(A_{\psi_{ji}} \sin\theta_j + B_{\psi_{ji}} \cos\theta_j)V_j - [C_{\psi_{ji}} \sin(\theta_{i}-\phi_{ij}) + D_{\psi_{ji}}\cos(\theta_{i}-\phi_{ij})]V_i} + {(A_{\psi_{ji}} \cos\theta_j - B_{\psi_{ji}} \sin\theta_j)V_j - [C_{\psi_{ji}} \cos(\theta_{i}-\phi_{ij}) - D_{\psi_{ji}} \sin(\theta_{i}-\phi_{ij})]V_i} \Bigg],\]

where:

\[ A_{\psi_{ji}} = g_{ij} + g_{\text{s}i}, \;\;\; B_{\psi_{ji}} = b_{ij} + b_{\text{s}i}, \;\;\; + C_{\psi_{ji}} = \cfrac{g_{ij}}{\tau_{ij}}, \;\;\; D_{\psi_{ji}} = \cfrac{b_{ij}}{\tau_{ij}}.\]

Jacobian expressions associated with the branch current magnitude function $h_{I_{ji}}(\mathbf x)$ remains identical to the one provided in To-Bus End Current Magnitude Measurements. Further, Jacobian expressions corresponding to the measurement function $h_{\psi_{ji}}(\mathbf x)$ are defined as follows:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{\psi_{ji}}(\mathbf x)}}{\mathrm \partial \theta_{i}} &= + \cfrac{A_{I_{ji}} V_i^2- [C_{I_{ji}} \cos(\theta_{ij}- \phi_{ij}) + D_{I_{ji}} \sin (\theta_{ij} - \phi_{ij}) ]V_iV_j}{h_{{I}_{ji}}^2(\mathbf x)} \\ + \cfrac{\mathrm \partial{h_{\psi_{ji}}(\mathbf x)}}{\mathrm \partial \theta_{j}} &= + \cfrac{B_{I_{ji}} V_j^2 - [C_{I_{ji}} \cos (\theta_{ij} - \phi_{ij}) + D_{I_{ji}} \sin(\theta_{ij}- \phi_{ij})]V_iV_j}{h_{{I}_{ji}}^2(\mathbf x)} \\ + \cfrac{\mathrm \partial{h_{\psi_{ji}}(\mathbf x)}}{\mathrm \partial V_{i}} &= + -\cfrac{[C_{I_{ji}} \sin (\theta_{ij} - \phi_{ij}) - D_{I_{ji}} \cos(\theta_{ij}- \phi_{ij})]V_j }{h_{{I}_{ji}}^2(\mathbf x)}\\ + \cfrac{\mathrm \partial{h_{\psi_{ji}}(\mathbf x)}}{\mathrm \partial V_{j}} &= + \cfrac{[C_{I_{ji}} \sin (\theta_{ij} - \phi_{ij}) - D_{I_{ji}} \cos(\theta_{ij}- \phi_{ij})]V_i }{h_{{I}_{ji}}^2(\mathbf x)}. + \end{aligned}\]


Weighted Least-Squares Estimation

Given the available set of measurements $\mathcal{M}$, the weighted least-squares estimator $\hat{\mathbf x}$, i.e., the solution of the weighted least-squares problem, can be found using the Gauss-Newton method:

\[ \Big[\mathbf J (\mathbf x^{(\nu)})^{T} \bm \Sigma^{-1} \mathbf J (\mathbf x^{(\nu)})\Big] \mathbf \Delta \mathbf x^{(\nu)} = + \mathbf J (\mathbf x^{(\nu)})^{T} \bm \Sigma^{-1} \mathbf r (\mathbf x^{(\nu)})\]

\[ \mathbf x^{(\nu+1)} = \mathbf x^{(\nu)} + \mathbf \Delta \mathbf x^{(\nu)},\]

where $\nu = \{0,1,2,\dots\}$ is the iteration index, $\mathbf \Delta \mathbf x \in \mathbb {R}^{n_{\text{u}}}$ is the vector of increments of the state variables, $\mathbf J (\mathbf x)\in \mathbb {R}^{k \times n_{\text{u}}}$ is the Jacobian matrix of measurement functions $\mathbf h (\mathbf x)$ at $\mathbf x=\mathbf x^{(\nu)}$, $\bm \Sigma \in \mathbb {R}^{k \times k}$ is a measurement error covariance matrix, and $\mathbf r (\mathbf x) = \mathbf{z} - \mathbf h (\mathbf x)$ is the vector of residuals [13, Ch. 10]. It is worth noting that assuming uncorrelated measurement errors leads to a diagonal covariance matrix $\bm \Sigma$ corresponding to measurement variances. However, when incorporating PMUs in a rectangular coordinate system and aiming to observe error correlation, this matrix loses its diagonal form.

The non-linear or AC state estimation represents a non-convex problem arising from the non-linear measurement functions [17]. Due to the fact that the values of state variables usually fluctuate in narrow boundaries, the non-linear model represents the mildly non-linear problem, where solutions are in a reasonable-sized neighborhood which enables the use of the Gauss-Newton method. The Gauss-Newton method can produce different rates of convergence, which can be anywhere from linear to quadratic [18, Sec. 9.2]. The convergence rate in regard to power system state estimation depends on the topology and measurements, and if parameters are consistent (e.g., free bad data measurement set), the method shows near quadratic convergence rate [13, Sec. 11.2].


Initialization

Let us begin by setting up a new set of measurements for the defined power system:

device = measurement()
+
+@wattmeter(label = "Watmeter ?")
+addWattmeter!(system, device; bus = 3, active = -0.5, variance = 1e-3)
+addWattmeter!(system, device; from = 1, active = 0.2, variance = 1e-4)
+
+@varmeter(label = "Varmeter ?")
+addVarmeter!(system, device; bus = 2, reactive = -0.3, variance = 1e-3)
+addVarmeter!(system, device; from = 1, reactive = 0.2, variance = 1e-4)
+
+@pmu(label = "PMU ?")
+addPmu!(system, device; bus = 1, magnitude = 1.0, angle = 0, polar = true)
+addPmu!(system, device; bus = 3, magnitude = 0.9, angle = -0.2)

To compute the voltage magnitudes and angles of buses using the Gauss-Newton method in JuliaGrid, we need to first execute the acModel! function to set up the system. Then, initialize the Gauss-Newton method using the gaussNewton function. The following code snippet demonstrates this process:

acModel!(system)
+analysis = gaussNewton(system, device)

Initially, the gaussNewton function constructs the mean vector holding measurement values:

julia> 𝐳 = analysis.method.mean8-element Vector{Float64}:
+ -0.5
+  0.2
+ -0.3
+  0.2
+  1.0
+  0.0
+  0.8820599200571175
+ -0.1788023977155551

Additionally, it forms the precision or weighting matrix denoted as $\mathbf W = \bm \Sigma^{-1}$. We can access these values using the following command:

julia> 𝐖 = analysis.method.precision8×8 SparseArrays.SparseMatrixCSC{Float64, Int64} with 8 stored entries:
+ 1000.0       ⋅       ⋅        ⋅         ⋅         ⋅    ⋅          ⋅
+     ⋅   10000.0      ⋅        ⋅         ⋅         ⋅    ⋅          ⋅
+     ⋅        ⋅   1000.0       ⋅         ⋅         ⋅    ⋅          ⋅
+     ⋅        ⋅       ⋅   10000.0        ⋅         ⋅    ⋅          ⋅
+     ⋅        ⋅       ⋅        ⋅   100000.0        ⋅    ⋅          ⋅
+     ⋅        ⋅       ⋅        ⋅         ⋅   100000.0   ⋅          ⋅
+     ⋅        ⋅       ⋅        ⋅         ⋅         ⋅   1.00756e5   ⋅
+     ⋅        ⋅       ⋅        ⋅         ⋅         ⋅    ⋅         1.22324e5

Finally, using initial bus voltage magnitudes and angles from the PowerSystem type, the function creates the starting vector $\mathbf{x}^{(0)}$ of bus voltage magnitudes $\mathbf{V}^{(0)}$ and angles $\bm{\Theta}^{(0)}$ for the Gauss-Newton method:

julia> 𝐕⁽⁰⁾ = analysis.voltage.magnitude3-element Vector{Float64}:
+ 1.0
+ 1.0
+ 1.0
julia> 𝚯⁽⁰⁾ = analysis.voltage.angle3-element Vector{Float64}: + 0.0 + 0.0 + 0.0

Here, we utilize a "flat start" approach in our method. It is important to keep in mind that when dealing with initial conditions in this manner, the Gauss-Newton method may encounter difficulties.


Iterative Process

To apply the Gauss-Newton method, JuliaGrid provides the solve! function. This function is utilized iteratively until a stopping criterion is met, as demonstrated in the following code snippet:

for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        break
+    end
+end

The function solve! calculates the vector of residuals at each iteration using the equation:

\[ \mathbf r (\mathbf x^{(\nu)}) = \mathbf{z} - \mathbf h (\mathbf x^{(\nu)}).\]

The resulting vector from these calculations is stored in the residual variable of the ACStateEstimation type and can be accessed through the following line of code:

julia> 𝐫 = analysis.method.residual8-element Vector{Float64}:
+  0.0035897072707465894
+ -0.0018254496928567787
+  0.015450068279420526
+  0.004682202837369032
+ -0.000582477295592243
+  0.0
+  0.0006121253938213833
+ -0.0002912281911411907

The order of the residual vector follows a specific pattern. If all device types exist, the first $|\mathcal{V}|$ elements correspond to voltmeters, followed by $|\mathcal{I}|$ elements corresponding to ammeters. Then we have $|\mathcal{P}|$ elements for wattmeters and $|\mathcal{Q}|$ elements for varmeters. Finally, we have $2|\bar{\mathcal{P}}|$ elements for PMUs. The order of these elements within specific devices follows the same order as they appear in the input data defined by the Measurement type.

At the same time, the function forms the Jacobian matrix $\mathbf{J} (\mathbf{x}^{(\nu)})$ and calculates the gain matrix $\mathbf{G} (\mathbf{x}^{(\nu)})$ using:

\[ \mathbf G (\mathbf x^{(\nu)}) = \mathbf J (\mathbf x^{(\nu)})^{T} \bm \Sigma^{-1} \mathbf J (\mathbf x^{(\nu)})\]

The Jacobian matrix and factorized gain matrix are stored in the ACStateEstimation type and can be accessed after each iteration:

julia> 𝐉 = analysis.method.jacobian8×6 SparseArrays.SparseMatrixCSC{Float64, Int64} with 26 stored entries:
+ -1.25163   -3.8625    5.11413   -0.290756  -0.738148  -0.0780565
+  1.45142   -1.45142    ⋅         0.257234   0.167117    ⋅
+  0.242596  -0.374185  0.131589  -1.43762    5.39454   -4.35201
+  0.146267  -0.146267   ⋅         1.84098   -1.65831     ⋅
+   ⋅          ⋅         ⋅         1.0         ⋅          ⋅
+  1.0         ⋅         ⋅          ⋅          ⋅          ⋅
+   ⋅          ⋅        0.178511    ⋅          ⋅         0.980103
+   ⋅          ⋅        0.881448    ⋅          ⋅        -0.198491
julia> 𝐋 = analysis.method.factorization.L6×6 SparseArrays.SparseMatrixCSC{Float64, Int64} with 16 stored entries: + 1.0 ⋅ ⋅ ⋅ ⋅ ⋅ + ⋅ 1.0 ⋅ ⋅ ⋅ ⋅ + ⋅ -0.225721 1.0 ⋅ ⋅ ⋅ + ⋅ -0.0446328 -0.0308989 1.0 ⋅ ⋅ + ⋅ 0.0119191 -0.028865 -0.423172 1.0 ⋅ + ⋅ 0.0215482 -0.0318412 0.0560725 -0.361923 1.0
julia> 𝐔 = analysis.method.factorization.U6×6 SparseArrays.SparseMatrixCSC{Float64, Int64} with 16 stored entries: + 1.0 ⋅ ⋅ ⋅ ⋅ ⋅ + ⋅ 0.570745 -0.311022 -0.0748446 0.013076 0.0303121 + ⋅ ⋅ 0.739248 -0.0277985 -0.0169892 -0.0240308 + ⋅ ⋅ ⋅ 0.726587 -0.201154 0.0341773 + ⋅ ⋅ ⋅ ⋅ 0.383459 -0.177955 + ⋅ ⋅ ⋅ ⋅ ⋅ 0.700467

Then finally, the function computes the vector of state variable increments using the equation:

\[ \mathbf \Delta \mathbf x^{(\nu)} = \mathbf G (\mathbf x^{(\nu)})^{-1} \mathbf J (\mathbf x^{(\nu)})^{T} \bm \Sigma^{-1} \mathbf r (\mathbf x^{(\nu)})\]

Tip

By default, JuliaGrid uses LU factorization as the primary method for factorizing the gain matrix $\mathbf{G} = \mathbf{L}\mathbf{U}$, aiming to compute the increments. Nevertheless, users have the flexibility to opt for QR or LDLt factorization as an alternative method.

Increment values are stored in the ACStateEstimation type and can be accessed after each iteration:

julia> 𝚫𝐱 = analysis.method.increment6-element Vector{Float64}:
+  0.0
+ -1.9027980794422067e-9
+  4.203195409667386e-12
+ -1.481900860169573e-10
+  6.916715767922354e-10
+  9.322525666335619e-11

Here again, the JuliaGrid implementation of the AC state estimation follows a specific order to store the increment vector and Jacobian matrix. The vector of increments first contains $n$ increments of bus voltage angles $\mathbf \Delta \bm{\Theta}$, followed by $n$ increments of bus voltage magnitudes $\mathbf \Delta \mathbf{V}$. This order also corresponds to the columns of the Jacobian matrix, while the order of rows of the Jacobian is defined according to the order of the residual vector.

Note that the increment vector and Jacobian matrix hold the slack bus with a known voltage angle. An element of the increment vector and a column of the Jacobian matrix are not deleted, and the presence on the slack bus is handled internally by JuliaGrid, which is evident from the factorization of the gain matrix.

The function solve! adds the computed increment term to the previous solution to obtain a new solution:

\[ \mathbf {x}^{(\nu + 1)} = \mathbf {x}^{(\nu)} + \mathbf \Delta \mathbf {x}^{(\nu)}.\]

Therefore, the bus voltage magnitudes $\mathbf{V} = [V_i]$ and angles $\bm{\Theta} = [\theta_i]$ are stored in the following vectors:

julia> 𝐕 = analysis.voltage.magnitude3-element Vector{Float64}:
+ 1.0005824771474021
+ 0.8752366339306804
+ 0.8993422332624245
julia> 𝚯 = analysis.voltage.angle3-element Vector{Float64}: + 0.0 + -0.13375723397946815 + -0.1998178530119528

Finally, the solve! function provides the maximum absolute value of state variable increments, typically employed as the termination criterion for the iteration loop. Specifically, if it falls below a predefined stopping criterion $\epsilon$, the algorithm converges:

\[ \max \{|\Delta x_i|,\; \forall i \} < \epsilon.\]


Jacobian Matrix

As a reminder, the Jacobian matrix consists of $n$ columns representing bus voltage angles $\bm{\Theta}$, followed by $n$ columns representing bus voltage magnitudes $\mathbf{V}$. The arrangement of rows is structured such that the first $|\mathcal{V}|$ rows correspond to voltmeters, followed by $|\mathcal{I}|$ rows corresponding to ammeters. Then, we have $|\mathcal{P}|$ rows for wattmeters and $|\mathcal{Q}|$ rows for varmeters. Finally, there are $2|\bar{\mathcal{P}}|$ rows for PMUs. The elements are computed based on the provided Jacobian expressions.


Precision Matrix

Let us revisit the precision matrix $\mathbf W$. In the previous example, we introduced a PMU in rectangular coordinates without considering correlations between measurement errors. Now, let us update that PMU to include correlation between measurement errors:

updatePmu!(system, device, analysis; label = "PMU 2", correlated = true)

Subsequently, we can examine the updated precision matrix $\mathbf W$:

julia> 𝐖 = analysis.method.precision8×8 SparseArrays.SparseMatrixCSC{Float64, Int64} with 10 stored entries:
+ 1000.0       ⋅       ⋅        ⋅   …        ⋅       ⋅               ⋅
+     ⋅   10000.0      ⋅        ⋅            ⋅       ⋅               ⋅
+     ⋅        ⋅   1000.0       ⋅            ⋅       ⋅               ⋅
+     ⋅        ⋅       ⋅   10000.0           ⋅       ⋅               ⋅
+     ⋅        ⋅       ⋅        ⋅            ⋅       ⋅               ⋅
+     ⋅        ⋅       ⋅        ⋅   …  100000.0      ⋅               ⋅
+     ⋅        ⋅       ⋅        ⋅            ⋅      1.00926e5    4567.25
+     ⋅        ⋅       ⋅        ⋅            ⋅   4567.25       122531.0

Observing the precision matrix, we notice that it loses its diagonal form due to the inclusion of measurement covariances in the model.


Alternative Formulation

The resolution of the WLS state estimation problem using the conventional method typically progresses smoothly. However, it is widely acknowledged that in certain situations common to real-world systems, this method can be vulnerable to numerical instabilities. Such conditions might impede the algorithm from converging to a satisfactory solution. In such cases, users may opt for an alternative formulation of the WLS state estimation, namely, employing an approach called orthogonal factorization [5, Sec. 3.2].

This approach is suitable when measurement errors are uncorrelated, and the precision matrix remains diagonal. Therefore, as a preliminary step, we need to eliminate the correlation, as we did previously:

updatePmu!(system, device; label = "PMU 2", correlated = false)

To address ill-conditioned situations arising from significant differences in measurement variances, users can now employ the orthogonal factorization approach:

analysis = gaussNewton(system, device, Orthogonal)
+
+for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        break
+    end
+end

To explain the method, we begin with the WLS equation:

\[ \Big[\mathbf J (\mathbf x^{(\nu)})^{T} \mathbf W \mathbf J (\mathbf x^{(\nu)})\Big] \mathbf \Delta \mathbf x^{(\nu)} = + \mathbf J (\mathbf x^{(\nu)})^{T} \mathbf W \mathbf r (\mathbf x^{(\nu)})\]

where $\mathbf W = \bm \Sigma^{-1}$. Subsequently, we can write:

\[ \left[{\mathbf W^{1/2}} \mathbf J (\mathbf x^{(\nu)})\right]^{T} {\mathbf W^{1/2}} \mathbf J (\mathbf x^{(\nu)}) \Delta \mathbf x^{(\nu)} = + \left[{\mathbf W^{1/2}} \mathbf J (\mathbf x^{(\nu)})\right]^{T} {\mathbf W^{1/2}} \mathbf r (\mathbf x^{(\nu)}).\]

Consequently, we have:

\[ \bar{\mathbf J}(\mathbf x^{(\nu)})^{T} \bar{\mathbf J}(\mathbf x^{(\nu)}) \Delta \mathbf x^{(\nu)} = \bar{\mathbf J}(\mathbf x^{(\nu)})^{T} \bar{\mathbf r} (\mathbf x^{(\nu)}),\]

where:

\[ \bar{\mathbf J}(\mathbf x^{(\nu)}) = {\mathbf W^{1/2}} \mathbf J (\mathbf x^{(\nu)}), \;\;\; \bar{\mathbf r} (\mathbf x^{(\nu)}) = {\mathbf W^{1/2}} \mathbf r (\mathbf x^{(\nu)}).\]

Therefore, within each iteration of the Gauss-Newton method, JuliaGrid conducts QR factorization on the rectangular matrix:

\[ \bar{\mathbf J}(\mathbf x^{(\nu)}) = {\mathbf W^{1/2}} \mathbf J (\mathbf x^{(\nu)}) = \mathbf{Q}\mathbf{R}.\]

Access to the factorized matrix is possible through:

julia> 𝐐 = analysis.method.factorization.Q8×8 SparseArrays.SPQR.QRSparseQ{Float64, Int64}
julia> 𝐑 = analysis.method.factorization.R6×6 SparseArrays.SparseMatrixCSC{Float64, Int64} with 15 stored entries: + -352.735 13.4535 56.1399 4.75183 8.68958 ⋅ + ⋅ 346.944 3.38577 17.9143 -67.839 ⋅ + ⋅ ⋅ -182.142 27.9602 -3.15354 ⋅ + ⋅ ⋅ ⋅ -368.212 98.7959 ⋅ + ⋅ ⋅ ⋅ ⋅ -207.309 ⋅ + ⋅ ⋅ ⋅ ⋅ ⋅ ⋅

To obtain the solution, JuliaGrid avoids explicitly forming the orthogonal matrix $\mathbf{Q}$. Once the algorithm converges, estimates of bus voltage magnitudes $\hat{\mathbf V} = [\hat{V}_i]$ and angles $\hat{\bm {\Theta}} = [\hat{\theta}_i]$, where $i \in \mathcal{N}$ can be accessed using variables:

julia> 𝐕 = analysis.voltage.magnitude3-element Vector{Float64}:
+ 1.0005824771474021
+ 0.8752366339306804
+ 0.8993422332624245
julia> 𝚯 = analysis.voltage.angle3-element Vector{Float64}: + 0.0 + -0.13375723397946815 + -0.1998178530119528

Bad Data Processing

Besides the state estimation algorithm, one of the essential state estimation routines is the bad data processing, whose main task is to detect and identify measurement errors, and eliminate them if possible. This is usually done by processing the measurement residuals [5, Ch. 5], and typically, the largest normalized residual test is used to identify bad data. The largest normalized residual test is performed after we obtained the solution of the state estimation in the repetitive process of identifying and eliminating bad data measurements one after another [19].

To illustrate this process, let us introduce a new measurement that contains an obvious outlier:

addWattmeter!(system, device; bus = 3, active = 5.1, variance = 1e-3)

Subsequently, we will construct the AC state estimation model and solve it:

analysis = gaussNewton(system, device)
+for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        break
+    end
+end

Now, the bad data processing can be executed:

outlier = residualTest!(system, device, analysis; threshold = 4.0)

In this step, we employ the largest normalized residual test, guided by the analysis outlined in [5, Sec. 5.7]. To be more precise, we compute all measurement residuals based on the obtained estimate of state variables:

\[ r_i = z_i - h_i(\hat {\mathbf x}), \;\;\; i \in \mathcal{M}.\]

The normalized residuals for all measurements are computed as follows:

\[ \bar{r}_{i} = \cfrac{|r_i|}{\sqrt{C_{ii}}} = \cfrac{|r_i|}{\sqrt{S_{ii}\Sigma_{ii}}}, \;\;\; i \in \mathcal{M}.\]

In this equation, we denote the diagonal entries of the residual covariance matrix $\mathbf C \in \mathbb{R}^{k \times k}$ as $C_{ii} = S_{ii}\Sigma_{ii}$, where $S_{ii}$ is the diagonal entry of the residual sensitivity matrix $\mathbf S$ representing the sensitivity of the measurement residuals to the measurement errors. For this specific configuration, the relationship is expressed as:

\[ \mathbf C = \mathbf S \bm \Sigma = \bm \Sigma - \mathbf J (\hat {\mathbf x}) [\mathbf J (\hat {\mathbf x})^T \bm \Sigma^{-1} \mathbf J (\hat {\mathbf x})]^{-1} \mathbf J (\hat {\mathbf x})^T.\]

It is important to note that only the diagonal entries of $\mathbf C$ are required. To obtain the inverse, the JuliaGrid package utilizes a computationally efficient sparse inverse method, retrieving only the necessary elements of the inverse.

The subsequent step involves selecting the largest normalized residual, and the $j$-th measurement is then suspected as bad data and potentially removed from the measurement set $\mathcal{M}$:

\[ \bar{r}_{j} = \text{max} \{\bar{r}_{i}, i \in \mathcal{M} \}.\]

Users can access this information using the variable:

julia> outlier.maxNormalizedResidual142.25304730981557

If the largest normalized residual, denoted as $\bar{r}_{j}$, satisfies the inequality:

\[ \bar{r}_{j} \ge \epsilon,\]

the corresponding measurement is identified as bad data and subsequently removed. In this example, the bad data identification threshold is set to $\epsilon = 4$. Users can verify the satisfaction of this inequality by inspecting:

julia> outlier.detecttrue

This indicates that the measurement labeled as:

julia> outlier.label"Watmeter 3"

is removed from the measurement set and marked as out-of-service.

Subsequently, we can solve the system again, but this time without the removed measurement:

analysis = gaussNewton(system, device)
+for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        break
+    end
+end

Following that, we check for outliers once more:

outlier = residualTest!(system, device, analysis; threshold = 4.0)

To examine the value:

julia> outlier.maxNormalizedResidual0.758584475019815

As this value is now less than the threshold $\epsilon = 4$, the measurement is not removed, or there are no outliers. This can also be verified by observing the bad data flag:

julia> outlier.detectfalse

Least Absolute Value Estimation

The least absolute value (LAV) method provides an alternative estimation approach that is considered more robust in comparison to the WLS method. The WLS state estimation problem relies on specific assumptions about measurement errors, whereas robust estimators aim to remain unbiased even in the presence of various types of measurement errors and outliers. This characteristic eliminates the need for bad data processing, as discussed in [5, Ch. 6]. It is important to note that robustness often comes at the cost of increased computational complexity.

This section outlines the method as described in [5, Sec. 6.5]. Hence, we consider the system of nonlinear equations:

\[ \mathbf{z}=\mathbf{h}(\mathbf x)+\mathbf{u}.\]

Subsequently, the LAV state estimator is derived as the solution to the optimization problem:

\[ \begin{aligned} + \text{minimize}& \;\;\; \sum_{i \in \mathcal{M}} |r_i|\\ + \text{subject\;to}& \;\;\; z_i - h_i(\mathbf x) = r_i, \;\;\; \forall i \in \mathcal{M}, + \end{aligned}\]

where $r_i$ represents the $i$-th measurement residual. Let $\eta_i$ be defined in a manner that ensures:

\[ |r_i| \leq \eta_i,\]

and replace the above inequality with two equalities using two non-negative slack variables $q_i$ and $w_i$:

\[ \begin{aligned} + r_i - q_i &= -\eta_i \\ + r_i + w_i &= \eta_i. + \end{aligned}\]

Let us now define two additional non-negative variables $\overline{r}_i$ and $\underline{r}_i$, which satisfy the following relationships:

\[ \begin{aligned} + r_i &= \overline{r}_i - \underline{r}_i\\ + \overline{r}_i &= \cfrac{1}{2} q_i \\ + \underline{r}_i &= \cfrac{1}{2} w_i. + \end{aligned}\]

Then, the above two equalities become:

\[ \begin{aligned} + r_i - 2\overline{r}_i &= -2 \eta_i \\ + r_i + 2 \underline{r}_i &= 2 \eta_i, + \end{aligned}\]

that is:

\[ \begin{aligned} + \overline{r}_i + \underline{r}_i = \eta_i. + \end{aligned}\]

Next, we define a vector of state variables according to two additional nonnegative vectors $\overline{\mathbf x} \in \mathbb {R}_{\ge 0}^{n_\text{u}}$ and $\underline{\mathbf x} \in \mathbb {R}_{\ge 0}^{n_\text{u}}$, which satisfy the following relationships:

\[ \mathbf x = \overline{\mathbf x} - \underline{\mathbf x}\]

Hence, the optimization problem can be written:

\[ \begin{aligned} + \text{minimize}& \;\;\; \sum_{i \in \mathcal{M}} (\overline{r}_i + \underline{r}_i) \\ + \text{subject\;to} & \;\;\; h_i(\overline{\mathbf x} - \underline{\mathbf x}) + \overline{r}_i - \underline{r}_i = z_i, \;\;\; \forall i \in \mathcal{M} \\ + & \;\;\; \overline{r}_i \geq 0, \; \underline{r}_i \geq 0, \;\;\; \forall i \in \mathcal{M} \\ + & \;\;\; \overline{\mathbf x} \succeq \mathbf 0, \; \underline{\mathbf x} \succeq \mathbf 0. + \end{aligned}\]

To form the above optimization problem, the user can call the following function:

using Ipopt
+
+analysis = acLavStateEstimation(system, device, Ipopt.Optimizer)

Then the user can solve the optimization problem by:

solve!(system, analysis)

As a result, we obtain optimal values for the four non-negative variables, while the state estimator is obtained by:

\[ \hat{\mathbf x} = \overline{\mathbf x} - \underline{\mathbf x}.\]

Users can retrieve the estimated bus voltage magnitudes $\hat{\mathbf V} = [\hat{V}_i]$ and angles $\hat{\bm {\Theta}} = [\hat{\theta}_i]$, $i \in \mathcal{N}$, using:

julia> 𝐕 = analysis.voltage.magnitude3-element Vector{Float64}:
+ 1.0000000064101187
+ 0.8716991294249965
+ 0.8915402891580015
julia> 𝚯 = analysis.voltage.angle3-element Vector{Float64}: + 0.0 + -0.133006380063307 + -0.19921333228739968

Observability Analysis

The state estimation algorithm aims to estimate the values of the state variables based on the measurement model described as a system of equations. Prior to applying the state estimation algorithm, the observability analysis determines the existence and uniqueness of the solution for the underlying system of equations. In cases where a unique solution is not guaranteed, the observability analysis identifies observable islands and prescribes an additional set of equations (pseudo-measurements) to achieve a unique solution [20].


Identification of Observable Islands

JuliaGrid employs standard observability analysis performed on the linear decoupled measurement model [13, Ch. 7]. Active power measurements from wattmeters are utilized to estimate bus voltage angles, while reactive power measurements from varmeters are used to estimate bus voltage magnitudes. This necessitates that measurements of active and reactive power come in pairs.

Let us illustrate this concept with the following example, where measurements form an unobservable system:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = "Bus 1", type = 3)
+addBus!(system; label = "Bus 2", type = 1, active = 0.1, reactive = 0.01)
+addBus!(system; label = "Bus 3", type = 2, active = 0.5, reactive = 0.01)
+addBus!(system; label = "Bus 4", type = 1, active = 0.2, reactive = 0.02)
+addBus!(system; label = "Bus 5", type = 1, active = 0.3, reactive = 0.03)
+
+@branch(resistance = 0.02, conductance = 1e-4, susceptance = 0.002)
+addBranch!(system; label = "Branch 1", from = "Bus 1", to = "Bus 2", reactance = 0.05)
+addBranch!(system; label = "Branch 2", from = "Bus 2", to = "Bus 3", reactance = 0.01)
+addBranch!(system; label = "Branch 3", from = "Bus 2", to = "Bus 4", reactance = 0.02)
+addBranch!(system; label = "Branch 4", from = "Bus 3", to = "Bus 4", reactance = 0.03)
+addBranch!(system; label = "Branch 5", from = "Bus 4", to = "Bus 5", reactance = 0.05)
+
+addGenerator!(system; label = "Generator 1", bus = "Bus 1", active = 4.2, reactive = 0.2)
+addGenerator!(system; label = "Generator 2", bus = "Bus 3", active = 0.2, reactive = 0.1)
+
+addWattmeter!(system, device; label = "Wattmeter 1", from = "Branch 1", active = 0.93)
+addVarmeter!(system, device; label = "Varmeter 1", from = "Branch 1", reactive = -0.41)
+
+addWattmeter!(system, device; label = "Wattmeter 2", bus = "Bus 2", active = -0.1)
+addVarmeter!(system, device; label = "Varmeter 2", bus = "Bus 2", reactive = -0.01)
+
+addWattmeter!(system, device; label = "Wattmeter 3", bus = "Bus 3", active = -0.30)
+addVarmeter!(system, device; label = "Varmeter 3", bus = "Bus 3", reactive = 0.52)

If the system lacks observability, the observability analysis needs to identify all potential observable islands that can be independently solved. An observable island is defined as follows: It is a segment of the power system where the flows across all branches within that island can be calculated solely from the available measurements. This independence holds regardless of the values chosen for the bus voltage angle at the slack bus [13, Sec. 7.1.1]. Within this context, two types of observable islands are evident:

  • flow observale islands,
  • maximal observable islands.

The selection between them relies on the power system's structure and the available measurements. Opting for detecting only flow observable islands simplifies the island detection function's complexity but increases the complexity in the restoration function compared to identifying maximal observable islands.


Flow Observale Islands

To identify flow observable islands, JuliaGrid employs a topological method outlined in [21]. The process begins with the examination of all active power flow measurements from wattmeters, aiming to determine the largest sets of connected buses within the network linked by branches with active power flow measurements. Subsequently, the analysis considers individual boundary or tie active power injection measurements, involving two islands that may potentially be merged into a single observable island. The user can initiate this process by calling the function:

islands = islandTopologicalFlow(system, device)

As a result, four flow observable islands are identified. The first island comprises Bus 1 and Bus 2, while the second, third, and fourth islands consist of Bus 3, Bus 4, and Bus 5, respectively:

julia> islands.island4-element Vector{Vector{Int64}}:
+ [1, 2]
+ [3]
+ [4]
+ [5]

Additionally, users can inspect the tie buses and branches resulting from the observability analysis we conducted:

julia> islands.tie.busSet{Int64} with 4 elements:
+  5
+  4
+  2
+  3
julia> islands.tie.branchSet{Int64} with 4 elements: + 5 + 4 + 2 + 3

This tie data will be utilized throughout the restoration step, where we introduce pseudo-measurements to merge the observable flow islands obtained.


Maximal Observale Islands

To identify maximal observable islands, we extend the analysis with an additional processing step. After processing individual injection tie measurements, we are left with a series of injection measurements that are not entirely contained within any observable zone. In this set of remaining tie injections, we now examine pairs involving three and only three previously determined observable zones (including individual buses). If we find such a pair, the three islands may be merged, and all injection measurements involving only nodes of this new island are excluded from further consideration. The procedure then restarts at the stage where we process tie active power injection measurements involving two and only two islands. If no mergers are possible with pairs, we then consider sets of three injection measurements involving four islands, and so on [21]. The user can initiate this by calling the function:

islands = islandTopological(system, device)

The outcome reveals the identification of two maximal observable islands:

julia> islands.island2-element Vector{Vector{Int64}}:
+ [1, 2, 3, 4]
+ [5]

It is evident that upon comparing this result with the flow islands, the merging of the two injection measurements at Bus 2 and Bus 3 consolidated the first, second, and third flow observable islands into a single island.

Here we can observe tie data:

julia> islands.tie.busSet{Int64} with 2 elements:
+  5
+  4
julia> islands.tie.branchSet{Int64} with 1 element: + 5

Compared to the tie data obtained after detecting flow observable islands, we now have a smaller set, indicating that the restoration step will be more computationally efficient.


Observability Restoration

Before commencing the restoration of observability in the context of the linear decoupled measurement model and observability analysis, it is imperative to ensure that the system possesses one bus voltage magnitude measurement. This necessity arises from the fact that observable islands are identified based on wattmeters, where wattmeters are tasked with estimating voltage angles. Since one voltage angle is already known from the slack bus, the same principle should be applied to bus voltage magnitudes. Therefore, to address this requirement, we add:

addVoltmeter!(system, device; bus = "Bus 1", magnitude = 1.0)

After determining the islands, the observability analysis merges these islands in a manner that protect previously determined observable states from being altered by the new set of equations defined by the additional measurements, called pseudo-measurements. In general, this can be achieved by ensuring that the set of new measurements forms a non-redundant set [13, Sec. 7.3.2], i.e., the set of equations must be linearly independent with respect to the global system. The goal of observability restoration is to find this non-redundant set.

The outcome of the island detection step results in the power system being divided into $m$ islands. Subsequently, we focus on the set of measurements $\mathcal{M}_\text{r} \subset \mathcal{M}$, which exclusively consists of:

  • active power injection measurements at tie buses,
  • bus voltage phasor measurements.

These measurements are retained from the phase where we identify observable islands, and are crucial in determining whether we need additional pseudo-measurements to be included in the measurement set $\mathcal{M}$. In this specific example, we do not have active power injection measurements at tie buses remaining after the identification of maximal observable islands. However, if we proceed with flow observable islands to the restoration step, we will have two injection measurements at Bus 2 and Bus 3.

However, let us introduce the matrix $\mathbf M_{\text{r}} \in \mathbb{R}^{r \times m}$, where $r = |\mathcal{M}_\text{r}|$. This matrix can be conceptualized as the coefficient matrix of a reduced network, with $m$ columns corresponding to islands and $r$ rows associated with the set $\mathcal{M}_\text{r}$. More precisely, if we construct the coefficient matrix $\mathbf H_\text{r}$ linked to the set $\mathcal{M}_\text{r}$ in the DC framework, the matrix $\mathbf M_{\text{r}}$ can be constructed by summing the columns of $\mathbf H_\text{r}$ that belong to a specific island [22].

Subsequently, the user needs to establish a set of pseudo-measurements, where measurements must come in pairs as well. Let us create that set:

pseudo = measurement()
+
+addWattmeter!(system, pseudo; label = "Pseudo-Wattmeter 1", bus = "Bus 1", active = 0.93)
+addVarmeter!(system, pseudo; label = "Pseudo-Varmeter 1", bus = "Bus 1", reactive = -0.41)
+
+addWattmeter!(system, pseudo; label = "Pseudo-Wattmeter 2", from = "Branch 5", active = 0.30)
+addVarmeter!(system, pseudo; label = "Pseudo-Varmeter 2", from = "Branch 5", reactive = 0.03)

From this set, the restoration step will only utilize the following:

  • active power flow measurements between tie buses,
  • active power injection measurements at tie buses,
  • bus voltage phasor measurements.

These pseudo-measurements $\mathcal{M}_\text{p}$ will define the reduced coefficient matrix $\mathbf M_{\text{p}} \in \mathbb{R}^{p \times m}$, where $p = |\mathcal{M}_\text{p}|$. In the current example, only Pseudo-Wattmeter 2 will contribute to the construction of the matrix $\mathbf M_{\text{p}}$. Similar to the previous case, measurement functions linked to the set $\mathcal{M}_\text{p}$ define the coefficient matrix $\mathbf H_\text{p}$, and the matrix $\mathbf M_{\text{p}}$ can be viewed as the sum of the columns of $\mathbf H_\text{p}$ belonging to a specific flow island.

Additionally, users have the option to include bus voltage angle measurements from PMUs. In this scenario, restoration can be conducted without merging observable islands into one island, as each island becomes globally observable when one angle is known. It is important to note that during the restoration step, JuliaGrid initially processes active power measurements and subsequently handles bus voltage angle measurements if they are present in the set of pseudo-measurements.

Users can execute the observability restoration procedure with the following:

restorationGram!(system, device, pseudo, islands; threshold = 1e-6)

The function constructs the reduced coefficient matrix as follows:

\[ \mathbf M = \begin{bmatrix} \mathbf M_{\text{r}} \\ \mathbf M_{\text{p}} \end{bmatrix},\]

and forms the corresponding Gram matrix:

\[ \mathbf D = \mathbf M \mathbf M^T.\]

The decomposition of $\mathbf D$ into its $\mathbf Q$ and $\mathbf R$ factors is achieved through QR factorization. Non-redundant measurements are identified by non-zero diagonal elements in $\mathbf R$. Specifically, if the diagonal element satisfies:

\[ |R_{ii}| < \epsilon,\]

JuliaGrid designates the corresponding measurement as redundant, where $\epsilon$ represents a pre-determined zero pivot threshold, set to 1e-6 in this example. The minimal set of pseudo-measurements for observability restoration corresponds to the non-zero diagonal elements at positions associated with the candidate pseudo-measurements. It is essential to note that an inappropriate choice of the zero pivot threshold may adversely affect observability restoration. Additionally, there is a possibility that the set of pseudo-measurements $\mathcal{M}_\text{p}$ may not be sufficient for achieving observability restoration.

Finally, the Pseudo-Wattmeter 2, and consequently Pseudo-Varmeter 2 measurements successfully restore observability, and these measurements are added to the device variable, which stores actual measurements:

julia> device.wattmeter.labelOrderedCollections.OrderedDict{String, Int64} with 4 entries:
+  "Wattmeter 1"        => 1
+  "Wattmeter 2"        => 2
+  "Wattmeter 3"        => 3
+  "Pseudo-Wattmeter 2" => 4
julia> device.varmeter.labelOrderedCollections.OrderedDict{String, Int64} with 4 entries: + "Varmeter 1" => 1 + "Varmeter 2" => 2 + "Varmeter 3" => 3 + "Pseudo-Varmeter 2" => 4

Here, we can confirm that the new measurement set establishes the observable system formed by a single island:

julia> islands = islandTopological(system, device);
julia> islands.island1-element Vector{Vector{Int64}}: + [1, 2, 3, 4, 5]

Next, we can construct the AC state estimation model and resolve it to obtain estimates of bus voltages:

analysis = gaussNewton(system, device)
+for iteration = 1:20
+    stopping = solve!(system, analysis)
+    if stopping < 1e-8
+        break
+    end
+end

Power Analysis

Once the computation of voltage magnitudes and angles at each bus is completed, various electrical quantities can be determined. JuliaGrid offers the power! function, which enables the calculation of powers associated with buses and branches. Here is an example code snippet demonstrating its usage:

power!(system, analysis)

The function stores the computed powers in the rectangular coordinate system. It calculates the following powers related to buses and branches:

BusActiveReactive
Injections$\mathbf{P} = [P_i]$$\mathbf{Q} = [Q_i]$
Generator injections$\mathbf{P}_{\text{p}} = [P_{\text{p}i}]$$\mathbf{Q}_{\text{p}} = [Q_{\text{p}i}]$
Shunt elements$\mathbf{P}_{\text{sh}} = [{P}_{\text{sh}i}]$$\mathbf{Q}_{\text{sh}} = [{Q}_{\text{sh}i}]$
BranchActiveReactive
From-bus end flows$\mathbf{P}_{\text{i}} = [P_{ij}]$$\mathbf{Q}_{\text{i}} = [Q_{ij}]$
To-bus end flows$\mathbf{P}_{\text{j}} = [P_{ji}]$$\mathbf{Q}_{\text{j}} = [Q_{ji}]$
Shunt elements$\mathbf{P}_{\text{s}} = [P_{\text{s}ij}]$$\mathbf{P}_{\text{s}} = [P_{\text{s}ij}]$
Series elements$\mathbf{P}_{\text{l}} = [P_{\text{l}ij}]$$\mathbf{Q}_{\text{l}} = [Q_{\text{l}ij}]$
Info

For a clear comprehension of the equations, symbols presented in this section, as well as for a better grasp of power directions, please refer to the Unified Branch Model.


Power Injections

Active and reactive power injections are stored as the vectors $\mathbf{P} = [P_i]$ and $\mathbf{Q} = [Q_i]$, respectively, and can be retrieved using the following commands:

julia> 𝐏 = analysis.power.injection.active5-element Vector{Float64}:
+  0.9299999999999997
+ -0.09999999999998169
+ -0.2999999999999997
+ -0.1987686762528627
+ -0.2980672917108779
julia> 𝐐 = analysis.power.injection.reactive5-element Vector{Float64}: + -0.4100000000000037 + -0.009999999999994251 + 0.5199999999999999 + -0.01886210737995113 + -0.0273822976584444

Generator Power Injections

We can calculate the active and reactive power injections supplied by generators at each bus $i \in \mathcal{N}$ by summing the active and reactive power injections and the active and reactive power demanded by consumers at each bus:

\[ \begin{aligned} + P_{\text{p}i} &= P_i + P_{\text{d}i}\\ + Q_{\text{p}i} &= Q_i + Q_{\text{d}i}. + \end{aligned}\]

The active and reactive power injections from the generators at each bus are stored as vectors, denoted by $\mathbf{P}_{\text{p}} = [P_{\text{p}i}]$ and $\mathbf{Q}_{\text{p}} = [Q_{\text{p}i}]$, which can be obtained using:

julia> 𝐏ₚ = analysis.power.supply.active5-element Vector{Float64}:
+ 0.9299999999999997
+ 1.8318679906315083e-14
+ 0.2000000000000003
+ 0.0012313237471373029
+ 0.0019327082891220648
julia> 𝐐ₚ = analysis.power.supply.reactive5-element Vector{Float64}: + -0.4100000000000037 + 5.748873599387139e-15 + 0.5299999999999999 + 0.0011378926200488713 + 0.0026177023415555993

Power at Bus Shunt Elements

Active and reactive powers associated with the shunt elements at each bus are represented by the vectors $\mathbf{P}_{\text{sh}} = [{P}_{\text{sh}i}]$ and $\mathbf{Q}_{\text{sh}} = [{Q}_{\text{sh}i}]$. To retrieve these powers in JuliaGrid, use the following commands:

julia> 𝐏ₛₕ = analysis.power.shunt.active5-element Vector{Float64}:
+ 0.0
+ 0.0
+ 0.0
+ 0.0
+ 0.0
julia> 𝐐ₛₕ = analysis.power.shunt.reactive5-element Vector{Float64}: + -0.0 + -0.0 + -0.0 + -0.0 + -0.0

Power Flows

The resulting active and reactive power flows at each from-bus end are stored as the vectors $\mathbf{P}_{\text{i}} = [P_{ij}]$ and $\mathbf{Q}_{\text{i}} = [Q_{ij}],$ respectively, and can be retrieved using the following commands:

julia> 𝐏ᵢ = analysis.power.from.active5-element Vector{Float64}:
+ 0.9299999999999997
+ 0.3543410147669059
+ 0.45491689043036315
+ 0.04859751029334397
+ 0.3000000000000007
julia> 𝐐ᵢ = analysis.power.from.reactive5-element Vector{Float64}: + -0.4100000000000037 + -0.39915753007224625 + -0.07044017499754598 + 0.120028223333823 + 0.030000000000002115

Similarly, the vectors of active and reactive power flows at the to-bus end are stored as $\mathbf{P}_{\text{j}} = [P_{ji}]$ and $\mathbf{Q}_{\text{j}} = [Q_{ji}]$, respectively, and can be retrieved using the following code:

julia> 𝐏ⱼ = analysis.power.to.active5-element Vector{Float64}:
+ -0.9092579051972395
+ -0.34859751029335007
+ -0.4506106531591515
+ -0.04815802309372233
+ -0.2980672917108779
julia> 𝐐ⱼ = analysis.power.to.reactive5-element Vector{Float64}: + 0.4595977050697902 + 0.399971776666188 + 0.07264836417613314 + -0.12151047155608216 + -0.0273822976584444

Power at Branch Shunt Elements

Active and reactive powers associated with the branch shunt elements at each branch are represented by the vectors $\mathbf{P}_{\text{s}} = [P_{\text{s}ij}]$ and $\mathbf{Q}_{\text{s}} = [Q_{\text{s}ij}]$. We can retrieve these values using the following code:

julia> 𝐏ₛ = analysis.power.charging.active5-element Vector{Float64}:
+ 0.0001003347527603625
+ 0.00010036612891864457
+ 9.990705202969285e-5
+ 9.96036754276124e-5
+ 9.840303916639445e-5
julia> 𝐐ₛ = analysis.power.charging.reactive5-element Vector{Float64}: + -0.00200669505520725 + -0.0020073225783728914 + -0.001998141040593857 + -0.001992073508552248 + -0.001968060783327889

Power at Branch Series Elements

Active and reactive powers associated with the branch series element at each branch are represented by the vectors $\mathbf{P}_{\text{l}} = [P_{\text{l}ij}]$ and $\mathbf{Q}_{\text{l}} = [Q_{\text{l}ij}]$. We can retrieve these values using the following code:

julia> 𝐏ₗ = analysis.power.series.active5-element Vector{Float64}:
+ 0.020641760050000006
+ 0.0056431383446334795
+ 0.004206330219180818
+ 0.0003398835241945116
+ 0.0018343052499558846
julia> 𝐐ₗ = analysis.power.series.reactive5-element Vector{Float64}: + 0.05160440012500001 + 0.0028215691723167393 + 0.004206330219180818 + 0.0005098252862917674 + 0.004585763124889711

Current Analysis

JuliaGrid offers the current! function, which enables the calculation of currents associated with buses and branches. Here is an example code snippet demonstrating its usage:

current!(system, analysis)

The function stores the computed currents in the polar coordinate system. It calculates the following currents related to buses and branches:

BusMagnitudeAngle
Injections$\mathbf{I} = [I_i]$$\bm{\psi} = [\psi_i]$
BranchMagnitudeAngle
From-bus end flows$\mathbf{I}_{\text{i}} = [I_{ij}]$$\bm{\psi}_{\text{i}} = [\psi_{ij}]$
To-bus end flows$\mathbf{I}_{\text{j}} = [I_{ji}]$$\bm{\psi}_{\text{j}} = [\psi_{ji}]$
Series elements$\mathbf{I}_{\text{l}} = [I_{\text{l}ij}]$$\bm{\psi}_{\text{l}} = [\psi_{\text{l}ij}]$
Info

For a clear comprehension of the equations, symbols presented in this section, as well as for a better grasp of power directions, please refer to the Unified Branch Model.


Current Injections

In JuliaGrid, complex current injections are stored in the vector of magnitudes denoted as $\mathbf{I} = [I_i]$ and the vector of angles represented as $\bm{\psi} = [\psi_i]$. You can retrieve them using the following commands:

julia> 𝐈 = analysis.current.injection.magnitude5-element Vector{Float64}:
+ 1.016366075781754
+ 0.10016401375540951
+ 0.6001449678888684
+ 0.20052110028938183
+ 0.3028848647714261
julia> 𝛙 = analysis.current.injection.angle5-element Vector{Float64}: + 0.4152273355552351 + 2.9874016125482736 + -2.1600612916320725 + 2.981962556358823 + 2.9703530209127296

Current Flows

To obtain the vectors of magnitudes $\mathbf{I}_{\text{i}} = [I_{ij}]$ and angles $\bm{\psi}_{\text{i}} = [\psi_{ij}]$ for the resulting complex current flows, you can use the following commands:

julia> 𝐈ᵢ = analysis.current.from.magnitude5-element Vector{Float64}:
+ 1.016366075781754
+ 0.5319677219357447
+ 0.45880483191253246
+ 0.1294526028513715
+ 0.3027941026063651
julia> 𝛙ᵢ = analysis.current.from.angle5-element Vector{Float64}: + 0.4152273355552351 + 0.7902836921556595 + 0.09909947276474262 + -1.2520733288814159 + -0.16468729573543564

Similarly, we can obtain the vectors of magnitudes $\mathbf{I}_{\text{j}} = [I_{ji}]$ and angles $\bm{\psi}_{\text{j}} = [\psi_{ji}]$ of the resulting complex current flows using the following code:

julia> 𝐈ⱼ = analysis.current.to.magnitude5-element Vector{Float64}:
+ 1.0154195547100446
+ 0.5303971255561436
+ 0.45839410908166384
+ 0.13126837938333577
+ 0.3028848647714261
julia> 𝛙ⱼ = analysis.current.to.angle5-element Vector{Float64}: + -2.7281052967296975 + -2.353658638494203 + -3.0467647355570158 + 1.8831146895682245 + 2.9703530209127296

Current at Branch Series Elements

To obtain the vectors of magnitudes $\mathbf{I}_{\text{l}} = [I_{\text{l}ij}]$ and angles $\bm{\psi}_{\text{l}} = [\psi_{\text{l}ij}]$ of the resulting complex current flows, one can use the following code:

julia> 𝐈ₗ = analysis.current.series.magnitude5-element Vector{Float64}:
+ 1.0159173207008532
+ 0.5311844474678019
+ 0.458602781237795
+ 0.13036171297480553
+ 0.30284527815007156
julia> 𝛙ₗ = analysis.current.series.angle5-element Vector{Float64}: + 0.4143465012225557 + 0.7891003404573693 + 0.0969541517042328 + -1.2553086990431555 + -0.16797520542382388
diff --git a/v0.2.0/tutorials/dcOptimalPowerFlow/index.html b/v0.2.0/tutorials/dcOptimalPowerFlow/index.html new file mode 100644 index 000000000..24a716637 --- /dev/null +++ b/v0.2.0/tutorials/dcOptimalPowerFlow/index.html @@ -0,0 +1,99 @@ + +DC Optimal Power Flow · JuliaGrid

DC Optimal Power Flow

To begin, let us generate the PowerSystem type, as illustrated by the following example:

using JuMP, HiGHS
+
+@labels(Integer)
+
+system = powerSystem()
+
+addBus!(system; label = 1, type = 3, angle = 0.17)
+addBus!(system; label = 2, type = 2, active = 0.1, conductance = 0.04)
+addBus!(system; label = 3, type = 1, active = 0.05)
+
+@branch(minDiffAngle = -pi, maxDiffAngle = pi)
+addBranch!(system; label = 1, from = 1, to = 2, reactance = 0.05, maxFromBus = 0.15)
+addBranch!(system; label = 2, from = 1, to = 3, reactance = 0.01, maxFromBus = 0.10)
+addBranch!(system; label = 3, from = 2, to = 3, reactance = 0.01, maxFromBus = 0.25)
+
+@generator(minActive = 0.0)
+addGenerator!(system; label = 1, bus = 1, active = 3.2, maxActive = 0.5)
+addGenerator!(system; label = 2, bus = 2, active = 0.2, maxActive = 0.3)
+
+cost!(system; label = 1, active = 2, polynomial = [1100.2; 500; 80])
+cost!(system; label = 2, active = 1, piecewise =  [10.85 12.3; 14.77 16.8; 18 18.1])

To review, we can conceptualize the bus/branch model as the graph denoted by $\mathcal{G} = (\mathcal{N}, \mathcal{E})$, where we have the set of buses $\mathcal{N} = \{1, \dots, n\}$, and the set of branches $\mathcal{E} \subseteq \mathcal{N} \times \mathcal{N}$ within the power system:

julia> 𝒩 = collect(keys(system.bus.label))3-element Vector{Int64}:
+ 1
+ 2
+ 3
julia> ℰ = [𝒩[system.branch.layout.from] 𝒩[system.branch.layout.to]]3×2 Matrix{Int64}: + 1 2 + 1 3 + 2 3

Moreover, we identify the set of generators as $\mathcal{S} = \{1, \dots, n_\text{g}\}$ within the power system:

julia> 𝒮 = collect(keys(system.generator.label))2-element Vector{Int64}:
+ 1
+ 2

Notation

Here, when referring to a vector $\mathbf{a}$, we use the notation $\mathbf{a} = [a_{i}]$ or $\mathbf{a} = [a_{ij}]$, where $a_i$ represents the element related with bus $i \in \mathcal{N}$ or generator $i \in \mathcal{S}$, while $a_{ij}$ denotes the element related with branch $(i,j) \in \mathcal{E}$.


Optimal Power Flow Model

In the DC optimal power flow, the active power outputs of the generators $\mathbf {P}_{\text{g}} = [{P}_{\text{g}i}]$, $i \in \mathcal{S}$, are represented as linear functions of the bus voltage angles $\bm{\Theta} = [{\theta}_{i}]$, $i \in \mathcal{N}$. Thus, the optimization variables in this model are the active power outputs of the generators and the bus voltage angles.

The DC optimal power flow model has the form:

\[\begin{aligned} + & {\text{minimize}} & & \sum_{i \in \mathcal{S}} f_i(P_{\text{g}i}) \\ + & \text{subject\;to} & & \theta_i - \theta_{\text{s}} = 0,\;\;\; i \in \mathcal{N_{\text{sb}}} \\[3pt] + & & & h_{P_i}(\mathbf {P}_{\text{g}}, \bm{\Theta}) = 0,\;\;\; \forall i \in \mathcal{N} \\[3pt] + & & & \theta_{ij}^\text{min} \leq \theta_i - \theta_j \leq \theta_{ij}^\text{max},\;\;\; \forall (i,j) \in \mathcal{E} \\[3pt] + & & & P_{ij}^{\text{min}} \leq h_{P_{ij}}(\theta_i, \theta_j) \leq P_{ij}^{\text{max}},\;\;\; \forall (i,j) \in \mathcal{E} \\[3pt] + & & & P_{\text{g}i}^\text{min} \leq P_{\text{g}i} \leq P_{\text{g}i}^\text{max} ,\;\;\; \forall i \in \mathcal{S}. +\end{aligned}\]

Essentially, the DC optimal power flow is focused on the minimization of the objective function related to the costs associated with the active power output of generators, all while ensuring the satisfaction of various constraints. This optimization task holds a crucial role in the efficient and timely management of electrical power systems. However, it is important to note that the solutions provided by the DC optimal power flow are approximate in nature.


Build Optimal Power Flow Model

To build the DC optimal power flow model, we must first load the power system and establish the DC model using:

dcModel!(system)

Afterward, the DC optimal power flow model is created using the dcOptimalPowerFlow function:

analysis = dcOptimalPowerFlow(system, HiGHS.Optimizer; active = "Pg", angle = "θ")

Optimization Variables

Hence, the variables in this model encompass the active power outputs of the generators denoted as $\mathbf{P}_{\text{g}} = [{P}_{\text{g}i}]$, where $i \in \mathcal{S}$, and the bus voltage angles represented by $\bm{\Theta} = [{\theta}_{i}]$, where $i \in \mathcal{N}$. You can access these variables using the following:

julia> 𝐏ₒ = analysis.method.variable.active2-element Vector{VariableRef}:
+ Pg[1]
+ Pg[2]
julia> 𝚯 = analysis.method.variable.angle3-element Vector{VariableRef}: + θ[1] + θ[2] + θ[3]

Objective Function

The objective function represents the sum of the active power cost functions $f_i(P_{\text{g}i})$, $i \in \mathcal{S}$, for each generator, where these cost functions can be polynomial or linear piecewise functions. It is important to note that only polynomial cost functions up to the second degree are included in the objective function. If higher-degree polynomials are present, they will be excluded from the objective function by JuliaGrid.


Polynomial Active Power Cost Function

The DC optimal power flow in JuliaGrid allows the cost function $f_i(P_{\text{g}i})$ to be represented as a polynomial of up to the second degree, making it possible to express the cost function as linear or quadratic. The possible representations are as follows:

\[\begin{aligned} + f_i(P_{\text{g}i}) &= a_1P_{\text{g}i} + a_0 \\ + f_i(P_{\text{g}i}) &= a_2 P_{\text{g}i}^2 + a_1P_{\text{g}i} + a_0. +\end{aligned}\]

Furthermore, it is worth noting that the function can be given simply as a constant with only the coefficient $a_0$, which implies that the cost of the generator remains constant regardless of the active power outputs. In conclusion, as illustrated in Figure 1, typical scenarios involve linear or quadratic cost functions, resulting in a best-case scenario for a linear optimization problem and a worst-case scenario for a quadratic optimization problem.

+
Figure 1: The polynomial cost functions of generator active power output.

When utilizing the cost! function within JuliaGrid, employing the polynomial keyword results in the polynomial being constructed with coefficients ordered from the highest degree to the lowest. For instance, in the provided case study, we created a quadratic polynomial represented as:

\[\begin{aligned} + f_1(P_{\text{g}1}) &= 1100.2 P_{\text{g}1}^2 + 500 P_{\text{g}1} + 80. +\end{aligned}\]

To access these coefficients, users can utilize the variable:

julia> f₁ = system.generator.cost.active.polynomial[1]3-element Vector{Float64}:
+ 1100.2
+  500.0
+   80.0

Linear Piecewise Active Power Cost Function

The DC optimal power flow in JuliaGrid offers another option for defining cost functions by using linear piecewise functions as approximations of the polynomial functions, as depicted in Figure 2.

+
Figure 2: The linear piecewise cost functions of active power output.

To define linear piecewise functions in JuliaGrid, users can utilize the cost! function with the piecewise keyword. The linear piecewise function is constructed using a matrix where each row defines a single point. The first column holds the generator's active power output, while the second column corresponds to the associated cost value. For example, in the provided case study, a linear piecewise function is created and can be accessed as follows:

julia> f₂ = system.generator.cost.active.piecewise[2]3×2 Matrix{Float64}:
+ 10.85  12.3
+ 14.77  16.8
+ 18.0   18.1

Similar to how convex linear piecewise functions are treated in the AC Optimal Power Flow, JuliaGrid adopts a constrained cost variable method for the linear piecewise functions. In this method, the piecewise linear cost function is converted into a series of linear inequality constraints for each segment, which are defined by two adjacent points along the line, along with a helper variable specific to the piecewise function. However, for linear piecewise functions that have only one segment defined by two points, JuliaGrid simplifies it into a standard linear function without requiring a helper variable.

Consequently, for a piecewise cost function denoted as $f_i(P_{\text{g}i})$ with $k$ segments (where $k > 1$), the $j$-th segment, defined by the points $[P_{\text{g}i,j}, f_i(P_{\text{g}i,j})]$ and $[P_{\text{g}i,j+1}, f_i(P_{\text{g}i,j+1})]$, is characterized by the following inequality constraints:

\[\cfrac{f_i(P_{\text{g}i,j+1}) - f_i(P_{\text{g}i,j})}{P_{\text{g}i,j+1} - P_{\text{g}i,j}}(P_{\text{g}i} - P_{\text{g}i,j}) + f_i(P_{\text{g}i,j}) \leq H_i, \;\;\; i \in \mathcal{S}, \;\;\; j = 1,\dots,k,\]

where $H_i$ represents the helper variable. To finalize this method, we simply need to include the helper variable $H_i$ in the objective function. This approach efficiently handles linear piecewise cost functions, providing the flexibility to capture nonlinear characteristics while still benefiting from the advantages of linear optimization techniques.

As an example, in the provided case study, the helper variable is defined as follows:

julia> H₂ = analysis.method.variable.actwise[2]actwise[2]

Lastly, the set of constraints introduced by the linear piecewise cost function is displayed as follows:

julia> print(analysis.method.constraint.piecewise.active)1.1479591836734695 Pg[2] - actwise[2] ≤ 0.15535714285714342
+0.40247678018575866 Pg[2] - actwise[2] ≤ -10.855417956656346

Objective Function

As previously explained, the objective function relies on the defined polynomial or linear piecewise cost functions and represents the sum of these costs. In the provided example, the objective function that must be minimized to obtain the optimal values for the active power output of the generators and the bus voltage angles can be accessed using the following code:

julia> JuMP.objective_function(analysis.method.jump)1100.2 Pg[1]² + 500 Pg[1] + actwise[2] + 80

Constraint Functions

In the following section, we will examine the various constraints defined within the DC optimal power flow model.


Slack Bus Constraint

The first equality constraint is linked to the slack bus, where the bus voltage angle denoted as $\theta_i$ is fixed to a constant value $\theta_{\text{s}}$. It can be expressed as follows:

\[\theta_i - \theta_{\text{s}} = 0,\;\;\; i \in \mathcal{N_{\text{sb}}},\]

where the set $\mathcal{N}_{\text{sb}}$ contains the index of the slack bus. To access the equality constraint from the model, we can utilize the variable:

julia> print(analysis.method.constraint.slack.angle)θ[1] = 0.17

Bus Active Power Balance Constraints

The second equality constraint in the optimization problem is associated with the active power balance equation:

\[h_{P_i}(\mathbf {P}_{\text{g}}, \bm{\Theta}) = 0,\;\;\; \forall i \in \mathcal{N}.\]

As elaborated in the Nodal Network Equations section, we can express the equation as follows:

\[h_{P_i}(\mathbf {P}_{\text{g}}, \bm{\Theta}) = \sum_{k \in \mathcal{S}_i} P_{\text{g}k} - \sum_{k = 1}^n {B}_{ik} \theta_k - P_{\text{d}i} - P_{\text{sh}i} - P_{\text{tr}i}.\]

In this equation, the set $\mathcal{S}_i \subseteq \mathcal{S}$ encompasses all generators connected to bus $i \in \mathcal{N}$, and $P_{\text{g}k}$ represents the active power output of the $k$-th generator within the set $\mathcal{S}_i$. More precisely, the variable $P_{\text{g}k}$ represents the optimization variable, as well as the bus voltage angle $\theta_k$.

The constant terms in these equations are determined by the active power demand at bus $P_{\text{d}i}$, the active power demanded by the shunt element $P_{\text{sh}i}$, and power related to the shift angle of the phase transformers $P_{\text{tr}i}$. The values representing these constant terms $\mathbf{P}_{\text{d}} = [P_{\text{d}i}]$, $\mathbf{P}_{\text{sh}} = [P_{\text{sh}i}]$, and $\mathbf{P}_{\text{tr}} = [P_{\text{tr}i}]$, $i, \in \mathcal{N}$, can be accessed:

julia> 𝐏ₒ = system.bus.demand.active3-element Vector{Float64}:
+ 0.0
+ 0.1
+ 0.05
julia> 𝐏ₛₕ = system.bus.shunt.conductance3-element Vector{Float64}: + 0.0 + 0.04 + 0.0
julia> 𝐏ₜᵣ = system.model.dc.shiftPower3-element Vector{Float64}: + 0.0 + 0.0 + 0.0

To retrieve constraints from the model, we can use:

julia> print(analysis.method.constraint.balance.active)Pg[1] - 120 θ[1] + 20 θ[2] + 100 θ[3] = 0
+Pg[2] + 20 θ[1] - 120 θ[2] + 100 θ[3] = 0.14
+100 θ[1] + 100 θ[2] - 200 θ[3] = 0.05

Bus Voltage Angle Difference Constraints

The inequality constraint related to the minimum and maximum bus voltage angle difference between the from-bus and to-bus ends of each branch is defined as follows:

\[\theta_{ij}^\text{min} \leq \theta_i - \theta_j \leq \theta_{ij}^\text{max},\;\;\; \forall (i,j) \in \mathcal{E},\]

where $\theta_{ij}^\text{min}$ represents the minimum, while $\theta_{ij}^\text{max}$ represents the maximum of the angle difference between adjacent buses. The values representing the voltage angle difference, denoted as $\bm{\Theta}_{\text{lm}} = [\theta_{ij}^\text{min}, \theta_{ij}^\text{max}]$, $(i,j) \in \mathcal{E}$, are provided as follows:

julia> 𝚯ₗₘ = [system.branch.voltage.minDiffAngle system.branch.voltage.maxDiffAngle]3×2 Matrix{Float64}:
+ -3.14159  3.14159
+ -3.14159  3.14159
+ -3.14159  3.14159

To retrieve constraints from the model, we can use:

julia> print(analysis.method.constraint.voltage.angle)θ[1] - θ[2] ∈ [-3.141592653589793, 3.141592653589793]
+θ[1] - θ[3] ∈ [-3.141592653589793, 3.141592653589793]
+θ[2] - θ[3] ∈ [-3.141592653589793, 3.141592653589793]

Branch Active Power Flow Constraints

The inequality constraint related to active power flow is used to represent thermal limits on power transmission. This constraint is defined as follows:

\[P_{ij}^{\text{min}} \leq h_{P_{ij}}(\theta_i, \theta_j) \leq P_{ij}^{\text{max}},\;\;\; \forall (i,j) \in \mathcal{E}.\]

The branch flow limits at the from-bus, denoted as $\mathbf{P}_{\text{f}} = [P_{ij}^\text{min}, P_{ij}^\text{max}]$ , can be retrieved as follows:

julia> 𝐏ₒ = [system.branch.flow.minFromBus system.branch.flow.maxFromBus]3×2 Matrix{Float64}:
+ 0.0  0.15
+ 0.0  0.1
+ 0.0  0.25

The active power flow at branch $(i,j) \in \mathcal{E}$ can be derived using the Branch Network Equations and is given by:

\[h_{P_{ij}}(\theta_i, \theta_j) = \frac{1}{\tau_{ij} x_{ij} }(\theta_i - \theta_j - \phi_{ij}).\]

To retrieve constraints from the model, we can use:

julia> print(analysis.method.constraint.flow.active)20 θ[1] - 20 θ[2] ∈ [0, 0.15]
+100 θ[1] - 100 θ[3] ∈ [0, 0.1]
+100 θ[2] - 100 θ[3] ∈ [0, 0.25]

Generator Active Power Capability Constraints

The inequality constraints associated with the minimum and maximum active power outputs of the generators are defined as follows:

\[P_{\text{g}i}^\text{min} \leq P_{\text{g}i} \leq P_{\text{g}i}^\text{max} ,\;\;\; \forall i \in \mathcal{S}.\]

In this representation, the lower and upper bounds are determined by the vector $\mathbf{P}_{\text{m}} = [P_{\text{g}i}^\text{min}, P_{\text{g}i}^\text{max}]$, $i \in \mathcal{S}$. We can access these bounds using the following variable:

julia> 𝐏ₘ = [system.generator.capability.minActive system.generator.capability.maxActive]2×2 Matrix{Float64}:
+ 0.0  0.5
+ 0.0  0.3

To retrieve constraints from the model, we can use:

julia> print(analysis.method.constraint.capability.active)Pg[1] ∈ [0, 0.5]
+Pg[2] ∈ [0, 0.3]

Optimal Power Flow Solution

To acquire the output active power of generators and the bus voltage angles, the user must invoke the function:

solve!(system, analysis)

Therefore, to get the vector of output active power of generators $\mathbf{P}_{\text{g}} = [P_{\text{g}i}]$, $i \in \mathcal{S}$, we can use:

julia> 𝐏ₒ = analysis.power.generator.active2-element Vector{Float64}:
+ 0.02499999999999991
+ 0.1650000000000027

Further, the resulting bus voltage angles $\bm{\Theta} = [\theta_{i}]$, $i \in \mathcal{N}$, are saved in the vector as follows:

julia> 𝚯 = analysis.voltage.angle3-element Vector{Float64}:
+ 0.17
+ 0.17000000000000004
+ 0.16975

Power Analysis

After obtaining the solution from the DC optimal power flow, we can calculate the powers related to buses and branches using the power! function:

power!(system, analysis)
Info

For a clear comprehension of the equations, symbols provided below, as well as for a better grasp of power directions, please refer to the Unified Branch Model.


Power Injections

Active power injections are stored as the vector $\mathbf{P} = [P_i]$, and can be retrieved using the following commands:

julia> 𝐏 = analysis.power.injection.active3-element Vector{Float64}:
+  0.02499999999999991
+  0.0650000000000027
+ -0.05

Generator Power Injections

The active power supplied by generators to the buses can be calculated by summing the active power outputs of the generators obtained from the optimal DC power flow. This can be expressed as:

\[ P_{\text{p}i} = \sum_{k=1}^{n_{\text{g}i}} P_{\text{g}k},\;\;\; \forall i \in \mathcal{N}.\]

Here, $P_{\text{g}k}$ represents the active power output of the $k$-th generator connected to bus $i \in \mathcal{N}$, and $n_{\text{g}i}$ denotes the total number of generators connected to the same bus. We can obtain the vector of active powers injected by generators into the buses, denoted as $\mathbf{P}_{\text{p}} = [P_{\text{p}i}]$, using the following command:

julia> 𝐏ₚ = analysis.power.supply.active3-element Vector{Float64}:
+ 0.02499999999999991
+ 0.1650000000000027
+ 0.0

Power Flows

The resulting from-bus active power flows are stored as the vector $\mathbf{P}_{\text{i}} = [P_{ij}]$, which can be retrieved using:

julia> 𝐏ᵢ = analysis.power.from.active3-element Vector{Float64}:
+ -5.551115123125783e-16
+  0.025000000000000022
+  0.025000000000002798

Similarly, the resulting to-bus active power flows are stored as the vector $\mathbf{P}_{\text{j}} = [P_{ji}]$, which can be retrieved using:

julia> 𝐏ⱼ = analysis.power.to.active3-element Vector{Float64}:
+  5.551115123125783e-16
+ -0.025000000000000022
+ -0.025000000000002798
diff --git a/v0.2.0/tutorials/dcPowerFlow/index.html b/v0.2.0/tutorials/dcPowerFlow/index.html new file mode 100644 index 000000000..1b6815131 --- /dev/null +++ b/v0.2.0/tutorials/dcPowerFlow/index.html @@ -0,0 +1,49 @@ + +DC Power Flow · JuliaGrid

DC Power Flow

JuliaGrid employs standard network components and the Unified Branch Model to obtain the DC power flow solution. To begin, let us generate the PowerSystem type, as illustrated by the following example:

@labels(Integer)
+
+@power(MW, MVAr, MVA)
+@voltage(pu, deg, V)
+
+system = powerSystem()
+
+addBus!(system; label = 1, type = 3)
+addBus!(system; label = 2, type = 1, active = 21.7)
+addBus!(system; label = 3, type = 2, conductance = 0.07)
+
+addBranch!(system; from = 1, to = 2, reactance = 0.26)
+addBranch!(system; from = 1, to = 3, reactance = 0.38)
+addBranch!(system; from = 2, to = 3, reactance = 0.17, turnsRatio = 0.97)
+
+addGenerator!(system; bus = 1, active = 2.0)
+addGenerator!(system; bus = 1, active = 4.0)
+addGenerator!(system; bus = 3, active = 5.0)

To review, we can conceptualize the bus/branch model as the graph denoted by $\mathcal{G} = (\mathcal{N}, \mathcal{E})$, where we have the set of buses $\mathcal{N} = \{1, \dots, n\}$, and the set of branches $\mathcal{E} \subseteq \mathcal{N} \times \mathcal{N}$ within the power system:

julia> 𝒩 = collect(keys(system.bus.label))3-element Vector{Int64}:
+ 1
+ 2
+ 3
julia> ℰ = [𝒩[system.branch.layout.from] 𝒩[system.branch.layout.to]]3×2 Matrix{Int64}: + 1 2 + 1 3 + 2 3

Notation

In this section, when referring to a vector $\mathbf{a}$, we use the notation $\mathbf{a} = [a_{i}]$ or $\mathbf{a} = [a_{ij}]$, where $a_i$ represents the element associated with bus $i \in \mathcal{N}$, and $a_{ij}$ represents the element associated with branch $(i,j) \in \mathcal{E}$.


Power Flow Solution

As discussed in section DC Model, the DC power flow problem can be represented by a set of linear equations:

\[ \mathbf {P} = \mathbf{B} \bm {\Theta} + \mathbf{P_\text{tr}} + \mathbf{P}_\text{sh}.\]


Implementation

JuliaGrid offers a set of functions to solve the DC power flow problem and obtain the bus voltage angles. Firstly, the power system is loaded and the DC model is built using the following code sequence:

dcModel!(system)

The DC power flow solution is obtained through a non-iterative approach by solving the system of linear equations:

\[ \bm {\Theta} = \mathbf{B}^{-1}(\mathbf {P} - \mathbf{P_\text{tr}} - \mathbf{P}_\text{sh}).\]

JuliaGrid begins the process by establishing the DC power flow framework:

analysis = dcPowerFlow(system)

The subsequent step involves performing the LU factorization of the nodal matrix $\mathbf{B} = \mathbf{L}\mathbf{U}$ and computing the bus voltage angles using:

solve!(system, analysis)
Tip

By default, JuliaGrid utilizes LU factorization as the primary method to factorize the nodal matrix. However, users maintain the flexibility to opt for alternative factorization methods such as LDLt or QR.

The factorization of the nodal matrix can be accessed using:

julia> 𝐋 = analysis.method.factorization.L3×3 SparseArrays.SparseMatrixCSC{Float64, Int64} with 4 stored entries:
+ 1.0    ⋅         ⋅
+  ⋅    1.0        ⋅
+  ⋅   -0.662261  1.0
julia> 𝐔 = analysis.method.factorization.U3×3 SparseArrays.SparseMatrixCSC{Float64, Int64} with 4 stored entries: + 1.0 ⋅ ⋅ + ⋅ 0.620383 -0.379617 + ⋅ ⋅ 0.337739

It is important to note that the slack bus voltage angle is excluded from the vector $\bm{\Theta}$ only during the computation step. Consequently, the corresponding elements in the vectors $\mathbf {P}$, $\mathbf{P_\text{tr}}$, $\mathbf{P}_\text{sh}$, and the corresponding row and column of the matrix $\mathbf{B}$ are removed. It is worth mentioning that this process is handled internally, and the stored elements remain unchanged.

Finally, the resulting bus voltage angles are saved in the vector as follows:

julia> 𝚯 = analysis.voltage.angle3-element Vector{Float64}:
+  0.0
+ -0.03214364268853274
+ -0.016746829916759843

Power Analysis

After obtaining the solution from the DC power flow, we can calculate powers related to buses, branches, and generators using the power! function:

power!(system, analysis)
Info

For a clear comprehension of the equations, symbols provided below, as well as for a better grasp of power directions, please refer to the Unified Branch Model.


Power Injections

Active power injections are stored as the vector $\mathbf{P} = [P_i]$, and can be retrieved using the following commands:

julia> 𝐏 = analysis.power.injection.active3-element Vector{Float64}:
+  0.1677
+ -0.217
+  0.05

Generator Power Injections

The active power supplied by generators to the buses can be calculated by summing the given generator active powers in the input data, except for the slack bus, which can be determined as:

\[ P_{\text{p}i} = P_i + P_{\text{d}i},\;\;\; i \in \mathcal{N}_{\text{sb}},\]

where $P_{\text{d}i}$ represents the active power demanded by consumers at the slack bus. The vector of active powers injected by generators into the buses, denoted by $\mathbf{P}_{\text{p}} = [P_{\text{p}i}]$, can be obtained using the following command:

julia> 𝐏ₚ = analysis.power.supply.active3-element Vector{Float64}:
+ 0.1677
+ 0.0
+ 0.05

Power Flows

The resulting from-bus active power flows are stored as the vector $\mathbf{P}_{\text{i}} = [P_{ij}]$, which can be retrieved using:

julia> 𝐏ᵢ = analysis.power.from.active3-element Vector{Float64}:
+  0.12362939495589513
+  0.04407060504410485
+ -0.09337060504410487

Similarly, the resulting to-bus active power flows are stored as the vector $\mathbf{P}_{\text{j}} = [P_{ji}]$, which can be retrieved using:

julia> 𝐏ⱼ = analysis.power.to.active3-element Vector{Float64}:
+ -0.12362939495589513
+ -0.04407060504410485
+  0.09337060504410487

Generators Power Outputs

The output active power of each generator located at bus $i \in \mathcal{N}_{\text{pv}} \cup \mathcal{N}_{\text{pq}}$ is equal to the active power specified in the input data. If there are multiple generators, their output active powers are also equal to the active powers specified in the input data. However, the output active power of a generator located at the slack bus will be:

\[ P_{\text{g}i} = P_i + P_{\text{d}i},\;\;\; i \in \mathcal{N}_{\text{sb}}.\]

In the case of multiple generators connected to the slack bus, the first generator in the input data is assigned the obtained value of $P_{\text{g}i}$. Then, this amount of power is reduced by the output active power of the other generators.

To retrieve the vector of active power outputs of generators, denoted as $\mathbf{P}_{\text{g}} = [P_{\text{g}i}]$, $i \in \mathcal{S}$, where the set $\mathcal{S}$ represents the set of generators, users can utilize the following command:

julia> 𝐏ₒ = analysis.power.generator.active3-element Vector{Float64}:
+ 0.12769999999999998
+ 0.04
+ 0.05
diff --git a/v0.2.0/tutorials/dcStateEstimation/index.html b/v0.2.0/tutorials/dcStateEstimation/index.html new file mode 100644 index 000000000..ce09cb32c --- /dev/null +++ b/v0.2.0/tutorials/dcStateEstimation/index.html @@ -0,0 +1,100 @@ + +DC State Estimation · JuliaGrid

DC State Estimation

To initiate the process, let us construct the PowerSystem type and formulate the DC model:

system = powerSystem()
+
+addBus!(system; label = 1, type = 3, angle = 0.0)
+addBus!(system; label = 2, type = 1, active = 0.1)
+addBus!(system; label = 3, type = 1, active = 1.3)
+addBranch!(system; label = 1, from = 1, to = 2, reactance = 0.2)
+addBranch!(system; label = 2, from = 1, to = 3, reactance = 0.1)
+addBranch!(system; label = 3, from = 2, to = 3, reactance = 0.3)
+addGenerator!(system; label = 1, bus = 1, active = 3.2)
+
+dcModel!(system)

To review, we can conceptualize the bus/branch model as the graph denoted by $\mathcal{G} = (\mathcal{N}, \mathcal{E})$, where we have the set of buses $\mathcal{N} = \{1, \dots, n\}$, and the set of branches $\mathcal{E} \subseteq \mathcal{N} \times \mathcal{N}$ within the power system:

julia> 𝒩 = collect(keys(system.bus.label))3-element Vector{String}:
+ "1"
+ "2"
+ "3"
julia> ℰ = [𝒩[system.branch.layout.from] 𝒩[system.branch.layout.to]]3×2 Matrix{String}: + "1" "2" + "1" "3" + "2" "3"

Following that, we will introduce the Measurement type and incorporate a set of measurement devices $\mathcal{M}$ into the graph $\mathcal{G}$. In typical scenarios, the DC state estimation model relies solely on active power measurements originating from the set of wattmeters $\mathcal{P}$. However, we provide the option for users to include measurements from the set of PMUs $\bar{\mathcal{P}}$. Specifically, we utilize only the PMUs installed at the buses $\bar{\mathcal{P}}_\text{b} \subset \bar{\mathcal{P}}$ that measure bus voltage angles. This process of adding measurement devices will be carried out in the State Estimation Model section. Currently, we are only initializing the Measurement type:

device = measurement()

Notation

Here, when referring to a vector $\mathbf{a}$, we use the notation $\mathbf{a} = [a_{i}]$ or $\mathbf{a} = [a_{ij}]$, where $a_i$ represents the element related with bus $i \in \mathcal{N}$ or measurement $i \in \mathcal{M}$, while $a_{ij}$ denotes the element related with branch $(i,j) \in \mathcal{E}$.


State Estimation Model

In accordance with the DC Model, the DC state estimation is derived through the linearization of the non-linear model. In this linearized model, all bus voltage magnitudes are assumed to be $V_i \approx 1$, $i \in \mathcal{N}$. Additionally, shunt elements and branch resistances are neglected. This simplification implies that the DC model disregards reactive powers and transmission losses, focusing solely on active powers. Consequently, the DC state estimation considers only bus voltage angles, represented as $\mathbf x \equiv \bm {\Theta}$, as the state variables. As a result, the total number of state variables is $n-1$, with one voltage angle corresponding to the slack bus.

Within the JuliaGrid framework for DC state estimation, the methodology encompasses both active power flow and injection measurements from the set $\mathcal{P}$, along with bus voltage angle measurements represented by the set $\bar{\mathcal{P}}_\text{b}$. These measurements contribute to the construction of a linear system of equations:

\[ \mathbf{z}=\mathbf{h}(\bm {\Theta})+\mathbf{u},\]

where $\mathbf{h}(\bm {\Theta})=$ $[h_1(\bm {\Theta})$, $\dots$, $h_k(\bm {\Theta})]^{{T}}$ is the vector of linear measurement functions, $\mathbf{z} = [z_1,\dots,z_k]^{\mathrm{T}}$ is the vector of measurement values, and $\mathbf{u} = [u_1,\dots,u_k]^{\mathrm{T}}$ is the vector of uncorrelated measurement errors, and this defines the vector of measurement variances $\mathbf{v} = [v_1,\dots,v_k]^{\mathrm{T}}$, where $k = |\mathcal{M}|$.

Therefore, the linear system of equations can be represented based on the specific devices from which measurements originate, whether wattmeters or PMUs:

\[ \begin{bmatrix} + \mathbf{z}_\mathcal{P}\\[3pt] + \mathbf{z}_{\bar{\mathcal{P}}_\text{b}} + \end{bmatrix} = + \begin{bmatrix} + \mathbf{h}_\mathcal{P}(\bm {\Theta})\\[3pt] + \mathbf{h}_{\bar{\mathcal{P}}_\text{b}}(\bm {\Theta}) + \end{bmatrix} + + \begin{bmatrix} + \mathbf{u}_\mathcal{P}\\[3pt] + \mathbf{u}_{\bar{\mathcal{P}}_\text{b}}. + \end{bmatrix}\]

In summary, upon user definition of the measurement devices, each $i$-th measurement device is linked to the measurement function $h_i(\bm {\Theta})$, the corresponding measurement value $z_i$, and the measurement variance $v_i$.


Active Power Injection Measurements

When adding a wattmeter $P_i \in \mathcal{P}$ at bus $i \in \mathcal{N}$, users specify that the wattmeter measures active power injection and define measurement value, variance and measurement function of vectors:

\[ \mathbf{z}_\mathcal{P} = [z_{P_{i}}], \;\;\; \mathbf{v}_\mathcal{P} = [v_{P_{i}}], \;\;\; \mathbf{h}_\mathcal{P}(\bm {\Theta}) = [h_{P_{i}}(\bm {\Theta})].\]

For example:

addWattmeter!(system, device; label = "P₃", bus = 3, active = -1.30, variance = 1e-3)

Here, utilizing the DC Model, we derive the function defining the active power injection as follows:

\[ h_{P_{i}}(\bm {\Theta}) = B_{ii}\theta_i + \sum_{j \in \mathcal{N}_i \setminus i} {B}_{ij} \theta_j + P_{\text{tr}i} + P_{\text{sh}i},\]

where $\mathcal{N}_i \setminus i$ contains buses incident to bus $i$, excluding bus $i$, with the following coefficient expressions:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{P_{i}}(\bm {\Theta})}}{\mathrm \partial \theta_{i}} = B_{ii}, \;\;\; + \cfrac{\mathrm \partial{{h_{P_{i}}}(\bm {\Theta})}}{\mathrm \partial \theta_{j}} = {B}_{ij}. + \end{aligned}\]


From-Bus End Active Power Flow Measurements

Additionally, when introducing a wattmeter at branch $(i,j) \in \mathcal{E}$, users specify that the wattmeter measures active power flow. It can be positioned at the from-bus end, denoted as $P_{ij} \in \mathcal{P}$, specifying the measurement value, variance and measurement function of vectors:

\[ \mathbf{z}_\mathcal{P} = [z_{P_{ij}}], \;\;\; \mathbf{v}_\mathcal{P} = [v_{P_{ij}}], \;\;\; \mathbf{h}_\mathcal{P}(\bm {\Theta}) = [h_{P_{ij}}(\bm {\Theta})].\]

For example:

addWattmeter!(system, device; label = "P₁₂", from = 1, active = 0.28, variance = 1e-4)

Here, the function describing active power flow at the from-bus end is defined as follows:

\[ h_{P_{ij}}(\bm {\Theta}) = \cfrac{1}{\tau_{ij} x_{ij}} (\theta_{i} -\theta_{j}-\phi_{ij}),\]

with the following coefficient expressions:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{P_{ij}}(\bm {\Theta})}}{\mathrm \partial \theta_{i}} = \cfrac{1}{\tau_{ij} x_{ij}}, \;\;\; + \cfrac{\mathrm \partial{{h_{P_{ij}}}(\bm {\Theta})}}{\mathrm \partial \theta_{j}} = -\cfrac{1}{\tau_{ij} x_{ij}}. + \end{aligned}\]


To-Bus End Active Power Flow Measurements

Similarly, a wattmeter can be placed at the to-bus end, denoted as $P_{ji} \in \mathcal{P}$, specifying the measurement value, variance and measurement function of vectors:

\[ \mathbf{z}_\mathcal{P} = [z_{P_{ji}}], \;\;\; \mathbf{v}_\mathcal{P} = [v_{P_{ji}}], \;\;\; \mathbf{h}_\mathcal{P}(\bm {\Theta}) = [h_{P_{ji}}(\bm {\Theta})].\]

For example:

addWattmeter!(system, device; label = "P₂₁", to = 1, active = -0.28, variance = 1e-4)

Thus, the function describing active power flow at the to-bus end is defined as follows:

\[ h_{P_{ji}}(\bm {\Theta}) = -\cfrac{1}{\tau_{ij} x_{ij}} (\theta_{i} -\theta_{j}-\phi_{ij}),\]

with the following coefficient expressions:

\[ \cfrac{\mathrm \partial{h_{P_{ji}}(\bm {\Theta})}}{\mathrm \partial \theta_{i}} = -\cfrac{1}{\tau_{ij} x_{ij}}, \;\;\; + \cfrac{\mathrm \partial{{h_{P_{ji}}}(\bm {\Theta})}}{\mathrm \partial \theta_{j}} = \cfrac{1}{\tau_{ij} x_{ij}}.\]


Bus Voltage Angle Measurements

If the user opts to include phasor measurements that measure bus voltage angle at bus $i \in \mathcal{N}$, denoted as $\theta_i \in \bar{\mathcal{P}}_\text{b}$, the user will specify the measurement values, variances, and measurement functions of vectors:

\[ \mathbf{z}_{\bar{\mathcal{P}}_\text{b}} = [z_{\theta_i}], \;\;\; \mathbf{v}_{\bar{\mathcal{P}}_\text{b}} = [v_{\theta_i}], \;\;\; \mathbf{h}_{\bar{\mathcal{P}}_\text{b}}(\bm {\Theta}) = [h_{\theta_{i}}(\bm {\Theta})].\]

For example:

addPmu!(system, device; label = "V₁, θ₁", bus = 1, magnitude = 1.0, angle = 0,
+varianceMagnitude = 1e-5, varianceAngle = 1e-6)

Here, the function defining the bus voltage angle measurement is straightforward:

\[ h_{\theta_{i}}(\bm {\Theta}) = \theta_{i},\]

with the following coefficient expression:

\[ \cfrac{\mathrm \partial{{h_{\theta_i}(\bm {\Theta})}}}{\mathrm \partial \theta_{i}}=1.\]


Weighted Least-Squares Estimation

The solution to the DC state estimation problem is determined by solving the linear weighted least-squares (WLS) problem, represented by the following formula:

\[ \mathbf H^{T} \bm \Sigma^{-1} \mathbf H \bm {\Theta} = \mathbf H^{T} \bm \Sigma^{-1} (\mathbf z - \mathbf{c}).\]

Here, $\mathbf z \in \mathbb {R}^{k}$ denotes the vector of measurement values, the vector $\mathbf c \in \mathbb {R}^{k}$ holds constant terms, $\mathbf {H} \in \mathbb {R}^{k \times (n-1)}$ represents the coefficient matrix, and $\bm \Sigma \in \mathbb {R}^{k \times k}$ is the measurement error covariance matrix, where the diagonal elements hold measurement variances.

The inclusion of the vector $\mathbf{c}$ is necessary due to the fact that measurement functions associated with active power measurements may include constant terms, especially when there are non-zero shift angles of transformers or shunt elements in the system consuming active powers, as evident from the provided measurement functions.


Implementation

JuliaGrid initiates the DC state estimation framework by setting up the WLS model, as illustrated in the following:

analysis = dcStateEstimation(system, device)

Coefficient Matrix

Using the above-described equations, JuliaGrid forms the coefficient matrix $\mathbf{H} \in \mathbb{R}^{k \times (n-1)}$:

julia> 𝐇 = analysis.method.coefficient4×3 SparseArrays.SparseMatrixCSC{Float64, Int64} with 8 stored entries:
+ -10.0  -3.33333  13.3333
+   5.0  -5.0        ⋅
+  -5.0   5.0        ⋅
+   1.0    ⋅         ⋅

Each row in the matrix corresponds to a specific measurement. The first $|\mathcal{P}|$ rows correspond to wattmeters, ordered as users add wattmeters, while the last $|{\bar{\mathcal{P}}_\text{b}}|$ rows correspond to PMUs, also in the order users add PMUs.


Precision Matrix

JuliaGrid opts not to retain the covariance matrix $\bm \Sigma$ but rather stores its inverse, the precision or weighting matrix denoted as $\mathbf W = \bm \Sigma^{-1}$. The order of these values corresponds to the description provided for the coefficient matrix. Users can access these values using the following command:

julia> 𝐖 = analysis.method.precision4×4 SparseArrays.SparseMatrixCSC{Float64, Int64} with 4 stored entries:
+ 1000.0       ⋅        ⋅    ⋅
+     ⋅   10000.0       ⋅    ⋅
+     ⋅        ⋅   10000.0   ⋅
+     ⋅        ⋅        ⋅   1.0e6

Mean Vector

Users can access the vector $\mathbf z - \mathbf{c}$, which contains the means of Gaussian distributions describing each measurement, using the following command:

julia> 𝐳 = analysis.method.mean4-element Vector{Float64}:
+ -1.3
+  0.28
+ -0.28
+  0.0

In the context of the power system, where phase-shifting transformers and shunt elements consuming active powers are absent, and the slack angle has a zero value, the vector $\mathbf{c}= \mathbf{0}$. Consequently, the vector of means holds values that are equal to the measurement values.


Estimate of State Variables

Once the model is established, we solve the WLS equation to derive the estimate of bus voltage angles:

\[ \hat{\bm {\Theta}} = [\mathbf H^{T} \bm \Sigma^{-1} \mathbf H]^{-1} \mathbf H^{T} \bm \Sigma^{-1} (\mathbf z - \mathbf{c}).\]

This process is executed using the solve! function:

solve!(system, analysis)

The initial step involves the LU factorization of the gain matrix:

\[ \mathbf G = \mathbf H^{T} \bm \Sigma^{-1} \mathbf H = \mathbf L \mathbf U.\]

Tip

By default, JuliaGrid utilizes LU factorization as the primary method to factorize the gain matrix. However, users maintain the flexibility to opt for alternative factorization methods such as LDLt or QR.

Access to the factorized gain matrix is available through:

julia> 𝐋 = analysis.method.factorization.L3×3 SparseArrays.SparseMatrixCSC{Float64, Int64} with 4 stored entries:
+ 1.0    ⋅         ⋅
+  ⋅    1.0        ⋅
+  ⋅   -0.217391  1.0
julia> 𝐔 = analysis.method.factorization.U3×3 SparseArrays.SparseMatrixCSC{Float64, Int64} with 4 stored entries: + 1.0 ⋅ ⋅ + ⋅ 0.92 -0.08 + ⋅ ⋅ 0.782609

Finally, the estimated bus voltage angles $\hat{\bm {\Theta}} = [\hat{\theta}_i]$, $i \in \mathcal{N}$, can be retrieved using the variable:

julia> 𝚯 = analysis.voltage.angle3-element Vector{Float64}:
+  0.0
+ -0.05600000000000001
+ -0.11150000000000002

It is essential to note that the slack bus voltage angle is temporarily excluded from the gain matrix $\mathbf G$ during computation. It is important to emphasize that this internal handling does not alter the stored elements.


Alternative Formulation

The resolution of the WLS state estimation problem using the conventional method typically progresses smoothly. However, it is widely acknowledged that in certain situations common to real-world systems, this method can be vulnerable to numerical instabilities. Such conditions might impede the algorithm from converging to a satisfactory solution. In such cases, users may opt for an alternative formulation of the WLS state estimation, namely, employing an approach called orthogonal factorization [5, Sec. 3.2].

To address ill-conditioned situations arising from significant differences in measurement variances, users can employ an alternative approach:

analysis = dcStateEstimation(system, device, Orthogonal)

To explain the method, we begin with the WLS equation:

\[ \mathbf H^{T} \mathbf W \mathbf H \bm {\Theta} = \mathbf H^{T} \mathbf W (\mathbf z - \mathbf{c}),\]

where $\mathbf W = \bm \Sigma^{-1}$. Subsequently, we can write:

\[ \left({\mathbf W^{1/2}} \mathbf H\right)^{T} {\mathbf W^{1/2}} \mathbf H \bm {\Theta} = \left({\mathbf W^{1/2}} \mathbf H\right)^{T} {\mathbf W^{1/2}} (\mathbf z - \mathbf{c}).\]

Consequently, we have:

\[ \bar{\mathbf{H}}^{T} \bar{\mathbf{H}} \bm {\Theta} = \bar{\mathbf{H}}^{T} \bar{\mathbf{z}},\]

where:

\[ \bar{\mathbf{H}} = {\mathbf W^{1/2}} \mathbf H; \;\;\; \bar{\mathbf{z}} = {\mathbf W^{1/2}} (\mathbf z - \mathbf{c}).\]

At this point, QR factorization is performed on the rectangular matrix:

\[ \bar{\mathbf{H}} = {\mathbf W^{1/2}} \mathbf H = \mathbf{Q}\mathbf{R}.\]

Executing this procedure involves the solve! function:

solve!(system, analysis)

Access to the factorized matrix is possible through:

julia> 𝐐 = analysis.method.factorization.Q4×4 SparseArrays.SPQR.QRSparseQ{Float64, Int64}
julia> 𝐑 = analysis.method.factorization.R3×3 SparseArrays.SparseMatrixCSC{Float64, Int64} with 4 stored entries: + 421.637 -105.409 0.0 + ⋅ 707.107 ⋅ + ⋅ ⋅ ⋅

To obtain the solution, JuliaGrid avoids materializing the orthogonal matrix $\mathbf{Q}$ and proceeds to solve the system, resulting in the estimate of state variables $\hat{\bm {\Theta}} = [\hat{\theta}_i]$, where $i \in \mathcal{N}$:

julia> 𝚯 = analysis.voltage.angle3-element Vector{Float64}:
+  0.0
+ -0.05600000000000001
+ -0.1115

Bad Data Processing

Besides the state estimation algorithm, one of the essential state estimation routines is the bad data processing, whose main task is to detect and identify measurement errors, and eliminate them if possible. This is usually done by processing the measurement residuals [5, Ch. 5], and typically, the largest normalized residual test is used to identify bad data. The largest normalized residual test is performed after we obtained the solution of the state estimation in the repetitive process of identifying and eliminating bad data measurements one after another [19].

To illustrate this process, let us introduce a new measurement that contains an obvious outlier:

addWattmeter!(system, device; label = "P₁", bus = 1, active = 13.1, variance = 1e-4)

Subsequently, we will construct the WLS state estimation model and solve it:

analysis = dcStateEstimation(system, device)
+solve!(system, analysis)

Now, the bad data processing can be executed:

outlier = residualTest!(system, device, analysis; threshold = 4.0)

In this step, we employ the largest normalized residual test, guided by the analysis outlined in [5, Sec. 5.7]. To be more precise, we compute all measurement residuals based on the obtained estimate of state variables:

\[ r_{i} = z_i - h_i(\hat {\bm {\Theta}}), \;\;\; i \in \mathcal{M}.\]

The normalized residuals for all measurements are computed as follows:

\[ \bar{r}_{i} = \cfrac{|r_i|}{\sqrt{C_{ii}}} = \cfrac{|r_i|}{\sqrt{S_{ii}\Sigma_{ii}}}, \;\;\; i \in \mathcal{M},\]

In this equation, we denote the diagonal entries of the residual covariance matrix $\mathbf C \in \mathbb{R}^{k \times k}$ as $C_{ii} = S_{ii}\Sigma_{ii}$, where $S_{ii}$ is the diagonal entry of the residual sensitivity matrix $\mathbf S$ representing the sensitivity of the measurement residuals to the measurement errors. For this specific configuration, the relationship is expressed as:

\[ \mathbf C = \mathbf S \bm \Sigma = \bm \Sigma - \mathbf H [\mathbf H^T \bm \Sigma^{-1} \mathbf H]^{-1} \mathbf H^T.\]

It is important to note that only the diagonal entries of $\mathbf C$ are required. To obtain the inverse, the JuliaGrid package utilizes a computationally efficient sparse inverse method, retrieving only the necessary elements of the inverse.

The subsequent step involves selecting the largest normalized residual, and the $j$-th measurement is then suspected as bad data and potentially removed from the measurement set $\mathcal{M}$:

\[ \bar{r}_{j} = \text{max} \{\bar{r}_{i}, i \in \mathcal{M} \},\]

Users can access this information using the variable:

julia> outlier.maxNormalizedResidual420.45601204468034

If the largest normalized residual, denoted as $\bar{r}_{j}$, satisfies the inequality:

\[ \bar{r}_{j} \ge \epsilon,\]

the corresponding measurement is identified as bad data and subsequently removed. In this example, the bad data identification threshold is set to $\epsilon = 4$. Users can verify the satisfaction of this inequality by inspecting the variable:

julia> outlier.detecttrue

This indicates that the measurement labeled as:

julia> outlier.label"P₁"

is removed from the DC model and marked as out-of-service.

Subsequently, we can immediately solve the system again, but this time without the removed measurement:

solve!(system, analysis)

Following that, we check for outliers once more:

outlier = residualTest!(system, device, analysis; threshold = 4.0)

To examine the value:

julia> outlier.maxNormalizedResidual4.76837158203125e-7

As this value is now less than the threshold $\epsilon = 4$, the measurement is not removed, or there are no outliers. This can also be verified by observing the bad data flag:

julia> outlier.detectfalse

Least Absolute Value Estimation

The least absolute value (LAV) method provides an alternative estimation approach that is considered more robust in comparison to the WLS method. The WLS state estimation problem relies on specific assumptions about measurement errors, whereas robust estimators aim to remain unbiased even in the presence of various types of measurement errors and outliers. This characteristic eliminates the need for bad data processing, as discussed in [5, Ch. 6]. It is important to note that robustness often comes at the cost of increased computational complexity.

It can be demonstrated that the problem can be expressed as a linear programming problem. This section outlines the method as described in [5, Sec. 6.5]. To revisit, we consider the system of linear equations:

\[ \mathbf{z}=\mathbf{h}(\bm {\Theta})+\mathbf{u}.\]

Subsequently, the LAV state estimator is derived as the solution to the optimization problem:

\[ \begin{aligned} + \text{minimize}& \;\;\; \mathbf a^T |\mathbf r|\\ + \text{subject\;to}& \;\;\; \mathbf{z} - \mathbf{H}\bm {\Theta} - \mathbf{c} =\mathbf r. + \end{aligned}\]

Here, $\mathbf a \in \mathbb {R}^{k}$ is the vector with all entries equal to one, and $\mathbf r$ represents the vector of measurement residuals. Let $\bm \eta$ be defined in a manner that ensures:

\[ |\mathbf r| \preceq \bm \eta,\]

and replace the above inequality with two equalities using the introduction of two non-negative slack variables $\mathbf q \in \mathbb {R}_{\ge 0}^{k}$ and $\mathbf w \in \mathbb {R}_{\ge 0}^{k}$:

\[ \begin{aligned} + \mathbf r - \mathbf q &= -\bm \eta \\ + \mathbf r + \mathbf w &= \bm \eta. + \end{aligned}\]

Let us now define four additional non-negative variables:

\[ \bm {\Theta}_x \in \mathbb {R}_{\ge 0}^{n}; \;\;\; \bm {\Theta}_y \in \mathbb {R}_{\ge 0}^{n}; \;\;\; + \mathbf {r}_x \in \mathbb {R}_{\ge 0}^{k}; \;\;\; \mathbf {r}_y \in \mathbb {R}_{\ge 0}^{k},\]

where:

\[ \bm {\Theta} = \bm {\Theta}_x - \bm {\Theta}_y; \;\;\; \mathbf r = \mathbf {r}_x - \mathbf {r}_y\\ + \mathbf {r}_x = \cfrac{1}{2} \mathbf q; \;\;\; \mathbf {r}_y = \cfrac{1}{2} \mathbf w.\]

Then, the above two equalities become:

\[ \begin{aligned} + \mathbf r - 2\mathbf {r}_x &= -2\bm \eta \\ + \mathbf r + 2 \mathbf {r}_y &= 2\bm \eta, + \end{aligned}\]

that is:

\[ \begin{aligned} + \mathbf {r}_x + \mathbf {r}_y = \bm \eta; \;\;\; \mathbf r = \mathbf {r}_x - \mathbf {r}_y. + \end{aligned}\]

Hence, the optimization problem can be written:

\[ \begin{aligned} + \text{minimize}& \;\;\; \mathbf a^T (\mathbf {r}_x + \mathbf {r}_y)\\ + \text{subject\;to}& \;\;\; \mathbf{H}(\bm {\Theta}_x - \bm {\Theta}_y) + \mathbf {r}_x - \mathbf {r}_y = \mathbf{z} - \mathbf{c} \\ + & \;\;\; \bm {\Theta}_x \succeq \mathbf 0, \; \bm {\Theta}_y \succeq \mathbf 0 \\ + & \;\;\; \mathbf {r}_x \succeq \mathbf 0, \; \mathbf {r}_y \succeq \mathbf 0. + \end{aligned}\]

To form the above optimization problem, the user can call the following function:

using Ipopt
+
+analysis = dcLavStateEstimation(system, device, Ipopt.Optimizer)

Then the user can solve the optimization problem by:

solve!(system, analysis)

As a result, we obtain optimal values for the four additional non-negative variables, while the state estimator is obtained by:

\[ \hat{\bm {\Theta}} = \bm {\Theta}_x - \bm {\Theta}_y.\]

Users can retrieve the estimated bus voltage angles $\hat{\bm {\Theta}} = [\hat{\theta}_i]$, $i \in \mathcal{N}$, using the variable:

julia> 𝚯 = analysis.voltage.angle3-element Vector{Float64}:
+  0.0
+ -0.05599999999991556
+ -0.1114999999999376

Power Analysis

After obtaining the solution from the DC state estimation, we can calculate powers related to buses and branches using the power! function:

power!(system, analysis)
Info

For a clear comprehension of the equations, symbols provided below, as well as for a better grasp of power directions, please refer to the Unified Branch Model.


Power Injections

Active power injections are stored as the vector $\mathbf{P} = [P_i]$, and can be retrieved using the following commands:

julia> 𝐏 = analysis.power.injection.active3-element Vector{Float64}:
+  1.3949999999989537
+ -0.09499999999950443
+ -1.2999999999994494

Generator Power Injections

We can determine the active power supplied by generators to the buses by summing the active power injections and the active power demanded by consumers at each bus:

\[ P_{\text{p}i} = P_i + P_{\text{d}i},\;\;\; i \in \mathcal{N}.\]

The vector of active power injected by generators into the buses, denoted by $\mathbf{P}_{\text{p}} = [P_{\text{p}i}]$, can be obtained using:

julia> 𝐏ₚ = analysis.power.supply.active3-element Vector{Float64}:
+ 1.3949999999989537
+ 0.00500000000049558
+ 5.506706202140776e-13

Power Flows

The resulting active power flows are stored as the vector $\mathbf{P}_{\text{i}} = [P_{ij}]$, which can be retrieved using:

julia> 𝐏ᵢ = analysis.power.from.active3-element Vector{Float64}:
+ 0.2799999999995778
+ 1.1149999999993758
+ 0.18500000000007344

Similarly, the resulting active power flows are stored as the vector $\mathbf{P}_{\text{j}} = [P_{ji}]$, which can be retrieved using:

julia> 𝐏ⱼ = analysis.power.to.active3-element Vector{Float64}:
+ -0.2799999999995778
+ -1.1149999999993758
+ -0.18500000000007344
diff --git a/v0.2.0/tutorials/measurementModel/index.html b/v0.2.0/tutorials/measurementModel/index.html new file mode 100644 index 000000000..1860adb23 --- /dev/null +++ b/v0.2.0/tutorials/measurementModel/index.html @@ -0,0 +1,67 @@ + +Measurement Model · JuliaGrid

Measurement Model

Let us begin by examining a power system. To do that, we will construct one as shown below:

system = powerSystem()
+device = measurement()
+
+addBus!(system; label = 1)
+addBus!(system; label = 2)
+addBus!(system; label = 3)
+
+@branch(reactance = 0.03)
+addBranch!(system; label = 1, from = 1, to = 2)
+addBranch!(system; label = 2, from = 1, to = 3)
+addBranch!(system; label = 3, from = 2, to = 3)

To review, we can conceptualize the bus/branch model as the graph denoted by $\mathcal{G} = (\mathcal{N}, \mathcal{E})$, where we have the set of buses $\mathcal{N} = \{1, \dots, n\}$, and the set of branches $\mathcal{E} \subseteq \mathcal{N} \times \mathcal{N}$ within the power system:

julia> 𝒩 = collect(keys(system.bus.label))3-element Vector{String}:
+ "1"
+ "2"
+ "3"
julia> ℰ = [𝒩[system.branch.layout.from] 𝒩[system.branch.layout.to]]3×2 Matrix{String}: + "1" "2" + "1" "3" + "2" "3"

Our goal is to monitor the power system, and this process involves collecting measurement data for various electrical quantities distributed throughout the power system.


Power System Monitoring

Measurement data is obtained through two main technologies: SCADA (Supervisory Control and Data Acquisition) and WAMS (Wide Area Measurement System). These technologies enable the collection of a wide range of measurements distributed throughout the power system. This extensive dataset allows us to employ state estimation algorithms to obtain the present state of the power system, in contrast to power flow algorithms, which are typically used for offline analyses. To commence, we will represent the entire set of measurement devices as $\mathcal{M}$.

SCADA provides legacy measurements with low sampling rates, making them unsuitable for capturing real-time system dynamics. It provides a snapshot of the power system's state, with delays measured in seconds and minutes. These legacy measurement devices, subsets of the set $\mathcal{M}$, include:

  • a set of voltmeters $\mathcal{V}$ for measuring bus voltage magnitudes,
  • a set of ammeters $\mathcal{I}$ for measuring branch current magnitudes,
  • a set of wattmeters $\mathcal{P}$ for active power injection and flow measurements,
  • a set of varmeters $\mathcal{Q}$ for reactive power injection and flow measurements.

In contrast, WAMS technology utilizes PMUs (Phasor Measurement Units) to provide data with high sampling rates, typically ranging between 10 and 20 ms, facilitating real-time monitoring of the system. Therefore, PMUs expand the set $\mathcal{M}$ as follows:

  • a set of PMUs $\bar{\mathcal{P}}$ for bus voltage and branch current phasor measurements.

Notation

In this section, when referring to a vector $\mathbf{a}$, we use the notation $\mathbf{a} = [a_{i}]$, where $a_i$ represents the element associated measurement $i \in \mathcal{M}$.


Measurement Model

The measurement model, as defined by the set $\mathcal{M}$, can be expressed as a system of equations [12]:

\[ \mathbf{z}=\mathbf{h}(\mathbf {x}) + \mathbf{u},\]

where $\mathbf {x}=[x_1,\dots,x_{n}]^{T}$ is the vector of state variables, $\mathbf{h}(\mathbf{x})=$ $[h_1(\mathbf{x})$, $\dots$, $h_k(\mathbf{x})]^{{T}}$ is the vector of measurement functions, $\mathbf{z} = [z_1,\dots,z_k]^{\mathrm{T}}$ is the vector of measurement values, and $\mathbf{u} = [u_1,\dots,u_k]^{\mathrm{T}}$ is the vector of measurement errors. In the context of transmission grids, this model is often an overdetermined system of equations $(k>s)$ [13, Sec. 2.1].

These errors are assumed to follow a Gaussian distribution with a zero-mean and covariance matrix $\bm \Sigma$. The diagonal elements of $\bm \Sigma$ correspond to the measurement variances $\mathbf{v} = [v_1,\dots,v_k]^T$, while the off-diagonal elements represent the covariances between the measurement errors $\mathbf{w} = [w_1,\dots,w_k]^{T}$. These covariances exist only if PMUs are observed in rectangular coordinates and correlation is required.


Gaussian Probability Density Function

Each legacy measurement and each magnitude or angle measurement from PMUs is associated with a measured value $z_i$, a measurement error $u_i$, and a measurement function $h_i(\mathbf{x})$. Assuming that measurement errors $u_i$ follow a zero mean Gaussian distribution, the probability density function associated with the $i$-th measurement is proportional to:

\[ \mathcal{N}(z_i|\mathbf{x},v_i) \propto \exp\Bigg\{\cfrac{[z_i-h_i(\mathbf{x})]^2}{2v_i}\Bigg\},\]

where $v_i$ is the measurement variance defined by the measurement error $u_i$, and the measurement function $h_i(\mathbf{x})$ connects the vector of state variables $\mathbf{x}$ to the value of the $i$-th measurement.


Artificial Generation of Measurement Values

When defining the system of equations, it is essential to have measurement values represented by $\mathbf{z}$. In JuliaGrid, users have the option to either directly specify measurement values or artificially generate the vector $\mathbf{z}$. The artificial generation process involves setting the keyword noise = true, which introduces white Gaussian noise with variances $[v_1, \dots, v_k]$ added to the provided values $[e_1, \dots, e_k]$, typically representing the exact values of the respective electrical quantities:

\[ \epsilon_i \sim \mathcal{N}(0,\,v_i) \\[5pt] + z_i = e_i + \epsilon_i.\]


Voltmeters

A voltmeter $V_i \in \mathcal{V}$ measures the bus voltage magnitude at bus $i \in \mathcal{N}$. Let us introduce two voltmeters that measure voltage magnitudes at the first and third bus. For the first voltmeter, we directly pass the measurement value, while for the second voltmeter, we generate the measurement value artificially:

addVoltmeter!(system, device; label = "V₁", bus = 1, magnitude = 1.1, variance = 1e-3)
+addVoltmeter!(system, device; label = "V₃", bus = 3, magnitude = 1.0, noise = true)

Consequently, we establish the set of voltmeters $\mathcal{V} \subset \mathcal{M}$:

julia> 𝒱 = collect(keys(device.voltmeter.label))2-element Vector{String}:
+ "V₁"
+ "V₃"

This set of voltmeters defines vectors of measurement values denoted as $\mathbf{z}_\mathcal{V} = [z_i]$ and variances denoted as $\mathbf{v}_\mathcal{V} = [v_i]$, where $i \in \mathcal{V}$, and can be accessed through the following variables:

julia> 𝐳ᵥ = device.voltmeter.magnitude.mean2-element Vector{Float64}:
+ 1.1
+ 0.9321236601753112
julia> 𝐯ᵥ = device.voltmeter.magnitude.variance2-element Vector{Float64}: + 0.001 + 0.01

Ammeters

An ammeter $I_{ij} \in \mathcal{I}$ measures the magnitude of branch current at the from-bus end of the branch $(i,j) \in \mathcal{E}$. Let us add this type of ammeter at the first branch between buses 1 and 2:

addAmmeter!(system, device; label = "I₁₂", from = 1, magnitude = 0.3, variance = 1e-3)

Additionally, an ammeter can measure the branch current magnitude at the to-bus end of the branch $(i,j) \in \mathcal{E}$, denoted as $I_{ji} \in \mathcal{I}$. For example, we can include this type of ammeter at the same branch:

addAmmeter!(system, device; label = "I₂₁", to = 1, magnitude = 0.2, variance = 1e-3)

Consequently, we establish the set of ammeters $\mathcal{I} \subset \mathcal{M}$:

julia> ℐ = collect(keys(device.ammeter.label))2-element Vector{String}:
+ "I₁₂"
+ "I₂₁"

This set of ammeters defines vectors of measurement values denoted as $\mathbf{z}_\mathcal{I} = [z_i]$ and variances denoted as $\mathbf{v}_\mathcal{I} = [v_i]$, where $i \in \mathcal{I}$, and can be accessed through the following variables:

julia> 𝐳ₒ = device.ammeter.magnitude.mean2-element Vector{Float64}:
+ 0.3
+ 0.2
julia> 𝐯ₒ = device.ammeter.magnitude.variance2-element Vector{Float64}: + 0.001 + 0.001

Wattmeters

A wattmeter $P_{i} \in \mathcal{P}$ measures the active power injection at bus $i \in \mathcal{N}$. Hence, let us add it to the second bus:

addWattmeter!(system, device; label = "P₂", bus = 2, active = 0.1, variance = 1e-4)

Next, a wattmeter denoted as $P_{ij} \in \mathcal{P}$ measures the active power flow at the from-bus end of the branch $(i,j) \in \mathcal{E}$. Let us add this type of wattmeter at the second branch:

addWattmeter!(system, device; label = "P₁₃", from = 2, active = 0.2, variance = 1e-3)

Moreover, a wattmeter can also measure the active power flow at the to-bus end of the branch $(i,j) \in \mathcal{E}$, denoted as $P_{ji} \in \mathcal{P}$. For example, we can include this type of wattmeter at the same branch:

addWattmeter!(system, device; label = "P₃₁", to = 2, active = 0.3, variance = 1e-3)

Consequently, we establish the set of wattmeters $\mathcal{P} \subset \mathcal{M}$:

julia> 𝒫 = collect(keys(device.wattmeter.label))3-element Vector{String}:
+ "P₂"
+ "P₁₃"
+ "P₃₁"

This set of wattmeters defines vectors of measurement values denoted as $\mathbf{z}_\mathcal{P} = [z_i]$ and variances denoted as $\mathbf{v}_\mathcal{P} = [v_i]$, where $i \in \mathcal{P}$, and can be accessed through the following variables:

julia> 𝐳ₚ = device.wattmeter.active.mean3-element Vector{Float64}:
+ 0.1
+ 0.2
+ 0.3
julia> 𝐯ₚ = device.wattmeter.active.variance3-element Vector{Float64}: + 0.0001 + 0.001 + 0.001

Varmeters

A varmeter $Q_{i} \in \mathcal{Q}$ measures the reactive power injection at bus $i \in \mathcal{N}$. Hence, let us add it to the first bus:

addVarmeter!(system, device; label = "Q₁", bus = 1, reactive = 0.01, variance = 1e-2)

Next, a varmeter denoted as $Q_{ij} \in \mathcal{Q}$ measures the reactive power flow at the from-bus end of the branch $(i,j) \in \mathcal{E}$. Let us add this type of varmeter at the first branch:

addVarmeter!(system, device; label = "Q₁₂", from = 1, reactive = 0.02, variance = 1e-3)

Moreover, a varmeter can also measure the reactive power flow at the to-bus end of the branch $(i,j) \in \mathcal{E}$, denoted as $Q_{ji} \in \mathcal{Q}$. For example, we can include this type of varmeter at the same branch:

addVarmeter!(system, device; label = "Q₂₁", to = 1, reactive = 0.03, noise = true)

Consequently, we establish the set of varmeters $\mathcal{Q} \subset \mathcal{M}$:

julia> 𝒬 = collect(keys(device.varmeter.label))3-element Vector{String}:
+ "Q₁"
+ "Q₁₂"
+ "Q₂₁"

This set of varmeters defines vectors of measurement values denoted as $\mathbf{z}_\mathcal{Q} = [z_i]$ and variances denoted as $\mathbf{v}_\mathcal{Q} = [v_i]$, where $i \in \mathcal{Q}$, and can be accessed through the following variables:

julia> 𝐳ₒ = device.varmeter.reactive.mean3-element Vector{Float64}:
+  0.01
+  0.02
+ -0.026643016052148777
julia> 𝐯ₒ = device.varmeter.reactive.variance3-element Vector{Float64}: + 0.01 + 0.001 + 0.01

PMUs

PMUs measure voltage and current phasors in the polar coordinate system, thus each PMU output is represented by magnitude and angle along with corresponding variances [14, Sec. 5.6]. When installed on buses, they measure bus voltage phasors, while on branches, they measure current phasors.

A PMU $(V_i, \theta_i) \in \bar{\mathcal{P}}$ measures the voltage phasor at bus $i \in \mathcal{N}$. Let us integrate this type of PMU at the first bus:

addPmu!(system, device; label = "V₁, θ₁", bus = 1, magnitude = 1, angle = 0, noise = true)

Next, a PMU $(I_{ij}, \psi_{ij}) \in \bar{\mathcal{P}}$ measures the branch current magnitude at the from-bus end of the branch $(i,j) \in \mathcal{E}$. Let us add this type of PMU at the first branch:

addPmu!(system, device; label = "I₁₂, ψ₁₂", from = 1, magnitude = 0.2, angle = -0.1)

Moreover, a PMU can measure the branch current magnitude at the to-bus end of the branch $(i,j) \in \mathcal{E}$, denoted as $(I_{ji}, \psi_{ji}) \in \bar{\mathcal{P}}$. For example, let us include this type of PMU at the same branch:

addPmu!(system, device; label = "I₂₁, ψ₂₁", to = 1, magnitude = 0.3, angle = -0.2)

Consequently, we establish the set of PMUs $\bar{\mathcal{P}} \subset \mathcal{M}$:

julia> 𝒫̄ = collect(keys(device.pmu.label))3-element Vector{String}:
+ "V₁, θ₁"
+ "I₁₂, ψ₁₂"
+ "I₂₁, ψ₂₁"

This set of PMUs establishes vectors representing measurement magnitudes and angles $\mathbf{z}_{\bar{\mathcal{P}}} = [z_i, z_j]$, along with their corresponding variances $\mathbf{v}_{\bar{\mathcal{P}}} = [v_i, v_j]$, where $(i, j) \in \bar{\mathcal{P}}$. These values can be accessed as:

julia> pmu = device.pmu;
julia> 𝐳ₚ = collect(Iterators.flatten(zip(pmu.magnitude.mean, pmu.angle.mean)))6-element Vector{Float64}: + 0.9977946507727047 + -0.0003049962814092644 + 0.2 + -0.1 + 0.3 + -0.2
julia> 𝐯ₚ = collect(Iterators.flatten(zip(pmu.magnitude.variance, pmu.angle.variance)))6-element Vector{Float64}: + 1.0e-5 + 1.0e-5 + 1.0e-5 + 1.0e-5 + 1.0e-5 + 1.0e-5
Info

PMUs can be handled in state estimation algorithms according to our definition in polar coordinate systems. However, they can also be processed in rectangular coordinates, where we observe the real and imaginary parts of the phasor measurements rather than magnitude and angle. Further details can be found in tutorials that describe specific state estimation analyses.


State Estimation

After establishing the measurement model, which includes specifying measurement values, variances, the locations of measurement devices, and known power system network parameters, the subsequent step involves the process of state estimation. State estimation is a component of energy management systems and typically encompasses network topology processing, observability analysis, state estimation algorithms, and bad data analysis.

The primary goal of state estimation algorithms is to determine state variables, often associated with bus voltages. Therefore, by representing the vector of state variables as $\mathbf{x}$ and the vector of noisy measurement values as $\mathbf{z}$, we can effectively describe the state estimation problem using the following conditional probability equation:

\[ p(\mathbf{x}|\mathbf{z})= \cfrac{p(\mathbf{z}|\mathbf{x})p(\mathbf{x})}{p(\mathbf{z})}.\]

If we assume that the prior probability distribution $p(\mathbf{x})$ is uniform and that $p(\mathbf{z})$ does not depend on $\mathbf{x}$, the maximum a posteriori solution simplifies to the maximum likelihood solution, as shown below [15]:

\[ \hat{\mathbf{x}} = \mathrm{arg}\max_{\mathbf{x}}p(\mathbf{x}|\mathbf{z}) = + \mathrm{arg}\max_{\mathbf{x}}p(\mathbf{z}|\mathbf{x}) = \mathrm{arg}\max_{\mathbf{x}}\mathcal{L}(\mathbf{z}|\mathbf{x}).\]

We can find this solution by maximizing the likelihood function $\mathcal{L}(\mathbf{z}|\mathbf{x})$, which is defined based on the likelihoods of $k$ independent measurements:

\[ \hat{\mathbf x} = \mathrm{arg} \max_{\mathbf{x}}\mathcal{L}(\mathbf{z}|\mathbf{x})= + \mathrm{arg} \max_{\mathbf{x}} \prod_{i=1}^k \mathcal{N}(z_i|\mathbf{x},v_i).\]

It can be demonstrated that the solution to the maximum a posteriori problem can be obtained by solving the following optimization problem, commonly referred to as the weighted least-squares problem [9, Sec. 9.3]:

\[ \hat{\mathbf x} = \mathrm{arg}\min_{\mathbf{x}} \sum_{i=1}^k\cfrac{[z_i-h_i(\mathbf x)]^2}{v_i}.\]

The state estimate, denoted as $\hat{\mathbf x}$, resulting from the solution to the above optimization problem, is known as the weighted least-squares estimator. Both the maximum likelihood and weighted least-squares estimators are equivalent to the maximum a posteriori solution [15, Sec. 8.6].

diff --git a/v0.2.0/tutorials/pmuStateEstimation/index.html b/v0.2.0/tutorials/pmuStateEstimation/index.html new file mode 100644 index 000000000..2d28263dd --- /dev/null +++ b/v0.2.0/tutorials/pmuStateEstimation/index.html @@ -0,0 +1,289 @@ + +PMU State Estimation · JuliaGrid

PMU State Estimation

To initiate the process, let us construct the PowerSystem type and formulate the AC model:

system = powerSystem()
+
+addBus!(system; label = 1, type = 3, active = 0.5)
+addBus!(system; label = 2, type = 1, reactive = 0.3)
+addBus!(system; label = 3, type = 1, active = 0.5)
+
+@branch(resistance = 0.02, susceptance = 0.04)
+addBranch!(system; label = 1, from = 1, to = 2, reactance = 0.6)
+addBranch!(system; label = 2, from = 1, to = 3, reactance = 0.7)
+addBranch!(system; label = 3, from = 2, to = 3, reactance = 0.2)
+
+addGenerator!(system; label = 1, bus = 1, active = 3.2, reactive = 0.2)
+
+acModel!(system)

To review, we can conceptualize the bus/branch model as the graph denoted by $\mathcal{G} = (\mathcal{N}, \mathcal{E})$, where we have the set of buses $\mathcal{N} = \{1, \dots, n\}$, and the set of branches $\mathcal{E} \subseteq \mathcal{N} \times \mathcal{N}$ within the power system:

julia> 𝒩 = collect(keys(system.bus.label))3-element Vector{String}:
+ "1"
+ "2"
+ "3"
julia> ℰ = [𝒩[system.branch.layout.from] 𝒩[system.branch.layout.to]]3×2 Matrix{String}: + "1" "2" + "1" "3" + "2" "3"

Following that, we will introduce the Measurement type and incorporate a set of PMUs $\mathcal{M} \equiv \bar{\mathcal{P}}$ into the graph $\mathcal{G}$, that capture both bus voltage and branch current phasors. To construct the linear PMU state estimation model, we represent the vector of state variables, as well as phasor measurements, in the rectangular coordinate system. This process of adding measurement devices will be carried out in the State Estimation Model section. Currently, we are only initializing the Measurement type:

device = measurement()

Notation

Here, when referring to a vector $\mathbf{a}$, we use the notation $\mathbf{a} = [a_{i}]$ or $\mathbf{a} = [a_{ij}]$, where $a_i$ represents the element related with bus $i \in \mathcal{N}$ or measurement $i \in \mathcal{M}$, while $a_{ij}$ denotes the element related with branch $(i,j) \in \mathcal{E}$.


State Estimation Model

Initially, PMUs output phasor measurements in polar coordinates. However, these measurements can be interpreted in rectangular coordinates, where the real and imaginary parts of bus voltages and branch current phasors serve as measurements. Additionally, to obtain the linear system of equations, we observe a vector of state variables in rectangular coordinates $\mathbf x \equiv[\mathbf{V}_\text{re},\mathbf{V}_\text{im}]$:

  • $\mathbf{V}_\mathrm{re} =\big[\Re(\bar{V}_1),\dots,\Re(\bar{V}_n)\big]^T$, representing the real parts of complex bus voltages,
  • $\mathbf{V}_\mathrm{im} =\big[\Im(\bar{V}_1),\dots,\Im(\bar{V}_n)\big]^T$, representing the imaginary parts of complex bus voltages.

Consequently, the total number of state variables is $2n$. It is worth noting that in this approach to state estimation, we do not require the slack bus.

The primary drawback of this method stems from measurement errors, which are associated with polar coordinates. Consequently, the covariance matrix must be transformed from polar to rectangular coordinates. As a result, errors from a single PMU are correlated, leading to a non-diagonal covariance matrix. Despite this, the covariance matrix is commonly treated as diagonal, impacting the state estimation accuracy in such scenarios.

Hence, the model includes real and imaginary parts of bus voltage and current phasor measurements from the set $\mathcal{M}$, contributing to the formulation of a linear system of equations:

\[ \mathbf{z}=\mathbf{h}(\mathbf x) + \mathbf{u}.\]

Here, $\mathbf{h}(\mathbf {x})= [h_1(\mathbf {x})$, $\dots$, $h_k(\mathbf {x})]^{{T}}$ represents the vector of linear measurement functions, where $k = 2|\bar{\mathcal{P}}|$ is the number of measurement functions, $\mathbf{z} = [z_1,\dots,z_k]^{T}$ denotes the vector of measurement values, and $\mathbf{u} = [u_1,\dots,u_k]^T$ represents the vector of measurement errors.

These errors are assumed to follow a Gaussian distribution with a zero mean and covariance matrix $\bm \Sigma$. The diagonal elements of $\bm \Sigma$ correspond to the measurement variances $\mathbf{v} = [v_1,\dots,v_k]^T$, while the off-diagonal elements represent the covariances between the measurement errors $\mathbf{w} = [w_1,\dots,w_k]^{T}$.

In summary, upon defining the PMU, each $i$-th PMU is associated with two measurement functions $h_{2i-1}(\mathbf x)$, $h_{2i}(\mathbf x)$, along with their respective measurement values $z_{2i-1}$, $z_{2i}$, as well as their variances $v_{2i-1}$, $v_{2i}$, and possibly covariances $w_{2i-1}$, $w_{2i}$.


Bus Voltage Phasor Measurements

When a PMU $(V_i, \theta_i) \in \bar{\mathcal{P}}$ is introduced at bus $i \in \mathcal{N}$ in this type of state estimation, users specify the measurement values, variances, and measurement functions of vectors as follows:

\[ \mathbf{z} = [z_{\Re(\bar{V}_{i})}, z_{\Im(\bar{V}_{i})}], \;\;\; \mathbf{v} = [v_{\Re(\bar{V}_{i})}, v_{\Im(\bar{V}_{i})}], \;\;\; \mathbf{h}(\mathbf {x}) = [h_{\Re(\bar{V}_{i})}(\mathbf {x}), h_{\Im(\bar{V}_{i})}(\mathbf {x})].\]

For example:

addPmu!(system, device; label = "V₂, θ₂", bus = 2, magnitude = 0.9, angle = -0.1,
+varianceMagnitude = 1e-5, varianceAngle = 1e-5)

Here, measurement values are obtained according to:

\[ \begin{aligned} + z_{\Re(\bar{V}_i)} = z_{V_i} \cos z_{\theta_i}\\ + z_{\Im(\bar{V}_i)} = z_{V_i} \sin z_{\theta_i}. + \end{aligned}\]

Utilizing the classical theory of propagation of uncertainty [16], the variances can be calculated as follows:

\[ \begin{aligned} + v_{\Re(\bar{V}_i)} &= + v_{V_i} \left[ \cfrac{\mathrm \partial} {\mathrm \partial z_{V_i}} (z_{V_i} \cos z_{\theta_i}) \right]^2 + + v_{\theta_i} \left[ \cfrac{\mathrm \partial} {\mathrm \partial z_{\theta_i}} (z_{V_i} \cos z_{\theta_i})\right]^2 = + v_{V_i} (\cos z_{\theta_i})^2 + v_{\theta_i} (z_{V_i} \sin z_{\theta_i})^2\\ + v_{\Im(\bar{V}_i)} &= + v_{V_i} \left[ \cfrac{\mathrm \partial} {\mathrm \partial z_{V_i}} (z_{V_i} \sin z_{\theta_i}) \right]^2 + + v_{\theta_i} \left[ \cfrac{\mathrm \partial} {\mathrm \partial z_{\theta_i}} (z_{V_i} \sin z_{\theta_i})\right]^2 = + v_{V_i} (\sin z_{\theta_i})^2 + v_{\theta_i} (z_{V_i} \cos z_{\theta_i})^2. + \end{aligned}\]

Lastly, the functions defining the bus voltage phasor measurement are:

\[ \begin{aligned} + h_{\Re(\bar{V}_i)}(\mathbf x) &= \Re(\bar{V}_i)\\ + h_{\Im(\bar{V}_i)}(\mathbf x) &= \Im(\bar{V}_i). + \end{aligned}\]

The coefficient expressions for measurement functions are as follows:

\[ \cfrac{\mathrm \partial{h_{\Re(\bar{V}_i)}(\mathbf x)}}{\mathrm \partial \Re(\bar{V}_i)}=1, \;\;\; + \cfrac{\mathrm \partial{h_{\Im(\bar{V}_i)}(\mathbf x)}}{\mathrm \partial \Im(\bar{V}_i)}=1.\;\;\;\]

In the previous example, the user neglected the covariances between the real and imaginary parts of the measurement. However, if desired, the user can also include them in the state estimation model by specifying the covariances of the vector:

\[ \mathbf{w} = [w_{\Re(\bar{V}_{i})}, w_{\Im(\bar{V}_{i})}].\]

addPmu!(system, device; label = "V₃, θ₃", bus = 3, magnitude = 0.9, angle = -0.2,
+varianceMagnitude = 1e-5, varianceAngle = 1e-5, correlated = true)

Then, the covariances are obtained as follows:

\[ w_{\Re(\bar{V}_{i})} = w_{\Im(\bar{V}_{i})} = + v_{V_i} \cfrac{\mathrm \partial} {\mathrm \partial z_{V_i}} (z_{V_i} \cos z_{\theta_i}) + \cfrac{\mathrm \partial} {\mathrm \partial z_{V_i}} (z_{V_i} \sin z_{\theta_i}) + + v_{\theta_i} \cfrac{\mathrm \partial} {\mathrm \partial z_{\theta_i}} (z_{V_i} \cos z_{\theta_i}) + \cfrac{\mathrm \partial} {\mathrm \partial z_{\theta_i}} (z_{V_i} \sin z_{\theta_i}),\]

which results in the solution:

\[ w_{\Re(\bar{V}_{i})} = w_{\Im(\bar{V}_{i})} = \cos z_{\theta_i} \sin z_{\theta_i}(v_{V_i} - v_{\theta_i} z_{V_i}^2).\]


From-Bus End Current Phasor Measurements

If the user chooses to include phasor measurement $(I_{ij}, \psi_{ij}) \in \bar{\mathcal{P}}$ in the state estimation model, the user will specify the measurement values, variances, and measurement functions of vectors:

\[ \mathbf{z} = [z_{\Re(\bar{I}_{ij})}, z_{\Im(\bar{I}_{ij})}], \;\;\; \mathbf{v} = [v_{\Re(\bar{I}_{ij})}, v_{\Im(\bar{I}_{ij})}], \;\;\; \mathbf{h}(\mathbf {x}) = [h_{\Re(\bar{I}_{ij})}(\mathbf {x}), h_{\Im(\bar{I}_{ij})}(\mathbf {x})].\]

For example:

addPmu!(system, device; label = "I₂₃, ψ₂₃", from = 3, magnitude = 0.3, angle = 0.4,
+varianceMagnitude = 1e-3, varianceAngle = 1e-4)

Here, measurement values are obtained according to:

\[ \begin{aligned} + z_{\Re(\bar{I}_{ij})} = z_{I_{ij}} \cos z_{\psi_{ij}}\\ + z_{\Im(\bar{I}_{ij})} = z_{I_{ij}} \sin z_{\psi_{ij}}. + \end{aligned}\]

Utilizing the classical theory of propagation of uncertainty [16], the variances can be calculated as follows:

\[ \begin{aligned} + v_{\Re(\bar{I}_{ij})} & = v_{I_{ij}} (\cos z_{\psi_{ij}})^2 + v_{\psi_{ij}} (z_{I_{ij}} \sin z_{\psi_{ij}})^2 \\ + v_{\Im(\bar{I}_{ij})} &= v_{I_{ij}} (\sin z_{\psi_{ij}})^2 + v_{\psi_{ij}} (z_{I_{ij}} \cos z_{\psi_{ij}})^2. + \end{aligned}\]

The functions defining the current phasor measurement at the from-bus end are:

\[ \begin{aligned} + h_{\Re(\bar{I}_{ij})}(\mathbf x) &= A \Re(\bar{V}_i) - B \Im(\bar{V}_i) - \left(C \cos\phi_{ij} - D \sin \phi_{ij}\right) \Re(\bar{V}_j) + \left(C\sin \phi_{ij} + D\cos \phi_{ij} \right) \Im(\bar{V}_j) \\ + h_{\Im(\bar{I}_{ij})}(\mathbf x) &= B \Re(\bar{V}_i) + A \Im(\bar{V}_i) - \left(C \sin \phi_{ij} + D \cos\phi_{ij}\right) \Re(\bar{V}_j) - \left(C\cos \phi_{ij} - D\sin \phi_{ij} \right)\Im(\bar{V}_j), + \end{aligned}\]

where:

\[ \begin{aligned} + A = \cfrac{g_{ij} + g_{\text{s}ij}}{\tau_{ij}^2},\;\;\; + B = \cfrac{b_{ij}+b_{\text{s}ij}} {\tau_{ij}^2},\;\;\; + C = \cfrac{g_{ij}}{\tau_{ij}},\;\;\; + D = \cfrac{b_{ij}}{\tau_{ij}}. + \end{aligned}\]

The coefficient expressions for measurement functions are as follows:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{\Re(\bar{I}_{ij})}(\mathbf x)}}{\mathrm \partial \Re(\bar{V}_i)} &= + \cfrac{\mathrm \partial{h_{\Im(\bar{I}_{ij})}(\mathbf x)}}{\mathrm \partial \Im(\bar{V}_i)} = A \\ + \cfrac{\mathrm \partial{h_{\Re(\bar{I}_{ij})}(\mathbf x)}} {\mathrm \partial \Re(\bar{V}_j)} &= + \cfrac{\mathrm \partial{h_{\Im(\bar{I}_{ij})}(\mathbf x)}} {\mathrm \partial \Im(\bar{V}_j)} = + - \left(C \cos\phi_{ij} - D \sin \phi_{ij}\right)\\ + \cfrac{\mathrm \partial{h_{\Re(\bar{I}_{ij})}(\mathbf x)}}{\mathrm \partial \Im(\bar{V}_i)} &=- + \cfrac{\mathrm \partial{h_{\Im(\bar{I}_{ij})}(\mathbf x)}}{\mathrm \partial \Re(\bar{V}_i)} = + -B \\ + \cfrac{\mathrm \partial{h_{\Re(\bar{I}_{ij})}(\mathbf x)}}{\mathrm \partial \Im(\bar{V}_j)} &= - + \cfrac{\mathrm \partial{h_{\Im(\bar{I}_{ij})}(\mathbf x)}}{\mathrm \partial\Re(\bar{V}_j)} = + \left(C\sin \phi_{ij} + D \cos \phi_{ij} \right). + \end{aligned}\]

In the previous example, the user neglects the covariances between the real and imaginary parts of the measurement. However, if desired, the user can also include them in the state estimation model by specifying the covariances of the vector:

\[ \mathbf{w} = [w_{\Re(\bar{I}_{ij})}, w_{\Im(\bar{I}_{ij})}].\]

addPmu!(system, device; label = "I₁₃, ψ₁₃", from = 2, magnitude = 0.3, angle = -0.5,
+varianceMagnitude = 1e-5, varianceAngle = 1e-5, correlated = true)

Then, the covariances are obtained as follows:

\[ w_{\Re(\bar{I}_{ij})} = w_{\Im(\bar{I}_{ij})} = \sin z_{\psi_{ij}} \cos z_{\psi_{ij}}(v_{I_{ij}} - v_{\psi_{ij}} z_{I_{ij}}^2).\]


To-Bus End Current Phasor Measurements

If the user chooses to include phasor measurement $(I_{ji}, \psi_{ji}) \in \bar{\mathcal{P}}$ in the state estimation model, the user will specify the measurement values, variances, and measurement functions of vectors:

\[ \mathbf{z} = [z_{\Re(\bar{I}_{ji})}, z_{\Im(\bar{I}_{ji})}], \;\;\; \mathbf{v} = [v_{\Re(\bar{I}_{ji})}, v_{\Im(\bar{I}_{ji})}], \;\;\; \mathbf{h}(\mathbf {x}) = [h_{\Re(\bar{I}_{ji})}(\mathbf {x}), h_{\Im(\bar{I}_{ji})}(\mathbf {x})].\]

For example:

addPmu!(system, device; label = "I₃₂, ψ₃₂", to = 3, magnitude = 0.3, angle = -2.9,
+varianceMagnitude = 1e-5, varianceAngle = 1e-5)

Here, measurement values are obtained according to:

\[ \begin{aligned} + z_{\Re(\bar{I}_{ji})} = z_{I_{ji}} \cos z_{\psi_{ji}}\\ + z_{\Im(\bar{I}_{ji})} = z_{I_{ji}} \sin z_{\psi_{ji}}. + \end{aligned}\]

The variances can be calculated as follows:

\[ \begin{aligned} + v_{\Re(\bar{I}_{ji})} &= v_{I_{ji}} (\cos z_{\psi_{ji}})^2 + v_{\psi_{ji}} (z_{I_{ji}} \sin z_{\psi_{ji}})^2 \\ + v_{\Im(\bar{I}_{ji})} &= v_{I_{ji}} (\sin z_{\psi_{ji}})^2 + v_{\psi_{ji}} (z_{I_{ji}} \cos z_{\psi_{ji}})^2. + \end{aligned}\]

The functions defining the current phasor measurement at the to-bus end are:

\[ \begin{aligned} + h_{\Re(\bar{I}_{ji})}(\mathbf x) &= \tau_{ij}^2 A \Re(\bar{V}_j) - \tau_{ij}^2 B \Im(\bar{V}_j) - \left(C \cos\phi_{ij} + D \sin \phi_{ij}\right) \Re(\bar{V}_i) - \left( C\sin \phi_{ij} - D\cos \phi_{ij} \right) \Im(\bar{V}_i)\\ + h_{\Im(\bar{I}_{ji})}(\mathbf x) &= \tau_{ij}^2 B \Re(\bar{V}_j) + \tau_{ij}^2 A \Im(\bar{V}_j) + \left(C \sin \phi_{ij} - D \cos\phi_{ij} \right) \Re(\bar{V}_i) - \left(C\cos \phi_{ij} + D\sin \phi_{ij}\right) \Im(\bar{V}_i). + \end{aligned}\]

The coefficient expressions for measurement functions are as follows:

\[ \begin{aligned} + \cfrac{\mathrm \partial{h_{\Re(\bar{I}_{ji})}(\mathbf x)}}{\mathrm \partial \Re(\bar{V}_i)} &= + \cfrac{\mathrm \partial{h_{\Im(\bar{I}_{ji})}(\mathbf x)}}{\mathrm \partial \Im(\bar{V}_i)} = + - \left(C \cos\phi_{ij} + D \sin \phi_{ij}\right)\\ + \cfrac{\mathrm \partial{h_{\Re(\bar{I}_{ji})}(\mathbf x)}} {\mathrm \partial \Re(\bar{V}_j)} &= + \cfrac{\mathrm \partial{h_{\Im(\bar{I}_{ji})}(\mathbf x)}} {\mathrm \partial \Im(\bar{V}_j)} = \tau_{ij}^2A\\ + \cfrac{\mathrm \partial{h_{\Re(\bar{I}_{ji})}(\mathbf x)}}{\mathrm \partial \Im(\bar{V}_i)} &= - + \cfrac{\mathrm \partial{h_{\Im(\bar{I}_{ji})}(\mathbf x)}}{\mathrm \partial \Re(\bar{V}_i)} = + -\left(C\sin \phi_{ij} - D\cos \phi_{ij} \right) \\ + \cfrac{\mathrm \partial{h_{\Re(\bar{I}_{ji})}(\mathbf x)}}{\mathrm \partial \Im(\bar{V}_j)} &= - + \cfrac{\mathrm \partial{h_{\Im(\bar{I}_{ji})}(\mathbf x)}}{\mathrm \partial \Re(\bar{V}_j)} = + -\tau_{ij}^2B. + \end{aligned}\]

As before, we are neglecting the covariances between the real and imaginary parts of the measurement. If desired, we can include them in the state estimation model by specifying the covariances of the vector:

\[ \mathbf{w} = [w_{\Re(\bar{I}_{ji})}, w_{\Im(\bar{I}_{ji})}].\]

addPmu!(system, device; label = "I₃₁, ψ₃₁", to = 2, magnitude = 0.3, angle = 2.5,
+varianceMagnitude = 1e-5, varianceAngle = 1e-5, correlated = true)

Then, the covariances are obtained as follows:

\[ w_{\Re(\bar{I}_{ji})} = w_{\Im(\bar{I}_{ji})} = \sin z_{\psi_{ji}} \cos z_{\psi_{ji}}(v_{I_{ji}} - v_{\psi_{ji}} z_{I_{ji}}^2).\]


Weighted Least-Squares Estimation

The solution to the PMU state estimation problem is determined by solving the linear weighted least-squares (WLS) problem, represented by the following formula:

\[ \mathbf H^{T} \bm \Sigma^{-1} \mathbf H \mathbf x = \mathbf H^{T} \bm \Sigma^{-1} \mathbf z.\]

Here, $\mathbf z \in \mathbb {R}^{k}$ denotes the vector of measurement values, $\mathbf {H} \in \mathbb {R}^{k \times 2n}$ represents the coefficient matrix, and $\bm \Sigma \in \mathbb {R}^{k \times k}$ is the measurement error covariance matrix.


Implementation

JuliaGrid initiates the PMU state estimation framework by setting up the WLS model, as illustrated in the following:

analysis = pmuStateEstimation(system, device)

Coefficient Matrix

Using the above-described equations, JuliaGrid forms the coefficient matrix $\mathbf{H} \in \mathbb{R}^{k \times 2n}$:

julia> 𝐇 = analysis.method.coefficient12×6 SparseArrays.SparseMatrixCSC{Float64, Int64} with 36 stored entries:
+   ⋅         1.0        ⋅          ⋅          ⋅         ⋅
+   ⋅          ⋅         ⋅          ⋅         1.0        ⋅
+   ⋅          ⋅        1.0         ⋅          ⋅         ⋅
+   ⋅          ⋅         ⋅          ⋅          ⋅        1.0
+   ⋅         0.49505  -0.49505     ⋅         4.9305   -4.9505
+   ⋅        -4.9305    4.9505      ⋅         0.49505  -0.49505
+  0.040783    ⋅       -0.040783   1.40741     ⋅       -1.42741
+ -1.40741     ⋅        1.42741    0.040783    ⋅       -0.040783
+   ⋅        -0.49505   0.49505     ⋅        -4.9505    4.9305
+   ⋅         4.9505   -4.9305      ⋅        -0.49505   0.49505
+ -0.040783    ⋅        0.040783  -1.42741     ⋅        1.40741
+  1.42741     ⋅       -1.40741   -0.040783    ⋅        0.040783

In this matrix, each row corresponds to a specific measurement in the rectangular coordinate system. Therefore, the $i$-th PMU is associated with the $2i - 1$ index of the row, representing the real part of the phasor measurement, while the $2i$ row corresponds to the imaginary part of the phasor measurement. Columns are ordered based on how the state variables are defined $\mathbf x \equiv[\mathbf{V}_\text{re},\mathbf{V}_\text{im}]$.


Precision Matrix

JuliaGrid opts not to retain the covariance matrix $\bm \Sigma$ but rather stores its inverse, the precision or weighting matrix denoted as $\mathbf W = \bm \Sigma^{-1}$. The order of these values corresponds to the description provided for the coefficient matrix. Users can access these values using the following command:

julia> 𝐖 = analysis.method.precision12×12 SparseArrays.SparseMatrixCSC{Float64, Int64} with 18 stored entries:
+ 1.0019e5   ⋅             ⋅         …   ⋅          ⋅          ⋅
+  ⋅        1.23169e5      ⋅             ⋅          ⋅          ⋅
+  ⋅         ⋅            1.00926e5      ⋅          ⋅          ⋅
+  ⋅         ⋅         4567.25           ⋅          ⋅          ⋅
+  ⋅         ⋅             ⋅             ⋅          ⋅          ⋅
+  ⋅         ⋅             ⋅         …   ⋅          ⋅          ⋅
+  ⋅         ⋅             ⋅             ⋅          ⋅          ⋅
+  ⋅         ⋅             ⋅             ⋅          ⋅          ⋅
+  ⋅         ⋅             ⋅             ⋅          ⋅          ⋅
+  ⋅         ⋅             ⋅            7.03786e5   ⋅          ⋅
+  ⋅         ⋅             ⋅         …   ⋅         4.62149e5  4.84789e5
+  ⋅         ⋅             ⋅             ⋅         4.84789e5  7.48963e5

The precision matrix does not maintain a diagonal form, indicating that correlations between the real and imaginary parts of the phasor measurements are included in the model. To ignore these correlations, simply omit the correlated keyword within the function that adds a PMU. For example:

device = measurement()
+
+@pmu(label = "PMU ?", noise = false)
+addPmu!(system, device; bus = 1, magnitude = 1.0, angle = 0.0)
+addPmu!(system, device; bus = 2, magnitude = 0.87, angle = -0.15)
+addPmu!(system, device; from = 1, magnitude = 0.30, angle = -0.71)
+addPmu!(system, device; from = 2, magnitude = 0.31, angle = -0.49)

Following this, we recreate the WLS state estimation model:

analysis = pmuStateEstimation(system, device)

Upon inspection, it becomes evident that the precision matrix maintains a diagonal structure:

julia> 𝐖 = analysis.method.precision8×8 SparseArrays.SparseMatrixCSC{Float64, Int64} with 8 stored entries:
+ 100000.0        ⋅    ⋅               ⋅   …   ⋅          ⋅          ⋅
+       ⋅   100000.0   ⋅               ⋅       ⋅          ⋅          ⋅
+       ⋅         ⋅   1.00546e5        ⋅       ⋅          ⋅          ⋅
+       ⋅         ⋅    ⋅         131177.0      ⋅          ⋅          ⋅
+       ⋅         ⋅    ⋅               ⋅       ⋅          ⋅          ⋅
+       ⋅         ⋅    ⋅               ⋅   …  2.09799e5   ⋅          ⋅
+       ⋅         ⋅    ⋅               ⋅       ⋅         1.25032e5   ⋅
+       ⋅         ⋅    ⋅               ⋅       ⋅          ⋅         3.37492e5

Mean Vector

To retrieve the vector $\mathbf z$, containing the means of Gaussian distributions for each measurement, users can utilize:

julia> 𝐳 = analysis.method.mean8-element Vector{Float64}:
+  1.0
+  0.0
+  0.8602308378043567
+ -0.13001117525203132
+  0.22750856279715245
+ -0.19555013130646098
+  0.2735231861691376
+ -0.14589402533305898

These values represent measurement values in the rectangular coordinate system as described earlier.


Estimate of State Variables

Next, the WLS equation is solved to obtain the estimate of state variables:

\[ \hat{\mathbf x} = [\mathbf H^{T} \bm \Sigma^{-1} \mathbf H]^{-1} \mathbf H^{T} \bm \Sigma^{-1} \mathbf z.\]

This process is executed using the solve! function:

solve!(system, analysis)

The initial step involves the LU factorization of the gain matrix:

\[ \mathbf G = \mathbf H^{T} \bm \Sigma^{-1} \mathbf H = \mathbf L \mathbf U.\]

Tip

By default, JuliaGrid utilizes LU factorization as the primary method to factorize the gain matrix. However, users maintain the flexibility to opt for alternative factorization methods such as LDLt or QR.

Access to the factorized gain matrix is available through:

julia> 𝐋 = analysis.method.factorization.L6×6 SparseArrays.SparseMatrixCSC{Float64, Int64} with 17 stored entries:
+  1.0          ⋅            ⋅           ⋅            ⋅         ⋅
+ -0.0470534   1.0           ⋅           ⋅            ⋅         ⋅
+ -0.522908   -8.10654e-5   1.0          ⋅            ⋅         ⋅
+   ⋅           ⋅          -1.78244     1.0           ⋅         ⋅
+   ⋅           ⋅           0.0154393  -0.00521047   1.0        ⋅
+  0.0165651  -0.344281    -0.0110068   0.0036689   -0.522906  1.0
julia> 𝐔 = analysis.method.factorization.U6×6 SparseArrays.SparseMatrixCSC{Float64, Int64} with 17 stored entries: + 0.494535 -0.00889224 -0.487608 ⋅ ⋅ 0.00896556 + ⋅ 0.479929 -0.000191972 ⋅ ⋅ -0.47321 + ⋅ ⋅ 0.25474 -0.219243 0.00155842 -0.00162742 + ⋅ ⋅ ⋅ 0.148187 -0.000633631 0.000653543 + ⋅ ⋅ ⋅ ⋅ 0.561653 -0.430201 + ⋅ ⋅ ⋅ ⋅ ⋅ 0.130906

Finally, JuliaGrid obtains the solution in the rectangular coordinate system and then transforms these solutions into the standard form given in the polar coordinate system.

The estimated bus voltage magnitudes $\hat{\mathbf V} = [\hat{V}_i]$ and angles $\hat{\bm {\Theta}} = [\hat{\theta}_i]$, $i \in \mathcal{N}$, can be retrieved using the variables:

julia> 𝐕 = analysis.voltage.magnitude3-element Vector{Float64}:
+ 0.9972846475719777
+ 0.8728310555274105
+ 0.89548122281777
julia> 𝚯 = analysis.voltage.angle3-element Vector{Float64}: + 0.0011070674719133831 + -0.1504959040059231 + -0.21044407465996606
Info

It is essential to note that the slack bus does not exist in the case of the PMU state estimation model.


Alternative Formulation

The resolution of the WLS state estimation problem using the conventional method typically progresses smoothly. However, it is widely acknowledged that in certain situations common to real-world systems, this method can be vulnerable to numerical instabilities. Such conditions might impede the algorithm from converging to a satisfactory solution. In such cases, users may opt for an alternative formulation of the WLS state estimation, namely, employing an approach called orthogonal factorization [5, Sec. 3.2]. This approach is suitable when measurement errors are uncorrelated, and the precision matrix remains diagonal.

To address ill-conditioned situations arising from significant differences in measurement variances, users can employ an alternative approach:

analysis = pmuStateEstimation(system, device, Orthogonal)

To explain the method, we begin with the WLS equation:

\[ \mathbf H^{T} \mathbf W \mathbf H \hat{\mathbf x} = \mathbf H^{T} \mathbf W \mathbf z,\]

where $\mathbf W = \bm \Sigma^{-1}$. Subsequently, we can write:

\[ \left({\mathbf W^{1/2}} \mathbf H\right)^{T} {\mathbf W^{1/2}} \mathbf H \hat{\mathbf x} = \left({\mathbf W^{1/2}} \mathbf H\right)^{T} {\mathbf W^{1/2}} \mathbf z.\]

Consequently, we have:

\[ \bar{\mathbf{H}}^{T} \bar{\mathbf{H}} \hat{\mathbf x} = \bar{\mathbf{H}}^{T} \bar{\mathbf{z}},\]

where:

\[ \bar{\mathbf{H}} = {\mathbf W^{1/2}} \mathbf H; \;\;\; \bar{\mathbf{z}} = {\mathbf W^{1/2}} \mathbf z.\]

At this point, QR factorization is performed on the rectangular matrix:

\[ \bar{\mathbf{H}} = {\mathbf W^{1/2}} \mathbf H = \mathbf{Q}\mathbf{R}.\]

Executing this procedure involves the solve! function:

solve!(system, analysis)

Access to the factorized matrix is possible through:

julia> 𝐐 = analysis.method.factorization.Q8×8 SparseArrays.SPQR.QRSparseQ{Float64, Int64}
julia> 𝐑 = analysis.method.factorization.R6×6 SparseArrays.SparseMatrixCSC{Float64, Int64} with 21 stored entries: + -1156.2 497.316 14.2388 -3.53502 586.583 -10.4591 + ⋅ 659.702 -3.91115 -3.88362 -442.195 7.88459 + ⋅ ⋅ -888.673 503.067 -2.68756 283.077 + ⋅ ⋅ ⋅ -574.977 -2.97106 247.685 + ⋅ ⋅ ⋅ ⋅ -384.983 3.24637 + ⋅ ⋅ ⋅ ⋅ ⋅ -337.119

To obtain the solution, JuliaGrid avoids materializing the orthogonal matrix $\mathbf{Q}$ and proceeds to solve the system, resulting in the estimate of bus voltage magnitudes $\hat{\mathbf V} = [\hat{V}_i]$ and angles $\hat{\bm {\Theta}} = [\hat{\theta}_i]$, where $i \in \mathcal{N}$:

julia> 𝐕 = analysis.voltage.magnitude3-element Vector{Float64}:
+ 0.9972846475719777
+ 0.8728310555274102
+ 0.89548122281777
julia> 𝚯 = analysis.voltage.angle3-element Vector{Float64}: + 0.001107067471913468 + -0.15049590400592316 + -0.21044407465996595

Bad Data Processing

Besides the state estimation algorithm, one of the essential state estimation routines is the bad data processing, whose main task is to detect and identify measurement errors, and eliminate them if possible. This is usually done by processing the measurement residuals [5, Ch. 5], and typically, the largest normalized residual test is used to identify bad data. The largest normalized residual test is performed after we obtained the solution of the state estimation in the repetitive process of identifying and eliminating bad data measurements one after another [19].

To illustrate this process, let us introduce a new measurement that contains an obvious outlier:

addPmu!(system, device; bus = 3, magnitude = 2.5, angle = 0.1)

Subsequently, we will construct the WLS state estimation model and solve it:

analysis = pmuStateEstimation(system, device)
+solve!(system, analysis)

Now, the bad data processing can be executed:

outlier = residualTest!(system, device, analysis; threshold = 4.0)

In this step, we employ the largest normalized residual test, guided by the analysis outlined in [5, Sec. 5.7]. To be more precise, we compute all measurement residuals in the rectangular coordinate system based on the obtained estimate of state variables:

\[ r_{i} = z_i - h_i(\hat {\mathbf x}), \;\;\; i \in \mathcal{M}.\]

The normalized residuals for all measurements are computed as follows:

\[ \bar{r}_{i} = \cfrac{|r_i|}{\sqrt{C_{ii}}} = \cfrac{|r_i|}{\sqrt{S_{ii}\Sigma_{ii}}}, \;\;\; i \in \mathcal{M}.\]

In this equation, we denote the diagonal entries of the residual covariance matrix $\mathbf C \in \mathbb{R}^{k \times k}$ as $C_{ii} = S_{ii}\Sigma_{ii}$, where $S_{ii}$ is the diagonal entry of the residual sensitivity matrix $\mathbf S$ representing the sensitivity of the measurement residuals to the measurement errors. For this specific configuration, the relationship is expressed as:

\[ \mathbf C = \mathbf S \bm \Sigma = \bm \Sigma - \mathbf H [\mathbf H^T \bm \Sigma^{-1} \mathbf H]^{-1} \mathbf H^T.\]

It is important to note that only the diagonal entries of $\mathbf C$ are required. To obtain the inverse, the JuliaGrid package utilizes a computationally efficient sparse inverse method, retrieving only the necessary elements of the inverse.

The subsequent step involves selecting the largest normalized residual, and the $j$-th measurement is then suspected as bad data and potentially removed from the measurement set $\mathcal{M}$:

\[ \bar{r}_{j} = \text{max} \{\bar{r}_{i}, i \in \mathcal{M} \}.\]

Users can access this information using the variable:

julia> outlier.maxNormalizedResidual387.72710598252246

If the largest normalized residual, denoted as $\bar{r}_{j}$, satisfies the inequality:

\[ \bar{r}_{j} \ge \epsilon,\]

the corresponding measurement is identified as bad data and subsequently removed. In this example, the bad data identification threshold is set to $\epsilon = 4$. Users can verify the satisfaction of this inequality by inspecting:

julia> outlier.detecttrue

This indicates that the measurement labeled as:

julia> outlier.label"PMU 5"

is removed from the PMU model and marked as out-of-service. Specifically, either the real or imaginary part of the corresponding measurement is identified as the outlier. Consequently, both parts of the measurement are removed from the PMU state estimation model.

Subsequently, we can immediately solve the system again, but this time without the removed measurement:

solve!(system, analysis)

Following that, we check for outliers once more:

outlier = residualTest!(system, device, analysis; threshold = 4.0)

To examine the value:

julia> outlier.maxNormalizedResidual1.289041523534379

As this value is now less than the threshold $\epsilon = 4$, the measurement is not removed, or there are no outliers. This can also be verified by observing the bad data flag:

julia> outlier.detectfalse

Least Absolute Value Estimation

The least absolute value (LAV) method provides an alternative estimation approach that is considered more robust in comparison to the WLS method. The WLS state estimation problem relies on specific assumptions about measurement errors, whereas robust estimators aim to remain unbiased even in the presence of various types of measurement errors and outliers. This characteristic eliminates the need for bad data processing, as discussed in [5, Ch. 6]. It is important to note that robustness often comes at the cost of increased computational complexity.

It can be demonstrated that the problem can be expressed as a linear programming problem. This section outlines the method as described in [5, Sec. 6.5]. To revisit, we consider the system of linear equations:

\[ \mathbf{z}=\mathbf{h}(\mathbf x)+\mathbf{u}+\mathbf{w}.\]

Subsequently, the LAV state estimator is derived as the solution to the optimization problem:

\[ \begin{aligned} + \text{minimize}& \;\;\; \mathbf a^T |\mathbf r|\\ + \text{subject\;to}& \;\;\; \mathbf{z} - \mathbf{H} \mathbf x =\mathbf r. + \end{aligned}\]

Here, $\mathbf a \in \mathbb {R}^{k}$ is the vector with all entries equal to one, and $\mathbf r$ represents the vector of measurement residuals. Let $\bm \eta$ be defined in a manner that ensures:

\[ |\mathbf r| \preceq \bm \eta,\]

and replace the above inequality with two equalities using the introduction of two non-negative slack variables $\mathbf q \in \mathbb {R}_{\ge 0}^{k}$ and $\mathbf w \in \mathbb {R}_{\ge 0}^{k}$:

\[ \begin{aligned} + \mathbf r - \mathbf q &= -\bm \eta \\ + \mathbf r + \mathbf w &= \bm \eta. + \end{aligned}\]

Let us now define four additional non-negative variables:

\[ \mathbf x_x \in \mathbb {R}_{\ge 0}^{n}, \;\;\; \mathbf x_y \in \mathbb {R}_{\ge 0}^{n}, \;\;\; + \mathbf {r}_x \in \mathbb {R}_{\ge 0}^{k}, \;\;\; \mathbf {r}_y \in \mathbb {R}_{\ge 0}^{k},\]

where:

\[ \mathbf x = \mathbf x_x - \mathbf x_y, \;\;\; \mathbf r = \mathbf {r}_x - \mathbf {r}_y\\ + \mathbf {r}_x = \cfrac{1}{2} \mathbf q, \;\;\; \mathbf {r}_y = \cfrac{1}{2} \mathbf w.\]

Then, the above two equalities become:

\[ \begin{aligned} + \mathbf r - 2\mathbf {r}_x &= -2\bm \eta \\ + \mathbf r + 2 \mathbf {r}_y &= 2\bm \eta, + \end{aligned}\]

that is:

\[ \begin{aligned} + \mathbf {r}_x + \mathbf {r}_y = \bm \eta, \;\;\; \mathbf r = \mathbf {r}_x - \mathbf {r}_y. + \end{aligned}\]

Hence, the optimization problem can be written:

\[ \begin{aligned} + \text{minimize}& \;\;\; \mathbf a^T (\mathbf {r}_x + \mathbf {r}_y)\\ + \text{subject\;to}& \;\;\; \mathbf{H}(\mathbf x_x - \mathbf x_y) + \mathbf {r}_x - \mathbf {r}_y = \mathbf{z} \\ + & \;\;\; \mathbf x_x \succeq \mathbf 0, \; \mathbf x_y \succeq \mathbf 0 \\ + & \;\;\; \mathbf {r}_x \succeq \mathbf 0, \; \mathbf {r}_y \succeq \mathbf 0. + \end{aligned}\]

To form the above optimization problem, the user can call the following function:

using Ipopt
+
+analysis = pmuLavStateEstimation(system, device, Ipopt.Optimizer)

Then the user can solve the optimization problem by:

solve!(system, analysis)

As a result, we obtain optimal values for the four additional non-negative variables, while the state estimator is obtained by:

\[ \hat{\mathbf x} = \mathbf x_x - \mathbf x_y.\]

Users can retrieve the estimated bus voltage magnitudes $\hat{\mathbf V} = [\hat{V}_i]$ and angles $\hat{\bm {\Theta}} = [\hat{\theta}_i]$, $i \in \mathcal{N}$, using:

julia> 𝐕 = analysis.voltage.magnitude3-element Vector{Float64}:
+ 0.9999997979268984
+ 0.876149703513198
+ 0.8983275932436058
julia> 𝚯 = analysis.voltage.angle3-element Vector{Float64}: + 2.1386863183370526e-7 + -0.15145892724417714 + -0.21100496414278708

Optimal PMU Placement

JuliaGrid utilizes the optimal PMU placement algorithm proposed in [23]. The optimal positioning of PMUs is framed as an integer linear programming problem, expressed as:

\[ \begin{aligned} + \text{minimize}& \;\;\; \sum_{i=1}^n d_i\\ + \text{subject\;to}& \;\;\; \mathbf A \mathbf d \ge \mathbf a. + \end{aligned}\]

Here, the vector $\mathbf d = [d_1,\dots,d_n]^T$ serves as the optimization variable, where $d_i \in \mathbb{F} = \{0,1\}$ is the PMU placement or a binary decision variable associated with the bus $i \in \mathcal{N}$. The all-one vector $\mathbf a$ is of dimension $n$. The binary connectivity matrix $\mathbf A \in \mathbb{F}^{n \times n}$ can be directly derived from the bus nodal matrix $\mathbf Y$ by converting its entries into binary form [24].

Consequently, we obtain the binary vector $\mathbf d = [d_1,\dots,d_n]^T$, where $d_i = 1$, $i \in \mathcal{N}$, suggests that a PMU should be placed at bus $i$. The primary aim of PMU placement in the power system is to determine a minimal set of PMUs such that the entire system is observable without relying on traditional measurements [23]. Specifically, when we observe $d_i = 1$, it indicates that the PMU is installed at bus $i \in \mathcal{N}$ to measure bus voltage phasor as well as all current phasors across branches incident to bus $i$.

Determining the optimal PMU placement involves analyzing the created power system. For example:

using GLPK
+
+system = powerSystem()
+
+addBus!(system; label = 1, type = 3, active = 0.5)
+addBus!(system; label = 2, type = 1, reactive = 0.3)
+addBus!(system; label = 3, type = 1, active = 0.5)
+
+@branch(resistance = 0.02, susceptance = 0.04)
+addBranch!(system; label = 1, from = 1, to = 2, reactance = 0.6)
+addBranch!(system; label = 2, from = 1, to = 2, reactance = 0.7)
+addBranch!(system; label = 3, from = 2, to = 3, reactance = 0.2)
+
+addGenerator!(system; label = 1, bus = 1, active = 3.2, reactive = 0.2)
+
+acModel!(system)
+placement = pmuPlacement(system, GLPK.Optimizer)

The placement variable contains data regarding the optimal placement of measurements. It lists all buses $i \in \mathcal{N}$ that satisfy $d_i = 1$:

julia> placement.busOrderedCollections.OrderedDict{String, Int64} with 1 entry:
+  "2" => 2

This PMU installed at bus 2 will measure the bus voltage phasor at the corresponding bus and all current phasors at the branches incident to bus 2 located at the from-bus or to-bus ends. These data are stored in the variables:

julia> placement.fromOrderedCollections.OrderedDict{String, Int64} with 1 entry:
+  "3" => 3
julia> placement.toOrderedCollections.OrderedDict{String, Int64} with 2 entries: + "1" => 1 + "2" => 2

Power Analysis

Once the computation of voltage magnitudes and angles at each bus is completed, various electrical quantities can be determined. JuliaGrid offers the power! function, which enables the calculation of powers associated with buses and branches. Here is an example code snippet demonstrating its usage:

power!(system, analysis)

The function stores the computed powers in the rectangular coordinate system. It calculates the following powers related to buses and branches:

BusActiveReactive
Injections$\mathbf{P} = [P_i]$$\mathbf{Q} = [Q_i]$
Generator injections$\mathbf{P}_{\text{p}} = [P_{\text{p}i}]$$\mathbf{Q}_{\text{p}} = [Q_{\text{p}i}]$
Shunt elements$\mathbf{P}_{\text{sh}} = [{P}_{\text{sh}i}]$$\mathbf{Q}_{\text{sh}} = [{Q}_{\text{sh}i}]$
BranchActiveReactive
From-bus end flows$\mathbf{P}_{\text{i}} = [P_{ij}]$$\mathbf{Q}_{\text{i}} = [Q_{ij}]$
To-bus end flows$\mathbf{P}_{\text{j}} = [P_{ji}]$$\mathbf{Q}_{\text{j}} = [Q_{ji}]$
Shunt elements$\mathbf{P}_{\text{s}} = [P_{\text{s}ij}]$$\mathbf{P}_{\text{s}} = [P_{\text{s}ij}]$
Series elements$\mathbf{P}_{\text{l}} = [P_{\text{l}ij}]$$\mathbf{Q}_{\text{l}} = [Q_{\text{l}ij}]$
Info

For a clear comprehension of the equations, symbols presented in this section, as well as for a better grasp of power directions, please refer to the Unified Branch Model.


Power Injections

Active and reactive power injections are stored as the vectors $\mathbf{P} = [P_i]$ and $\mathbf{Q} = [Q_i]$, respectively, and can be retrieved using the following commands:

julia> 𝐏 = analysis.power.injection.active3-element Vector{Float64}:
+  0.4216631622492523
+ -0.19530673833785805
+ -0.22132365772451618
julia> 𝐐 = analysis.power.injection.reactive3-element Vector{Float64}: + 0.3612603793317748 + -0.4503322130040679 + 0.11258234719068802

Generator Power Injections

We can calculate the active and reactive power injections supplied by generators at each bus $i \in \mathcal{N}$ by summing the active and reactive power injections and the active and reactive power demanded by consumers at each bus:

\[ \begin{aligned} + P_{\text{p}i} &= P_i + P_{\text{d}i}\\ + Q_{\text{p}i} &= Q_i + Q_{\text{d}i}. + \end{aligned}\]

The active and reactive power injections from the generators at each bus are stored as vectors, denoted by $\mathbf{P}_{\text{p}} = [P_{\text{p}i}]$ and $\mathbf{Q}_{\text{p}} = [Q_{\text{p}i}]$, which can be obtained using:

julia> 𝐏ₚ = analysis.power.supply.active3-element Vector{Float64}:
+  0.9216631622492524
+ -0.19530673833785805
+  0.2786763422754838
julia> 𝐐ₚ = analysis.power.supply.reactive3-element Vector{Float64}: + 0.3612603793317748 + -0.1503322130040679 + 0.11258234719068802

Power at Bus Shunt Elements

Active and reactive powers associated with the shunt elements at each bus are represented by the vectors $\mathbf{P}_{\text{sh}} = [{P}_{\text{sh}i}]$ and $\mathbf{Q}_{\text{sh}} = [{Q}_{\text{sh}i}]$. To retrieve these powers in JuliaGrid, use the following commands:

julia> 𝐏ₛₕ = analysis.power.shunt.active3-element Vector{Float64}:
+ 0.0
+ 0.0
+ 0.0
julia> 𝐐ₛₕ = analysis.power.shunt.reactive3-element Vector{Float64}: + -0.0 + -0.0 + -0.0

Power Flows

The resulting active and reactive power flows at each from-bus end are stored as the vectors $\mathbf{P}_{\text{i}} = [P_{ij}]$ and $\mathbf{Q}_{\text{i}} = [Q_{ij}],$ respectively, and can be retrieved using the following commands:

julia> 𝐏ᵢ = analysis.power.from.active3-element Vector{Float64}:
+ 0.22750847062127627
+ 0.19415469162797616
+ 0.2229482965705423
julia> 𝐐ᵢ = analysis.power.from.reactive3-element Vector{Float64}: + 0.19555014549544905 + 0.16571023383632527 + -0.1278285740854087

Similarly, the vectors of active and reactive power flows at the to-bus end are stored as $\mathbf{P}_{\text{j}} = [P_{ji}]$ and $\mathbf{Q}_{\text{j}} = [Q_{ji}]$, respectively, and can be retrieved using the following code:

julia> 𝐏ⱼ = analysis.power.to.active3-element Vector{Float64}:
+ -0.2255440305084955
+ -0.19271100439990477
+ -0.22132365772451618
julia> 𝐐ⱼ = analysis.power.to.reactive3-element Vector{Float64}: + -0.17196970008842855 + -0.1505339388302306 + 0.11258234719068802

Power at Branch Shunt Elements

Active and reactive powers associated with the branch shunt elements at each branch are represented by the vectors $\mathbf{P}_{\text{s}} = [P_{\text{s}ij}]$ and $\mathbf{Q}_{\text{s}} = [Q_{\text{s}ij}]$. We can retrieve these values using the following code:

julia> 𝐏ₛ = analysis.power.charging.active3-element Vector{Float64}:
+ 0.0
+ 0.0
+ 0.0
julia> 𝐐ₛ = analysis.power.charging.reactive3-element Vector{Float64}: + -0.03535275797640205 + -0.03535275797640205 + -0.03149261535498228

Power at Branch Series Elements

Active and reactive powers associated with the branch series element at each branch are represented by the vectors $\mathbf{P}_{\text{l}} = [P_{\text{l}ij}]$ and $\mathbf{Q}_{\text{l}} = [Q_{\text{l}ij}]$. We can retrieve these values using the following code:

julia> 𝐏ₗ = analysis.power.series.active3-element Vector{Float64}:
+ 0.0019644401127807513
+ 0.0014436872280713317
+ 0.0016246388460260893
julia> 𝐐ₗ = analysis.power.series.reactive3-element Vector{Float64}: + 0.05893320338342248 + 0.050529052982496686 + 0.016246388460260896

Current Analysis

JuliaGrid offers the current! function, which enables the calculation of currents associated with buses and branches. Here is an example code snippet demonstrating its usage:

current!(system, analysis)

The function stores the computed currents in the polar coordinate system. It calculates the following currents related to buses and branches:

BusMagnitudeAngle
Injections$\mathbf{I} = [I_i]$$\bm{\psi} = [\psi_i]$
BranchMagnitudeAngle
From-bus end flows$\mathbf{I}_{\text{i}} = [I_{ij}]$$\bm{\psi}_{\text{i}} = [\psi_{ij}]$
To-bus end flows$\mathbf{I}_{\text{j}} = [I_{ji}]$$\bm{\psi}_{\text{j}} = [\psi_{ji}]$
Series elements$\mathbf{I}_{\text{l}} = [I_{\text{l}ij}]$$\bm{\psi}_{\text{l}} = [\psi_{\text{l}ij}]$
Info

For a clear comprehension of the equations, symbols presented in this section, as well as for a better grasp of power directions, please refer to the Unified Branch Model.


Current Injections

In JuliaGrid, complex current injections are stored in the vector of magnitudes denoted as $\mathbf{I} = [I_i]$ and the vector of angles represented as $\bm{\psi} = [\psi_i]$. You can retrieve them using the following commands:

julia> 𝐈 = analysis.current.injection.magnitude3-element Vector{Float64}:
+ 0.5552558047196623
+ 0.5602470534871392
+ 0.2764160838803776
julia> 𝛙 = analysis.current.injection.angle3-element Vector{Float64}: + -0.7084001797708159 + 1.8285495088264339 + -2.8820321950004284

Current Flows

To obtain the vectors of magnitudes $\mathbf{I}_{\text{i}} = [I_{ij}]$ and angles $\bm{\psi}_{\text{i}} = [\psi_{ij}]$ for the resulting complex current flows, you can use the following commands:

julia> 𝐈ᵢ = analysis.current.from.magnitude3-element Vector{Float64}:
+ 0.29999999996813004
+ 0.2552566398975199
+ 0.29332239932118076
julia> 𝛙ᵢ = analysis.current.from.angle3-element Vector{Float64}: + -0.7100000222772045 + -0.7065199041778824 + 0.3691383932390542

Similarly, we can obtain the vectors of magnitudes $\mathbf{I}_{\text{j}} = [I_{ji}]$ and angles $\bm{\psi}_{\text{j}} = [\psi_{ji}]$ of the resulting complex current flows using the following code:

julia> 𝐈ⱼ = analysis.current.to.magnitude3-element Vector{Float64}:
+ 0.3237186097853939
+ 0.27910332071759625
+ 0.2764160838803776
julia> 𝛙ⱼ = analysis.current.to.angle3-element Vector{Float64}: + 2.3387018720254247 + 2.3270001254267854 + -2.8820321950004284

Current at Branch Series Elements

To obtain the vectors of magnitudes $\mathbf{I}_{\text{l}} = [I_{\text{l}ij}]$ and angles $\bm{\psi}_{\text{l}} = [\psi_{\text{l}ij}]$ of the resulting complex current flows, one can use the following code:

julia> 𝐈ₗ = analysis.current.series.magnitude3-element Vector{Float64}:
+ 0.3134039017610302
+ 0.26867147486022164
+ 0.2850121792157389
julia> 𝛙ₗ = analysis.current.series.angle3-element Vector{Float64}: + -0.75841409129973 + -0.7631714293392173 + 0.31577645020972367
diff --git a/v0.2.0/tutorials/powerSystemModel/index.html b/v0.2.0/tutorials/powerSystemModel/index.html new file mode 100644 index 000000000..7354af3c1 --- /dev/null +++ b/v0.2.0/tutorials/powerSystemModel/index.html @@ -0,0 +1,204 @@ + +Power System Model · JuliaGrid

Power System Model

Power system analyses commonly utilize the unified branch model that provides linear relationships between voltages and currents. However, as the focus is on power calculations rather than current calculations, the resulting equations become nonlinear, posing challenges in solving them [6]. Hence, to accurately analyze power systems without any approximations, we use the AC model, which is a crucial component of our framework. In contrast, to obtain a linear system of equations for various DC analyses, we introduce approximations in the unified branch model, resulting in the DC model.

Info

In this section, we not only describe the AC and DC models derived from the unified branch model but also furnish the power and current equations utilized in all JuliaGrid analyses.

A common way to describe the power system network topology is through the bus/branch model, which employs the two-port $\pi$-model, which results in the unified branch model. The bus/branch model can be represented by a graph denoted by $\mathcal{G} = (\mathcal{N}, \mathcal{E})$, where the set of nodes $\mathcal{N} = \{1, \dots, n\}$ corresponds to buses, and the set of edges $\mathcal{E} \subseteq \mathcal{N} \times \mathcal{N}$ represents the branches of the power network.

Let us now construct the power system:

@labels(Integer)
+
+@power(MW, MVAr, MVA)
+@voltage(pu, deg, V)
+
+system = powerSystem()
+
+addBus!(system; label = 1, type = 3)
+addBus!(system; label = 2, type = 1, active = 21.7, reactive = 12.7)
+addBus!(system; label = 3, type = 2, conductance = 2.1, susceptance = 1.2)
+
+addBranch!(system; from = 1, to = 2, resistance = 0.02, reactance = 0.06, susceptance = 0.05)
+addBranch!(system; from = 2, to = 3, reactance = 0.21, turnsRatio = 0.98, shiftAngle = 1.2)
+
+addGenerator!(system; bus = 1, active = 40.0, reactive = 42.4)

The given example provides the set of buses $\mathcal{N}$ and the set of branches $\mathcal{E}$:

julia> 𝒩 = collect(keys(system.bus.label))3-element Vector{Int64}:
+ 1
+ 2
+ 3
julia> ℰ = [𝒩[system.branch.layout.from] 𝒩[system.branch.layout.to]]2×2 Matrix{Int64}: + 1 2 + 2 3

Notation

In this section, when referring to a vector $\mathbf{a}$, we use the notation $\mathbf{a} = [a_{ij}]$, where $a_{ij}$ represents the generic element associated with the branch $(i,j) \in \mathcal{E}$.


AC Model

JuliaGrid is based on common network elements and benefits from the unified branch model to perform various analyses based on the system of nonlinear equations. To generate matrices and vectors for AC or nonlinear analysis, JuliaGrid employs the acModel! function:

acModel!(system)

Unified Branch Model

The equivalent unified $\pi$-model for a branch $(i,j) \in \mathcal{E}$ incident to the buses $\{i,j\} \in \mathcal{N}$ is shown in Figure 1.

+
Figure 1: The equivalent branch model, where the transformer is located at the from-bus end of the branch.
Info

The directions of the currents $\bar{I}_{ij}$, $\bar{I}_{ji}$, $\bar{I}_{\text{s}i}$, and $\bar{I}_{\text{s}j}$ are vital for power flow analysis. Positive power aligns with the assumed current direction, moving away from the bus, while negative power implies a reverse flow towards the bus. JuliaGrid consistently uses these directions, along with $\bar{I}_{\text{l}ij}$, for power and current calculations.

The branch series admittance $y_{ij}$ is inversely proportional to the branch series impedance $z_{ij}$:

\[ y_{ij} = \frac{1}{z_{ij}} = \frac{1}{r_{ij} + \text{j}x_{ij}} = + \frac{r_{ij}}{r_{ij}^2 + x_{ij}^2} - \text{j}\frac{x_{ij}}{r_{ij}^2 + x_{ij}^2} = g_{ij} + \text{j}b_{ij},\]

where $r_{ij}$ is a resistance, $x_{ij}$ is a reactance, $g_{ij}$ is a conductance and $b_{ij}$ is a susceptance of the branch.

The vectors of resistances, denoted by $\mathbf{r} = [r_{ij}]$, and reactances, denoted by $\mathbf{x} = [x_{ij}]$, are stored in the variables:

julia> 𝐫 = system.branch.parameter.resistance2-element Vector{Float64}:
+ 0.02
+ 0.0
julia> 𝐱 = system.branch.parameter.reactance2-element Vector{Float64}: + 0.06 + 0.21

Moreover, the ac field stores the computed vector of branch series admittances $\mathbf{y} = [y_{ij}]$:

julia> 𝐲 = system.model.ac.admittance2-element Vector{ComplexF64}:
+ 5.0 - 15.0im
+ 0.0 - 4.761904761904763im

The branch shunt admittance $y_{\text{s}ij}$ is equal to:

\[y_{\text{s}ij} = g_{\text{s}ij} + \text{j}b_{\text{s}ij},\]

where $g_{\text{s}ij}$ represents the shunt conductance of the branch, and $b_{\text{s}ij}$ represents the shunt susceptance. Both of these values are positive for real line sections. It is worth noting that while the shunt conductance $g_{\text{s}ij}$ is often insignificantly small and can be ignored in many cases, it is included in the analyses to ensure comprehensive consideration of all potential scenarios.

Within JuliaGrid, the total shunt conductances and susceptances of branches are stored. In order to obtain the vectors $\mathbf{g}_\text{s} = [g_{\text{s}ij}]$ and $\mathbf{b}_\text{s} = [b_{\text{s}ij}]$, the conductances and susceptances must be distributed by considering the ends of the branches:

julia> 𝐠ₛ = 0.5 * system.branch.parameter.conductance2-element Vector{Float64}:
+ 0.0
+ 0.0
julia> 𝐛ₛ = 0.5 * system.branch.parameter.susceptance2-element Vector{Float64}: + 0.025 + 0.0

The transformer complex ratio $\alpha_{ij}$ is defined:

\[ \alpha_{ij} = \cfrac{1}{\tau_{ij}}e^{-\text{j}\phi_{ij}},\]

where $\tau_{ij} \neq 0$ is a transformer turns ratio, while $\phi_{ij}$ is a transformer phase shift angle, always located at the from-bus end of the branch. Note, if $\tau_{ij} = 1$ and $\phi_{ij} = 0$ the model describes the line. In-phase transformers are defined if $\tau_{ij} \neq 1$, $\phi_{ij} = 0$, and $y_{\text{s}ij} = 0$, while phase-shifting transformers are obtained if $\tau_{ij} \neq 1$, $\phi_{ij} \neq 0$, and $y_{\text{s}ij} = 0$.

These transformer parameters are stored in the vectors $\bm{\tau} = [\tau_{ij}]$ and $\bm{\phi} = [\phi_{ij}]$, respectively:

julia> 𝛕 = system.branch.parameter.turnsRatio2-element Vector{Float64}:
+ 1.0
+ 0.98
julia> 𝚽 = system.branch.parameter.shiftAngle2-element Vector{Float64}: + 0.0 + 0.020943951023931952

Branch Shunt Elements

The currents flowing through shunt admittances denoted as $y_{\text{s}ij}$ are defined as follows:

\[ \begin{aligned} + \bar{I}_{\text{s}i} &= \alpha_{ij} y_{\text{s}ij}\bar{V}_i, \;\;\; (i,j) \in \mathcal{E} \\ + \bar{I}_{\text{s}j} &= y_{\text{s}ij}\bar{V}_j, \;\;\; (i,j) \in \mathcal{E}. + \end{aligned}\]

With these specified currents in place, it becomes straightforward to compute both the total active and reactive power that branch shunt elements demand and inject concerning the power system:

\[ S_{\text{s}ij} = P_{\text{s}ij} + \text{j}Q_{\text{s}ij} = \alpha_{ij} \bar{V}_i \bar{I}_{\text{s}i}^* + \bar{V}_j \bar{I}_{\text{s}j}^* = y_{\text{s}ij}^*(\alpha_{ij}^2 {V}_i^2 + {V}_j^2), \;\;\; (i,j) \in \mathcal{E}.\]

For real branch sections, the reactive power is negative, $Q_{\text{s}ij} < 0$, signifying that the branch injects reactive power due to its capacitive nature. The negative sign implies that the power flow direction opposes the assumed direction set by the currents $\bar{I}_{\text{s}i}$ and $\bar{I}_{\text{s}j}$. The active power $P_{\text{s}ij}$ represents active losses within the branch shunt admittances.


Branch Series Element

The current flowing through a series admittance, denoted as $y_{ij}$, is defined as follows:

\[ \bar{I}_{\text{l}ij} = \alpha_{ij} y_{ij}\bar{V}_i - y_{ij}\bar{V}_i, \;\;\; (i,j) \in \mathcal{E}.\]

Consequently, the active and reactive powers associated with the branch series element are as follows:

\[ S_{\text{l}ij} = P_{\text{l}ij} + \text{j}Q_{\text{l}ij} = (\alpha_{ij} \bar{V}_i - \bar{V}_j) \bar{I}_{\text{l}ij}^* = y_{ij}^* (\alpha_{ij} \bar{V}_i - \bar{V}_j) (\alpha_{ij} \bar{V}_i - \bar{V}_j)^*, \;\;\; (i,j) \in \mathcal{E}.\]

The active power $P_{\text{l}ij}$ accounts for losses originating from the resistance $r_{ij}$ of the branch, while the reactive power $Q_{\text{l}ij}$ represents losses resulting from the inductive characteristics of the impedance defined by reactance $x_{ij}$. This can be observed when the reactive power is positive $Q_{\text{l}ij} > 0$.


Branch Network Equations

Using Kirchhoff's circuit laws, the branch model can be described by complex expressions:

\[ \begin{bmatrix} + \bar{I}_{ij} \\ \bar{I}_{ji} + \end{bmatrix} = + \begin{bmatrix} + \cfrac{1}{\tau_{ij}^2}({y}_{ij} + y_{\text{s}ij}) & -\alpha_{ij}^*{y}_{ij}\\ + -\alpha_{ij}{y}_{ij} & {y}_{ij} + y_{\text{s}ij} + \end{bmatrix} + \begin{bmatrix} + \bar{V}_i \\ \bar{V}_j + \end{bmatrix}.\]

The admittance parameters are stored in the vectors $\mathbf{y}_{\text{ii}} = [({y}_{ij} + y_{\text{s}ij}) / \tau_{ij}^2]$, $\mathbf{y}_{\text{ij}} = [-\alpha_{ij}^*{y}_{ij}]$, $\mathbf{y}_{\text{ji}} = [-\alpha_{ij}{y}_{ij}]$, and $\mathbf{y}_{\text{jj}} = [{y}_{ij} + y_{\text{s}ij}]$ and can be found in the variables:

julia> 𝐲ᵢᵢ = system.model.ac.nodalFromFrom2-element Vector{ComplexF64}:
+ 5.0 - 14.975im
+ 0.0 - 4.958251522183218im
julia> 𝐲ᵢⱼ = system.model.ac.nodalFromTo2-element Vector{ComplexF64}: + -5.0 + 15.0im + -0.10176102955955763 + 4.85802081377476im
julia> 𝐲ⱼᵢ = system.model.ac.nodalToFrom2-element Vector{ComplexF64}: + -5.0 + 15.0im + 0.10176102955955763 + 4.85802081377476im
julia> 𝐲ⱼⱼ = system.model.ac.nodalToTo2-element Vector{ComplexF64}: + 5.0 - 14.975im + 0.0 - 4.761904761904763im

In this context, we have easily derived the active and reactive power flow at the from-bus end of the branch:

\[ S_{ij} = P_{ij} + \text{j}Q_{ij} = \bar{V}_i \left[\cfrac{1}{\tau_{ij}^2}({y}_{ij} + y_{\text{s}ij}) \bar{V}_i - \alpha_{ij}^*{y}_{ij} \bar{V}_j\right]^*, \;\;\; (i,j) \in \mathcal{E}.\]

Similarly, we can determine the active and reactive power flow at the to-bus end of the branch:

\[ {S}_{ji} = P_{ji} + \text{j}Q_{ji} = \bar{V}_j \left[-\alpha_{ij}{y}_{ij} \bar{V}_i + ({y}_{ij} + y_{\text{s}ij}) \bar{V}_j\right]^*, \;\;\; (i,j) \in \mathcal{E}.\]

Positive values of active or reactive power, $P_{ij} > 0$ or $Q_{ij} > 0$, indicate power flow originating from the from-bus and moving towards the to-bus, following the direction of the current $\bar{I}_{ij}$. Conversely, negative values, $P_{ij} < 0$ or $Q_{ij} < 0$, signify power flow in the opposite direction. The same principles apply to $P_{ji} > 0$ or $Q_{ji} > 0$, indicating power flow from the to-bus to the from-bus, aligned with the current $\bar{I}_{ji}$, while negative values, $P_{ji} < 0$ or $Q_{ji} < 0$, denote the reverse flow direction.


Nodal Network Equations

Let us consider an illustrative example from our case study, depicted in Figure 2. This example provides a smooth transition to the general case, demonstrating a system with three buses represented as $\mathcal{N} = \{1, 2, 3\}$ and two branches $\mathcal{E} = \{(1, 2), (2, 3)\}$, where bus $2$ is incident to the shunt element with admittance ${y}_{\text{sh}2}$.

+
Figure 2: The example of the system with three buses and two branches.
Info

The current $\bar{I}_{\text{sh}2}$ follows the convention of coming out from the bus in terms of its direction. When calculating powers related to shunt elements, this current direction is assumed. Therefore, in cases where power is positive, it signifies alignment with the assumed current direction, emerging away from the bus. Conversely, when power is negative, the direction is reversed, indicating a flow towards the bus.

According to the Branch Network Equations each branch is described using the system of equations as follows:

\[ \begin{bmatrix} + \bar{I}_{12} \\ \bar{I}_{21} + \end{bmatrix} = + \begin{bmatrix} + \cfrac{1}{\tau_{12}^2}({y}_{12} + y_{\text{s}12}) & -\alpha_{12}^*{y}_{12}\\ + -\alpha_{12}{y}_{12} & {y}_{12} + y_{\text{s}12} + \end{bmatrix} + \begin{bmatrix} + \bar{V}_1 \\ \bar{V}_2 + \end{bmatrix}\]

\[ \begin{bmatrix} + \bar{I}_{23} \\ \bar{I}_{32} + \end{bmatrix} = + \begin{bmatrix} + \cfrac{1}{\tau_{23}^2}({y}_{23} + y_{\text{s}23}) & -\alpha_{23}^*{y}_{23}\\ + -\alpha_{23}{y}_{23} & {y}_{23} + y_{\text{s}23} + \end{bmatrix} + \begin{bmatrix} + \bar{V}_2 \\ \bar{V}_3 + \end{bmatrix}.\]

The complex current injections at buses are:

\[ \begin{aligned} + \bar{I}_1 &= \bar{I}_{12} = \cfrac{1}{\tau_{12}^2}({y}_{12} + y_{\text{s}12}) \bar{V}_1 -\alpha_{12}^*{y}_{12} \bar{V}_2 \\ + \bar{I}_2 &= \bar{I}_{21} + \bar{I}_{23} + \bar{I}_{\text{sh}2} = -\alpha_{12}{y}_{12} \bar{V}_1 + ({y}_{12} + y_{\text{s}12}) \bar{V}_2 + + \cfrac{1}{\tau_{23}^2}({y}_{23} + y_{\text{s}23}) \bar{V}_2 -\alpha_{23}^*{y}_{23} \bar{V}_3 + {y}_{\text{sh}2} \bar{V}_2 \\ + \bar{I}_3 &= \bar{I}_{32} = -\alpha_{23}{y}_{23} \bar{V}_2 + ({y}_{23} + y_{\text{s}23}) \bar{V}_3. + \end{aligned}\]

The system of equations can be written in the matrix form:

\[ \begin{bmatrix} + \bar{I}_1 \\ \bar{I}_2 \\ \bar{I}_3 + \end{bmatrix} = + \begin{bmatrix} + \cfrac{1}{\tau_{12}^2}({y}_{12} + y_{\text{s}12}) & -\alpha_{12}^*{y}_{12} & 0 \\ + -\alpha_{12}{y}_{12} & {y}_{12} + y_{\text{s}12} + \cfrac{1}{\tau_{23}^2}({y}_{23} + y_{\text{s}23}) + {y}_{\text{sh}2} & -\alpha_{23}^*{y}_{23} \\ + 0 & -\alpha_{23}{y}_{23} & {y}_{23} + y_{\text{s}23} + \end{bmatrix} + \begin{bmatrix} + \bar{V}_1 \\ \bar{V}_2 \\ \bar{V}_3 + \end{bmatrix}.\]

This system of equations can be generalized to accommodate the scenario where the set $\mathcal{N}$ comprises $n$ buses:

\[ \mathbf {\bar {I}} = \mathbf{Y} \mathbf {\bar {V}},\]

where $\mathbf {\bar {V}} \in \mathbb{C}^{n}$ is the vector of bus complex voltages, and $\mathbf {\bar {I}} \in \mathbb{C}^{n}$ is the vector of complex current injections at buses. The matrix $\mathbf{Y} = \mathbf{G} + \text{j}\mathbf{B} \in \mathbb{C}^{n \times n}$ is the bus or nodal admittance matrix, with elements:

  • the diagonal elements, where $i \in \mathcal{N}$, are equal to:

    \[Y_{ii} = G_{ii} + \text{j}B_{ii} = {y}_{\text{sh}i} + +\sum\limits_{e \in \mathcal{E}, \; e(1) = i} \cfrac{1}{\tau_{ij}^2}({y}_{ij} + y_{\text{s}ij}) + \sum\limits_{e \in \mathcal{E}, \; e(2) = i} ({y}_{ji} + y_{\text{s}ji}),\]

  • the non-diagonal elements, where $i = e(1),\; j = e(2), \; e \in \mathcal{E}$, are equal to:

    \[ \begin{aligned} + Y_{ij} &= G_{ij} + \text{j}B_{ij} = -\alpha_{ij}^*{y}_{ij} \\[4pt] + Y_{ji} &= G_{ji} + \text{j}B_{ji} = -\alpha_{ij}{y}_{ij}. + \end{aligned}\]

When a branch is not incident (or adjacent) to a bus the corresponding element in the nodal admittance matrix $\mathbf{Y}$ is equal to zero. The nodal admittance matrix $\mathbf{Y}$ is sparse (i.e., a small number of elements are non-zeros) for real-world power systems. Although it is often assumed that the matrix $\mathbf{Y}$ is symmetrical, it is not a general case. For example, in the presence of phase shifting transformers the matrix $\mathbf{Y}$ is not symmetric [7, Sec. 9.6]. JuliaGrid stores both the matrix $\mathbf{Y}$ and its transpose $\mathbf{Y}^T$ in the ac field of the PowerSystem type:

julia> 𝐘 = system.model.ac.nodalMatrix3×3 SparseArrays.SparseMatrixCSC{ComplexF64, Int64} with 7 stored entries:
+  5.0-14.975im      -5.0+15.0im               ⋅
+ -5.0+15.0im         5.0-19.9333im  -0.101761+4.85802im
+      ⋅         0.101761+4.85802im      0.021-4.7499im
julia> 𝐘ᵀ = system.model.ac.nodalMatrixTranspose3×3 SparseArrays.SparseMatrixCSC{ComplexF64, Int64} with 7 stored entries: + 5.0-14.975im -5.0+15.0im ⋅ + -5.0+15.0im 5.0-19.9333im 0.101761+4.85802im + ⋅ -0.101761+4.85802im 0.021-4.7499im

Bus Injections

From the previous analysis, we can determine the complex current injection at each bus as follows:

\[ \bar{I}_i = \sum\limits_{j = 1}^n {Y}_{ij} \bar{V}_j, \;\;\; i \in \mathcal{N}.\]

Furthermore, the calculation of active and reactive power injection at each bus is expressed by the following equation:

\[ {S}_i = P_i + \text{j}Q_i = \bar{V}_i \sum\limits_{j = 1}^n {Y}_{ij}^* \bar{V}_{j}^*, \;\;\; i \in \mathcal{N}.\]

Positive values of active or reactive powers, $P_i > 0$ or $Q_i > 0$, indicate that the bus is supplying power into the power system. Conversely, negative values, $P_i < 0$ or $Q_i < 0$, suggest that the bus is drawing active or reactive power from the power system.


Bus Shunt Element

Based on the previous analysis, we can determine the active and reactive power at the shunt element of each bus using the following equation:

\[ {S}_{\text{sh}i} = {P}_{\text{sh}i} + \text{j}{Q}_{\text{sh}i} = \bar{V}_{i}\bar{I}_{\text{sh}i}^* = {y}_{\text{sh}i}^*{V}_{i}^2, \;\;\; i \in \mathcal{N}.\]

The positive active power value ${P}_{\text{sh}i} > 0$ indicates that the shunt element is consuming active power. In terms of power flow, this signifies that active power flows from bus $i \in \mathcal{N}$ towards the ground. A negative reactive power value ${Q}_{\text{sh}i} < 0$ suggests that the shunt element is injecting reactive power into the power system. This implies that the direction of reactive power is from the ground to bus $i \in \mathcal{N}$, illustrating the capacitive nature of the shunt component. Conversely, if ${Q}_{\text{sh}i} > 0$, it indicates an inductive characteristic, implying that the shunt component is absorbing reactive power.


DC Model

The DC model is obtained by linearization of the nonlinear model, and it provides an approximate solution. In the typical operating conditions, the difference of bus voltage angles between adjacent buses $(i,j) \in \mathcal{E}$ is very small $\theta_{i}-\theta_{j} \approx 0$, which implies $\cos (\theta_{i}-\theta_{j})\approx 1$ and $\sin (\theta_{i}-\theta_{j}) \approx \theta_{i}-\theta_{j}$. Further, all bus voltage magnitudes are $V_i \approx 1$, $i \in \mathcal{N}$, and all branch shunt admittances and branch resistances can be neglected. This implies that the DC model ignores the reactive powers and transmission losses and takes into account only the active powers.

Therefore, the DC power flow takes only bus voltage angles $\bm \Theta \in \mathbb{R}^{n}$ as variables. To create vectors and matrices related to DC or linear analyses, JuliaGrid uses the function dcModel!:

dcModel!(system)

Branch Network Equations

According to the above assumptions, we start from the Unified Branch Model:

\[ \begin{bmatrix} + \bar{I}_{ij} \\ \bar{I}_{ji} + \end{bmatrix} = \cfrac{1}{\text{j}x_{ij}} + \begin{bmatrix} + \cfrac{1}{\tau_{ij}^2} && -\alpha_{ij}^*\\ + -\alpha_{ij} && 1 + \end{bmatrix} + \begin{bmatrix} + \bar{V}_{i} \\ \bar{V}_{j} + \end{bmatrix},\]

where $\bar{V}_{i} = \text{e}^{\text{j}\theta_{i}}$ and $\bar{V}_{j} = \text{e}^{\text{j}\theta_{j}}$. Further, we have:

\[ \begin{aligned} + \bar{I}_{ij} &= \cfrac{1}{\text{j}x_{ij}} \left[\cfrac{1}{\tau_{ij}^2} \text{e}^{\text{j}\theta_{i}} - + \cfrac{1}{\tau_{ij}}\text{e}^{\text{j}(\phi_{ij} + \theta_j)} \right] \\ + \bar{I}_{ji} &= \cfrac{1}{\text{j}x_{ij}} \left[-\cfrac{1}{\tau_{ij}}\text{e}^{\text{j}(\theta_i - \phi_{ij})} + \text{e}^{\text{j}\theta_{j}} \right]. + \end{aligned}\]

The active power flows are derived as follows:

\[ \begin{aligned} + P_{ij} &= \Re\{\bar{V}_{i}\bar{I}_{ij}^*\} = + \Re \left\{\text{j}\cfrac{1}{x_{ij}} + \left[\cfrac{1}{\tau_{ij}^2} - \cfrac{1}{\tau_{ij}}e^{\text{j}(\theta_i - \theta_j - \phi_{ij})} \right] \right\} \\ + P_{ji} &= \Re\{\bar{V}_{j}\bar{I}_{ji}^*\} = + \Re \left\{\text{j}\cfrac{1}{x_{ij}} + \left[1-\cfrac{1}{\tau_{ij}}e^{\text{j}(-\theta_i +\theta_j + \phi_{ij})} \right] \right\}. + \end{aligned}\]

The real components are:

\[ \begin{aligned} + P_{ij} &=\cfrac{1}{\tau_{ij}x_{ij}} \sin(\theta_{i} -\theta_{j}-\phi_{ij}) \approx \cfrac{1}{\tau_{ij} x_{ij}} (\theta_{i} -\theta_{j}-\phi_{ij}) \\ + P_{ji} &=\cfrac{1}{\tau_{ij}x_{ij}} \sin(\theta_{j} -\theta_{i}+\phi_{ij}) \approx -\cfrac{1}{\tau_{ij} x_{ij}} (\theta_{i} - \theta_{j}-\phi_{ij}), + \end{aligned}\]

where ${1}/({\tau_{ij} x_{ij}})$ represents the branch admittance in the DC framework. To recall, the PowerSystem type stores the reactances as vector $\mathbf{x} = [x_{ij}]$ in the variable:

julia> 𝐱 = system.branch.parameter.reactance2-element Vector{Float64}:
+ 0.06
+ 0.21

Furthermore, the computed branch admittances in the DC framework are stored in the vector $\mathbf{y} = [{1}/({\tau_{ij} x_{ij}})]$:

julia> 𝐲 = system.model.dc.admittance2-element Vector{Float64}:
+ 16.666666666666668
+  4.8590864917395535

We can conclude that $P_{ij}=-P_{ji}$ holds. With the DC model, the linear network equations relate active powers to bus voltage angles, versus complex currents to complex bus voltages in the AC model [8]. Consequently, analogous to the Branch Network Equations we can write:

\[ \begin{bmatrix} + P_{ij} \\ P_{ji} + \end{bmatrix} = \cfrac{1}{\tau_{ij}x_{ij}} + \begin{bmatrix} + 1 && -1\\ + -1 && 1 + \end{bmatrix} + \begin{bmatrix} + \theta_{i} \\ \theta_{j} + \end{bmatrix} + \cfrac{\phi_{ij}}{\tau_{ij}x_{ij}} + \begin{bmatrix} + -1 \\ 1 + \end{bmatrix}.\]


Nodal Network Equations

As before, let us consider an illustrative example from our case study, depicted in Figure 3. This example provides a smooth transition to the general case, demonstrating a system with three buses represented as $\mathcal{N} = \{1, 2, 3\}$ and two branches $\mathcal{E} = \{(1, 2), (2, 3)\}$, where bus $2$ is incident to the shunt element with admittance ${g}_{\text{sh}2}$.

+
Figure 3: The example of the system with three buses and two branches.

Each branch in the DC framework is described with a system of equations as follows:

\[ \begin{bmatrix} + P_{12} \\ P_{21} + \end{bmatrix} = \cfrac{1}{\tau_{12}x_{12}} + \begin{bmatrix} + 1 && -1\\ + -1 && 1 + \end{bmatrix} + \begin{bmatrix} + \theta_{1} \\ \theta_{2} + \end{bmatrix} + \cfrac{\phi_{12}}{\tau_{12}x_{12}} + \begin{bmatrix} + -1 \\ 1 + \end{bmatrix}\]

\[ \begin{bmatrix} + P_{23} \\ P_{32} + \end{bmatrix} = \cfrac{1}{\tau_{23}x_{23}} + \begin{bmatrix} + 1 && -1\\ + -1 && 1 + \end{bmatrix} + \begin{bmatrix} + \theta_{2} \\ \theta_{3} + \end{bmatrix} + \cfrac{\phi_{23}}{\tau_{23}x_{23}} + \begin{bmatrix} + -1 \\ 1 + \end{bmatrix}.\]

The active power injections at buses are:

\[ \begin{aligned} + P_{1} &= P_{12} =\cfrac{1}{\tau_{12}x_{12}} \theta_{1} - \cfrac{1}{\tau_{12}x_{12}} \theta_{2} - \cfrac{\phi_{12}}{\tau_{12}x_{12}} \\ + P_{2} &= P_{21} + P_{23} + P_{\text{sh}2} = -\cfrac{1}{\tau_{12}x_{12}} \theta_{1} + \cfrac{1}{\tau_{12}x_{12}} \theta_{2} + \cfrac{\phi_{12}}{\tau_{12}x_{12}} + + \cfrac{1}{\tau_{23}x_{23}} \theta_{2} - \cfrac{1}{\tau_{23}x_{23}} \theta_{3} - \cfrac{\phi_{23}}{\tau_{23}x_{23}} + {g}_{\text{sh}2} \\ + P_{3} &= {P}_{32} = -\cfrac{1}{\tau_{23}x_{23}} \theta_{2} +\cfrac{1}{\tau_{23}x_{23}} \theta_{3} + \cfrac{\phi_{23}}{\tau_{23}x_{23}}, + \end{aligned}\]

where the active power injected by the shunt element at the bus $2$ is equal to:

\[ P_{\text{sh}2} = \Re\{\bar{V}_{2}\bar{I}_{\text{sh}2}^*\} = \Re\{\bar{V}_{2}{y}_{\text{sh}2}^*\bar{V}_{2}^*\} = V_2^2 {g}_{\text{sh}2} = {g}_{\text{sh}2}.\]

The system of equations can be written in the matrix form:

\[ \begin{bmatrix} + P_{1} \\ P_{2} \\ P_{3} + \end{bmatrix} = + \begin{bmatrix} + \cfrac{1}{\tau_{12}x_{12}} & - \cfrac{1}{\tau_{12}x_{12}} & 0 \\ + -\cfrac{1}{\tau_{12}x_{12}} & \cfrac{1}{\tau_{12}x_{12}} + \cfrac{1}{\tau_{23}x_{23}} & -\cfrac{1}{\tau_{23}x_{23}} \\ + 0 & -\cfrac{1}{\tau_{23}x_{23}} &\cfrac{1}{\tau_{23}x_{23}} + \end{bmatrix} + \begin{bmatrix} + \theta_{1} \\ \theta_{2} \\ \theta_{3} + \end{bmatrix} + + \begin{bmatrix} + - \cfrac{\phi_{12}}{\tau_{12}x_{12}} \\ \cfrac{\phi_{12}}{\tau_{12}x_{12}} - \cfrac{\phi_{23}}{\tau_{23}x_{23}} \\ \cfrac{\phi_{23}}{\tau_{23}x_{23}} + \end{bmatrix} + + \begin{bmatrix} + 0 \\ {g}_{\text{sh}2} \\ 0 + \end{bmatrix}.\]

This system of equations can be generalized to accommodate the scenario where the set $\mathcal{N}$ comprises $n$ buses:

\[ \mathbf {P} = \mathbf{B} \bm {\Theta} + \mathbf{P_\text{tr}} + \mathbf{P}_\text{sh},\]

where $\bm \Theta \in \mathbb{R}^{n}$ is the vector of bus voltage angles.

The vector $\mathbf {P} \in \mathbb{R}^{n}$ contains active power injections at buses caused by generators and demands. In JuliaGrid, the vector can be recovered using a command:

julia> 𝐏 = system.bus.supply.active - system.bus.demand.active3-element Vector{Float64}:
+  0.4
+ -0.217
+  0.0

The vector $\mathbf{P_\text{tr}} \in \mathbb{R}^{n}$ represents active powers related to the non-zero shift angle of transformers. This vector is stored in the dc field, and we can access it using:

julia> 𝐏ₜᵣ = system.model.dc.shiftPower3-element Vector{Float64}:
+  0.0
+ -0.10176846950404254
+  0.10176846950404254

The vector $\mathbf{P}_\text{sh} \in \mathbb{R}^{n}$ represents active powers consumed by shunt elements. We can access this vector using:

julia> 𝐏ₛₕ = system.bus.shunt.conductance3-element Vector{Float64}:
+ 0.0
+ 0.0
+ 0.021

The bus or nodal matrix in the DC framework is given as $\mathbf{B} \in \mathbb{R}^{n \times n}$, with elements:

  • the diagonal elements, where $i \in \mathcal{N}$, are equal to:

    \[B_{ii} = \sum\limits_{e \in \mathcal{E},\; i \in e} \cfrac{1}{\tau_{ij}x_{ij}},\]

  • the non-diagonal elements, where $i = e(1),\; j = e(2), \; e \in \mathcal{E}$, are equal to:

    \[ \begin{aligned} + B_{ij} &= -\cfrac{1}{\tau_{ij}x_{ij}} \\[3pt] + B_{ji} &= -\cfrac{1}{\tau_{ij}x_{ij}}. + \end{aligned}\]

The sparse nodal matrix $\mathbf{B}$ is stored in the dc field, and we can access it using:

julia> 𝐁 = system.model.dc.nodalMatrix3×3 SparseArrays.SparseMatrixCSC{Float64, Int64} with 7 stored entries:
+  16.6667  -16.6667     ⋅
+ -16.6667   21.5258   -4.85909
+    ⋅       -4.85909   4.85909

Bus Injection

From the previous analysis, the calculation of active power injection at each bus is expressed by:

\[ P_i = \sum_{j = 1}^n {B}_{ij} \theta_j + P_{\text{tr}i} + P_{\text{sh}i}, \;\;\; i \in \mathcal{N}.\]

diff --git a/versions.js b/versions.js index 8321ad2d8..46870d7be 100644 --- a/versions.js +++ b/versions.js @@ -1,7 +1,8 @@ var DOC_VERSIONS = [ "stable", + "v0.2", "v0.1", "dev", ]; -var DOCUMENTER_NEWEST = "v0.1.9"; +var DOCUMENTER_NEWEST = "v0.2.0"; var DOCUMENTER_STABLE = "stable";