power-grid-model 1.11.45__py3-none-musllinux_1_2_x86_64.whl → 1.12.114__py3-none-musllinux_1_2_x86_64.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.
- power_grid_model/__init__.py +4 -4
- power_grid_model/_core/buffer_handling.py +24 -4
- power_grid_model/_core/data_handling.py +66 -12
- power_grid_model/_core/data_types.py +21 -11
- power_grid_model/_core/dataset_definitions.py +6 -5
- power_grid_model/_core/error_handling.py +39 -30
- power_grid_model/_core/errors.py +4 -0
- power_grid_model/_core/options.py +14 -13
- power_grid_model/_core/power_grid_core.py +24 -28
- power_grid_model/_core/power_grid_dataset.py +39 -28
- power_grid_model/_core/power_grid_meta.py +37 -18
- power_grid_model/_core/power_grid_model.py +382 -44
- power_grid_model/_core/power_grid_model_c/__init__.py +3 -0
- power_grid_model/_core/power_grid_model_c/get_pgm_dll_path.py +63 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_c/basics.h +251 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_c/buffer.h +108 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_c/dataset.h +332 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_c/dataset_definitions.h +1060 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_c/handle.h +111 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_c/meta_data.h +189 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_c/model.h +130 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_c/options.h +142 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_c/serialization.h +118 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_c.h +36 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_cpp/basics.hpp +65 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_cpp/buffer.hpp +61 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_cpp/dataset.hpp +224 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_cpp/handle.hpp +108 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_cpp/meta_data.hpp +84 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_cpp/model.hpp +63 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_cpp/options.hpp +52 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_cpp/serialization.hpp +124 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_cpp/utils.hpp +81 -0
- power_grid_model/_core/power_grid_model_c/include/power_grid_model_cpp.hpp +19 -0
- power_grid_model/_core/power_grid_model_c/lib/cmake/power_grid_model/power_grid_modelConfig.cmake +37 -0
- power_grid_model/_core/power_grid_model_c/lib/cmake/power_grid_model/power_grid_modelConfigVersion.cmake +65 -0
- power_grid_model/_core/power_grid_model_c/lib/cmake/power_grid_model/power_grid_modelTargets-release.cmake +19 -0
- power_grid_model/_core/power_grid_model_c/lib/cmake/power_grid_model/power_grid_modelTargets.cmake +144 -0
- power_grid_model/_core/power_grid_model_c/lib/libpower_grid_model_c.so +0 -0
- power_grid_model/_core/power_grid_model_c/lib/libpower_grid_model_c.so.1.12.114 +0 -0
- power_grid_model/_core/power_grid_model_c/share/LICENSE +292 -0
- power_grid_model/_core/power_grid_model_c/share/README.md +15 -0
- power_grid_model/_core/serialization.py +11 -9
- power_grid_model/_core/typing.py +2 -2
- power_grid_model/_core/utils.py +15 -9
- power_grid_model/data_types.py +1 -1
- power_grid_model/typing.py +1 -1
- power_grid_model/utils.py +67 -7
- power_grid_model/validation/__init__.py +2 -2
- power_grid_model/validation/_rules.py +15 -23
- power_grid_model/validation/_validation.py +2 -2
- power_grid_model/validation/errors.py +7 -6
- power_grid_model/validation/utils.py +5 -6
- {power_grid_model-1.11.45.dist-info → power_grid_model-1.12.114.dist-info}/METADATA +10 -30
- power_grid_model-1.12.114.dist-info/RECORD +68 -0
- {power_grid_model-1.11.45.dist-info → power_grid_model-1.12.114.dist-info}/WHEEL +1 -1
- power_grid_model-1.12.114.dist-info/entry_points.txt +3 -0
- power_grid_model-1.12.114.dist-info/sboms/auditwheel.cdx.json +1 -0
- power_grid_model/_core/_power_grid_core.so +0 -0
- power_grid_model-1.11.45.dist-info/RECORD +0 -38
- power_grid_model-1.11.45.dist-info/top_level.txt +0 -1
- {power_grid_model-1.11.45.dist-info → power_grid_model-1.12.114.dist-info}/licenses/LICENSE +0 -0
power_grid_model/__init__.py
CHANGED
|
@@ -30,8 +30,6 @@ from power_grid_model.enum import (
|
|
|
30
30
|
from power_grid_model.typing import ComponentAttributeMapping
|
|
31
31
|
|
|
32
32
|
__all__ = [
|
|
33
|
-
"attribute_dtype",
|
|
34
|
-
"attribute_empty_value",
|
|
35
33
|
"AngleMeasurementType",
|
|
36
34
|
"Branch3Side",
|
|
37
35
|
"BranchSide",
|
|
@@ -43,12 +41,14 @@ __all__ = [
|
|
|
43
41
|
"DatasetType",
|
|
44
42
|
"FaultPhase",
|
|
45
43
|
"FaultType",
|
|
46
|
-
"initialize_array",
|
|
47
44
|
"LoadGenType",
|
|
48
45
|
"MeasuredTerminalType",
|
|
49
46
|
"PowerGridModel",
|
|
50
|
-
"power_grid_meta_data",
|
|
51
47
|
"ShortCircuitVoltageScaling",
|
|
52
48
|
"TapChangingStrategy",
|
|
53
49
|
"WindingType",
|
|
50
|
+
"attribute_dtype",
|
|
51
|
+
"attribute_empty_value",
|
|
52
|
+
"initialize_array",
|
|
53
|
+
"power_grid_meta_data",
|
|
54
54
|
]
|
|
@@ -7,15 +7,19 @@ Power grid model buffer handler
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
from dataclasses import dataclass
|
|
10
|
-
from typing import cast
|
|
10
|
+
from typing import cast, overload
|
|
11
11
|
|
|
12
12
|
import numpy as np
|
|
13
13
|
|
|
14
14
|
from power_grid_model._core.data_types import (
|
|
15
15
|
AttributeType,
|
|
16
16
|
ComponentData,
|
|
17
|
+
DenseBatchArray,
|
|
18
|
+
DenseBatchColumnarData,
|
|
17
19
|
DenseBatchData,
|
|
18
20
|
IndexPointer,
|
|
21
|
+
SingleArray,
|
|
22
|
+
SingleColumnarData,
|
|
19
23
|
SingleComponentData,
|
|
20
24
|
SparseBatchArray,
|
|
21
25
|
SparseBatchData,
|
|
@@ -88,6 +92,10 @@ def _get_raw_data_view(data: np.ndarray, dtype: np.dtype) -> VoidPtr:
|
|
|
88
92
|
return np.ascontiguousarray(data, dtype=dtype).ctypes.data_as(VoidPtr)
|
|
89
93
|
|
|
90
94
|
|
|
95
|
+
@overload
|
|
96
|
+
def _get_raw_component_data_view(data: np.ndarray, schema: ComponentMetaData) -> VoidPtr: ...
|
|
97
|
+
@overload
|
|
98
|
+
def _get_raw_component_data_view(data: dict[AttributeType, np.ndarray], schema: ComponentMetaData) -> None: ...
|
|
91
99
|
def _get_raw_component_data_view(
|
|
92
100
|
data: np.ndarray | dict[AttributeType, np.ndarray], schema: ComponentMetaData
|
|
93
101
|
) -> VoidPtr | None:
|
|
@@ -200,9 +208,15 @@ def _get_dense_buffer_properties(
|
|
|
200
208
|
n_total_elements = actual_batch_size * n_elements_per_scenario
|
|
201
209
|
|
|
202
210
|
if is_batch is not None and is_batch != actual_is_batch:
|
|
203
|
-
raise ValueError(
|
|
211
|
+
raise ValueError(
|
|
212
|
+
f"Incorrect/inconsistent data provided: {'batch' if actual_is_batch else 'single'} "
|
|
213
|
+
f"data provided but {'batch' if is_batch else 'single'} data expected. {VALIDATOR_MSG}"
|
|
214
|
+
)
|
|
204
215
|
if batch_size is not None and batch_size != actual_batch_size:
|
|
205
|
-
raise ValueError(
|
|
216
|
+
raise ValueError(
|
|
217
|
+
f"Incorrect/inconsistent batch size provided: {actual_batch_size} scenarios provided "
|
|
218
|
+
f"but {batch_size} scenarios expected. {VALIDATOR_MSG}"
|
|
219
|
+
)
|
|
206
220
|
|
|
207
221
|
return BufferProperties(
|
|
208
222
|
is_sparse=is_sparse_property,
|
|
@@ -480,7 +494,13 @@ def _create_sparse_buffer(properties: BufferProperties, schema: ComponentMetaDat
|
|
|
480
494
|
return cast(SparseBatchData, {"data": data, "indptr": indptr})
|
|
481
495
|
|
|
482
496
|
|
|
483
|
-
|
|
497
|
+
@overload
|
|
498
|
+
def _create_contents_buffer(shape, dtype, columns: None) -> SingleArray | DenseBatchArray: ...
|
|
499
|
+
@overload
|
|
500
|
+
def _create_contents_buffer(
|
|
501
|
+
shape, dtype, columns: list[AttributeType]
|
|
502
|
+
) -> SingleColumnarData | DenseBatchColumnarData: ...
|
|
503
|
+
def _create_contents_buffer(shape, dtype, columns):
|
|
484
504
|
if columns is None:
|
|
485
505
|
return np.empty(shape=shape, dtype=dtype)
|
|
486
506
|
|
|
@@ -6,16 +6,26 @@
|
|
|
6
6
|
Data handling
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
+
from typing import Literal, overload
|
|
10
|
+
|
|
9
11
|
import numpy as np
|
|
10
12
|
|
|
11
|
-
from power_grid_model._core.data_types import
|
|
12
|
-
|
|
13
|
+
from power_grid_model._core.data_types import (
|
|
14
|
+
BatchDataset,
|
|
15
|
+
Dataset,
|
|
16
|
+
DenseBatchArray,
|
|
17
|
+
SingleArray,
|
|
18
|
+
SingleColumnarData,
|
|
19
|
+
SingleDataset,
|
|
20
|
+
)
|
|
21
|
+
from power_grid_model._core.dataset_definitions import ComponentType, ComponentTypeVar, DatasetType
|
|
13
22
|
from power_grid_model._core.enum import CalculationType, ComponentAttributeFilterOptions
|
|
14
23
|
from power_grid_model._core.errors import PowerGridUnreachableHitError
|
|
15
24
|
from power_grid_model._core.power_grid_dataset import CConstDataset, CMutableDataset
|
|
16
25
|
from power_grid_model._core.power_grid_meta import initialize_array, power_grid_meta_data
|
|
17
|
-
from power_grid_model._core.typing import ComponentAttributeMapping
|
|
26
|
+
from power_grid_model._core.typing import ComponentAttributeMapping, ComponentAttributeMappingDict
|
|
18
27
|
from power_grid_model._core.utils import process_data_filter
|
|
28
|
+
from power_grid_model.data_types import DenseBatchColumnarData
|
|
19
29
|
|
|
20
30
|
|
|
21
31
|
def get_output_type(*, calculation_type: CalculationType, symmetric: bool) -> DatasetType:
|
|
@@ -38,7 +48,7 @@ def get_output_type(*, calculation_type: CalculationType, symmetric: bool) -> Da
|
|
|
38
48
|
if calculation_type == CalculationType.short_circuit:
|
|
39
49
|
return DatasetType.sc_output
|
|
40
50
|
|
|
41
|
-
raise NotImplementedError
|
|
51
|
+
raise NotImplementedError
|
|
42
52
|
|
|
43
53
|
|
|
44
54
|
def prepare_input_view(input_data: SingleDataset) -> CConstDataset:
|
|
@@ -85,6 +95,54 @@ def prepare_output_view(output_data: Dataset, output_type: DatasetType) -> CMuta
|
|
|
85
95
|
return CMutableDataset(output_data, dataset_type=output_type)
|
|
86
96
|
|
|
87
97
|
|
|
98
|
+
@overload
|
|
99
|
+
def create_output_data(
|
|
100
|
+
output_component_types: None | set[ComponentTypeVar] | list[ComponentTypeVar],
|
|
101
|
+
output_type: DatasetType,
|
|
102
|
+
all_component_count: dict[ComponentType, int],
|
|
103
|
+
is_batch: Literal[False],
|
|
104
|
+
batch_size: int,
|
|
105
|
+
) -> dict[ComponentType, SingleArray]: ...
|
|
106
|
+
@overload
|
|
107
|
+
def create_output_data(
|
|
108
|
+
output_component_types: None | set[ComponentTypeVar] | list[ComponentTypeVar],
|
|
109
|
+
output_type: DatasetType,
|
|
110
|
+
all_component_count: dict[ComponentType, int],
|
|
111
|
+
is_batch: Literal[True],
|
|
112
|
+
batch_size: int,
|
|
113
|
+
) -> dict[ComponentType, DenseBatchArray]: ...
|
|
114
|
+
@overload
|
|
115
|
+
def create_output_data(
|
|
116
|
+
output_component_types: ComponentAttributeFilterOptions,
|
|
117
|
+
output_type: DatasetType,
|
|
118
|
+
all_component_count: dict[ComponentType, int],
|
|
119
|
+
is_batch: Literal[False],
|
|
120
|
+
batch_size: int,
|
|
121
|
+
) -> dict[ComponentType, SingleColumnarData]: ...
|
|
122
|
+
@overload
|
|
123
|
+
def create_output_data(
|
|
124
|
+
output_component_types: ComponentAttributeFilterOptions,
|
|
125
|
+
output_type: DatasetType,
|
|
126
|
+
all_component_count: dict[ComponentType, int],
|
|
127
|
+
is_batch: Literal[True],
|
|
128
|
+
batch_size: int,
|
|
129
|
+
) -> dict[ComponentType, DenseBatchColumnarData]: ...
|
|
130
|
+
@overload
|
|
131
|
+
def create_output_data(
|
|
132
|
+
output_component_types: ComponentAttributeMappingDict,
|
|
133
|
+
output_type: DatasetType,
|
|
134
|
+
all_component_count: dict[ComponentType, int],
|
|
135
|
+
is_batch: Literal[False],
|
|
136
|
+
batch_size: int,
|
|
137
|
+
) -> SingleDataset: ...
|
|
138
|
+
@overload
|
|
139
|
+
def create_output_data(
|
|
140
|
+
output_component_types: ComponentAttributeMappingDict,
|
|
141
|
+
output_type: DatasetType,
|
|
142
|
+
all_component_count: dict[ComponentType, int],
|
|
143
|
+
is_batch: Literal[True],
|
|
144
|
+
batch_size: int,
|
|
145
|
+
) -> BatchDataset: ...
|
|
88
146
|
def create_output_data(
|
|
89
147
|
output_component_types: ComponentAttributeMapping,
|
|
90
148
|
output_type: DatasetType,
|
|
@@ -96,7 +154,7 @@ def create_output_data(
|
|
|
96
154
|
Create the output dataset based on component and batch size from the model; and output attributes requested by user.
|
|
97
155
|
|
|
98
156
|
Args:
|
|
99
|
-
output_component_types:
|
|
157
|
+
output_component_types (ComponentAttributeMapping):
|
|
100
158
|
the output components the user seeks to extract
|
|
101
159
|
output_type:
|
|
102
160
|
the type of output that the user will see (as per the calculation options)
|
|
@@ -118,11 +176,7 @@ def create_output_data(
|
|
|
118
176
|
result_dict: Dataset = {}
|
|
119
177
|
|
|
120
178
|
for name, count in all_component_count.items():
|
|
121
|
-
|
|
122
|
-
if is_batch:
|
|
123
|
-
shape: tuple[int] | tuple[int, int] = (batch_size, count)
|
|
124
|
-
else:
|
|
125
|
-
shape = (count,)
|
|
179
|
+
shape: tuple[int, int] | int = (batch_size, count) if is_batch else count
|
|
126
180
|
|
|
127
181
|
requested_component = processed_output_types[name]
|
|
128
182
|
dtype = power_grid_meta_data[output_type][name].dtype
|
|
@@ -134,8 +188,8 @@ def create_output_data(
|
|
|
134
188
|
ComponentAttributeFilterOptions.everything,
|
|
135
189
|
ComponentAttributeFilterOptions.relevant,
|
|
136
190
|
]:
|
|
137
|
-
result_dict[name] = {attr: np.empty(shape, dtype=dtype[attr]) for attr in dtype.names}
|
|
191
|
+
result_dict[name] = {attr: np.empty(shape=shape, dtype=dtype[attr]) for attr in dtype.names}
|
|
138
192
|
elif isinstance(requested_component, list | set):
|
|
139
|
-
result_dict[name] = {attr: np.empty(shape, dtype=dtype[attr]) for attr in requested_component}
|
|
193
|
+
result_dict[name] = {attr: np.empty(shape=shape, dtype=dtype[attr]) for attr in requested_component}
|
|
140
194
|
|
|
141
195
|
return result_dict
|
|
@@ -9,35 +9,35 @@ Data types for library-internal use. In an attempt to clarify type hints, some t
|
|
|
9
9
|
have been defined and explained in this file.
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
|
-
from typing import
|
|
12
|
+
from typing import TypedDict, TypeVar
|
|
13
13
|
|
|
14
14
|
import numpy as np
|
|
15
15
|
|
|
16
|
-
from power_grid_model._core.dataset_definitions import ComponentTypeVar
|
|
16
|
+
from power_grid_model._core.dataset_definitions import ComponentType, ComponentTypeVar
|
|
17
17
|
|
|
18
|
-
SingleArray
|
|
18
|
+
type SingleArray = np.ndarray
|
|
19
19
|
|
|
20
|
-
AttributeType
|
|
20
|
+
type AttributeType = str
|
|
21
21
|
|
|
22
|
-
SingleColumn
|
|
23
|
-
|
|
24
|
-
DenseBatchArray: TypeAlias = np.ndarray
|
|
22
|
+
type SingleColumn = np.ndarray
|
|
23
|
+
type DenseBatchArray = np.ndarray
|
|
25
24
|
|
|
26
25
|
SingleColumnarData = dict[AttributeType, SingleColumn]
|
|
27
26
|
|
|
28
27
|
_SingleComponentData = TypeVar("_SingleComponentData", SingleArray, SingleColumnarData) # deduction helper
|
|
29
28
|
SingleComponentData = SingleArray | SingleColumnarData
|
|
30
29
|
|
|
31
|
-
|
|
30
|
+
SingleRowBasedDataset = dict[ComponentTypeVar, SingleArray]
|
|
31
|
+
SingleColumnarDataset = dict[ComponentTypeVar, SingleColumnarData]
|
|
32
32
|
SingleDataset = dict[ComponentTypeVar, _SingleComponentData]
|
|
33
33
|
|
|
34
34
|
BatchList = list[SingleDataset]
|
|
35
35
|
|
|
36
|
-
BatchColumn
|
|
36
|
+
type BatchColumn = np.ndarray
|
|
37
37
|
|
|
38
38
|
DenseBatchColumnarData = dict[AttributeType, BatchColumn]
|
|
39
39
|
|
|
40
|
-
IndexPointer
|
|
40
|
+
type IndexPointer = np.ndarray
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
class SparseBatchColumnarData(TypedDict):
|
|
@@ -86,7 +86,7 @@ class SparseBatchArray(TypedDict):
|
|
|
86
86
|
|
|
87
87
|
SparseBatchData = SparseBatchArray | SparseBatchColumnarData
|
|
88
88
|
|
|
89
|
-
SparseDataComponentType
|
|
89
|
+
type SparseDataComponentType = str
|
|
90
90
|
|
|
91
91
|
BatchColumnarData = DenseBatchColumnarData | SparseBatchColumnarData
|
|
92
92
|
|
|
@@ -113,6 +113,16 @@ Dataset = dict[ComponentTypeVar, _ComponentData]
|
|
|
113
113
|
|
|
114
114
|
DenseBatchData = DenseBatchArray | DenseBatchColumnarData
|
|
115
115
|
|
|
116
|
+
# overloads that only match on latest PGM type
|
|
117
|
+
SingleRowBasedOutputDataset = dict[ComponentType, SingleArray]
|
|
118
|
+
SingleColumnarOutputDataset = dict[ComponentType, SingleColumnarData]
|
|
119
|
+
SingleOutputDataset = dict[ComponentType, SingleComponentData]
|
|
120
|
+
DenseBatchRowBasedOutputDataset = dict[ComponentType, DenseBatchArray]
|
|
121
|
+
DenseBatchColumnarOutputDataset = dict[ComponentType, DenseBatchColumnarData]
|
|
122
|
+
DenseBatchOutputDataset = dict[ComponentType, DenseBatchData]
|
|
123
|
+
OutputDataset = dict[ComponentType, ComponentData]
|
|
124
|
+
|
|
125
|
+
|
|
116
126
|
NominalValue = int
|
|
117
127
|
|
|
118
128
|
RealValue = float
|
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
# This file is automatically generated. DO NOT modify it manually!
|
|
8
8
|
|
|
9
|
+
from collections.abc import Mapping
|
|
9
10
|
from enum import Enum, EnumMeta
|
|
10
|
-
from typing import
|
|
11
|
+
from typing import TypeVar
|
|
11
12
|
|
|
12
13
|
# fmt: off
|
|
13
14
|
|
|
@@ -75,10 +76,10 @@ class ComponentType(str, Enum, metaclass=_MetaEnum):
|
|
|
75
76
|
fault = "fault"
|
|
76
77
|
|
|
77
78
|
|
|
78
|
-
DatasetTypeLike
|
|
79
|
+
type DatasetTypeLike = DatasetType | str
|
|
79
80
|
DatasetTypeVar = TypeVar("DatasetTypeVar", bound=DatasetTypeLike) # helper used for type deduction
|
|
80
81
|
|
|
81
|
-
ComponentTypeLike
|
|
82
|
+
type ComponentTypeLike = ComponentType | str
|
|
82
83
|
ComponentTypeVar = TypeVar("ComponentTypeVar", bound=ComponentTypeLike) # helper used for type deduction
|
|
83
84
|
|
|
84
85
|
|
|
@@ -89,7 +90,7 @@ def _str_to_datatype(data_type: DatasetTypeLike) -> DatasetType:
|
|
|
89
90
|
return DatasetType[data_type]
|
|
90
91
|
|
|
91
92
|
|
|
92
|
-
def _map_to_datatypes(data: Mapping[
|
|
93
|
+
def _map_to_datatypes[K: DatasetTypeLike, V](data: Mapping[K, V]) -> dict[DatasetType, V]:
|
|
93
94
|
"""Helper function to map datatype str keys to DatasetType."""
|
|
94
95
|
return {_str_to_datatype(key): value for key, value in data.items()}
|
|
95
96
|
|
|
@@ -101,7 +102,7 @@ def _str_to_component_type(component: ComponentTypeLike) -> ComponentType:
|
|
|
101
102
|
return ComponentType[component]
|
|
102
103
|
|
|
103
104
|
|
|
104
|
-
def _map_to_component_types(data: Mapping[
|
|
105
|
+
def _map_to_component_types[K: ComponentTypeLike, V](data: Mapping[K, V]) -> dict[ComponentType, V]:
|
|
105
106
|
"""Helper function to map componenttype str keys to ComponentType."""
|
|
106
107
|
return {_str_to_component_type(key): value for key, value in data.items()}
|
|
107
108
|
|
|
@@ -7,6 +7,7 @@ Error handling
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
import re
|
|
10
|
+
from enum import IntEnum
|
|
10
11
|
|
|
11
12
|
import numpy as np
|
|
12
13
|
|
|
@@ -33,6 +34,7 @@ from power_grid_model._core.errors import (
|
|
|
33
34
|
PowerGridBatchError,
|
|
34
35
|
PowerGridDatasetError,
|
|
35
36
|
PowerGridError,
|
|
37
|
+
PowerGridIllegalOperationError,
|
|
36
38
|
PowerGridNotImplementedError,
|
|
37
39
|
PowerGridSerializationError,
|
|
38
40
|
PowerGridUnreachableHitError,
|
|
@@ -40,14 +42,17 @@ from power_grid_model._core.errors import (
|
|
|
40
42
|
TapSearchStrategyIncompatibleError,
|
|
41
43
|
)
|
|
42
44
|
from power_grid_model._core.index_integer import IdxNp
|
|
43
|
-
from power_grid_model._core.power_grid_core import
|
|
45
|
+
from power_grid_model._core.power_grid_core import get_power_grid_core as get_pgc
|
|
44
46
|
|
|
45
47
|
VALIDATOR_MSG = "\nTry validate_input_data() or validate_batch_data() to validate your data.\n"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class _PgmCErrorCode(IntEnum):
|
|
51
|
+
NO_ERROR = 0
|
|
52
|
+
REGULAR_ERROR = 1
|
|
53
|
+
BATCH_ERROR = 2
|
|
54
|
+
SERIALIZATION_ERROR = 3
|
|
55
|
+
|
|
51
56
|
|
|
52
57
|
_MISSING_CASE_FOR_ENUM_RE = re.compile(r" is not implemented for (.+) #(-?\d+)!\n")
|
|
53
58
|
_INVALID_ARGUMENTS_RE = re.compile(r" is not implemented for ") # multiple different flavors
|
|
@@ -82,6 +87,7 @@ _INVALID_CALCULATION_METHOD_RE = re.compile(r"The calculation method is invalid
|
|
|
82
87
|
_INVALID_SHORT_CIRCUIT_PHASE_OR_TYPE_RE = re.compile(r"short circuit type") # multiple different flavors
|
|
83
88
|
_TAP_STRATEGY_SEARCH_OPT_INCMPT_RE = re.compile(r"Search method is incompatible with optimization strategy: ")
|
|
84
89
|
_POWER_GRID_DATASET_ERROR_RE = re.compile(r"Dataset error: ") # multiple different flavors
|
|
90
|
+
_POWER_GRID_ILLEGAL_OPERATION_ERROR_RE = re.compile(r"Illegal operation: ") # multiple different flavors
|
|
85
91
|
_POWER_GRID_UNREACHABLE_HIT_RE = re.compile(r"Unreachable code hit when executing ") # multiple different flavors
|
|
86
92
|
_POWER_GRID_NOT_IMPLEMENTED_ERROR_RE = re.compile(r"The functionality is either not supported or not yet implemented!")
|
|
87
93
|
|
|
@@ -108,6 +114,7 @@ _ERROR_MESSAGE_PATTERNS = {
|
|
|
108
114
|
_INVALID_SHORT_CIRCUIT_PHASE_OR_TYPE_RE: InvalidShortCircuitPhaseOrType,
|
|
109
115
|
_TAP_STRATEGY_SEARCH_OPT_INCMPT_RE: TapSearchStrategyIncompatibleError,
|
|
110
116
|
_POWER_GRID_DATASET_ERROR_RE: PowerGridDatasetError,
|
|
117
|
+
_POWER_GRID_ILLEGAL_OPERATION_ERROR_RE: PowerGridIllegalOperationError,
|
|
111
118
|
_POWER_GRID_UNREACHABLE_HIT_RE: PowerGridUnreachableHitError,
|
|
112
119
|
_POWER_GRID_NOT_IMPLEMENTED_ERROR_RE: PowerGridNotImplementedError,
|
|
113
120
|
}
|
|
@@ -133,30 +140,32 @@ def find_error(batch_size: int = 1, decode_error: bool = True) -> RuntimeError |
|
|
|
133
140
|
Returns: error object, can be none
|
|
134
141
|
|
|
135
142
|
"""
|
|
136
|
-
error_code: int =
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
143
|
+
error_code: int = get_pgc().error_code()
|
|
144
|
+
match error_code:
|
|
145
|
+
case _PgmCErrorCode.NO_ERROR:
|
|
146
|
+
return None
|
|
147
|
+
case _PgmCErrorCode.REGULAR_ERROR:
|
|
148
|
+
error_message = get_pgc().error_message()
|
|
149
|
+
error_message += VALIDATOR_MSG
|
|
150
|
+
return _interpret_error(error_message, decode_error=decode_error)
|
|
151
|
+
case _PgmCErrorCode.BATCH_ERROR:
|
|
152
|
+
error_message = "There are errors in the batch calculation." + VALIDATOR_MSG
|
|
153
|
+
error = PowerGridBatchError(error_message)
|
|
154
|
+
n_fails = get_pgc().n_failed_scenarios()
|
|
155
|
+
failed_idxptr = get_pgc().failed_scenarios()
|
|
156
|
+
failed_msgptr = get_pgc().batch_errors()
|
|
157
|
+
error.failed_scenarios = np.ctypeslib.as_array(failed_idxptr, shape=(n_fails,)).copy()
|
|
158
|
+
error.error_messages = [failed_msgptr[i].decode() for i in range(n_fails)] # type: ignore
|
|
159
|
+
error.errors = [_interpret_error(message, decode_error=decode_error) for message in error.error_messages]
|
|
160
|
+
all_scenarios = np.arange(batch_size, dtype=IdxNp)
|
|
161
|
+
mask = np.ones(batch_size, dtype=np.bool_)
|
|
162
|
+
mask[error.failed_scenarios] = False
|
|
163
|
+
error.succeeded_scenarios = all_scenarios[mask]
|
|
164
|
+
return error
|
|
165
|
+
case _PgmCErrorCode.SERIALIZATION_ERROR:
|
|
166
|
+
return PowerGridSerializationError(get_pgc().error_message())
|
|
167
|
+
case _:
|
|
168
|
+
return RuntimeError("Unknown error!")
|
|
160
169
|
|
|
161
170
|
|
|
162
171
|
def assert_no_error(batch_size: int = 1, decode_error: bool = True):
|
power_grid_model/_core/errors.py
CHANGED
|
@@ -124,6 +124,10 @@ class PowerGridNotImplementedError(PowerGridError):
|
|
|
124
124
|
"""The functionality is either not supported or not yet implemented."""
|
|
125
125
|
|
|
126
126
|
|
|
127
|
+
class PowerGridIllegalOperationError(PowerGridError):
|
|
128
|
+
"""An illegal operation was attempted to the C API, such as accessing a null pointer."""
|
|
129
|
+
|
|
130
|
+
|
|
127
131
|
class PowerGridUnreachableHitError(PowerGridError):
|
|
128
132
|
"""Supposedly unreachable code was hit.
|
|
129
133
|
|
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
Option class
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
from
|
|
9
|
+
from collections.abc import Callable
|
|
10
|
+
from typing import Any
|
|
10
11
|
|
|
11
|
-
from power_grid_model._core.power_grid_core import OptionsPtr,
|
|
12
|
+
from power_grid_model._core.power_grid_core import OptionsPtr, get_power_grid_core as get_pgc
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class OptionSetter:
|
|
@@ -35,15 +36,15 @@ class Options:
|
|
|
35
36
|
|
|
36
37
|
_opt: OptionsPtr
|
|
37
38
|
# option setter
|
|
38
|
-
calculation_type = OptionSetter(
|
|
39
|
-
calculation_method = OptionSetter(
|
|
40
|
-
symmetric = OptionSetter(
|
|
41
|
-
error_tolerance = OptionSetter(
|
|
42
|
-
max_iterations = OptionSetter(
|
|
43
|
-
threading = OptionSetter(
|
|
44
|
-
tap_changing_strategy = OptionSetter(
|
|
45
|
-
short_circuit_voltage_scaling = OptionSetter(
|
|
46
|
-
experimental_features = OptionSetter(
|
|
39
|
+
calculation_type = OptionSetter(get_pgc().set_calculation_type)
|
|
40
|
+
calculation_method = OptionSetter(get_pgc().set_calculation_method)
|
|
41
|
+
symmetric = OptionSetter(get_pgc().set_symmetric)
|
|
42
|
+
error_tolerance = OptionSetter(get_pgc().set_err_tol)
|
|
43
|
+
max_iterations = OptionSetter(get_pgc().set_max_iter)
|
|
44
|
+
threading = OptionSetter(get_pgc().set_threading)
|
|
45
|
+
tap_changing_strategy = OptionSetter(get_pgc().set_tap_changing_strategy)
|
|
46
|
+
short_circuit_voltage_scaling = OptionSetter(get_pgc().set_short_circuit_voltage_scaling)
|
|
47
|
+
experimental_features = OptionSetter(get_pgc().set_experimental_features)
|
|
47
48
|
|
|
48
49
|
@property
|
|
49
50
|
def opt(self) -> OptionsPtr:
|
|
@@ -56,11 +57,11 @@ class Options:
|
|
|
56
57
|
|
|
57
58
|
def __new__(cls, *args, **kwargs):
|
|
58
59
|
instance = super().__new__(cls, *args, **kwargs)
|
|
59
|
-
instance._opt =
|
|
60
|
+
instance._opt = get_pgc().create_options()
|
|
60
61
|
return instance
|
|
61
62
|
|
|
62
63
|
def __del__(self):
|
|
63
|
-
|
|
64
|
+
get_pgc().destroy_options(self._opt)
|
|
64
65
|
|
|
65
66
|
# not copyable
|
|
66
67
|
def __copy__(self):
|
|
@@ -6,15 +6,18 @@
|
|
|
6
6
|
Loader for the dynamic library
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
import
|
|
10
|
-
import
|
|
9
|
+
import threading
|
|
10
|
+
from collections.abc import Callable
|
|
11
11
|
from ctypes import CDLL, POINTER, c_char, c_char_p, c_double, c_size_t, c_void_p
|
|
12
12
|
from inspect import signature
|
|
13
13
|
from itertools import chain
|
|
14
|
-
from pathlib import Path
|
|
15
|
-
from typing import Callable
|
|
16
14
|
|
|
17
15
|
from power_grid_model._core.index_integer import IdC, IdxC
|
|
16
|
+
from power_grid_model._core.power_grid_model_c.get_pgm_dll_path import get_pgm_dll_path
|
|
17
|
+
|
|
18
|
+
# threading local
|
|
19
|
+
_thread_local_data = threading.local()
|
|
20
|
+
|
|
18
21
|
|
|
19
22
|
# integer index
|
|
20
23
|
IdxPtr = POINTER(IdxC)
|
|
@@ -125,23 +128,7 @@ def _load_core() -> CDLL:
|
|
|
125
128
|
Returns: DLL/SO object
|
|
126
129
|
|
|
127
130
|
"""
|
|
128
|
-
|
|
129
|
-
dll_file = "_power_grid_core.dll" if platform.system() == "Windows" else "_power_grid_core.so"
|
|
130
|
-
dll_path = Path(__file__).parent / dll_file
|
|
131
|
-
|
|
132
|
-
# if local DLL is not found, try to find the DLL from conda environment
|
|
133
|
-
if (not dll_path.exists()) and ("CONDA_PREFIX" in os.environ):
|
|
134
|
-
if platform.system() == "Windows":
|
|
135
|
-
dll_file = "power_grid_model_c.dll"
|
|
136
|
-
elif platform.system() == "Darwin":
|
|
137
|
-
dll_file = "libpower_grid_model_c.dylib"
|
|
138
|
-
elif platform.system() == "Linux":
|
|
139
|
-
dll_file = "libpower_grid_model_c.so"
|
|
140
|
-
else:
|
|
141
|
-
raise NotImplementedError(f"Unsupported platform: {platform.system()}")
|
|
142
|
-
# the dll will be found through conda environment
|
|
143
|
-
dll_path = Path(dll_file)
|
|
144
|
-
|
|
131
|
+
dll_path = get_pgm_dll_path()
|
|
145
132
|
cdll = CDLL(str(dll_path))
|
|
146
133
|
# assign return types
|
|
147
134
|
# handle
|
|
@@ -184,7 +171,7 @@ def make_c_binding(func: Callable):
|
|
|
184
171
|
if is_destroy_func:
|
|
185
172
|
getattr(_CDLL, f"PGM_{name}").argtypes = c_argtypes
|
|
186
173
|
else:
|
|
187
|
-
getattr(_CDLL, f"PGM_{name}").argtypes = [HandlePtr
|
|
174
|
+
getattr(_CDLL, f"PGM_{name}").argtypes = [HandlePtr, *c_argtypes]
|
|
188
175
|
getattr(_CDLL, f"PGM_{name}").restype = c_restype
|
|
189
176
|
|
|
190
177
|
# binding function
|
|
@@ -213,14 +200,12 @@ class PowerGridCore:
|
|
|
213
200
|
"""
|
|
214
201
|
|
|
215
202
|
_handle: HandlePtr
|
|
216
|
-
_instance: "PowerGridCore | None" = None
|
|
217
203
|
|
|
218
204
|
# singleton of power grid core
|
|
219
205
|
def __new__(cls, *args, **kwargs):
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
return cls._instance
|
|
206
|
+
instance = super().__new__(cls, *args, **kwargs)
|
|
207
|
+
instance._handle = _CDLL.PGM_create_handle()
|
|
208
|
+
return instance
|
|
224
209
|
|
|
225
210
|
def __del__(self):
|
|
226
211
|
_CDLL.PGM_destroy_handle(self._handle)
|
|
@@ -499,6 +484,12 @@ class PowerGridCore:
|
|
|
499
484
|
def dataset_const_get_info(self, dataset: ConstDatasetPtr) -> DatasetInfoPtr: # type: ignore[empty-body]
|
|
500
485
|
pass # pragma: no cover
|
|
501
486
|
|
|
487
|
+
@make_c_binding
|
|
488
|
+
def dataset_const_set_next_cartesian_product_dimension(
|
|
489
|
+
self, dataset: ConstDatasetPtr, next_dataset: ConstDatasetPtr
|
|
490
|
+
) -> None: # type: ignore[empty-body]
|
|
491
|
+
pass # pragma: no cover
|
|
492
|
+
|
|
502
493
|
@make_c_binding
|
|
503
494
|
def dataset_writable_get_info(self, dataset: WritableDatasetPtr) -> DatasetInfoPtr: # type: ignore[empty-body]
|
|
504
495
|
pass # pragma: no cover
|
|
@@ -578,4 +569,9 @@ class PowerGridCore:
|
|
|
578
569
|
|
|
579
570
|
|
|
580
571
|
# make one instance
|
|
581
|
-
|
|
572
|
+
def get_power_grid_core() -> PowerGridCore:
|
|
573
|
+
try:
|
|
574
|
+
return _thread_local_data.power_grid_core
|
|
575
|
+
except AttributeError:
|
|
576
|
+
_thread_local_data.power_grid_core = PowerGridCore()
|
|
577
|
+
return _thread_local_data.power_grid_core
|