Skip to content

Commit

Permalink
Merge pull request #45 from upb-lea/component_study
Browse files Browse the repository at this point in the history
Component study
  • Loading branch information
gituser789 authored Aug 29, 2023
2 parents 1de2efb + 63e0022 commit e24d33a
Show file tree
Hide file tree
Showing 12 changed files with 275 additions and 182 deletions.
56 changes: 47 additions & 9 deletions femmt/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -1058,10 +1058,14 @@ def excitation_sweep(self, frequency_list: List, current_list_list: List, phi_de
self.mesh.generate_hybrid_mesh(color_scheme, colors_geometry, visualize_before=visualize_before, save_png=save_png)
self.mesh.generate_electro_magnetic_mesh()

for count_frequency in range(0, len(frequency_list)):

check_model_mqs_condition_already_performerd = False
for count_frequency, value_frequency in enumerate(range(0, len(frequency_list))):
self.excitation(frequency=frequency_list[count_frequency], amplitude_list=current_list_list[count_frequency],
phase_deg_list=phi_deg_list_list[count_frequency]) # frequency and current
if count_frequency == 0: self.check_model_mqs_condition()
if value_frequency != 0 and not check_model_mqs_condition_already_performerd:
self.check_model_mqs_condition()
check_model_mqs_condition_already_performerd = True
self.write_simulation_parameters_to_pro_files()
self.generate_load_litz_approximation_parameters()
self.simulate()
Expand Down Expand Up @@ -1129,7 +1133,40 @@ def component_study(self, time_current_vectors: List[List[List[float]]]):
self.excitation_sweep(frequency_list, current_list_list, phi_deg_list_list, inductance_dict=inductance_dict,
core_hyst_loss=float(p_hyst))

def center_tapped_pre_study(self, time_current_vectors: List[List[List[float]]], plot_waveforms: bool = False):
def center_tapped_pre_study(self, time_current_vectors: List[List[List[float]]], plot_waveforms: bool = False)\
-> Dict:
"""
As magnetizing currents are often non-sinusoidal, some corrections in the simulation current waveforms
are needed. This function calculates the new current waveforms for the center tapped study to get
inductance values and so on.
:param time_current_vectors: time-current vectors for primary and secondary
:type time_current_vectors: List[List[List[float]]]
:param plot_waveforms: True to watch the pre-calculated waveforms
:type plot_waveforms: bool
:return: new current waveform vector
:rtype: Dict
return dict:
center_tapped_study_excitation = {
"hysteresis": {
"frequency": None,
"transformer": {
"current_amplitudes": None,
"current_phases_deg": None
},
"choke": {
"current_amplitudes": None,
"current_phases_deg": None
}
},
"linear_losses": {
"frequencies": None,
"current_amplitudes": None,
"current_phases_deg": None
}
}
"""

def hysteresis_loss_excitation(input_time_current_vectors):
# collect simulation input parameters from time_current_vectors
Expand Down Expand Up @@ -1294,14 +1331,15 @@ def linear_loss_excitation(time_current_vectors: List[List[List[float]]]):

return center_tapped_study_excitation

def stacked_core_center_tapped_study(self, center_tapped_study_excitation, no_primary_coil_turns=None, non_sine_hysteresis_correction=False):
def stacked_core_center_tapped_study(self, center_tapped_study_excitation, number_primary_coil_turns: int = None,
non_sine_hysteresis_correction: bool = False):
"""
Comprehensive component analysis for center tapped transformers with dedicated choke.
:param non_sine_hysteresis_correction:
:param non_sine_hysteresis_correction: True to enable the non-sinusoidal hysteresis correction factor
:param center_tapped_study_excitation:
:param time_current_vectors:
:param plot_waveforms:
:param number_primary_coil_turns: number of primary coil turns. Needed due to a special trick to get the transformer losses without effect of the choke
:type number_primary_coil_turns: int
:return:
"""

Expand All @@ -1321,7 +1359,7 @@ def factor_triangular_hysteresis_loss_iGSE(D, alpha):
# print(f"{p_hyst = }")


ps_primary_coil_turns = [150000+i for i in range(no_primary_coil_turns)]
ps_primary_coil_turns = [150000 + i for i in range(number_primary_coil_turns)]
self.overwrite_conductors_with_air(ps_primary_coil_turns)
self.excitation(frequency=center_tapped_study_excitation["hysteresis"]["frequency"],
amplitude_list=center_tapped_study_excitation["hysteresis"]["transformer"]["current_amplitudes"],
Expand All @@ -1346,7 +1384,7 @@ def factor_triangular_hysteresis_loss_iGSE(D, alpha):
# p_hyst = factor_triangular_hysteresis_loss_iGSE(D=0.5, alpha=alpha_from_db) * p_hyst
# print(f"{p_hyst = }")

ps_primary_coil_turns = [150000 + i for i in range(no_primary_coil_turns)]
ps_primary_coil_turns = [150000 + i for i in range(number_primary_coil_turns)]

self.overwrite_air_conductors_with_conductors(list(np.array(ps_primary_coil_turns)+1000000))
self.excitation(frequency=center_tapped_study_excitation["hysteresis"]["frequency"],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import numpy as np

import femmt as fmt
import materialdatabase as mdb
import os

def basic_example_inductor(onelab_folder: str = None, show_visual_outputs: bool = True, is_test: bool = False):
def advanced_example_inductor_sweep(onelab_folder: str = None, show_visual_outputs: bool = True, is_test: bool = False):

example_results_folder = os.path.join(os.path.dirname(__file__), "example_results")
if not os.path.exists(example_results_folder):
Expand All @@ -16,7 +17,7 @@ def basic_example_inductor(onelab_folder: str = None, show_visual_outputs: bool

# 1. chose simulation type
geo = fmt.MagneticComponent(component_type=fmt.ComponentType.Inductor, working_directory=working_directory,
silent=True, is_gui=is_test)
verbosity=fmt.Verbosity.Silent, is_gui=is_test)

# This line is for automated pytest running on github only. Please ignore this line!
if onelab_folder is not None: geo.file_data.onelab_folder_path = onelab_folder
Expand All @@ -33,27 +34,17 @@ def basic_example_inductor(onelab_folder: str = None, show_visual_outputs: bool

core = fmt.Core(core_type=fmt.CoreType.Single,
core_dimensions=core_dimensions,
material="N95", temperature=30, frequency=inductor_frequency,
material=mdb.Material.N95, temperature=30, frequency=inductor_frequency,
# permeability_datasource="manufacturer_datasheet",
# permeability_datasource=fmt.MaterialDataSource.Custom, mu_r_abs=2000, phi_mu_deg=1,

permeability_datasource=fmt.MaterialDataSource.Measurement,
permeability_datatype=fmt.MeasurementDataType.ComplexPermeability,
# permeability_measurement_setup="LEA_LK",
permeability_measurement_setup="small_signal2",
# permeability_measurement_setup="small_signal1",
permeability_measurement_setup=mdb.MeasurementSetup.LEA_LK,
permittivity_datasource=fmt.MaterialDataSource.Measurement,
permittivity_datatype=fmt.MeasurementDataType.ComplexPermittivity,
# permittivity_measurement_setup="LEA_LK")
permittivity_measurement_setup="small_signal")

# permeability_datasource = fmt.MaterialDataSource.Custom, mu_r_abs=1945, phi_mu_deg=1.551,
# permittivity_datasource = fmt.MaterialDataSource.Custom,
# permittivity_datatype = fmt.MeasurementDataType.ComplexPermittivity,
# sigma=complex(0.34999993, 1.9999996) # 500kHz 5.9476647885531e-06
# # sigma = complex(0.38499992, 2.19999956) # 550kHz
# # sigma=complex(0.69999986, 3.9999992) # 1MHz
# )
permittivity_measurement_setup=mdb.MeasurementSetup.LEA_LK)

geo.set_core(core)

# 3. set air gap parameters
Expand Down Expand Up @@ -105,4 +96,4 @@ def basic_example_inductor(onelab_folder: str = None, show_visual_outputs: bool


if __name__ == "__main__":
basic_example_inductor(show_visual_outputs=True)
advanced_example_inductor_sweep(show_visual_outputs=True)
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#femmt libraries
import femmt as fmt
import materialdatabase as mdb



Expand Down Expand Up @@ -45,13 +46,13 @@
temperature=100,

# sweep parameters: geometry and material
material_list = ["N95"],
material_list = [mdb.Material.N95],
core_inner_diameter_min_max_list= [18e-3, 22e-3],
window_w_min_max_list= [10e-3, 14e-3],
window_h_bot_min_max_list= [13e-3, 15e-3],
max_transformer_total_height=40e-3,
primary_litz_wire_list= ["1.71x140x0.1"],
metal_sheet_thickness_list= [0.0005, 0.0015],
metal_sheet_thickness_list= [0.5e-3, 1.5e-3],
primary_coil_turns_min_max_list = [1,5],

# fix parameters
Expand All @@ -66,7 +67,7 @@
if __name__ == '__main__':
time_start = datetime.datetime.now()

fmt.StackedTransformerOptimization.FemSimulation.start_proceed_study(study_name, dab_transformer_config, 15,
fmt.StackedTransformerOptimization.FemSimulation.start_proceed_study(study_name, dab_transformer_config, 1000,
number_objectives=4,
sampler=optuna.samplers.NSGAIIISampler())
#fmt.StackedTransformerOptimization.FemSimulation.show_study_results(study_name, dab_transformer_config)
7 changes: 4 additions & 3 deletions femmt/examples/basic_inductor.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import femmt as fmt
import materialdatabase as mdb
import os

def basic_example_inductor(onelab_folder: str = None, show_visual_outputs: bool = True, is_test: bool = False):
Expand Down Expand Up @@ -96,14 +97,14 @@ def example_thermal_simulation(show_visual_outputs: bool = True):
core = fmt.Core(core_type=fmt.CoreType.Single,
core_dimensions=core_dimensions,
detailed_core_model=False,
material="N49", temperature=45, frequency=inductor_frequency,
material=mdb.Material.N49, temperature=45, frequency=inductor_frequency,
# permeability_datasource="manufacturer_datasheet",
permeability_datasource=fmt.MaterialDataSource.Measurement,
permeability_datatype=fmt.MeasurementDataType.ComplexPermeability,
permeability_measurement_setup="LEA_LK",
permeability_measurement_setup=mdb.MeasurementSetup.LEA_LK,
permittivity_datasource=fmt.MaterialDataSource.Measurement,
permittivity_datatype=fmt.MeasurementDataType.ComplexPermittivity,
permittivity_measurement_setup="LEA_LK", mdb_verbosity=fmt.Verbosity.Silent)
permittivity_measurement_setup=mdb.MeasurementSetup.LEA_LK, mdb_verbosity=fmt.Verbosity.Silent)
# mu_rel=3000, phi_mu_deg=10,
# sigma=0.5)
geo.set_core(core)
Expand Down
65 changes: 65 additions & 0 deletions femmt/examples/basic_inductor_foil_vertical.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import femmt as fmt
import os


def basic_example_inductor_foil_vertical(onelab_folder: str = None, show_visual_outputs: bool = True, is_test: bool = False):
# Choose wrap para type
wrap_para_type = fmt.WrapParaType.FixedThickness
# wrap_para_type = fmt.WrapParaType.Interpolate

example_results_folder = os.path.join(os.path.dirname(__file__), "example_results")
if not os.path.exists(example_results_folder):
os.mkdir(example_results_folder)

# Example for a transformer with multiple virtual winding windows.
working_directory = os.path.join(example_results_folder, "inductor_foil_vertical")
if not os.path.exists(working_directory):
os.mkdir(working_directory)

# Choose wrap para type
wrap_para_type = fmt.WrapParaType.FixedThickness

# Set is_gui = True so FEMMt won't ask for the onelab path if no config is found.
geo = fmt.MagneticComponent(component_type=fmt.ComponentType.Inductor, working_directory=working_directory,
verbosity=fmt.Verbosity.Silent, is_gui=is_test)

# This line is for automated pytest running on github only. Please ignore this line!
if onelab_folder is not None: geo.file_data.onelab_folder_path = onelab_folder

core_db = fmt.core_database()["PQ 40/40"]
core_dimensions = fmt.dtos.SingleCoreDimensions(core_inner_diameter=core_db["core_inner_diameter"],
window_w=core_db["window_w"],
window_h=core_db["window_h"],
core_h=core_db["core_h"])

core = fmt.Core(core_type=fmt.CoreType.Single, core_dimensions=core_dimensions,
mu_r_abs=3100, phi_mu_deg=12,
sigma=0.6, permeability_datasource=fmt.MaterialDataSource.Custom,
permittivity_datasource=fmt.MaterialDataSource.Custom)
geo.set_core(core)

air_gaps = fmt.AirGaps(fmt.AirGapMethod.Center, core)
air_gaps.add_air_gap(fmt.AirGapLegPosition.CenterLeg, 0.0005)
geo.set_air_gaps(air_gaps)

insulation = fmt.Insulation()
insulation.add_core_insulations(0.001, 0.001, 0.002, 0.001)
insulation.add_winding_insulations([[0.0005]])
geo.set_insulation(insulation)

winding_window = fmt.WindingWindow(core, insulation)
vww = winding_window.split_window(fmt.WindingWindowSplit.NoSplit)

winding = fmt.Conductor(0, fmt.Conductivity.Copper, winding_material_temperature=25)
winding.set_rectangular_conductor(thickness=1e-3)

vww.set_winding(winding, 5, fmt.WindingScheme.FoilVertical, wrap_para_type)
geo.set_winding_windows([winding_window])

geo.create_model(freq=100000, pre_visualize_geometry=show_visual_outputs, save_png=False)

geo.single_simulation(freq=100000, current=[3], show_fem_simulation_results=show_visual_outputs)


if __name__ == "__main__":
basic_example_inductor_foil_vertical(show_visual_outputs=True)
Loading

0 comments on commit e24d33a

Please sign in to comment.