Skip to content

Commit 280aeb0

Browse files
authored
Merge pull request #175 from upb-lea/dct
inductor optimization fixes
2 parents 8e48172 + e0e166a commit 280aeb0

5 files changed

Lines changed: 120 additions & 77 deletions

File tree

docs/wordlist

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,14 @@ NbSetpsPerPeriod
450450
NbSteps
451451
WaveformType
452452
powerloss
453+
StoReluctanceModelInput
454+
StoReluctanceModelOutput
455+
StoFemInput
456+
StoFemOutput
457+
IoReluctanceModelInput
458+
IoReluctanceModelOutput
459+
IoFemInput
460+
IoFemOutput
453461

454462
# electrostatic
455463
capacitive

femmt/optimization/io.py

Lines changed: 68 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
import tqdm
1919

2020
# onw libraries
21-
from femmt.optimization.io_dtos import (InductorOptimizationDTO, InductorOptimizationTargetAndFixedParameters, FemInput,
22-
FemOutput, ReluctanceModelInput, ReluctanceModelOutput)
21+
from femmt.optimization.io_dtos import (InductorOptimizationDTO, InductorOptimizationTargetAndFixedParameters, IoFemInput,
22+
IoFemOutput, IoReluctanceModelInput, IoReluctanceModelOutput)
2323
import femmt.functions as ff
2424
import femmt.functions_reluctance as fr
2525
import femmt.optimization.ito_functions as itof
@@ -208,7 +208,7 @@ def objective(trial: optuna.Trial, config: InductorOptimizationDTO, target_and_f
208208
material_mu_r_abs = material_mu_r_abs_value
209209
magnet_material_model = target_and_fixed_parameters.magnet_hub_model_list[count]
210210

211-
reluctance_model_input = ReluctanceModelInput(
211+
reluctance_model_input = IoReluctanceModelInput(
212212
core_inner_diameter=core_inner_diameter,
213213
window_w=window_w,
214214
window_h=window_h,
@@ -222,14 +222,15 @@ def objective(trial: optuna.Trial, config: InductorOptimizationDTO, target_and_f
222222
magnet_material_model=magnet_material_model,
223223

224224
temperature=config.temperature,
225+
time_extracted_vec=target_and_fixed_parameters.time_extracted_vec,
225226
current_extracted_vec=target_and_fixed_parameters.current_extracted_vec,
226227
fundamental_frequency=target_and_fixed_parameters.fundamental_frequency,
227228
fft_frequency_list=target_and_fixed_parameters.fft_frequency_list,
228229
fft_amplitude_list=target_and_fixed_parameters.fft_amplitude_list,
229230
fft_phases_list=target_and_fixed_parameters.fft_phases_list
230231
)
231232
try:
232-
reluctance_output: ReluctanceModelOutput = InductorOptimization.ReluctanceModel.single_reluctance_model_simulation(reluctance_model_input)
233+
reluctance_output: IoReluctanceModelOutput = InductorOptimization.ReluctanceModel.single_reluctance_model_simulation(reluctance_model_input)
233234
except ValueError as e:
234235
logger.debug("bot air gap: No fitting air gap length")
235236
return float('nan'), float('nan')
@@ -245,13 +246,13 @@ def objective(trial: optuna.Trial, config: InductorOptimizationDTO, target_and_f
245246
return reluctance_output.volume, reluctance_output.p_loss_total
246247

247248
@staticmethod
248-
def single_reluctance_model_simulation(reluctance_input: ReluctanceModelInput) -> ReluctanceModelOutput:
249+
def single_reluctance_model_simulation(reluctance_input: IoReluctanceModelInput) -> IoReluctanceModelOutput:
249250
"""Perform a single reluctance model simulation. E.g. during optimization or during a re-simulation of a single operating point.
250251
251252
:param reluctance_input: Input parameters for the reluctance model simulation.
252-
:type reluctance_input: ReluctanceModelInput
253+
:type reluctance_input: IoReluctanceModelInput
253254
:return: Output parameters of the reluctance model simulation
254-
:rtype: ReluctanceModelOutput
255+
:rtype: IoReluctanceModelOutput
255256
"""
256257
target_total_reluctance = reluctance_input.turns ** 2 / reluctance_input.target_inductance
257258

@@ -263,7 +264,11 @@ def single_reluctance_model_simulation(reluctance_input: ReluctanceModelInput) -
263264

264265
r_air_gap_target = target_total_reluctance - r_core
265266

266-
flux = reluctance_input.turns * reluctance_input.current_extracted_vec / target_total_reluctance
267+
# prepare equidistant flux vector for the magnet loss simulation
268+
time_interp = np.linspace(reluctance_input.time_extracted_vec[0], reluctance_input.time_extracted_vec[-1], 1024)
269+
current_interp = np.interp(time_interp, reluctance_input.time_extracted_vec, reluctance_input.current_extracted_vec)
270+
271+
flux = reluctance_input.turns * current_interp / target_total_reluctance
267272
core_cross_section = (reluctance_input.core_inner_diameter / 2) ** 2 * np.pi
268273
flux_density = flux / core_cross_section
269274

@@ -323,7 +328,7 @@ def single_reluctance_model_simulation(reluctance_input: ReluctanceModelInput) -
323328

324329
p_loss = p_winding + p_core
325330

326-
reluctance_model_output = ReluctanceModelOutput(
331+
reluctance_model_output = IoReluctanceModelOutput(
327332
p_loss_total=p_loss,
328333
volume=volume,
329334
area_to_heat_sink=area_to_heat_sink,
@@ -656,7 +661,7 @@ def full_simulation(df_geometry: pd.DataFrame, current_waveform: list, inductor_
656661
# instantiate material-specific model
657662
magnet_material_model: mh.loss.LossModel = mh.loss.LossModel(material=material_name, team="paderborn")
658663

659-
reluctance_model_input = ReluctanceModelInput(
664+
reluctance_model_input = IoReluctanceModelInput(
660665
core_inner_diameter=core_inner_diameter,
661666
window_w=window_w,
662667
window_h=df_geometry["params_window_h"][index],
@@ -670,14 +675,15 @@ def full_simulation(df_geometry: pd.DataFrame, current_waveform: list, inductor_
670675
magnet_material_model=magnet_material_model,
671676

672677
temperature=local_config.temperature,
678+
time_extracted_vec=target_and_fix_parameters.time_extracted_vec,
673679
current_extracted_vec=target_and_fix_parameters.current_extracted_vec,
674680
fundamental_frequency=target_and_fix_parameters.fundamental_frequency,
675681
fft_frequency_list=target_and_fix_parameters.fft_frequency_list,
676682
fft_amplitude_list=target_and_fix_parameters.fft_amplitude_list,
677683
fft_phases_list=target_and_fix_parameters.fft_phases_list
678684
)
679685

680-
reluctance_output: ReluctanceModelOutput = InductorOptimization.ReluctanceModel.single_reluctance_model_simulation(reluctance_model_input)
686+
reluctance_output: IoReluctanceModelOutput = InductorOptimization.ReluctanceModel.single_reluctance_model_simulation(reluctance_model_input)
681687

682688
p_total = reluctance_output.p_loss_total
683689

@@ -727,7 +733,7 @@ def fem_simulations_from_reluctance_df(reluctance_df: pd.DataFrame, config: Indu
727733
core_inner_diameter = reluctance_df["params_core_inner_diameter"][index].item()
728734
window_w = reluctance_df["params_window_w"][index].item()
729735
window_h = reluctance_df["params_window_h"][index].item()
730-
fem_input = FemInput(
736+
fem_input = IoFemInput(
731737
simulation_name=f"case_{reluctance_df['number'][index].item()}",
732738
working_directory=fem_working_directory,
733739
core_inner_diameter=core_inner_diameter,
@@ -744,15 +750,17 @@ def fem_simulations_from_reluctance_df(reluctance_df: pd.DataFrame, config: Indu
744750
fft_frequency_list=target_and_fix_parameters.fft_frequency_list,
745751
fft_amplitude_list=target_and_fix_parameters.fft_amplitude_list,
746752
fft_phases_list=target_and_fix_parameters.fft_phases_list,
753+
time_vec=target_and_fix_parameters.time_extracted_vec,
754+
current_vec=target_and_fix_parameters.current_extracted_vec
747755
)
748756

749757
# fem simulation here
750758
fem_output = InductorOptimization.FemSimulation.single_fem_simulation(fem_input, False)
751759

752-
reluctance_df.loc[index, 'fem_inductance'] = fem_output.fem_inductance
753-
reluctance_df.loc[index, 'fem_p_loss_winding'] = fem_output.fem_p_loss_winding
754-
reluctance_df.loc[index, 'fem_eddy_core'] = fem_output.fem_eddy_core
755-
reluctance_df.loc[index, 'fem_core'] = fem_output.fem_core_total
760+
reluctance_df.loc[index, 'fem_inductance'] = fem_output.inductance
761+
reluctance_df.loc[index, 'fem_p_loss_winding'] = fem_output.p_loss_winding
762+
reluctance_df.loc[index, 'fem_eddy_core'] = fem_output.p_core_sine
763+
reluctance_df.loc[index, 'fem_core'] = fem_output.p_core_magnet
756764

757765
# copy result files to result-file folder
758766
source_json_file = os.path.join(
@@ -855,18 +863,18 @@ def fem_vs_reluctance(df: pd.DataFrame, config: InductorOptimizationDTO):
855863
return df
856864

857865
@staticmethod
858-
def single_fem_simulation(fem_input: FemInput, show_visual_outputs: bool = False) -> FemOutput:
866+
def single_fem_simulation(fem_input: IoFemInput, show_visual_outputs: bool = False) -> IoFemOutput:
859867
"""
860868
Perform a single FEM simulation.
861869
862870
For parallel simulations, use different working directories.
863871
864872
:param fem_input: FEM input DTO
865-
:type fem_input: FemInput
873+
:type fem_input: IoFemInput
866874
:param show_visual_outputs: True to show visual outputs
867875
:type show_visual_outputs: bool
868876
:return: FEM output DTO
869-
:rtype: FemOutput
877+
:rtype: IoFemOutput
870878
"""
871879
# 1. chose simulation type
872880
geo = fmt.MagneticComponent(simulation_type=fmt.SimulationType.FreqDomain, component_type=fmt.ComponentType.Inductor,
@@ -926,16 +934,33 @@ def single_fem_simulation(fem_input: FemInput, show_visual_outputs: bool = False
926934
current_amplitudes = [[current] for current in fem_input.fft_amplitude_list]
927935
phases = [[phase] for phase in fem_input.fft_phases_list]
928936

937+
# prepare core loss simulation
938+
peak_current = np.max(fem_input.current_vec)
939+
custom_b_wave = 1 / peak_current * fem_input.current_vec
940+
time_interp = np.linspace(fem_input.time_vec[0], fem_input.time_vec[-1], 1024)
941+
current_interp = np.interp(time_interp, fem_input.time_vec, fem_input.current_vec)
942+
normalized_current_interp = 1 / peak_current * current_interp
943+
944+
# perform single hysteresis loss simulation where a sinusoidal signal with the peak amplitude is used
945+
geo.single_simulation(freq=fem_input.fundamental_frequency, current=[peak_current],
946+
plot_interpolation=False, show_fem_simulation_results=show_visual_outputs)
947+
948+
# read the flux per mesh cell and transfer it into losses with the help of the magnet model
949+
hyst_losses_custom = geo.calc_hystersis_losses_with_MagNet_model_PB_based_on_mesh_results(b_wave=fmt.WaveformType.Custom,
950+
custom_b_wave=normalized_current_interp)
951+
952+
result_dict_hyst = geo.read_log()
953+
954+
# get the winding losses
929955
geo.excitation_sweep(frequency_list=fem_input.fft_frequency_list, current_list_list=current_amplitudes,
930956
phi_deg_list_list=phases, show_last_fem_simulation=show_visual_outputs)
931-
932957
result_dict = geo.read_log()
933958

934-
fem_output = FemOutput(
935-
fem_inductance=result_dict['single_sweeps'][0]['winding1']['flux_over_current'][0],
936-
fem_p_loss_winding=result_dict['total_losses']['winding1']['total'],
937-
fem_eddy_core=result_dict['total_losses']['eddy_core'],
938-
fem_core_total=result_dict['total_losses']['core'],
959+
fem_output = IoFemOutput(
960+
inductance=result_dict['single_sweeps'][0]['winding1']['flux_over_current'][0],
961+
p_loss_winding=result_dict['total_losses']['winding1']['total'],
962+
p_core_sine=result_dict_hyst['total_losses']['core'],
963+
p_core_magnet=hyst_losses_custom,
939964
volume=result_dict["misc"]["core_2daxi_total_volume"]
940965
)
941966
return fem_output
@@ -1017,7 +1042,7 @@ def full_simulation(df_geometry: pd.DataFrame, current_waveform: list, inductor_
10171042

10181043
material_mu_r_abs = np.abs(np.array([mu_real_at_f + 1j * mu_imag_at_f]))
10191044

1020-
fem_input = FemInput(
1045+
fem_input = IoFemInput(
10211046
# general parameters
10221047
working_directory=working_directory,
10231048
simulation_name='xx',
@@ -1040,7 +1065,10 @@ def full_simulation(df_geometry: pd.DataFrame, current_waveform: list, inductor_
10401065
fundamental_frequency=target_and_fix_parameters.fundamental_frequency,
10411066
fft_frequency_list=target_and_fix_parameters.fft_frequency_list,
10421067
fft_amplitude_list=target_and_fix_parameters.fft_amplitude_list,
1043-
fft_phases_list=target_and_fix_parameters.fft_phases_list
1068+
fft_phases_list=target_and_fix_parameters.fft_phases_list,
1069+
1070+
time_vec=target_and_fix_parameters.time_extracted_vec,
1071+
current_vec=target_and_fix_parameters.current_extracted_vec
10441072
)
10451073

10461074
fem_output = InductorOptimization.FemSimulation.single_fem_simulation(fem_input, False)
@@ -1051,7 +1079,7 @@ def full_simulation(df_geometry: pd.DataFrame, current_waveform: list, inductor_
10511079
# instantiate material-specific model
10521080
magnet_material_model: mh.loss.LossModel = mh.loss.LossModel(material=material_name, team="paderborn")
10531081

1054-
reluctance_model_input = ReluctanceModelInput(
1082+
reluctance_model_input = IoReluctanceModelInput(
10551083
core_inner_diameter=core_inner_diameter,
10561084
window_w=window_w,
10571085
window_h=df_geometry["params_window_h"][index_number],
@@ -1065,31 +1093,32 @@ def full_simulation(df_geometry: pd.DataFrame, current_waveform: list, inductor_
10651093
magnet_material_model=magnet_material_model,
10661094

10671095
temperature=local_config.temperature,
1096+
time_extracted_vec=target_and_fix_parameters.time_extracted_vec,
10681097
current_extracted_vec=target_and_fix_parameters.current_extracted_vec,
10691098
fundamental_frequency=target_and_fix_parameters.fundamental_frequency,
10701099
fft_frequency_list=target_and_fix_parameters.fft_frequency_list,
10711100
fft_amplitude_list=target_and_fix_parameters.fft_amplitude_list,
1072-
fft_phases_list=target_and_fix_parameters.fft_phases_list
1101+
fft_phases_list=target_and_fix_parameters.fft_phases_list,
10731102
)
10741103

1075-
reluctance_output: ReluctanceModelOutput = InductorOptimization.ReluctanceModel.single_reluctance_model_simulation(reluctance_model_input)
1104+
reluctance_output: IoReluctanceModelOutput = InductorOptimization.ReluctanceModel.single_reluctance_model_simulation(reluctance_model_input)
10761105

1077-
p_core = reluctance_output.p_hyst + fem_output.fem_eddy_core
1078-
p_total = p_core + fem_output.fem_p_loss_winding
1106+
p_core = reluctance_output.p_hyst + fem_output.p_core_sine
1107+
p_total = p_core + fem_output.p_loss_winding
10791108

10801109
if print_derivations:
10811110
logger.info(f"Inductance reluctance: {local_config.target_inductance}")
1082-
logger.info(f"Inductance FEM: {fem_output.fem_inductance}")
1111+
logger.info(f"Inductance FEM: {fem_output.inductance}")
10831112
logger.info(f"Inductance derivation: "
1084-
f"{(fem_output.fem_inductance - local_config.target_inductance) / local_config.target_inductance * 100} %")
1113+
f"{(fem_output.inductance - local_config.target_inductance) / local_config.target_inductance * 100} %")
10851114
logger.info(f"Volume reluctance: {reluctance_output.volume}")
10861115
logger.info(f"Volume FEM: {fem_output.volume}")
10871116
logger.info(f"Volume derivation: {(reluctance_output.volume - fem_output.volume) / reluctance_output.volume * 100} %")
10881117
logger.info(f"P_winding reluctance: {reluctance_output.p_winding}")
1089-
logger.info(f"P_winding FEM: {fem_output.fem_p_loss_winding}")
1090-
logger.info(f"P_winding derivation: {(fem_output.fem_p_loss_winding - reluctance_output.p_winding) / fem_output.fem_p_loss_winding * 100} %")
1118+
logger.info(f"P_winding FEM: {fem_output.p_loss_winding}")
1119+
logger.info(f"P_winding derivation: {(fem_output.p_loss_winding - reluctance_output.p_winding) / fem_output.p_loss_winding * 100} %")
10911120
logger.info(f"P_hyst reluctance: {reluctance_output.p_hyst}")
1092-
logger.info(f"P_hyst FEM: {fem_output.fem_core_total}")
1093-
logger.info(f"P_hyst derivation: {(reluctance_output.p_hyst - fem_output.fem_core_total) / reluctance_output.p_hyst * 100} %")
1121+
logger.info(f"P_hyst FEM: {fem_output.p_core_magnet}")
1122+
logger.info(f"P_hyst derivation: {(reluctance_output.p_hyst - fem_output.p_core_magnet) / reluctance_output.p_hyst * 100} %")
10941123

1095-
return reluctance_output.volume, p_total, reluctance_output.area_to_heat_sink, fem_output.fem_p_loss_winding, p_core
1124+
return reluctance_output.volume, p_total, reluctance_output.area_to_heat_sink, fem_output.p_loss_winding, p_core

femmt/optimization/io_dtos.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class InductorOptimizationTargetAndFixedParameters:
6868
fft_phases_list: list[float]
6969

7070
@dataclasses.dataclass
71-
class FemInput:
71+
class IoFemInput:
7272
"""Input DTO for a FEM simulation within the inductor optimization."""
7373

7474
# general parameters
@@ -95,18 +95,22 @@ class FemInput:
9595
fft_amplitude_list: list[float]
9696
fft_phases_list: list[float]
9797

98+
# magnet loss model
99+
time_vec: list[float]
100+
current_vec: list[float]
101+
98102
@dataclasses.dataclass
99-
class FemOutput:
103+
class IoFemOutput:
100104
"""Output DTO for a FEM simulation within the inductor optimization."""
101105

102-
fem_inductance: float
103-
fem_p_loss_winding: float
104-
fem_eddy_core: float
105-
fem_core_total: float
106+
inductance: float
107+
p_loss_winding: float
108+
p_core_sine: float
109+
p_core_magnet: float
106110
volume: float
107111

108112
@dataclasses.dataclass
109-
class ReluctanceModelInput:
113+
class IoReluctanceModelInput:
110114
"""Input DTO for reluctance model simulation within the inductor optimization."""
111115

112116
target_inductance: float
@@ -122,14 +126,15 @@ class ReluctanceModelInput:
122126
magnet_material_model: LossModel
123127

124128
temperature: float
129+
time_extracted_vec: list
125130
current_extracted_vec: list
126131
fundamental_frequency: float
127132
fft_frequency_list: list[float]
128133
fft_amplitude_list: list[float]
129134
fft_phases_list: list[float]
130135

131136
@dataclasses.dataclass
132-
class ReluctanceModelOutput:
137+
class IoReluctanceModelOutput:
133138
"""output DTO for reluctance model simulation within the inductor optimization."""
134139

135140
volume: float

0 commit comments

Comments
 (0)