cd /news/developer-tools/apec-2026-s10-python-for-power-elect… · home › topics › developer-tools › article
[ARTICLE · art-152202] src=gist.github.com ↗ pub= topic=developer-tools verified=true sentiment=· neutral

APEC 2026 S10: Python For Power Electronics: From Zero To AI . Flyback Magnetic Ansys Automation

A developer published a Python script that automates the construction of a flyback transformer model in Ansys Maxwell 3D using the PyAEDT library, covering core geometry, gapping, bobbin, and winding parameters. The script defines ferrite material properties with Steinmetz core-loss coefficients, builds the core and winding window via boolean subtraction, and configures an eddy-current solution for a 120 kHz design with 30 primary and 10 secondary turns. It is presented as a training lesson on scripting power-electronics magnetics simulation.

by read8 min views3 publishedOct 18, 2026

| | import shutil | | | import os | | | import sys | | | import time | | | import pyaedt | | | from pyaedt.modeler.cad.object3d import Object3d | | | number_segments_arcs = 12 | | | gap_length = 500e-6 | | | resudial_gap_length = 0.000005 | | | bobbin_thickness = 0.001 | | | dim = {"A": 0.02850, "B": 0.01400, "C": 0.01140, "D": 0.00960, "E": 0.02170, "F": 0.00990} | | | primary_wire_diameter = 0.0005 | | | primary_wire_coating = 34e-6 | | | secondary_wire_diameter = 0.00147 | | | primary_number_turns = 30 | | | secondary_number_turns = 10 | | | secondary_strand_diameter = 50e-6 | | | secondary_number_strands = 400 | | | frequency = 120000 | | | current_primary = 0.7 | | | current_secondary = 2.1 | | | voltage_secondary = 12 | | | material = { | | | "name": "95", | | | "initial_permeability": 2980, | | | "resistivity": 2, | | | "steinmetz_k": 6.941832847, | | | "steinmetz_alpha": 1.433728921, | | | "steinmetz_beta": 2.494912103, | | | } |

|  | color_ferrite = [89, 94, 107] | 
|  | color_copper = [242, 140, 102] | 
|  | color_litz = [0xd3, 0xe1, 0xf5] | 
|  | color_teflon = [0x53, 0x97, 0x96] | 
|  | color_bobbin = [52, 52, 52] | 
|  | color_tape = [0xed, 0xbe, 0x1c] | 

| | output_dir = "C:/Users/alfonso/Magnetics training/outputs" |

|  | os.makedirs(output_dir, exist_ok=True) | 
|  | project = pyaedt.Maxwell3d( | 
|  | project=f"{output_dir}/Lesson_27_{time.time()}", | 

| | solution_type="EddyCurrent", | | | non_graphical=False, | | | new_desktop=False, | | | close_on_exit=False | | | ) | | | project.modeler.model_units = "meter" | | | aedt_material = project.materials.add_material(material["name"]) | | | aedt_material.permeability = material["initial_permeability"] | | | conductivity = 1.0 / material["resistivity"] | | | aedt_material.conductivity = conductivity | | | aedt_material.set_power_ferrite_coreloss( |

|  | cm=material["steinmetz_k"], | 
|  | x=material["steinmetz_alpha"], | 
|  | y=material["steinmetz_beta"] | 

| | ) | | | core = project.modeler.create_box( |

|  | origin=[-dim["C"] / 2, -dim["A"] / 2, -2 * dim["B"] / 2], | 
|  | sizes=[dim["C"], dim["A"], 2 * dim["B"]], | 

| | name="core", | | | material=material["name"] | | | ) | | | core.color = color_ferrite | | | core.transparency = 0 | | | project.modeler.fit_all() | | | central_column = project.modeler.create_cylinder( | | | orientation=pyaedt.constants.AXIS.Z, |

|  | origin=[0, 0, -dim["D"]], | 
|  | radius=dim["F"] / 2, | 
|  | height=dim["D"] * 2, | 

| | num_sides=number_segments_arcs, | | | name="central_column", | | | material="air" | | | ) | | | winding_window = project.modeler.create_cylinder( | | | orientation=pyaedt.constants.AXIS.Z, |

|  | origin=[0, 0, -dim["D"]], | 
|  | radius=dim["E"] / 2, | 
|  | height=dim["D"] * 2, | 

| | num_sides=number_segments_arcs, | | | name="winding_window", | | | material="air" | | | ) | | | winding_window.subtract(central_column, True) | | | core.subtract(winding_window, False) | | | gap = project.modeler.create_box( |

|  | origin=[-dim["F"] / 2, -dim["F"] / 2, -0], | 
|  | sizes=[dim["F"], dim["F"], gap_length], | 

| | name="gap", | | | material="air" | | | ) | | | core.subtract(gap, False) | | | resudial_gap = project.modeler.create_box( |

|  | origin=[-dim["A"] / 2, -dim["A"] / 2, -0], | 
|  | sizes=[dim["A"], dim["A"], resudial_gap_length], | 

| | name="resudial_gap", | | | material="air" | | | ) | | | core.subtract(resudial_gap, False) | | | project.set_core_losses( | | | assignment=[core.name], | | | core_loss_on_field=True | | | ) | | | bobbin = project.modeler.create_cylinder( | | | orientation=pyaedt.constants.AXIS.Z, |

|  | origin=[0, 0, -dim["D"]], | 
|  | radius=dim["E"] / 2, | 
|  | height=dim["D"] * 2, | 

| | num_sides=number_segments_arcs, | | | name="bobbin", | | | material="PVC plastic" | | | ) | | | bobbin.color = color_bobbin | | | bobbin.transparency = 0 | | | bobbin_winding_window = project.modeler.create_cylinder( | | | orientation=pyaedt.constants.AXIS.Z, |

|  | origin=[0, 0, -dim["D"] + bobbin_thickness], | 
|  | radius=dim["E"] / 2, | 
|  | height=dim["D"] * 2 - bobbin_thickness * 2, | 

| | num_sides=number_segments_arcs, | | | name="bobbin", | | | material="air" | | | ) | | | bobbin_winding_window_hole = project.modeler.create_cylinder( | | | orientation=pyaedt.constants.AXIS.Z, |

|  | origin=[0, 0, -dim["D"]], | 
|  | radius=dim["F"] / 2 + bobbin_thickness, | 
|  | height=dim["D"] * 2, | 

| | num_sides=number_segments_arcs, | | | name="central_column", | | | material="air" | | | ) | | | bobbin_winding_window.subtract(bobbin_winding_window_hole, False) | | | bobbin.subtract(central_column, False) | | | bobbin.subtract(bobbin_winding_window, False) |

|  | primary_terminals = [] | 
|  | current_turn_height = (primary_number_turns - 1) * (primary_wire_diameter + 2 * primary_wire_coating) / 2 | 
|  | for index in range(0, primary_number_turns): | 

| | turn_section = project.modeler.create_circle( | | | orientation=pyaedt.constants.PLANE.YZ, | | | origin=[0, dim["F"] / 2 + bobbin_thickness + primary_wire_coating + primary_wire_diameter / 2, current_turn_height], | | | radius=primary_wire_diameter / 2, | | | num_sides=number_segments_arcs, | | | is_covered=True, | | | name=f"Primary_turn_{index}", | | | material="copper", | | | non_model=False | | | ) | | | turn_object = project.modeler.sweep_around_axis( | | | assignment=turn_section, | | | axis=pyaedt.constants.AXIS.Z, | | | sweep_angle=360, | | | draft_angle=0, | | | number_of_segments=number_segments_arcs | | | ) | | | turn_object.section( | | | plane=pyaedt.constants.PLANE.YZ, | | | create_new=True | | | ) | | | turn_object.transparency = 0 | | | conducting_section_names = project.modeler.get_objects_w_string(f"{turn_object.name}_Section") |

|  | assert len(conducting_section_names) == 1 | 
|  | conducting_section = project.modeler.get_object_from_name(conducting_section_names[0]) | 

| | sections = project.modeler.separate_bodies(conducting_section) |

|  | assert len(sections) == 2 | 
|  | conducting_section = sections[0] | 
|  | project.modeler.delete(sections[1]) | 
|  | terminal = project.assign_coil( | 

| | assignment=conducting_section, | | | conductors_number=1, | | | polarity="Positive", | | | name=f"{turn_object.name}_terminal" | | | ) | | | primary_terminals.append(terminal.name) | | | current_turn_height -= primary_wire_diameter + 2 * primary_wire_coating | | | secondary_terminals = [] | | | litz_wire_material = project.materials.duplicate_material( | | | material="copper", | | | name=f"Litz {secondary_number_strands}x{secondary_strand_diameter * 1000}" | | | ) | | | litz_wire_material.stacking_type = "Litz Wire" | | | litz_wire_material.wire_type = "Round" | | | litz_wire_material.strand_number = secondary_number_strands | | | litz_wire_material.wire_diameter = f"{secondary_wire_diameter}meter" |

|  | current_turn_height = (secondary_number_turns - 1) * (secondary_wire_diameter) / 2 | 
|  | for index in range(0, secondary_number_turns): | 

| | turn_section = project.modeler.create_circle( | | | orientation=pyaedt.constants.PLANE.YZ, | | | origin=[0, dim["F"] / 2 + bobbin_thickness + primary_wire_diameter + 2 * primary_wire_coating + secondary_wire_diameter / 2, current_turn_height], | | | radius=secondary_wire_diameter / 2, | | | num_sides=number_segments_arcs, | | | is_covered=True, | | | name=f"Secondary_turn_{index}", | | | material=litz_wire_material.name, | | | non_model=False | | | ) | | | turn_object = project.modeler.sweep_around_axis( | | | assignment=turn_section, | | | axis=pyaedt.constants.AXIS.Z, | | | sweep_angle=360, | | | draft_angle=0, | | | number_of_segments=number_segments_arcs | | | ) | | | turn_object.section( | | | plane=pyaedt.constants.PLANE.YZ, | | | create_new=True | | | ) | | | turn_object.color = color_litz | | | turn_object.transparency = 0 | | | conducting_section_names = project.modeler.get_objects_w_string(f"{turn_object.name}_Section") |

|  | assert len(conducting_section_names) == 1 | 
|  | conducting_section = project.modeler.get_object_from_name(conducting_section_names[0]) | 

| | sections = project.modeler.separate_bodies(conducting_section) |

|  | assert len(sections) == 2 | 
|  | conducting_section = sections[0] | 
|  | project.modeler.delete(sections[1]) | 
|  | terminal = project.assign_coil( | 

| | assignment=conducting_section, | | | conductors_number=1, | | | polarity="Negative", | | | name=f"{turn_object.name}_terminal" | | | ) | | | secondary_terminals.append(terminal.name) | | | current_turn_height -= secondary_wire_diameter | | | primary = project.assign_winding( | | | winding_type="Current", | | | is_solid=True, | | | current=current_primary, | | | resistance=0, | | | inductance=0, | | | voltage=0, | | | parallel_branches=1, | | | phase=0, | | | name="primary", | | | ) | | | secondary = project.assign_winding( | | | winding_type="Voltage", | | | is_solid=False, | | | current=0, | | | resistance=voltage_secondary / current_secondary, | | | inductance=0, | | | voltage=voltage_secondary, | | | parallel_branches=1, | | | phase=0, | | | name="secondary", | | | ) | | | project.add_winding_coils( | | | assignment=primary.name, | | | coils=[x for i, x in enumerate(primary_terminals)] | | | ) | | | project.add_winding_coils( | | | assignment=secondary.name, | | | coils=[x for i, x in enumerate(secondary_terminals)] | | | ) |

|  | matrix = project.assign_matrix(assignment=[primary.name, secondary.name], matrix_name="solution_matrix") | 
|  | padding = { | 

| | "x_pos": 50, | | | "y_pos": 50, | | | "z_pos": 50, | | | "x_neg": 50, | | | "y_neg": 50, | | | "z_neg": 50, | | | } | | | region = project.modeler.create_region( | | | pad_percent=[padding["x_pos"], padding["x_neg"], padding["y_pos"], padding["y_neg"], padding["z_pos"], padding["z_neg"]], | | | is_percentage=True | | | ) |

|  | setup = project.create_setup("Setup") | 
|  | setup.props["Frequency"] = f"{frequency * 3}" | 
|  | setup.props["PercentRefinement"] = 10 | 
|  | setup.props["MaximumPasses"] = 40 | 
|  | setup.props["PercentError"] = 5 | 
|  | setup.props["HasSweepSetup"] = True | 

| | setup.add_eddy_current_sweep( | | | range_type="LinearStep", | | | start=0.1, | | | end=frequency * 3, | | | count=frequency, | | | units="Hz", | | | clear=True, | | | save_all_fields=True | | | ) |

|  | project.modeler.fit_all() | 
|  | project.analyze() | 
|  | project.release_desktop(close_projects=False, close_desktop=False) |
── more in #developer-tools 4 stories · sorted by recency
── more on @ansys 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/apec-2026-s10-python…] indexed:0 read:8min 2026-10-18 · —