diff --git a/docs/tutorial/general_usage.md b/docs/tutorial/general_usage.md index 112ff5f..55c4c8b 100755 --- a/docs/tutorial/general_usage.md +++ b/docs/tutorial/general_usage.md @@ -648,6 +648,7 @@ The *operating condition* directory is structured in: (dgcv_venv) user@dynawo:~/work/MyTests/Results$ tree PCS_RTE-I10/Islanding/DeltaP10DeltaQ4 -L 1 PCS_RTE-I10/Islanding/DeltaP10DeltaQ4 ├── curves_calculated.csv +├── curves_reference.csv ├── Omega.dyd ├── Omega.par ├── outputs diff --git a/src/dgcv/core/simulator.py b/src/dgcv/core/simulator.py index 607cfec..05bce70 100644 --- a/src/dgcv/core/simulator.py +++ b/src/dgcv/core/simulator.py @@ -15,6 +15,7 @@ from dgcv.core.validator import Disconnection_Model from dgcv.electrical.generator_variables import generator_variables from dgcv.model.producer import Producer +import pandas as pd def get_cfg_oc_name(pcs_bm_name: str, oc_name: str) -> str: @@ -124,7 +125,7 @@ def obtain_reference_curve( working_oc_dir: Path, pcs_bm_name: str, curves: Path, - ) -> float: + ) -> tuple[float, pd.DataFrame]: """Virtual method""" pass @@ -135,7 +136,7 @@ def obtain_simulated_curve( bm_name: str, oc_name: str, reference_event_start_time: float, - ) -> tuple[str, dict, int, bool, bool]: + ) -> tuple[str, dict, int, bool, bool, pd.DataFrame]: """Virtual method""" pass diff --git a/src/dgcv/core/validator.py b/src/dgcv/core/validator.py index 0baf7cc..abfc323 100644 --- a/src/dgcv/core/validator.py +++ b/src/dgcv/core/validator.py @@ -106,6 +106,7 @@ def validate( sim_output_path: str, event_params: dict, fs: float, + curves: dict, ) -> dict: """Virtual method""" pass diff --git a/src/dgcv/curves/manager.py b/src/dgcv/curves/manager.py index e893864..17dcd98 100644 --- a/src/dgcv/curves/manager.py +++ b/src/dgcv/curves/manager.py @@ -64,22 +64,18 @@ def __obtain_files_curve( if success: importer = CurvesImporter(working_oc_dir, get_cfg_oc_name(pcs_bm_name, oc_name)) ( - df_imported_curve, + df_imported_curves, curves_dict, sim_t_event_end, fs, ) = importer.get_curves_dataframe(self._producer.get_zone()) - if df_imported_curve.empty: + if df_imported_curves.empty: success = False has_imported_curves = False - df_imported_curve = df_imported_curve.set_index("time") - if is_reference: - df_imported_curve.to_csv(working_oc_dir / "curves_reference.csv", sep=";") - else: - df_imported_curve.to_csv(working_oc_dir / "curves_calculated.csv", sep=";") - self._generators = self.__get_generators(df_imported_curve) - self._gens = _get_generators_ini(self._generators, df_imported_curve) + if not is_reference: + self._generators = self.__get_generators(df_imported_curves) + self._gens = _get_generators_ini(self._generators, df_imported_curves) if importer.config.has_option("Curves-Metadata", "is_field_measurements"): self._is_field_measurements = bool( @@ -116,6 +112,7 @@ def __obtain_files_curve( fault_duration = 0 fs = 0 self._generators_imax = {} + df_imported_curves = pd.DataFrame() config_section = get_cfg_oc_name(pcs_bm_name, oc_name) + ".Event" connect_event_to = config.get_value(config_section, "connect_event_to") @@ -139,6 +136,7 @@ def __obtain_files_curve( fs, success, has_imported_curves, + df_imported_curves, ) def obtain_reference_curve( @@ -147,7 +145,7 @@ def obtain_reference_curve( pcs_bm_name: str, oc_name: str, curves: Path, - ) -> float: + ) -> tuple[float, pd.DataFrame]: """Read the reference curves. Parameters @@ -165,16 +163,19 @@ def obtain_reference_curve( ------- float Instant of time when the event is triggered + DataFrame + Curves imported from the file """ ( event_params, fs, success, has_imported_curves, + curves, ) = self.__obtain_files_curve( working_oc_dir, pcs_bm_name, oc_name, curves, is_reference=True ) - return event_params["start_time"] + return event_params["start_time"], curves def obtain_simulated_curve( self, @@ -183,7 +184,7 @@ def obtain_simulated_curve( bm_name: str, oc_name: str, reference_event_start_time: float, - ) -> tuple[str, dict, float, bool, bool]: + ) -> tuple[str, dict, float, bool, bool, pd.DataFrame]: """Read the input curves to get the simulated curves. Parameters @@ -213,12 +214,15 @@ def obtain_simulated_curve( True if simulation is success bool True if simulation calculated curves + DataFrame + Simulation calculated curves """ ( event_params, fs, success, has_imported_curves, + curves, ) = self.__obtain_files_curve( working_oc_dir, pcs_bm_name, oc_name, self.get_producer().get_producer_curves() ) @@ -229,6 +233,7 @@ def obtain_simulated_curve( fs, success, has_imported_curves, + curves, ) def get_disconnection_model(self) -> Disconnection_Model: diff --git a/src/dgcv/curves/reader.py b/src/dgcv/curves/reader.py index 08c5a6c..d8ab23a 100644 --- a/src/dgcv/curves/reader.py +++ b/src/dgcv/curves/reader.py @@ -189,12 +189,12 @@ def load(self, remove_file=True): if remove_file: file.unlink() - def read(self, data: pd.Dataframe): + def read(self, data: pd.DataFrame): """Read and import the data from the file. Parameters ---------- - data: Dataframe + data: DataFrame Dataframe with all the curves data """ self._time_values = data[self._time_name] diff --git a/src/dgcv/dynawo/dynawo.py b/src/dgcv/dynawo/dynawo.py index 15b73db..4daf618 100644 --- a/src/dgcv/dynawo/dynawo.py +++ b/src/dgcv/dynawo/dynawo.py @@ -309,9 +309,7 @@ def _get_modulus(complex_list: list) -> list: return np.abs(complex_list).tolist() -def _create_curves( - variable_translations: dict, input_file: Path, output_file: Path, f_nom: float -) -> pd.DataFrame: +def _create_curves(variable_translations: dict, input_file: Path) -> pd.DataFrame: """From the curve file generated by the Dynawo dynamic simulator, a new file is created where the values of the different curves are expressed in the units specified in the file and/or different curves are added to obtain the required curves. @@ -322,10 +320,6 @@ def _create_curves( Dictionary with correspondences between tool variables and Dynawo variables input_file: Path Curve file created by Dynawo - output_file: Path - Curve file for tool analysis - f_nom: float - Nominal frequency Returns ------- @@ -401,11 +395,7 @@ def _create_curves( else: curves_dict[i] = list(df_curves[i]) - curves_final = pd.DataFrame(curves_dict) - curves_final = curves_final.set_index("time") - curves_final.to_csv(output_file, sep=";") - - return curves_final + return pd.DataFrame(curves_dict) def get_dynawo_version( @@ -488,7 +478,6 @@ def run_base_dynawo( launcher_dwo: Path, jobs_filename: str, variable_translations: dict, - f_nom: float, inputs_path: Path, output_path: Path, save_file: bool = True, @@ -503,8 +492,6 @@ def run_base_dynawo( Name of the JOBS file variable_translations: dict Dictionary with correspondences between tool variables and Dynawo variables - f_nom: float - Nominal frequency inputs_path: Path Directory with Dynawo inputs output_path: Path @@ -541,8 +528,6 @@ def run_base_dynawo( curves_calculated = _create_curves( variable_translations, dynawo_output_dir / "curves/curves.csv", - inputs_path / "curves_calculated.csv", - f_nom, ) return success, log, has_error, curves_calculated @@ -585,7 +570,7 @@ def check_voltage_dip( if not is_simulation_success: return -1 - time_values = list(curves.index.values) + time_values = list(curves["time"]) voltage_values = list(curves[bus_pdr_voltage]) if fault_duration > time_values[-1]: diff --git a/src/dgcv/dynawo/simulator.py b/src/dgcv/dynawo/simulator.py index 715d17e..6b929fc 100644 --- a/src/dgcv/dynawo/simulator.py +++ b/src/dgcv/dynawo/simulator.py @@ -517,7 +517,6 @@ def __execute_dynawo( self._launcher_dwo, "TSOModel", self._curves_dict, - self._f_nom, working_oc_dir, jobs_output_dir, ) @@ -625,7 +624,7 @@ def __get_hiz_fault( fault_start, fault_duration, last_fault_xpu, - fault_rpu=last_fault_rpu, + last_fault_rpu, ) def __get_bolted_fault( @@ -681,7 +680,6 @@ def __run_time_cct( self._launcher_dwo, "TSOModel", self._curves_dict, - self._f_nom, working_oc_dir_attempt, jobs_output_dir, save_file=False, @@ -809,7 +807,7 @@ def obtain_simulated_curve( bm_name: str, oc_name: str, reference_event_start_time: float, - ) -> tuple[str, dict, int, bool, bool]: + ) -> tuple[str, dict, int, bool, bool, pd.DataFrame]: """Runs Dynawo to get the simulated curves. Parameters @@ -837,6 +835,8 @@ def obtain_simulated_curve( True if simulation is success bool True if simulation calculated curves + DataFrame + Simulation calculated curves """ # Prepare environment to validate it, @@ -896,6 +896,7 @@ def obtain_simulated_curve( success = False has_dynawo_curves = False event_params = dict() + curves_calculated = pd.DataFrame() self._logger.close_handlers() @@ -905,6 +906,7 @@ def obtain_simulated_curve( 0, success, has_dynawo_curves, + curves_calculated, ) def get_disconnection_model(self) -> Disconnection_Model: diff --git a/src/dgcv/model/benchmark.py b/src/dgcv/model/benchmark.py index 1d58518..48e3693 100644 --- a/src/dgcv/model/benchmark.py +++ b/src/dgcv/model/benchmark.py @@ -473,6 +473,7 @@ def __validate( fs: float, success: bool, has_simulated_curves: bool, + curves: dict, ): op_cond_success, results = op_cond.validate( pcs_benchmark_name, @@ -482,6 +483,7 @@ def __validate( fs, success, has_simulated_curves, + curves, ) # Statuses for the Summary Report @@ -534,6 +536,7 @@ def validate( success, has_simulated_curves, has_curves, + curves, ) = op_cond.has_required_curves(pcs_benchmark_name, self._name) if has_curves == 0: op_cond_success, results, compliance = self.__validate( @@ -545,6 +548,7 @@ def validate( fs, success, has_simulated_curves, + curves, ) # If there is a correct simulation, the report must be created success |= op_cond_success diff --git a/src/dgcv/model/operating_condition.py b/src/dgcv/model/operating_condition.py index b48e18d..afc1ea0 100644 --- a/src/dgcv/model/operating_condition.py +++ b/src/dgcv/model/operating_condition.py @@ -79,9 +79,10 @@ def __obtain_curve( working_oc_dir = self._working_dir / self._pcs_name / bm_name / self._name manage_files.create_dir(working_oc_dir) + curves = dict() reference_event_start_time = None if self.__has_reference_curves(): - reference_event_start_time = self._manager.obtain_reference_curve( + reference_event_start_time, curves["reference"] = self._manager.obtain_reference_curve( working_oc_dir, pcs_bm_name, self._name, self.__get_reference_curves() ) @@ -91,6 +92,7 @@ def __obtain_curve( fs, success, has_simulated_curves, + curves["calculated"], ) = self._simulator.obtain_simulated_curve( working_oc_dir, pcs_bm_name, @@ -106,6 +108,7 @@ def __obtain_curve( fs, success, has_simulated_curves, + curves, ) def __validate( @@ -115,6 +118,7 @@ def __validate( jobs_output_dir: Path, event_params: dict, fs: float, + curves: dict, ) -> dict: if self._validator.is_defined_cct(): @@ -137,6 +141,7 @@ def __validate( jobs_output_dir, event_params, fs, + curves, ) # Operational point without defining its validations @@ -158,6 +163,7 @@ def validate( fs: float, success: bool, has_simulated_curves: bool, + curves: dict, ) -> tuple[bool, dict]: """Validate the Benchmark. @@ -177,6 +183,8 @@ def validate( True if simulation is success has_simulated_curves: bool True if simulation calculated curves + curves: dict + Calculated and reference curves Returns ------- @@ -193,6 +201,7 @@ def validate( jobs_output_dir, event_params, fs, + curves, ) else: results = {"compliance": False, "curves": None} @@ -204,7 +213,7 @@ def has_required_curves( self, pcs_bm_name: str, bm_name: str, - ) -> tuple[Path, Path, dict, float, bool, bool, int]: + ) -> tuple[Path, Path, dict, float, bool, bool, int, dict]: """Check if all curves are present. Parameters @@ -233,6 +242,8 @@ def has_required_curves( 1 producer's curves are missing 2 reference curves are missing 3 all curves are missing + dict + Calculated and reference curves """ dgcv_logging.get_logger("Operating Condition").info( "RUNNING BENCHMARK: " + pcs_bm_name + ", OPER. COND.: " + self._name @@ -245,6 +256,7 @@ def has_required_curves( fs, success, has_simulated_curves, + curves, ) = self.__obtain_curve( pcs_bm_name, bm_name, @@ -257,18 +269,15 @@ def has_required_curves( # handled differently. sim_curves = True if not self._producer.is_dynawo_model(): - if not (working_oc_dir / "curves_calculated.csv").is_file(): + if curves["calculated"].empty: dgcv_logging.get_logger("Operating Condition").warning( "Test without producer curves file" ) sim_curves = False else: - csv_calculated_curves = manage_files.read_curves( - working_oc_dir / "curves_calculated.csv" - ) missed_curves = [] for key in measurement_names: - if key not in csv_calculated_curves: + if key not in curves["calculated"]: missed_curves.append(key) sim_curves = False if not sim_curves: @@ -278,18 +287,15 @@ def has_required_curves( ref_curves = True if self.__has_reference_curves(): - if not (working_oc_dir / "curves_reference.csv").is_file(): + if curves["reference"].empty: dgcv_logging.get_logger("Operating Condition").warning( "Test without reference curves file" ) ref_curves = False else: - csv_reference_curves = manage_files.read_curves( - working_oc_dir / "curves_reference.csv" - ) missed_curves = [] for key in measurement_names: - if key not in csv_reference_curves: + if key not in curves["reference"]: missed_curves.append(key) ref_curves = False if not ref_curves: @@ -315,6 +321,7 @@ def has_required_curves( success, has_simulated_curves, has_curves, + curves, ) def get_name(self) -> str: diff --git a/src/dgcv/validation/model.py b/src/dgcv/validation/model.py index c40d176..69de1b5 100644 --- a/src/dgcv/validation/model.py +++ b/src/dgcv/validation/model.py @@ -1131,6 +1131,7 @@ def validate( sim_output_path: str, event_params: dict, fs: float, + curves: dict, ) -> dict: """Model Validation. @@ -1157,9 +1158,11 @@ def validate( # if reference_curves is None: # reference_curves = calculated_curves - csv_calculated_curves = manage_files.read_curves(working_path / "curves_calculated.csv") - if (working_path / "curves_reference.csv").is_file(): - csv_reference_curves = manage_files.read_curves(working_path / "curves_reference.csv") + csv_calculated_curves = curves["calculated"] + csv_calculated_curves.to_csv(working_path / "curves_calculated.csv", sep=";") + if not curves["reference"].empty: + csv_reference_curves = curves["reference"] + csv_reference_curves.to_csv(working_path / "curves_reference.csv", sep=";") else: csv_reference_curves = None diff --git a/src/dgcv/validation/performance.py b/src/dgcv/validation/performance.py index 34b10d8..9fd455b 100644 --- a/src/dgcv/validation/performance.py +++ b/src/dgcv/validation/performance.py @@ -522,6 +522,7 @@ def validate( sim_output_path: str, event_params: dict, fs: float, + curves: dict, ) -> dict: """Electric Performance Verification. @@ -543,9 +544,11 @@ def validate( dict Compliance results """ - calculated_curves = manage_files.read_curves(working_path / "curves_calculated.csv") - if (working_path / "curves_reference.csv").is_file(): - reference_curves = manage_files.read_curves(working_path / "curves_reference.csv") + calculated_curves = curves["calculated"] + calculated_curves.to_csv(working_path / "curves_calculated.csv", sep=";") + if not curves["reference"].empty: + reference_curves = curves["reference"] + reference_curves.to_csv(working_path / "curves_reference.csv", sep=";") else: reference_curves = None