diff --git a/femmt/component.py b/femmt/component.py index 8cc93a01..42855a82 100644 --- a/femmt/component.py +++ b/femmt/component.py @@ -73,6 +73,8 @@ def __init__(self, component_type: ComponentType = ComponentType.Inductor, worki # Create file paths class in order to handle all paths self.file_data = FileData(working_directory) + # Clear result folder structure in case of missing + self.file_data.clear_previous_simulation_results() # Variable to set silent mode self.verbosity = verbosity @@ -414,14 +416,14 @@ def set_air_gaps(self, air_gaps: AirGaps): self.air_gaps = air_gaps - def set_winding_windows(self, winding_windows: list[WindingWindow], mesh_accuracy: float = 0.5): + def set_winding_windows(self, winding_windows: List[WindingWindow], mesh_accuracy: float = 0.5): """ Adds the winding windows to the model. Creates the windings list, which contains the conductors from the virtual winding windows but sorted by the winding_number (ascending). Sets empty lists for excitation parameters :param winding_windows: List of WindingWindow objects - :type winding_windows: list[WindingWindow] + :type winding_windows: List[WindingWindow] :param mesh_accuracy: a mesh_accuracy of 0.5 is recommended. Do not change this parameter, except performing thousands of simulations, e.g. a Pareto optimization. In this case, the value can be set e.g. to 0.8 :type mesh_accuracy: float """ @@ -2527,6 +2529,7 @@ def load_result(self, res_name: str, res_type: str = "value", last_n: int = 1, p if res_type == "circuit": res_path = self.file_data.e_m_circuit_folder_path + with open(os.path.join(res_path, f"{res_name}.dat")) as fd: lines = fd.readlines()[-last_n:] diff --git a/femmt/data.py b/femmt/data.py index 6411707d..38a05750 100644 --- a/femmt/data.py +++ b/femmt/data.py @@ -1,8 +1,11 @@ # Python standard libraries import os +import shutil + import numpy as np from typing import List +import femmt # Local libraries from femmt.enumerations import ConductorType from femmt.model import Conductor @@ -23,6 +26,24 @@ def create_folders(*args) -> None: if not os.path.exists(folder): os.mkdir(folder) + def clear_previous_simulation_results(self): + self.clean_folder_structure(self.results_folder_path) + + @staticmethod + def clean_folder_structure(folder_path: str): + """ + Cleans all files from a folder structure. The folder structure remains intact. + """ + try: + for root, dirs, files in os.walk(folder_path): + for file in files: + file_path = os.path.join(root, file) + os.remove(file_path) + # print(f"remove {file_path}") + print("All simulation results from previous simulations have been deleted successfully.") + except OSError: + print("Error occurred while deleting files and subdirectories.") + def update_paths(self, working_directory: str, electro_magnetic_folder_path: str = None, strands_coefficients_folder_path: str = None) -> None: """Sets the local path based on the given working directory diff --git a/femmt/model.py b/femmt/model.py index b5bbf9ff..852cf6e7 100644 --- a/femmt/model.py +++ b/femmt/model.py @@ -1015,7 +1015,7 @@ def split_window(self, split_type: WindingWindowSplit, split_distance: float = 0 else: raise Exception(f"Winding window split type {split_type} not found") - def NCellsSplit(self, split_distance: float = 0, horizontal_split_factors: list[float] = None, + def NCellsSplit(self, split_distance: float = 0, horizontal_split_factors: List[float] = None, vertical_split_factor: float = 0.5): self.vertical_split_factor = vertical_split_factor # Convert horizontal_split_factors to a numpy array @@ -1193,7 +1193,7 @@ def combine_vww(self, vww1: VirtualWindingWindow, vww2: VirtualWindingWindow) -> return new_vww - def NHorizontalSplit(self, horizontal_split_factors: list[float] = None, vertical_split_factors: list[float] = None): + def NHorizontalSplit(self, horizontal_split_factors: List[float] = None, vertical_split_factors: List[float] = None): if vertical_split_factors == None: vertical_split_factors = [None] * (len(horizontal_split_factors)+1) diff --git a/femmt/optimization/ito_functions.py b/femmt/optimization/ito_functions.py index 3f9f56d2..598ab8e4 100644 --- a/femmt/optimization/ito_functions.py +++ b/femmt/optimization/ito_functions.py @@ -82,8 +82,10 @@ def set_up_folder_structure(working_directory: str) -> WorkingDirectories: os.makedirs(working_directories.fem_working_directory, exist_ok=True) - # generate 20 folders for 20 possible parallel calculations - for process_number in list(range(1,21)): + # generate 50 folders for 50 possible parallel calculations + number_of_processes = 50 + + for process_number in list(range(1,number_of_processes+1)): single_process_directory = os.path.join(working_directories.fem_working_directory, f"process_{process_number}") os.makedirs(single_process_directory, exist_ok=True) @@ -96,7 +98,7 @@ def set_up_folder_structure(working_directory: str) -> WorkingDirectories: if not os.path.isdir(working_directory): os.mkdir(working_directory) - for process_number in list(range(1,21)): + for process_number in list(range(1,number_of_processes+1)): # Setup necessary files and directories single_process_directory = os.path.join(working_directories.fem_working_directory, f"process_{process_number}") electro_magnetic_directory_single_process = os.path.join(single_process_directory, "electro_magnetic") diff --git a/femmt/optimization/sto.py b/femmt/optimization/sto.py index beda47e0..aaeef2fb 100644 --- a/femmt/optimization/sto.py +++ b/femmt/optimization/sto.py @@ -501,6 +501,8 @@ def show_study_results(study_name: str, config: StoSingleInputConfig, """ Show the results of a study. + A local .html file is generated under config.working_directory to store the interactive plotly plots on disk. + :param study_name: Name of the study :type study_name: str :param config: Integrated transformer configuration file @@ -524,6 +526,8 @@ def show_study_results(study_name: str, config: StoSingleInputConfig, print(f"{l_s_absolute_error = }") fig = optuna.visualization.plot_pareto_front(study, targets=lambda t: (t.values[0] if -l_h_absolute_error < t.values[2] < l_h_absolute_error else None, t.values[1] if -l_s_absolute_error < t.values[3] < l_s_absolute_error else None), target_names=["volume", "loss"]) + fig.write_html( + f"{config.working_directory}/{study_name}_error_lh_{l_h_absolute_error}_error_ls_{l_s_absolute_error}_{datetime.datetime.now().isoformat(timespec='minutes')}.html") fig.show() @staticmethod @@ -532,6 +536,8 @@ def show_study_results3(study_name: str, config: StoSingleInputConfig, """ Show the results of a study. + A local .html file is generated under config.working_directory to store the interactive plotly plots on disk. + :param study_name: Name of the study :type study_name: str :param config: Integrated transformer configuration file @@ -555,9 +561,8 @@ def show_study_results3(study_name: str, config: StoSingleInputConfig, print(f"{error_difference_inductance_sum = }") fig = optuna.visualization.plot_pareto_front(study, targets=lambda t: (t.values[0] if error_difference_inductance_sum > t.values[2] else None, t.values[1] if error_difference_inductance_sum > t.values[2] else None), target_names=["volume", "loss"]) - #fig = optuna.visualization.plot_pareto_front(study, targets=lambda t: (t.values[0], t.values[1]), target_names=["volume", "loss"]) - # fig = optuna.visualization.plot_pareto_front(study, targets=lambda t: (t.values[2] if True else None, t.values[1] if True else None), target_names=["inductance_error_normalized", "loss"]) + fig.write_html(f"{config.working_directory}/{study_name}_error_diff_{error_difference_inductance_sum}_{datetime.datetime.now().isoformat(timespec='minutes')}.html") fig.show() @staticmethod @@ -692,10 +697,10 @@ def re_simulate_single_result(study_name: str, config: StoSingleInputConfig, num bobbin_coil_left=config.insulations.iso_primary_inner_bobbin, bobbin_coil_right=config.insulations.iso_right_core, center_foil_additional_bobbin=0e-3, - interleaving_scheme=femmt.InterleavingSchemesFoilLitz.ter_3_4_sec_ter_4_3_sec, + interleaving_scheme=InterleavingSchemesFoilLitz(loaded_trial_params['interleaving_scheme']), # misc - interleaving_type=femmt.CenterTappedInterleavingType.TypeC, + interleaving_type=CenterTappedInterleavingType(loaded_trial_params['interleaving_type']), primary_coil_turns=primary_coil_turns, winding_temperature=config.temperature)