NREL-erad 0.0.0a0__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- erad/__init__.py +1 -0
- erad/constants.py +20 -20
- erad/cypher_queries/load_data_v1.cypher +211 -211
- erad/data/World_Earthquakes_1960_2016.csv +23410 -23410
- erad/db/assets/critical_infras.py +170 -170
- erad/db/assets/distribution_lines.py +101 -101
- erad/db/credential_model.py +20 -20
- erad/db/disaster_input_model.py +23 -23
- erad/db/inject_earthquake.py +52 -52
- erad/db/inject_flooding.py +53 -53
- erad/db/neo4j_.py +162 -162
- erad/db/utils.py +13 -13
- erad/exceptions.py +68 -68
- erad/metrics/check_microgrid.py +208 -208
- erad/metrics/metric.py +178 -178
- erad/programs/backup.py +61 -61
- erad/programs/microgrid.py +44 -44
- erad/scenarios/abstract_scenario.py +102 -102
- erad/scenarios/common.py +92 -92
- erad/scenarios/earthquake_scenario.py +161 -161
- erad/scenarios/fire_scenario.py +160 -160
- erad/scenarios/flood_scenario.py +493 -493
- erad/scenarios/flows.csv +671 -0
- erad/scenarios/utilities.py +75 -75
- erad/scenarios/wind_scenario.py +89 -89
- erad/utils/ditto_utils.py +252 -252
- erad/utils/hifld_utils.py +147 -147
- erad/utils/opendss_utils.py +357 -357
- erad/utils/overpass.py +76 -76
- erad/utils/util.py +178 -178
- erad/visualization/plot_graph.py +218 -218
- {NREL_erad-0.0.0a0.dist-info → nrel_erad-1.0.0.dist-info}/METADATA +65 -61
- nrel_erad-1.0.0.dist-info/RECORD +42 -0
- {NREL_erad-0.0.0a0.dist-info → nrel_erad-1.0.0.dist-info}/WHEEL +1 -2
- {NREL_erad-0.0.0a0.dist-info → nrel_erad-1.0.0.dist-info/licenses}/LICENSE.txt +28 -28
- NREL_erad-0.0.0a0.dist-info/RECORD +0 -42
- NREL_erad-0.0.0a0.dist-info/top_level.txt +0 -1
@@ -1,103 +1,103 @@
|
|
1
|
-
""" Module contains the base class defination for all scenarios.
|
2
|
-
|
3
|
-
Each scenario type will extend the base class to implement a given scenario
|
4
|
-
"""
|
5
|
-
|
6
|
-
|
7
|
-
from shapely.geometry import MultiPolygon, Polygon, LineString, Point
|
8
|
-
from datetime import datetime
|
9
|
-
from typing import *
|
10
|
-
import shapely
|
11
|
-
|
12
|
-
from erad.scenarios.common import AssetTypes
|
13
|
-
|
14
|
-
class BaseScenario:
|
15
|
-
|
16
|
-
"""Base class for scenario defination.
|
17
|
-
|
18
|
-
Attributes:
|
19
|
-
geodata (MultiPolygon, Point, LineString): Region of interest
|
20
|
-
probability_model (dict): Dictionary mapping asset types to probability funcitons
|
21
|
-
timestamp (datetime): Scenario occurance time
|
22
|
-
kwargs (dict): Additional parameters relevant for a particular scenario type
|
23
|
-
|
24
|
-
"""
|
25
|
-
|
26
|
-
def __init__(self, geodata : Union[MultiPolygon, Point, LineString] , probability_model : dict, timestamp : datetime, **kwargs) -> None:
|
27
|
-
"""Constructor for BaseScenario class.
|
28
|
-
|
29
|
-
Args:
|
30
|
-
geodata (MultiPolygon, Point, LineString): Region of interest
|
31
|
-
probability_model (dict): Dictionary mapping asset types to probability funcitons
|
32
|
-
timestamp (datetime): Scenario occurance time
|
33
|
-
kwargs (dict): Additional parameters relevant for a particular scenario type
|
34
|
-
"""
|
35
|
-
if probability_model is None:
|
36
|
-
probability_model = self.fragility_curves
|
37
|
-
self.valitate_user_defined_fragility_curves(probability_model)
|
38
|
-
|
39
|
-
|
40
|
-
if isinstance(geodata, Polygon):
|
41
|
-
geodata = MultiPolygon([geodata])
|
42
|
-
|
43
|
-
if isinstance(geodata, MultiPolygon):
|
44
|
-
print("Is multipolygon")
|
45
|
-
self.multipolygon = geodata
|
46
|
-
elif isinstance(geodata, Point):
|
47
|
-
print("Is point")
|
48
|
-
self.origin = geodata
|
49
|
-
elif isinstance(geodata, LineString):
|
50
|
-
print("Is linestring")
|
51
|
-
self.front = geodata
|
52
|
-
else:
|
53
|
-
print(geodata, Point)
|
54
|
-
raise Exception(f"Invalid data type {type(geodata)}")
|
55
|
-
|
56
|
-
self.probability_model = probability_model
|
57
|
-
self.to_projection = f"epsg:{self.identify_stateplane_projection}"
|
58
|
-
self.timestamp = timestamp
|
59
|
-
return
|
60
|
-
|
61
|
-
@property
|
62
|
-
def area(self) -> float:
|
63
|
-
"""Method to calculate area of affected region."""
|
64
|
-
raise NotImplementedError("Method needs to be defined in derived classes")
|
65
|
-
|
66
|
-
@property
|
67
|
-
def polygon(self) -> MultiPolygon:
|
68
|
-
"""Method to return polygon for the affected region."""
|
69
|
-
raise NotImplementedError("Method needs to be defined in derived classes")
|
70
|
-
|
71
|
-
@property
|
72
|
-
def boundary(self) -> LineString:
|
73
|
-
"""Method to return boundary for the affected region."""
|
74
|
-
raise NotImplementedError("Method needs to be defined in derived classes")
|
75
|
-
|
76
|
-
@property
|
77
|
-
def centroid(self) -> Point:
|
78
|
-
"""Method to return the centroid of the affected region."""
|
79
|
-
raise NotImplementedError("Method needs to be defined in derived classes")
|
80
|
-
|
81
|
-
def increment_time(self) -> dict:
|
82
|
-
"""Method to increment simulation time for time evolviong scenarios."""
|
83
|
-
raise NotImplementedError("Method needs to be defined in derived classes")
|
84
|
-
|
85
|
-
def calculate_survival_probability(self, assets : dict, timestamp : datetime) -> dict:
|
86
|
-
"""Method to calculate survival probaility of asset types.
|
87
|
-
|
88
|
-
Args:
|
89
|
-
assets (dict): The dictionary of all assets and their corresponding asset types
|
90
|
-
"""
|
91
|
-
raise NotImplementedError("Method needs to be defined in derived classes")
|
92
|
-
|
93
|
-
def plot(self):
|
94
|
-
"""Method to plot survival probaility of in the region of interest"""
|
95
|
-
raise NotImplementedError("Method needs to be defined in derived classes")
|
96
|
-
|
97
|
-
def asset_survial_probability(self, asset_type):
|
98
|
-
raise NotImplementedError("Method needs to be defined in derived classes")
|
99
|
-
|
100
|
-
def valitate_user_defined_fragility_curves(self, distributions):
|
101
|
-
for asset_type in distributions:
|
102
|
-
assert AssetTypes.has_asset(asset_type), f"{asset_type} is not a valid asset type. Valid options are {list(AssetTypes.__members__.keys())}"
|
1
|
+
""" Module contains the base class defination for all scenarios.
|
2
|
+
|
3
|
+
Each scenario type will extend the base class to implement a given scenario
|
4
|
+
"""
|
5
|
+
|
6
|
+
|
7
|
+
from shapely.geometry import MultiPolygon, Polygon, LineString, Point
|
8
|
+
from datetime import datetime
|
9
|
+
from typing import *
|
10
|
+
import shapely
|
11
|
+
|
12
|
+
from erad.scenarios.common import AssetTypes
|
13
|
+
|
14
|
+
class BaseScenario:
|
15
|
+
|
16
|
+
"""Base class for scenario defination.
|
17
|
+
|
18
|
+
Attributes:
|
19
|
+
geodata (MultiPolygon, Point, LineString): Region of interest
|
20
|
+
probability_model (dict): Dictionary mapping asset types to probability funcitons
|
21
|
+
timestamp (datetime): Scenario occurance time
|
22
|
+
kwargs (dict): Additional parameters relevant for a particular scenario type
|
23
|
+
|
24
|
+
"""
|
25
|
+
|
26
|
+
def __init__(self, geodata : Union[MultiPolygon, Point, LineString] , probability_model : dict, timestamp : datetime, **kwargs) -> None:
|
27
|
+
"""Constructor for BaseScenario class.
|
28
|
+
|
29
|
+
Args:
|
30
|
+
geodata (MultiPolygon, Point, LineString): Region of interest
|
31
|
+
probability_model (dict): Dictionary mapping asset types to probability funcitons
|
32
|
+
timestamp (datetime): Scenario occurance time
|
33
|
+
kwargs (dict): Additional parameters relevant for a particular scenario type
|
34
|
+
"""
|
35
|
+
if probability_model is None:
|
36
|
+
probability_model = self.fragility_curves
|
37
|
+
self.valitate_user_defined_fragility_curves(probability_model)
|
38
|
+
|
39
|
+
|
40
|
+
if isinstance(geodata, Polygon):
|
41
|
+
geodata = MultiPolygon([geodata])
|
42
|
+
|
43
|
+
if isinstance(geodata, MultiPolygon):
|
44
|
+
print("Is multipolygon")
|
45
|
+
self.multipolygon = geodata
|
46
|
+
elif isinstance(geodata, Point):
|
47
|
+
print("Is point")
|
48
|
+
self.origin = geodata
|
49
|
+
elif isinstance(geodata, LineString):
|
50
|
+
print("Is linestring")
|
51
|
+
self.front = geodata
|
52
|
+
else:
|
53
|
+
print(geodata, Point)
|
54
|
+
raise Exception(f"Invalid data type {type(geodata)}")
|
55
|
+
|
56
|
+
self.probability_model = probability_model
|
57
|
+
self.to_projection = f"epsg:{self.identify_stateplane_projection}"
|
58
|
+
self.timestamp = timestamp
|
59
|
+
return
|
60
|
+
|
61
|
+
@property
|
62
|
+
def area(self) -> float:
|
63
|
+
"""Method to calculate area of affected region."""
|
64
|
+
raise NotImplementedError("Method needs to be defined in derived classes")
|
65
|
+
|
66
|
+
@property
|
67
|
+
def polygon(self) -> MultiPolygon:
|
68
|
+
"""Method to return polygon for the affected region."""
|
69
|
+
raise NotImplementedError("Method needs to be defined in derived classes")
|
70
|
+
|
71
|
+
@property
|
72
|
+
def boundary(self) -> LineString:
|
73
|
+
"""Method to return boundary for the affected region."""
|
74
|
+
raise NotImplementedError("Method needs to be defined in derived classes")
|
75
|
+
|
76
|
+
@property
|
77
|
+
def centroid(self) -> Point:
|
78
|
+
"""Method to return the centroid of the affected region."""
|
79
|
+
raise NotImplementedError("Method needs to be defined in derived classes")
|
80
|
+
|
81
|
+
def increment_time(self) -> dict:
|
82
|
+
"""Method to increment simulation time for time evolviong scenarios."""
|
83
|
+
raise NotImplementedError("Method needs to be defined in derived classes")
|
84
|
+
|
85
|
+
def calculate_survival_probability(self, assets : dict, timestamp : datetime) -> dict:
|
86
|
+
"""Method to calculate survival probaility of asset types.
|
87
|
+
|
88
|
+
Args:
|
89
|
+
assets (dict): The dictionary of all assets and their corresponding asset types
|
90
|
+
"""
|
91
|
+
raise NotImplementedError("Method needs to be defined in derived classes")
|
92
|
+
|
93
|
+
def plot(self):
|
94
|
+
"""Method to plot survival probaility of in the region of interest"""
|
95
|
+
raise NotImplementedError("Method needs to be defined in derived classes")
|
96
|
+
|
97
|
+
def asset_survial_probability(self, asset_type):
|
98
|
+
raise NotImplementedError("Method needs to be defined in derived classes")
|
99
|
+
|
100
|
+
def valitate_user_defined_fragility_curves(self, distributions):
|
101
|
+
for asset_type in distributions:
|
102
|
+
assert AssetTypes.has_asset(asset_type), f"{asset_type} is not a valid asset type. Valid options are {list(AssetTypes.__members__.keys())}"
|
103
103
|
return
|
erad/scenarios/common.py
CHANGED
@@ -1,93 +1,93 @@
|
|
1
|
-
from shapely.geometry import MultiPolygon, Point,Polygon
|
2
|
-
from random import random,seed
|
3
|
-
from enum import IntEnum
|
4
|
-
import numpy as np
|
5
|
-
|
6
|
-
class ScenarioTypes(IntEnum):
|
7
|
-
flood_m = 0
|
8
|
-
wind_m_per_s = 1
|
9
|
-
fire_m = 2
|
10
|
-
earthquake_pga = 3
|
11
|
-
|
12
|
-
class AssetTypes(IntEnum):
|
13
|
-
substation = 0
|
14
|
-
solar_panels = 1
|
15
|
-
buried_lines = 2
|
16
|
-
wind_turbines= 3
|
17
|
-
battery_storage = 4
|
18
|
-
transmission_poles = 5
|
19
|
-
distribution_poles = 6
|
20
|
-
transmission_overhead_lines = 7
|
21
|
-
distribution_overhead_lines = 8
|
22
|
-
#substructures
|
23
|
-
#conduit_burial
|
24
|
-
|
25
|
-
@classmethod
|
26
|
-
def has_value(cls, value):
|
27
|
-
return value in cls._value2member_map_
|
28
|
-
|
29
|
-
@classmethod
|
30
|
-
def has_asset(cls, asset):
|
31
|
-
print(asset)
|
32
|
-
return asset in cls.__members__
|
33
|
-
|
34
|
-
|
35
|
-
def asset_list(x1=41.255, y1=-117.33, x2=41.255, y2=-117.33, samples=100):
|
36
|
-
|
37
|
-
x = np.linspace(x1, x2, samples)
|
38
|
-
y = np.linspace(y1, y2, samples)
|
39
|
-
|
40
|
-
seed(3)
|
41
|
-
asset_probabilities = {
|
42
|
-
AssetTypes.substation: 1 / 10000.0,
|
43
|
-
AssetTypes.solar_panels : 1/500,
|
44
|
-
AssetTypes.buried_lines : 1/10.0,
|
45
|
-
AssetTypes.wind_turbines : 1/5000,
|
46
|
-
AssetTypes.battery_storage :1/2000,
|
47
|
-
AssetTypes.transmission_poles: 1 / 10.0,
|
48
|
-
AssetTypes.distribution_poles : 1 / 10.0,
|
49
|
-
AssetTypes.transmission_overhead_lines : 1/10.0,
|
50
|
-
AssetTypes.distribution_overhead_lines : 1/10.0,
|
51
|
-
}
|
52
|
-
|
53
|
-
heights_ft = {
|
54
|
-
AssetTypes.substation.name : 3,
|
55
|
-
AssetTypes.solar_panels.name : 10,
|
56
|
-
AssetTypes.buried_lines.name : -3,
|
57
|
-
AssetTypes.wind_turbines.name : 25,
|
58
|
-
AssetTypes.battery_storage.name : 4,
|
59
|
-
AssetTypes.transmission_poles.name : 0,
|
60
|
-
AssetTypes.distribution_poles.name : 0,
|
61
|
-
AssetTypes.transmission_overhead_lines.name : 100,
|
62
|
-
AssetTypes.distribution_overhead_lines.name : 30,
|
63
|
-
}
|
64
|
-
|
65
|
-
assets = {
|
66
|
-
AssetTypes.substation.name : {},
|
67
|
-
AssetTypes.solar_panels.name : {},
|
68
|
-
AssetTypes.buried_lines.name : {},
|
69
|
-
AssetTypes.wind_turbines.name : {},
|
70
|
-
AssetTypes.battery_storage.name :{},
|
71
|
-
AssetTypes.transmission_poles.name : {},
|
72
|
-
AssetTypes.distribution_poles.name : {},
|
73
|
-
AssetTypes.transmission_overhead_lines.name : {},
|
74
|
-
AssetTypes.distribution_overhead_lines.name : {},
|
75
|
-
}
|
76
|
-
|
77
|
-
for asset_type, probability in asset_probabilities.items():
|
78
|
-
asset_id = 0
|
79
|
-
for x1 in x:
|
80
|
-
for y1 in y:
|
81
|
-
if random() < probability:
|
82
|
-
assets[asset_type.name][f"{asset_type.name} {asset_id}"] = {"coordinates" : (x1, y1), "heights_ft": heights_ft[asset_type.name]}
|
83
|
-
asset_id += 1
|
84
|
-
|
85
|
-
p1 = Point(x.min(), y.min())
|
86
|
-
p2 = Point(x.max(), y.min())
|
87
|
-
p3 = Point(x.max(), y.max())
|
88
|
-
p4 = Point(x.min(), y.max())
|
89
|
-
pointList = [p1, p2, p3, p4, p1]
|
90
|
-
poly = Polygon(pointList)
|
91
|
-
mypoly = MultiPolygon([poly])
|
92
|
-
|
1
|
+
from shapely.geometry import MultiPolygon, Point,Polygon
|
2
|
+
from random import random,seed
|
3
|
+
from enum import IntEnum
|
4
|
+
import numpy as np
|
5
|
+
|
6
|
+
class ScenarioTypes(IntEnum):
|
7
|
+
flood_m = 0
|
8
|
+
wind_m_per_s = 1
|
9
|
+
fire_m = 2
|
10
|
+
earthquake_pga = 3
|
11
|
+
|
12
|
+
class AssetTypes(IntEnum):
|
13
|
+
substation = 0
|
14
|
+
solar_panels = 1
|
15
|
+
buried_lines = 2
|
16
|
+
wind_turbines= 3
|
17
|
+
battery_storage = 4
|
18
|
+
transmission_poles = 5
|
19
|
+
distribution_poles = 6
|
20
|
+
transmission_overhead_lines = 7
|
21
|
+
distribution_overhead_lines = 8
|
22
|
+
#substructures
|
23
|
+
#conduit_burial
|
24
|
+
|
25
|
+
@classmethod
|
26
|
+
def has_value(cls, value):
|
27
|
+
return value in cls._value2member_map_
|
28
|
+
|
29
|
+
@classmethod
|
30
|
+
def has_asset(cls, asset):
|
31
|
+
print(asset)
|
32
|
+
return asset in cls.__members__
|
33
|
+
|
34
|
+
|
35
|
+
def asset_list(x1=41.255, y1=-117.33, x2=41.255, y2=-117.33, samples=100):
|
36
|
+
|
37
|
+
x = np.linspace(x1, x2, samples)
|
38
|
+
y = np.linspace(y1, y2, samples)
|
39
|
+
|
40
|
+
seed(3)
|
41
|
+
asset_probabilities = {
|
42
|
+
AssetTypes.substation: 1 / 10000.0,
|
43
|
+
AssetTypes.solar_panels : 1/500,
|
44
|
+
AssetTypes.buried_lines : 1/10.0,
|
45
|
+
AssetTypes.wind_turbines : 1/5000,
|
46
|
+
AssetTypes.battery_storage :1/2000,
|
47
|
+
AssetTypes.transmission_poles: 1 / 10.0,
|
48
|
+
AssetTypes.distribution_poles : 1 / 10.0,
|
49
|
+
AssetTypes.transmission_overhead_lines : 1/10.0,
|
50
|
+
AssetTypes.distribution_overhead_lines : 1/10.0,
|
51
|
+
}
|
52
|
+
|
53
|
+
heights_ft = {
|
54
|
+
AssetTypes.substation.name : 3,
|
55
|
+
AssetTypes.solar_panels.name : 10,
|
56
|
+
AssetTypes.buried_lines.name : -3,
|
57
|
+
AssetTypes.wind_turbines.name : 25,
|
58
|
+
AssetTypes.battery_storage.name : 4,
|
59
|
+
AssetTypes.transmission_poles.name : 0,
|
60
|
+
AssetTypes.distribution_poles.name : 0,
|
61
|
+
AssetTypes.transmission_overhead_lines.name : 100,
|
62
|
+
AssetTypes.distribution_overhead_lines.name : 30,
|
63
|
+
}
|
64
|
+
|
65
|
+
assets = {
|
66
|
+
AssetTypes.substation.name : {},
|
67
|
+
AssetTypes.solar_panels.name : {},
|
68
|
+
AssetTypes.buried_lines.name : {},
|
69
|
+
AssetTypes.wind_turbines.name : {},
|
70
|
+
AssetTypes.battery_storage.name :{},
|
71
|
+
AssetTypes.transmission_poles.name : {},
|
72
|
+
AssetTypes.distribution_poles.name : {},
|
73
|
+
AssetTypes.transmission_overhead_lines.name : {},
|
74
|
+
AssetTypes.distribution_overhead_lines.name : {},
|
75
|
+
}
|
76
|
+
|
77
|
+
for asset_type, probability in asset_probabilities.items():
|
78
|
+
asset_id = 0
|
79
|
+
for x1 in x:
|
80
|
+
for y1 in y:
|
81
|
+
if random() < probability:
|
82
|
+
assets[asset_type.name][f"{asset_type.name} {asset_id}"] = {"coordinates" : (x1, y1), "heights_ft": heights_ft[asset_type.name]}
|
83
|
+
asset_id += 1
|
84
|
+
|
85
|
+
p1 = Point(x.min(), y.min())
|
86
|
+
p2 = Point(x.max(), y.min())
|
87
|
+
p3 = Point(x.max(), y.max())
|
88
|
+
p4 = Point(x.min(), y.max())
|
89
|
+
pointList = [p1, p2, p3, p4, p1]
|
90
|
+
poly = Polygon(pointList)
|
91
|
+
mypoly = MultiPolygon([poly])
|
92
|
+
|
93
93
|
return assets, mypoly
|