Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/experimental validation tests #471

Merged
merged 13 commits into from
Jan 17, 2024
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -198,14 +198,28 @@ enum PGM_SerializationFormat {
};

/**
* @brief Enumeration of short circuit voltage scaling
* @brief Enumeration of short circuit voltage scaling.
*
*/
enum PGM_ShortCircuitVoltageScaling {
PGM_short_circuit_voltage_scaling_minimum = 0, /**< voltage scaling for minimum short circuit currents */
PGM_short_circuit_voltage_scaling_maximum = 1, /**< voltage scaling for maximum short circuit currents */
};

/**
* @brief Enumeration of experimental features.
*
* [Danger mode]
*
* The behavior of experimental features may not be final and no stability guarantees are made to the users.
* Which features (if any) are enabled in experimental mode may change over time.
*
*/
enum PGM_ExperimentalFeatures {
PGM_experimental_features_disabled = 0, /**< disable experimental features */
PGM_experimental_features_enabled = 1, /**< enable experimental features */
};

#ifdef __cplusplus
}
#endif
Expand Down
mgovers marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ PGM_API void PGM_set_calculation_type(PGM_Handle* handle, PGM_Options* opt, PGM_
*
* @param handle
* @param opt The pointer to the option instance.
* @param method Ssee #PGM_CalculationMethod .
* @param method See #PGM_CalculationMethod .
*/
PGM_API void PGM_set_calculation_method(PGM_Handle* handle, PGM_Options* opt, PGM_Idx method);

Expand Down Expand Up @@ -110,6 +110,20 @@ PGM_API void PGM_set_threading(PGM_Handle* handle, PGM_Options* opt, PGM_Idx thr
PGM_API void PGM_set_short_circuit_voltage_scaling(PGM_Handle* handle, PGM_Options* opt,
PGM_Idx short_circuit_voltage_scaling);

/**
* @brief Enable/disable experimental features.
*
* [Danger mode]
*
* The behavior of experimental features may not be final and no stability guarantees are made to the users.
* Features marked as 'experimental' as well as the behavior of experimental functionality itself may change over time.
*
* @param handle
* @param opt pointer to option instance
* @param experimental_features See #PGM_ExperimentalFeatures
*/
PGM_API void PGM_set_experimental_features(PGM_Handle* handle, PGM_Options* opt, PGM_Idx experimental_features);

#ifdef __cplusplus
}
#endif
Expand Down
3 changes: 2 additions & 1 deletion power_grid_model_c/power_grid_model_c/src/model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ void PGM_calculate(PGM_Handle* handle, PGM_PowerGridModel* model, PGM_Options co
}
break;
case PGM_state_estimation:
if (calculation_method == CalculationMethod::newton_raphson) {
if (calculation_method == CalculationMethod::newton_raphson &&
opt->experimental_features == PGM_experimental_features_disabled) {
// this option is experimental and should not be exposed to the user
throw MissingCaseForEnumError{"CalculationType", opt->calculation_type};
}
Expand Down
3 changes: 3 additions & 0 deletions power_grid_model_c/power_grid_model_c/src/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ void PGM_set_short_circuit_voltage_scaling(PGM_Handle* /* handle */, PGM_Options
PGM_Idx short_circuit_voltage_scaling) {
opt->short_circuit_voltage_scaling = short_circuit_voltage_scaling;
}
void PGM_set_experimental_features(PGM_Handle* handle, PGM_Options* opt, PGM_Idx experimental_features) {
opt->experimental_features = experimental_features;
}
1 change: 1 addition & 0 deletions power_grid_model_c/power_grid_model_c/src/options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ struct PGM_Options {
Idx max_iter{20};
Idx threading{-1};
Idx short_circuit_voltage_scaling{PGM_short_circuit_voltage_scaling_maximum};
Idx experimental_features{PGM_experimental_features_disabled};
};

#endif
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ version = {file = "PYPI_VERSION"}
[tool.pytest.ini_options]
testpaths = ["tests/unit"]
addopts = ["--cov=power_grid_model", "--cov-report", "term", "--cov-report", "html:python_cov_html", "--cov-report", "xml:python_coverage.xml", "--cov-fail-under=95"]
xfail_strict = true

[tool.black]
line-length = 120
Expand Down
1 change: 1 addition & 0 deletions src/power_grid_model/core/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class Options:
max_iterations = OptionSetter(pgc.set_max_iter)
threading = OptionSetter(pgc.set_threading)
short_circuit_voltage_scaling = OptionSetter(pgc.set_short_circuit_voltage_scaling)
experimental_features = OptionSetter(pgc.set_experimental_features)

@property
def opt(self) -> OptionsPtr:
Expand Down
6 changes: 6 additions & 0 deletions src/power_grid_model/core/power_grid_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,12 @@ def set_short_circuit_voltage_scaling(
) -> None: # type: ignore[empty-body]
pass # pragma: no cover

@make_c_binding
def set_experimental_features(
self, opt: OptionsPtr, experimental_features: int
) -> None: # type: ignore[empty-body]
pass # pragma: no cover

@make_c_binding
def set_symmetric(self, opt: OptionsPtr, sym: int) -> None: # type: ignore[empty-body]
pass # pragma: no cover
Expand Down
136 changes: 104 additions & 32 deletions src/power_grid_model/core/power_grid_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from power_grid_model.core.index_integer import IdNp, IdxNp
from power_grid_model.core.options import Options
from power_grid_model.core.power_grid_core import ConstDatasetPtr, IDPtr, IdxPtr, ModelPtr, power_grid_core as pgc
from power_grid_model.enum import CalculationMethod, CalculationType, ShortCircuitVoltageScaling
from power_grid_model.enum import CalculationMethod, CalculationType, ShortCircuitVoltageScaling, _ExperimentalFeatures


class PowerGridModel:
Expand Down Expand Up @@ -194,6 +194,7 @@ def as_enum_value(key_enum: str, type_: Type[IntEnum]):

as_enum_value("calculation_method", CalculationMethod)
as_enum_value("short_circuit_voltage_scaling", ShortCircuitVoltageScaling)
as_enum_value("experimental_features", _ExperimentalFeatures)

opt = Options()
for key, value in kwargs.items():
Expand Down Expand Up @@ -262,6 +263,101 @@ def _calculate_impl(

return output_data

def _calculate_power_flow(
self,
*,
symmetric: bool = True,
error_tolerance: float = 1e-8,
max_iterations: int = 20,
calculation_method: Union[CalculationMethod, str] = CalculationMethod.newton_raphson,
update_data: Optional[Dict[str, Union[np.ndarray, Dict[str, np.ndarray]]]] = None,
threading: int = -1,
output_component_types: Optional[Union[Set[str], List[str]]] = None,
continue_on_batch_error: bool = False,
experimental_features: Union[_ExperimentalFeatures, str] = _ExperimentalFeatures.disabled,
):
calculation_type = CalculationType.power_flow
options = self._options(
calculation_type=calculation_type,
symmetric=symmetric,
error_tolerance=error_tolerance,
max_iterations=max_iterations,
calculation_method=calculation_method,
threading=threading,
experimental_features=experimental_features,
)
return self._calculate_impl(
calculation_type=calculation_type,
symmetric=symmetric,
update_data=update_data,
output_component_types=output_component_types,
options=options,
continue_on_batch_error=continue_on_batch_error,
)

def _calculate_state_estimation(
self,
*,
symmetric: bool = True,
error_tolerance: float = 1e-8,
max_iterations: int = 20,
calculation_method: Union[CalculationMethod, str] = CalculationMethod.iterative_linear,
update_data: Optional[Dict[str, Union[np.ndarray, Dict[str, np.ndarray]]]] = None,
threading: int = -1,
output_component_types: Optional[Union[Set[str], List[str]]] = None,
continue_on_batch_error: bool = False,
experimental_features: Union[_ExperimentalFeatures, str] = _ExperimentalFeatures.disabled,
) -> Dict[str, np.ndarray]:
calculation_type = CalculationType.state_estimation
options = self._options(
calculation_type=calculation_type,
symmetric=symmetric,
error_tolerance=error_tolerance,
max_iterations=max_iterations,
calculation_method=calculation_method,
threading=threading,
experimental_features=experimental_features,
)
return self._calculate_impl(
calculation_type=calculation_type,
symmetric=symmetric,
update_data=update_data,
output_component_types=output_component_types,
options=options,
continue_on_batch_error=continue_on_batch_error,
)

def _calculate_short_circuit(
self,
*,
calculation_method: Union[CalculationMethod, str] = CalculationMethod.iec60909,
update_data: Optional[Dict[str, Union[np.ndarray, Dict[str, np.ndarray]]]] = None,
threading: int = -1,
output_component_types: Optional[Union[Set[str], List[str]]] = None,
continue_on_batch_error: bool = False,
short_circuit_voltage_scaling: Union[ShortCircuitVoltageScaling, str] = ShortCircuitVoltageScaling.maximum,
experimental_features: Union[_ExperimentalFeatures, str] = _ExperimentalFeatures.disabled,
) -> Dict[str, np.ndarray]:
calculation_type = CalculationType.short_circuit
symmetric = False

options = self._options(
calculation_type=calculation_type,
symmetric=symmetric,
calculation_method=calculation_method,
threading=threading,
short_circuit_voltage_scaling=short_circuit_voltage_scaling,
experimental_features=experimental_features,
)
return self._calculate_impl(
calculation_type=calculation_type,
symmetric=symmetric,
update_data=update_data,
output_component_types=output_component_types,
options=options,
continue_on_batch_error=continue_on_batch_error,
)

def calculate_power_flow(
self,
*,
Expand Down Expand Up @@ -334,21 +430,14 @@ def calculate_power_flow(
Raises:
Exception: In case an error in the core occurs, an exception will be thrown.
"""
calculation_type = CalculationType.power_flow
options = self._options(
calculation_type=calculation_type,
return self._calculate_power_flow(
symmetric=symmetric,
error_tolerance=error_tolerance,
max_iterations=max_iterations,
calculation_method=calculation_method,
threading=threading,
)
return self._calculate_impl(
calculation_type=calculation_type,
symmetric=symmetric,
update_data=update_data,
threading=threading,
output_component_types=output_component_types,
options=options,
continue_on_batch_error=continue_on_batch_error,
)

Expand Down Expand Up @@ -421,21 +510,14 @@ def calculate_state_estimation(
Raises:
Exception: In case an error in the core occurs, an exception will be thrown.
"""
calculation_type = CalculationType.state_estimation
options = self._options(
calculation_type=calculation_type,
return self._calculate_state_estimation(
symmetric=symmetric,
error_tolerance=error_tolerance,
max_iterations=max_iterations,
calculation_method=calculation_method,
threading=threading,
)
return self._calculate_impl(
calculation_type=calculation_type,
symmetric=symmetric,
update_data=update_data,
threading=threading,
output_component_types=output_component_types,
options=options,
continue_on_batch_error=continue_on_batch_error,
)

Expand Down Expand Up @@ -501,23 +583,13 @@ def calculate_short_circuit(
Raises:
Exception: In case an error in the core occurs, an exception will be thrown.
"""
calculation_type = CalculationType.short_circuit
symmetric = False

options = self._options(
calculation_type=calculation_type,
symmetric=symmetric,
return self._calculate_short_circuit(
calculation_method=calculation_method,
threading=threading,
short_circuit_voltage_scaling=short_circuit_voltage_scaling,
)
return self._calculate_impl(
calculation_type=calculation_type,
symmetric=symmetric,
update_data=update_data,
threading=threading,
output_component_types=output_component_types,
options=options,
continue_on_batch_error=continue_on_batch_error,
short_circuit_voltage_scaling=short_circuit_voltage_scaling,
)

def __del__(self):
Expand Down
7 changes: 7 additions & 0 deletions src/power_grid_model/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,10 @@ class ShortCircuitVoltageScaling(IntEnum):

minimum = 0
maximum = 1


class _ExperimentalFeatures(IntEnum):
TonyXiang8787 marked this conversation as resolved.
Show resolved Hide resolved
"""Experimental features"""

disabled = 0
enabled = 1
8 changes: 8 additions & 0 deletions tests/cpp_validation_tests/test_validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,14 @@ std::optional<CaseParam> construct_case(std::filesystem::path const& case_dir, j
if (j.contains("fail")) {
j.at("fail").get_to(param.fail);
}
if (j.contains("extra_params")) {
if (json const& extra_params = j.at("extra_params"); extra_params.contains(calculation_method)) {
if (json const& method_extra_params = extra_params.at(calculation_method);
method_extra_params.contains("fail")) {
method_extra_params.at("fail").get_to(param.fail);
}
}
}
if (calculation_type == "short_circuit") {
j.at("short_circuit_voltage_scaling").get_to(param.short_circuit_voltage_scaling);
}
Expand Down