Metrics documentation
DiTTo has the capability to extract metrics from a system once parsed in the core representation. This enables the user to compute metrics when doing a conversion from one format to another.
The advantage compared to computing metrics on a given format is that no conversion is needed prior to the caculation.
List of available metrics
Here is the list of implemented metrics with their description. The list is organized in different sections to ease the search.
Realistic electrical design and equipment parameters (MV)
Metric name | Type | Unit | Metric description | Comments |
---|---|---|---|---|
mv_len_mi | Float | miles | The total length of medium voltage lines. | Needs the nominal voltages |
mv_3ph_len_mi | Float | miles | The total length of medium voltage, 3 phase lines. | Needs the nominal voltages |
mv_oh_3ph_len_mi | Float | miles | The total length of medium voltage, overhead, 3 phase lines. | Needs the nominal voltages and line_type. |
mv_2ph_len_mi | Float | miles | The total length of medium voltage, 2 phase lines. | Needs the nominal voltages |
mv_oh_2ph_len_mi | Float | miles | The total length of medium voltage, overhead, 2 phase lines. | Needs the nominal voltages and line_type. |
mv_1ph_len_mi | Float | miles | The total length of medium voltage, 1 phase lines. | Needs the nominal voltages |
mv_oh_1ph_len_mi | Float | miles | The total length of medium voltage, overhead, 1 phase lines. | Needs the nominal voltages and line_type. |
perct_mv_oh_len | Float | - | Percentage of MV lines that are overhead lines. | Needs the nominal voltages and line_type. |
ratio_mv_len_to_num_cust | Float | miles | mv_length_miles devided by the number of customers. | Needs nominal voltages and load information. |
max_sub_node_distance_mi | Float | miles | Maximum distance between the substation and any node of the network. | |
nominal_medium_voltage_class | Float | Volts | Nominal voltage of medium voltage. |
Realistic electrical design and equipment parameters (LV)
Metric name | Type | Unit | Metric description | Comments |
---|---|---|---|---|
lv_len_mi | Float | miles | The total length of low voltage lines. | Needs the nominal voltages |
lv_3ph_len_mi | Float | miles | The total length of low voltage, 3 phase lines. | Needs the nominal voltages |
lv_oh_3ph_len_mi | Float | miles | The total length of low voltage, overhead, 3 phase lines. | Needs the nominal voltages and line_type. |
lv_1ph_len_mi | Float | miles | The total length of low voltage, 1 phase lines. | Needs the nominal voltages |
lv_oh_1ph_len_mi | Float | miles | The total length of low voltage, overhead, 1 phase lines. | Needs the nominal voltages and line_type. |
max_lv_line: | Float | miles | The maximum length between a distribution transformer and a low voltage customer. | Needs the nominal voltages |
lv_2ph_len_mi | Float | miles | The total length of low voltage, 2 phase lines. | Needs the nominal voltages |
lv_oh_2ph_len_mi | Float | miles | The total length of low voltage, overhead, 2 phase lines. | Needs the nominal voltages and line_type. |
perct_lv_oh_len | Float | - | Percentage of LV lines that are overhead lines. | Needs the nominal voltages and line_type. |
ratio_lv_len_to_num_cust | Float | miles | lv_length_miles devided by the number of customers. | Needs nominal voltages and load information. |
Voltage control schemes
Metric name | Type | Unit | Metric description | Comments |
---|---|---|---|---|
num_regulators | Integer | - | The number of regulator objects. | |
num_capacitors | Integer | - | The number of capacitor banks. | |
num_boosters | Integer | - | The number of boosters. | Boosters are not currently implemented in DiTTo. |
avg_regulator_sub_distance_mi | Float | miles | Mean distance between the substation and regulator objects. | If no regulator, this metric is Nan. |
avg_capacitor_sub_distance_mi | Float | miles | Mean distance between the substation and capacitor bank objects. | If no capacitor, this metric is Nan. |
Basic protection
Metric name | Type | Unit | Metric description | Comments |
---|---|---|---|---|
num_fuses | Integer | - | Number of Fuses. | |
num_reclosers | Integer | - | Number of Reclosers. | |
num_sectionalizers | Integer | - | Number of Sectionalizers. | |
num_sectionalizers_per_recloser | Float | - | No_of_Sectionalizers divided by No_of_Reclosers. | If no recloser, this metric is Nan |
avg_recloser_sub_distance_mi | Float | miles | Mean distance between the substation and recloser objects. | If no recloser, this metric is Nan |
num_breakers | Integer | - | Number of Breakers. |
Reconfiguration Options
Metric name | Type | Unit | Metric description | Comments |
---|---|---|---|---|
num_switches | Integer | - | Number of switches. | |
num_interruptors | Integer | - | Number of interruptors. | |
num_links_adjacent_feeders | Integer | - | Number of links between the current feeder and other feeders. | This metrics only works when computing metrics per feeder on a system with multiple feeders. |
num_loops | Integer | - | Number of loops within the feeder. |
Transformers
Metric name | Type | Unit | Metric description | Comments |
---|---|---|---|---|
num_distribution_transformers | Integer | - | Number of distribution transformers. | |
num_overloaded_transformers | Integer | - | Number of distribution transformers where its secondary KVA rating is smaller than the sum of downstream load KVA. | |
sum_distribution_transformer_mva | Float | MVA | Sum of distribution transformer total capacity (sum of ratings accross the windings) | |
num_1ph_transformers | Integer | - | Number of one phase transformers. | |
num_3ph_transformers | Integer | - | Number of three phase transformers. | |
ratio_1ph_to_3ph_transformers | Float | - | nb_1ph_Xfrm divided by nb_3ph_Xfrm | if there is no three phase transformer, this metric is Nan. |
Substations
Metric name | Type | Unit | Metric description | Comments |
---|---|---|---|---|
substation_name | String | - | The name of the substation. | |
sub_capacity_mva | Float | MVA | The capacity of the substation. |
Load specification
Metric name | Type | Unit | Metric description | Comments |
---|---|---|---|---|
sum_load_kw | Float | Watts | Total active power demand. | |
sum_load_pha_kw | Float | Watts | Total active power demand on phase A. | |
sum_load_phb_kw | Float | Watts | Total active power demand on phase B. | |
sum_load_phc_kw | Float | Watts | Total active power demand on phase C. | |
sum_load_kvar | Float | Vars | Total reactive power demand. | |
perct_lv_pha_load_kw | Float | - | Percentage of low voltage active power demand on phase A. | |
perct_lv_phb_load_kw | Float | - | Percentage of low voltage active power demand on phase B. | |
perct_lv_phc_load_kw | Float | - | Percentage of low voltage active power demand on phase C. | |
num_lv_1ph_loads | Integer | - | Number of low voltage, 1 phase loads | |
num_lv_3ph_loads | Integer | - | Number of low voltage, 3 phase loads | |
num_mv_3ph_loads | Integer | - | Number of medium voltage, 3 phase loads | |
avg_num_load_per_transformer | Float | - | Average number of loads per distribution transformer. | |
avg_load_pf | Float | - | Average power factor for loads. | |
avg_load_imbalance_by_phase | Float | Watts | TODO | |
num_customers | Integer | - | Number of customers. | Need customer information. |
customer_density | Float | per square miles | No_of_Customers divided by the convex Hull surface of the feeder. | |
load_density_kw | Float | per square miles | Total_Demand_kW divided by the convex Hull surface of the feeder. | |
load_density_kvar | Float | per square miles | Total_Reactive_Power_kVar divided by the convex Hull surface of the feeder. |
Graph Topology
Metric name | Type | Unit | Metric description | Comments |
---|---|---|---|---|
avg_degree | Float | - | Mean degree. | |
Char_path_Length | Float | - | Average path length. | |
diameter | Float | - | Diameter of the graph. |
How to compute the metrics
Easy situation: compute metrics on a single feeder
Method 1: Command Line Interface
Not implemented yet.
Method 2: Using a Python script
Step 1: Read the model into DiTTo
We assume that we have a model in OpenDSS representing a single feeder, and that we want to compute all the available metrics on it. The first step is to read in the model (more information on reading capabilities in cli-examples.md
)
from ditto.model.store import Store
from ditto.readers.opendss.read import Reader
model = Store() #Create a Store object
#Initialize the reader with the master and coordinate files of our system
dss_reader = Reader(master_file='./OpenDSS/master.dss',
buscoordinates_file='./OpenDSS/buscoords.dss')
#Parse...
dss_reader.parse(model)
Step 2: Modify the model (optional)
This step is optional but most of the time needed. In our example, since we are reading from OpenDSS, we do not have information on the nominal voltages for Nodes
and Lines
. Since a lot of metrics are divided according to low voltage (LV) and medium voltage (MV), we need to add this information.
In this situation, we have the nominal voltage of the source as well as the nominal voltage of the transformers (primary and secondary). We can use the following approach that will go from the source down to the customers and set the nominal voltages of the equipments:
from ditto.modify.system_structure import system_structure_modifier
#Create a system_structure_modifier object
#We can specify the name of the source and its voltage
#Otherwise, the source and its voltage will be search in the model
modifier = system_structure_modifier(model)
#Set the nominal voltages of all nodes in the system
modifier.set_nominal_voltages_recur()
#Use the nodes voltages to set the nominal voltages of the lines
modifier.set_nominal_voltages_recur_line()
This example only shows one of the modification possibilities. More information on modifications and post-processing can be found in modifications.md
Step 3: Compute the metrics
This step of the process creates a NetworkAnalyzer
object with the modified model and compute the metrics on it:
from ditto.metrics.network_analysis import NetworkAnalyzer
#Instanciate the NetworkAnalyzer object
#WARNING: In case the model was modified, we need to use modifier.model
#If we did not do any changes, then simply pass model
#Again, the name of the source can be provided to avoid the search
network_analyst = NetworkAnalyzer(modifier.model)
#Compute all the metrics
network_analyst.compute_all_metrics()
In this example, we have a single feeder so we call the compute_all_metrics()
method. It is also possible to compute metrics per feeder when we have a system with multiple feeders using the compute_all_metrics_per_feeder()
method. The process might be a bit more complicated since the network has to be properly partitioned. More information for this process is available in the section "Advanced: Compute metrics for multiple feeders".
Step 4: View/export the results
The final step of the process is obviously to have a look at the metrics. There are mainly two ways to do so. The first method is simply to look at the results
attribute of the NetworkAnalyzer
:
print(network_analyst.results)
This prints a dictionary where the keys are the feeder names (in our case we have only one key since we have only one feeder), and the values are dictionaries holding the metrics:
{'name_of_feeder1': {'name_of_metric1': value1,
'name_of_metric2': value2,
...
}
'name_of_feeder2': {'name_of_metric1': value1,
'name_of_metric2': value2,
...
}
...
}
Getting a the value of a specific metric for a given feeder:
print(network_analyst.results['name_of_feeder1']['name_of_metric2'])
The second method is to export the metrics first and look at the export. The metrics can be exported to Excel using:
#Provide the path to the file
network_analyst.export('./output/metrics.xlsx')
Note that this will not export distribution metrics. To export everything in network_analyst.results
use the JSON export method:
network_analyst.export_json('./output/metrics.json')
Advanced: compute metrics for multiple feeders
Method 1: Command Line Interface
Not implemented yet.
Method 2: Using a Python script
It is also possible to extract metrics when we have a system composed of multiple feeders. In this situation, we might want to:
- compute the metrics on the whole system
- compute the metrics for all feeders
The first point is straightforward, just proceed as for the single feeder case.
Step 1 and 2: Read and modify as before
For computing metrics per feeder, we first read the model into DiTTo and apply, if needed, modifications to it (exactly as for the single feeder case):
from ditto.model.store import Store
from ditto.readers.opendss.read import Reader
from ditto.modify.system_structure import system_structure_modifier
model = Store() #Create a Store object
#Initialize the reader with the master and coordinate files of our system
dss_reader = Reader(master_file='./OpenDSS/master.dss',
buscoordinates_file='./OpenDSS/buscoords.dss')
#Parse...
dss_reader.parse(model)
#Create a system_structure_modifier object
#We can specify the name of the source and its voltage
#Otherwise, the source and its voltage will be search in the model
modifier = system_structure_modifier(model)
#Set the nominal voltages of all nodes in the system
modifier.set_nominal_voltages_recur()
#Use the nodes voltages to set the nominal voltages of the lines
modifier.set_nominal_voltages_recur_line()
Step 3: Create a network analyzer
We then create a NetworkAnalyzer
object as for the single feeder case:
from ditto.metrics.network_analysis import NetworkAnalyzer
#Instanciate the NetworkAnalyzer object
network_analyst = NetworkAnalyzer(modifier.model)
Step 4: Provide information on the feeder compositions
Now, we need to provide feeder information to the NetworkAnalyzer
using the add_feeder_information()
method wich takes the following inputs:
feeder_names
List of names for the feedersfeeder_nodes
List of lists which contains all nodes in the feeders. Thats is,feeder_nodes[2]
is the full list of nodes belonging tofeeder_names[2]
substations
List of the substation names.feeder_types
This could be a list of strings to tag each feeder with a type (industrial
rural
or a single string to tag all feeders with the same type.
Example:
#Fake feeder information
feeder_names = ['feeder_1', 'feeder_2', 'feeder_3']
feeder_nodes = [ ['A','B','C'], ['D','E','F','G','H'], ['I','J','K','L']]
substations = ['sub_1', 'sub2', 'sub3']
feeder_types = ['industrial', 'rural', 'urban']
#Add the feeder information to the network analyzer
network_analyst.add_feeder_information(feeder_names, feeder_nodes, substations, feeder_types)
This means that you currently have to generate the 4 arguments yourself. Algorithms to automatically split a given network into multiple feeders are currently tested yet but none has been released yet.
Step 5: Split the network and compute the metrics
Once this is done, we simply have to call the following methods:
#Split the network representation into multiple subnetworks
network_analyst.split_network_into_feeders()
#Loop over the DiTTo objects and set the feeder_name attribute
network_analyst.tag_objects()
#Set the names
network_analyst.model.set_names()
#Compute the metrics per feeders
network_analyst.compute_all_metrics_per_feeder()
Step 6: Export the metrics
This works exactly as for the single feeder case.