Skip to content

Commit 17c6e93

Browse files
author
Othman Abujazar
committed
seperate the electrostatic material from the magnetic material
1 parent 81bdd0a commit 17c6e93

9 files changed

Lines changed: 178 additions & 106 deletions

femmt/component.py

Lines changed: 120 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,7 +1322,10 @@ def write_simulation_parameters_to_pro_files(self):
13221322
logger.info("Write simulation parameters to .pro files (file communication).")
13231323

13241324
# Write initialization parameters for simulation in 'Parameter.pro' file
1325-
self.write_electro_magnetic_parameter_pro()
1325+
if self.simulation_type == SimulationType.ElectroStatic:
1326+
self.write_electro_static_parameter_pro()
1327+
else:
1328+
self.write_electro_magnetic_parameter_pro()
13261329

13271330
# Write postprocessing parameters in 'postquantities.pro' file
13281331
self.write_electro_magnetic_post_pro()
@@ -3458,20 +3461,10 @@ def write_electro_magnetic_parameter_pro(self):
34583461
text_file.write("Flag_Time_Domain = 1;\n")
34593462
text_file.write("Flag_Freq_Domain = 0;\n")
34603463
text_file.write("Flag_Static = 0;\n")
3461-
if self.simulation_type == SimulationType.ElectroStatic:
3462-
text_file.write("Flag_Static = 1;\n")
3463-
text_file.write("Flag_Freq_Domain = 0;\n")
3464-
text_file.write("Flag_Time_Domain = 0;\n")
3465-
3466-
# Airgap number
3467-
if self.simulation_type == SimulationType.ElectroStatic:
3468-
text_file.write("n_airgaps = {};\n".format(len(self.air_gaps.midpoints)))
3469-
3470-
# Frequency
3471-
if not self.simulation_type == SimulationType.ElectroStatic:
3472-
text_file.write("Freq = %s;\n" % self.frequency)
3473-
text_file.write(f"delta = {self.delta};\n")
34743464

3465+
# Frequency
3466+
text_file.write("Freq = %s;\n" % self.frequency)
3467+
text_file.write(f"delta = {self.delta};\n")
34753468
# time domain parameters
34763469
if self.simulation_type == SimulationType.TimeDomain:
34773470
text_file.write(f"T = {self.time_period};\n")
@@ -3503,8 +3496,6 @@ def write_electro_magnetic_parameter_pro(self):
35033496
winding_number=winding_number)
35043497

35053498
if self.windings[winding_number].parallel:
3506-
if self.simulation_type == SimulationType.ElectroStatic:
3507-
raise Exception("Parallel winding are not considered yet for electrostatic simulation")
35083499
text_file.write(f"NbrCond_{winding_number + 1} = 1;\n")
35093500
text_file.write(f"AreaCell_{winding_number + 1} = {self.windings[winding_number].a_cell * turns};\n")
35103501
else:
@@ -3551,32 +3542,6 @@ def write_electro_magnetic_parameter_pro(self):
35513542
text_file.write(f"Val_EE_{winding_number + 1} = {self.current_density[winding_number]};\n")
35523543
raise NotImplementedError
35533544

3554-
if self.simulation_type == SimulationType.ElectroStatic:
3555-
if self.voltage is not None:
3556-
text_file.write("Flag_voltage = 1;\n")
3557-
text_file.write("Flag_charge = 0;\n")
3558-
turns = self.voltage[winding_number]
3559-
for turn_index, voltage_value in enumerate(turns):
3560-
text_file.write(f"Voltage_{winding_number + 1}_{turn_index + 1} = {voltage_value};\n")
3561-
elif self.charge is not None:
3562-
text_file.write("Flag_charge = 1;\n")
3563-
text_file.write("Flag_voltage = 0;\n")
3564-
turns = self.charge[winding_number]
3565-
for turn_index, charge_value in enumerate(turns):
3566-
text_file.write(f"Charge_{winding_number + 1}_{turn_index + 1} = {charge_value};\n")
3567-
3568-
if self.v_core is not None:
3569-
text_file.write("v_core = {};\n".format(self.v_core))
3570-
text_file.write("Flag_excite_core = 1;\n")
3571-
else:
3572-
text_file.write("Flag_excite_core = 0;\n")
3573-
3574-
if self.v_ground_out_boundary == 0:
3575-
text_file.write("Flag_ground_OutBoundary = 1;\n")
3576-
text_file.write("v_ground_OutBoundary = 0;\n")
3577-
else:
3578-
text_file.write("Flag_ground_OutBoundary = 0;\n")
3579-
35803545
logger.info(f"Cell surface area: {self.windings[winding_number].a_cell}, "
35813546
f"Reduced frequency: {self.red_freq[winding_number]}")
35823547

@@ -3601,35 +3566,123 @@ def write_electro_magnetic_parameter_pro(self):
36013566
text_file.write("er_layer_insulation = 1.0;\n")
36023567
text_file.write(f"er_bobbin = {self.insulation.er_bobbin};\n")
36033568

3604-
if not self.simulation_type == SimulationType.ElectroStatic:
3605-
# Core Material
3606-
text_file.write(f"mur = {self.core.material.mu_r_abs};\n") # mur is predefined to a fixed value
3607-
if self.core.material.permeability_type == PermeabilityType.FromData:
3608-
text_file.write("Flag_Permeability_From_Data = 1;\n") # mur is predefined to a fixed value
3569+
# Core Material
3570+
text_file.write(f"mur = {self.core.material.mu_r_abs};\n") # mur is predefined to a fixed value
3571+
if self.core.material.permeability_type == PermeabilityType.FromData:
3572+
text_file.write("Flag_Permeability_From_Data = 1;\n") # mur is predefined to a fixed value
3573+
else:
3574+
text_file.write("Flag_Permeability_From_Data = 0;\n") # mur is predefined to a fixed value
3575+
if self.core.material.permeability_type == PermeabilityType.FixedLossAngle:
3576+
# Real part of complex permeability
3577+
text_file.write(f"mur_real = {self.core.material.mu_r_abs * np.cos(np.deg2rad(self.core.material.phi_mu_deg))};\n")
3578+
# Imaginary part of complex permeability
3579+
text_file.write(
3580+
f"mur_imag = {self.core.material.mu_r_abs * np.sin(np.deg2rad(self.core.material.phi_mu_deg))};\n")
3581+
# loss angle for complex representation of hysteresis loss
3582+
text_file.write("Flag_Fixed_Loss_Angle = 1;\n")
3583+
else:
3584+
text_file.write(
3585+
"Flag_Fixed_Loss_Angle = 0;\n") # loss angle for complex representation of hysteresis loss
3586+
3587+
# Complex (equivalent) conductivity
3588+
self.core.material.complex_conductance = \
3589+
self.core.material.dc_conductivity + complex(0, 1) * 2 * np.pi * self.frequency * self.core.material.complex_permittivity
3590+
if self.core.material.complex_conductance != 0 and self.core.material.complex_conductance is not None:
3591+
text_file.write("Flag_Conducting_Core = 1;\n")
3592+
text_file.write(f"sigma_core_real = {self.core.material.complex_conductance.real};\n")
3593+
text_file.write(f"sigma_core_imag = {self.core.material.complex_conductance.imag};\n")
3594+
else:
3595+
text_file.write("Flag_Conducting_Core = 0;\n")
3596+
3597+
text_file.close()
3598+
3599+
def write_electro_static_parameter_pro(self):
3600+
"""
3601+
Write the needed parameters to the "ElectrostaticParameter.pro" file.
3602+
3603+
This file is generated by python and is read by gmsh to hand over some parameters.
3604+
"""
3605+
text_file = open(os.path.join(self.file_data.electro_magnetic_folder_path, "ElectrostaticParameter.pro"), "w")
3606+
3607+
# component types
3608+
if self.component_type == ComponentType.Inductor:
3609+
text_file.write("Number_of_Windings = {};\n".format(len(self.windings)))
3610+
3611+
if self.component_type == ComponentType.Transformer:
3612+
text_file.write("Number_of_Windings = {};\n".format(len(self.windings)))
3613+
3614+
if self.component_type == ComponentType.IntegratedTransformer:
3615+
text_file.write("Number_of_Windings = {};\n".format(len(self.windings)))
3616+
3617+
text_file.write("Flag_Static = 1;\n")
3618+
3619+
# Airgap number
3620+
text_file.write("n_airgaps = {};\n".format(len(self.air_gaps.midpoints)))
3621+
3622+
# Conductor specific definitions
3623+
for winding_number in range(len(self.windings)):
3624+
# -- Geometry --
3625+
# Core Parts
3626+
text_file.write(f"nCoreParts = {len(self.mesh.plane_surface_core)};\n")
3627+
3628+
turns = ff.get_number_of_turns_of_winding(winding_windows=self.winding_windows, windings=self.windings,
3629+
winding_number=winding_number)
3630+
3631+
if self.windings[winding_number].parallel:
3632+
raise Exception("Parallel winding are not considered yet for electrostatic simulation")
36093633
else:
3610-
text_file.write("Flag_Permeability_From_Data = 0;\n") # mur is predefined to a fixed value
3611-
if self.core.material.permeability_type == PermeabilityType.FixedLossAngle:
3612-
# Real part of complex permeability
3613-
text_file.write(f"mur_real = {self.core.material.mu_r_abs * np.cos(np.deg2rad(self.core.material.phi_mu_deg))};\n")
3614-
# Imaginary part of complex permeability
3615-
text_file.write(
3616-
f"mur_imag = {self.core.material.mu_r_abs * np.sin(np.deg2rad(self.core.material.phi_mu_deg))};\n")
3617-
# loss angle for complex representation of hysteresis loss
3618-
text_file.write("Flag_Fixed_Loss_Angle = 1;\n")
3634+
text_file.write(f"NbrCond_{winding_number + 1} = {turns};\n")
3635+
text_file.write(f"AreaCell_{winding_number + 1} = {self.windings[winding_number].a_cell};\n")
3636+
3637+
# relative permittivity
3638+
# Turn insulation is not implemented yet for RectangularSolid
3639+
# Or if the turn insulation is not drawn
3640+
if self.windings[winding_number].conductor_type == ConductorType.RectangularSolid or not self.insulation.turn_ins:
3641+
text_file.write(f"er_turns_insulation_{winding_number + 1} = 1.0;\n")
36193642
else:
3620-
text_file.write(
3621-
"Flag_Fixed_Loss_Angle = 0;\n") # loss angle for complex representation of hysteresis loss
3622-
3623-
# Complex (equivalent) conductivity
3624-
self.core.material.complex_conductance = \
3625-
self.core.material.dc_conductivity + complex(0, 1) * 2 * np.pi * self.frequency * self.core.material.complex_permittivity
3626-
if self.core.material.complex_conductance != 0 and self.core.material.complex_conductance is not None:
3627-
text_file.write("Flag_Conducting_Core = 1;\n")
3628-
text_file.write(f"sigma_core_real = {self.core.material.complex_conductance.real};\n")
3629-
text_file.write(f"sigma_core_imag = {self.core.material.complex_conductance.imag};\n")
3643+
text_file.write(f"er_turns_insulation_{winding_number + 1} = {self.insulation.er_turn_insulation[winding_number]};\n")
3644+
3645+
# For stranded Conductors:
3646+
# text_file.write(f"NbrstrandedCond = {self.turns};\n") # redundant
3647+
if self.windings[winding_number].conductor_type == ConductorType.RoundLitz:
3648+
raise Exception("RoundLitz conductor type not yet implemented for electrostatic simulation")
3649+
3650+
# could be needed in future
3651+
text_file.write(f"Rc_{winding_number + 1} = {self.windings[winding_number].conductor_radius};\n")
3652+
3653+
if self.voltage is not None:
3654+
text_file.write("Flag_voltage = 1;\n")
3655+
text_file.write("Flag_charge = 0;\n")
3656+
turns = self.voltage[winding_number]
3657+
for turn_index, voltage_value in enumerate(turns):
3658+
text_file.write(f"Voltage_{winding_number + 1}_{turn_index + 1} = {voltage_value};\n")
3659+
elif self.charge is not None:
3660+
text_file.write("Flag_charge = 1;\n")
3661+
text_file.write("Flag_voltage = 0;\n")
3662+
turns = self.charge[winding_number]
3663+
for turn_index, charge_value in enumerate(turns):
3664+
text_file.write(f"Charge_{winding_number + 1}_{turn_index + 1} = {charge_value};\n")
3665+
3666+
if self.v_core is not None:
3667+
text_file.write("v_core = {};\n".format(self.v_core))
3668+
text_file.write("Flag_excite_core = 1;\n")
36303669
else:
3631-
text_file.write("Flag_Conducting_Core = 0;\n")
3670+
text_file.write("Flag_excite_core = 0;\n")
36323671

3672+
if self.v_ground_out_boundary == 0:
3673+
text_file.write("Flag_ground_OutBoundary = 1;\n")
3674+
text_file.write("v_ground_OutBoundary = 0;\n")
3675+
else:
3676+
text_file.write("Flag_ground_OutBoundary = 0;\n")
3677+
3678+
# Nature Constants
3679+
text_file.write(f"e0 = {epsilon_0};\n")
3680+
text_file.write(f"er_core= {self.core.material.eps_r};\n")
3681+
if self.insulation.er_layer_insulation is not None:
3682+
text_file.write(f"er_layer_insulation = {self.insulation.er_layer_insulation};\n")
3683+
else:
3684+
text_file.write("er_layer_insulation = 1.0;\n")
3685+
text_file.write(f"er_bobbin = {self.insulation.er_bobbin};\n")
36333686
text_file.close()
36343687

36353688
def write_electro_magnetic_post_pro(self):
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Number_of_Windings = 1;
2+
Flag_Static = 1;
3+
n_airgaps = 1;
4+
nCoreParts = 1;
5+
NbrCond_1 = 7;
6+
AreaCell_1 = 4.159092813207812e-06;
7+
er_turns_insulation_1 = 3.5;
8+
Rc_1 = 0.0011506;
9+
Flag_voltage = 1;
10+
Flag_charge = 0;
11+
Voltage_1_1 = 1.0;
12+
Voltage_1_2 = 0.8333333333333334;
13+
Voltage_1_3 = 0.6666666666666667;
14+
Voltage_1_4 = 0.5;
15+
Voltage_1_5 = 0.33333333333333337;
16+
Voltage_1_6 = 0.16666666666666663;
17+
Voltage_1_7 = 0.0;
18+
v_core = 0;
19+
Flag_excite_core = 1;
20+
Flag_ground_OutBoundary = 0;
21+
e0 = 8.8541878128e-12;
22+
er_core= 100000.0;
23+
er_layer_insulation = 3.5;
24+
er_bobbin = 4.5;

femmt/electro_magnetic/ind_axi_python_controlled_electrostatic.pro

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// ----------------------
2-
Include "Parameter.pro";
2+
Include "ElectrostaticParameter.pro";
33
Include "postquantities.pro";
44
// All Variables - remove or create in python
55
// ----------------------
@@ -180,7 +180,7 @@ Function {
180180
SurfCore[] = SurfaceArea[]{CORE_PN} ;
181181
// Materials
182182
er_air = 1;
183-
er_core = 100000;
183+
er_core = er_core;
184184
//er_cond_insulation = 3;
185185
For n In {1:n_windings}
186186
epsilon[#{Cond_Insulation~{n}}] = e0 * er_turns_insulation~{n};

femmt/examples/basic_inductor_electrostatic.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,7 @@ def basic_example_inductor_electrostatic(onelab_folder: str = None, show_visual_
5252
window_h=core_db["window_h"],
5353
core_h=core_db["core_h"])
5454

55-
core_material = fmt.ImportedComplexCoreMaterial(material=fmt.Material.N49,
56-
temperature=45,
57-
permeability_datasource=fmt.DataSource.TDK_MDT,
58-
permittivity_datasource=fmt.DataSource.LEA_MTB,
59-
mdb_verbosity=fmt.Verbosity.Silent)
55+
core_material = fmt.ElectrostaticCoreMaterial(eps_r=100e3)
6056

6157
core = fmt.Core(material=core_material,
6258
core_type=fmt.CoreType.Single,

femmt/examples/basic_inductor_foil_vertical_electrostatic.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,7 @@ def basic_example_inductor_foil_vertical_electrostatic(onelab_folder: str = None
4949
window_h=core_db["window_h"],
5050
core_h=core_db["core_h"])
5151

52-
core_material = fmt.ImportedComplexCoreMaterial(material=fmt.Material.N49,
53-
temperature=45,
54-
permeability_datasource=fmt.DataSource.TDK_MDT,
55-
permittivity_datasource=fmt.DataSource.LEA_MTB,
56-
mdb_verbosity=fmt.Verbosity.Silent)
52+
core_material = fmt.ElectrostaticCoreMaterial(eps_r=100e3)
5753

5854
core = fmt.Core(material=core_material,
5955
core_type=fmt.CoreType.Single,

femmt/examples/basic_transformer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,10 @@ def example_thermal_simulation(show_thermal_visual_outputs: bool = True, flag_in
147147
winding1 = fmt.Conductor(0, fmt.ConductorMaterial.Copper)
148148
winding1.set_solid_round_conductor(0.0011, fmt.ConductorArrangement.Square)
149149

150-
# winding1 = fmt.Conductor(0, fmt.Conductivity.Copper)
150+
# winding1 = fmt.Conductor(0, fmt.ConductorMaterial.Copper)
151151
# winding1.set_litz_round_conductor(0.0011, 50, 0.00011, None, fmt.ConductorArrangement.Square)
152152

153-
# winding2 = fmt.Conductor(1, fmt.Conductivity.Copper)
153+
# winding2 = fmt.Conductor(1, fmt.ConductorMaterial.Copper)
154154
# winding2.set_solid_round_conductor(0.0011, fmt.ConductorArrangement.Square)
155155

156156
winding2 = fmt.Conductor(1, fmt.ConductorMaterial.Copper)

femmt/examples/basic_transformer_electrostatic.py

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,25 +43,13 @@ def basic_example_transformer_electrostatic(onelab_folder: str = None, show_visu
4343
geo.file_data.onelab_folder_path = onelab_folder
4444

4545
# 2. set core parameters
46-
# core_dimensions = fmt.dtos.SingleCoreDimensions(core_inner_diameter=0.02, window_w=0.01, window_h=0.03,
47-
# core_h=0.02)
48-
# core = fmt.Core(core_dimensions=core_dimensions, mu_r_abs=3100, phi_mu_deg=12, sigma=1.2,
49-
# permeability_datasource=fmt.MaterialDataSource.Custom,
50-
# permittivity_datasource=fmt.MaterialDataSource.Custom,
51-
# detailed_core_model=False)
52-
# geo.set_core(core)
5346
core_db = fmt.core_database()["PQ 40/40"]
5447
core_dimensions = fmt.dtos.SingleCoreDimensions(core_inner_diameter=core_db["core_inner_diameter"],
5548
window_w=core_db["window_w"],
5649
window_h=core_db["window_h"],
5750
core_h=core_db["core_h"])
58-
# core_material = fmt.ImportedComplexCoreMaterial(material=fmt.Material.N49,
59-
# temperature=45,
60-
# permeability_datasource=fmt.DataSource.TDK_MDT,
61-
# permittivity_datasource=fmt.DataSource.LEA_MTB,
62-
# mdb_verbosity=fmt.Verbosity.Silent)
63-
64-
core = fmt.Core(material=None,
51+
core_material = fmt.ElectrostaticCoreMaterial(eps_r=100e3)
52+
core = fmt.Core(material=core_material,
6553
core_type=fmt.CoreType.Single,
6654
core_dimensions=core_dimensions,
6755
detailed_core_model=False)

femmt/model.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,29 @@ def to_dict(self) -> Dict[str, Any]:
489489
"permittivity_datatype": MeasurementDataType.ComplexPermittivity
490490
}
491491

492+
class ElectrostaticCoreMaterial:
493+
"""Defines material properties for electrostatic simulations."""
494+
495+
def __init__(self, eps_r: float):
496+
"""
497+
Define the dielectric constant of the core.
498+
499+
:param eps_r: Relative permittivity of the core material.
500+
:type eps_r: float
501+
"""
502+
self.eps_r = eps_r
503+
504+
def to_dict(self):
505+
"""Return a dictionary representation of the core material.
506+
507+
Useful for serialization or logging.
508+
509+
:return: Dictionary of core material parameters.
510+
:rtype: dict
511+
"""
512+
return {
513+
"eps_r": self.eps_r
514+
}
492515

493516
class Core:
494517
"""Combines geometry and material properties of a magnetic core.
@@ -500,7 +523,7 @@ class Core:
500523
"""
501524

502525
def __init__(self,
503-
material: ImportedComplexCoreMaterial | LinearComplexCoreMaterial,
526+
material: ImportedComplexCoreMaterial | LinearComplexCoreMaterial | ElectrostaticCoreMaterial,
504527
core_type: CoreType = CoreType.Single,
505528
core_dimensions: Optional[object] = None,
506529
detailed_core_model: bool = False):

0 commit comments

Comments
 (0)