Skip to content

Commit 5d33f1c

Browse files
authored
FEAT: Magnet collector (#429)
1 parent e4463ce commit 5d33f1c

File tree

3 files changed

+381
-0
lines changed

3 files changed

+381
-0
lines changed
42.9 KB
Loading
59.9 KB
Loading
Lines changed: 381 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,381 @@
1+
# # Magnetic behavior of a magnet-collector system
2+
#
3+
# This example shows how to use PyAEDT to understand the magnetic behavior of a simplified
4+
# magnet-collector system when the magnet position changes.
5+
# The example shows how to setup the model, an optimetrics analysis to sweep the magnet position
6+
# and the post-processing of the results, from report creation to field plotting using PyVista.
7+
#
8+
# Keywords: **Maxwell 3D**, **Magnetostatic**, **Magnetic**, **Optimetrics**.
9+
10+
# ## Perform imports and define constants
11+
#
12+
# Perform required imports.
13+
14+
# +
15+
import os
16+
import tempfile
17+
import time
18+
19+
import ansys.aedt.core # Interface to Ansys Electronics Desktop
20+
from ansys.aedt.core.generic.constants import Axis
21+
22+
# -
23+
24+
# ## Define constants
25+
#
26+
# Constants help ensure consistency and avoid repetition throughout the example.
27+
28+
AEDT_VERSION = "2025.2"
29+
NUM_CORES = 4
30+
NG_MODE = False # Open AEDT UI when it is launched.
31+
32+
# ## Create temporary directory
33+
#
34+
# Create a temporary working directory.
35+
# The name of the working folder is stored in ``temp_folder.name``.
36+
#
37+
# > **Note:** The final cell in the notebook cleans up the temporary folder. If you want to
38+
# > retrieve the AEDT project and data, do so before executing the final cell in the notebook.
39+
40+
temp_folder = tempfile.TemporaryDirectory(suffix=".ansys")
41+
42+
# ## Launch Maxwell 3d
43+
#
44+
# Create an instance of
45+
# the ``Maxwell3d`` class. The Ansys Electronics Desktop will be launched
46+
# with an active Maxwell3D design. The ``m3d`` object is subsequently
47+
# used to create and simulate the model.
48+
49+
m3d = ansys.aedt.core.Maxwell3d(
50+
project="magnet_collector",
51+
solution_type="Magnetostatic",
52+
version=AEDT_VERSION,
53+
non_graphical=NG_MODE,
54+
new_desktop=True,
55+
)
56+
57+
# ## Define variables
58+
#
59+
# Later on we want to see how the magnetic behavior of the system changes with the position of the magnet.
60+
61+
m3d["magnet_radius"] = "2mm"
62+
m3d["magnet_height"] = "15mm"
63+
m3d["magnet_z_pos"] = "0mm"
64+
65+
# ## Add materials
66+
#
67+
# Create custom material ``"Aimant"``.
68+
69+
mat = m3d.materials.add_material("Aimant")
70+
mat.permeability = "1.1"
71+
mat.set_magnetic_coercivity(value=2005600, x=1, y=1, z=0)
72+
mat.update()
73+
74+
# ## Create non-linear magnetic material with single valued BH curve
75+
#
76+
# Create list with BH curve data
77+
78+
bh_curve = [
79+
[0.0, 0.0],
80+
[0.032, 0.5],
81+
[0.049, 0.8],
82+
[0.065, 1],
83+
[0.081, 1.13],
84+
[0.17, 1.52],
85+
[0.32, 1.59],
86+
[0.65, 1.62],
87+
[0.81, 1.65],
88+
[1.61, 1.7],
89+
[3.19, 1.75],
90+
[4.78, 1.79],
91+
[6.34, 1.83],
92+
[7.96, 1.86],
93+
[15.89, 1.99],
94+
[31.77, 2.1],
95+
[63.53, 2.2],
96+
[158.77, 2.41],
97+
[317.48, 2.65],
98+
[635, 3.1],
99+
]
100+
101+
# ## Create custom material "Fer" and assign the BH curve to the permeability value
102+
103+
mat = m3d.materials.add_material("Fer")
104+
mat.permeability.value = bh_curve
105+
mat.set_magnetic_coercivity(value=0, x=1, y=0, z=0)
106+
mat.update()
107+
108+
# ## Create the collector
109+
#
110+
# Create a simple geometry to model the collector and assign a material to it.
111+
112+
# +
113+
collector = m3d.modeler.create_cylinder(
114+
orientation=ansys.aedt.core.constants.AXIS.Z,
115+
origin=[12, 13, 25],
116+
height="3mm",
117+
radius="9.5mm",
118+
axisdir="Z",
119+
name="collector",
120+
)
121+
cylinder2 = m3d.modeler.create_cylinder(
122+
orientation=ansys.aedt.core.constants.AXIS.Z,
123+
origin=[12, 13, 25],
124+
height="3mm",
125+
radius="8mm",
126+
axisdir="Z",
127+
name="cyl2",
128+
)
129+
130+
m3d.modeler.subtract(
131+
blank_list=[collector], tool_list=[cylinder2], keep_originals=False
132+
)
133+
134+
cylinder3 = m3d.modeler.create_cylinder(
135+
orientation=ansys.aedt.core.constants.AXIS.Z,
136+
origin=[12, 13, 28],
137+
height="3mm",
138+
radius="8.7mm",
139+
axisdir="Z",
140+
name="cyl3",
141+
)
142+
cylinder4 = m3d.modeler.create_cylinder(
143+
orientation=ansys.aedt.core.constants.AXIS.Z,
144+
origin=[12, 13, 28],
145+
height="3mm",
146+
radius="2mm",
147+
axisdir="Z",
148+
name="cyl4",
149+
)
150+
151+
m3d.modeler.subtract(
152+
blank_list=[cylinder3], tool_list=[cylinder4], keep_originals=False
153+
)
154+
m3d.modeler.unite(assignment=[collector, cylinder3], keep_originals=False)
155+
156+
collector.material_name = "Fer"
157+
# -
158+
159+
# ## Create magnet
160+
#
161+
# Create a cylinder and assign a material to it.
162+
163+
magnet = m3d.modeler.create_cylinder(
164+
orientation=Axis.Z,
165+
origin=[0, 0, "magnet_z_pos"],
166+
radius="magnet_radius",
167+
height="magnet_height",
168+
num_sides=0,
169+
name="magnet",
170+
material="Aimant",
171+
)
172+
173+
# ## Create a polyline
174+
#
175+
# Create a polyline to plot the field onto.
176+
# The polyline is placed in the center of the collector so to capture the magnetic flux density.
177+
178+
line = m3d.modeler.create_polyline(points=[[12, 13, 0], [12, 13, "32mm"]], name="line")
179+
180+
# ## Create a vacuum region to enclose all objects
181+
182+
region = m3d.modeler.create_region(
183+
pad_value=50, pad_type="Percentage Offset", name="Region"
184+
)
185+
186+
# ## Create the collector cross-section on the XZ plane
187+
188+
collector_relative_cs = m3d.modeler.create_coordinate_system(
189+
origin=[12, 13, 28], name="collector_cs"
190+
)
191+
section = m3d.modeler.create_rectangle(
192+
orientation="XZ",
193+
position=[-25, 0, -35],
194+
dimension_list=["50mm", "50mm"],
195+
name="section",
196+
)
197+
m3d.modeler.set_working_coordinate_system("Global")
198+
199+
# ## Create a dummy geometry for mesh operations
200+
#
201+
# Create a cylinder that encloses the polyline to force the mesh to be finer on the polyline.
202+
203+
dummy_cylinder = m3d.modeler.create_cylinder(
204+
orientation=Axis.Z,
205+
origin=[12, 13, 0],
206+
radius="1mm",
207+
height="32mm",
208+
num_sides=6,
209+
name="dummy_cylinder",
210+
)
211+
212+
# ## Create a custom named expression
213+
#
214+
# Create a custom named expression to calculate relative permeability of the ferromagnetic material.
215+
# This expression is used to see how the relative permeability of the collector changes with magnet position.
216+
217+
mu_r = {
218+
"name": "mu_r",
219+
"description": "Relative permeability of the ferromagnetic material",
220+
"design_type": ["Maxwell 3D"],
221+
"fields_type": ["Fields"],
222+
"primary_sweep": "Time",
223+
"assignment": "",
224+
"assignment_type": [""],
225+
"operations": [
226+
"NameOfExpression('Mag_B')",
227+
"NameOfExpression('Mag_H')",
228+
"Scalar_Constant(1.25664e-06)",
229+
"Operation('*')",
230+
"Operation('/')",
231+
],
232+
"report": ["Field_3D"],
233+
}
234+
m3d.post.fields_calculator.add_expression(mu_r, None)
235+
236+
# ## Set mesh operations
237+
#
238+
# Assign mesh operations to the dummy cylinder and the collector.
239+
240+
poly_mesh = m3d.mesh.assign_length_mesh(
241+
assignment=[dummy_cylinder], maximum_length="1mm", name="polyline"
242+
)
243+
collector_mesh = m3d.mesh.assign_length_mesh(
244+
assignment=[collector],
245+
inside_selection=False,
246+
maximum_length="3.8mm",
247+
name="collector",
248+
)
249+
250+
# ## Create simulation setup
251+
252+
setup = m3d.create_setup()
253+
setup.props["MaximumPasses"] = 10
254+
setup.props["PercentRefinement"] = 30
255+
setup.props["PercentError"] = 2
256+
setup.props["MinimumPasses"] = 2
257+
setup.props["NonlinearResidual"] = 1e-3
258+
259+
# ## Add parametric sweep
260+
#
261+
# Create a linear count sweep where the parameter to sweep is ``"magnet_z_pos"``.
262+
# The magnet position is changed at each step to see how the magnetic behavior of the system changes.
263+
# Enable the saving fields option.
264+
265+
# +
266+
param_sweep = m3d.parametrics.add(
267+
variable="magnet_z_pos",
268+
start_point=m3d["magnet_z_pos"],
269+
end_point="25mm",
270+
step=5,
271+
variation_type="LinearCount",
272+
)
273+
274+
param_sweep.props["ProdOptiSetupDataV2"]["SaveFields"] = True
275+
# -
276+
277+
# ## Analyze parametric sweep
278+
279+
param_sweep.analyze(cores=NUM_CORES)
280+
281+
# ## Create reports
282+
#
283+
# Create rectangular and data plots on the polyline for different magnet positions.
284+
285+
# +
286+
data_table = m3d.post.create_report(
287+
expressions="Mag_B",
288+
report_category="Fields",
289+
plot_type="Data Table",
290+
plot_name="Mag_B",
291+
variations={"magnet_z_pos": "All"},
292+
context=line.name,
293+
polyline_points=101,
294+
)
295+
296+
rectangular_plot = m3d.post.create_report(
297+
expressions="Mag_B",
298+
report_category="Fields",
299+
plot_type="Rectangular Plot",
300+
plot_name="Mag_B",
301+
variations={"magnet_z_pos": "All"},
302+
context=line.name,
303+
polyline_points=101,
304+
)
305+
# -
306+
307+
# ## Create field plots
308+
#
309+
# Create field plots over the collector cross-section and on
310+
# the collector surface to see how the magnetic flux density (B),
311+
# the vector B field, the magnetic field strength (H) and the permeability
312+
# of the ferromagnetic material (μ) change.
313+
314+
mag_b = m3d.post.create_fieldplot_surface(
315+
assignment=[section.name], quantity="Mag_B", plot_name="Mag_B", field_type="Fields"
316+
)
317+
vector_b = m3d.post.create_fieldplot_volume(
318+
assignment=[collector.name],
319+
quantity="B_Vector",
320+
plot_name="B_Vector",
321+
field_type="Fields",
322+
)
323+
mag_h = m3d.post.create_fieldplot_surface(
324+
assignment=[section.name], quantity="Mag_H", plot_name="Mag_H", field_type="Fields"
325+
)
326+
mu_r = m3d.post.create_fieldplot_surface(
327+
assignment=[collector.name], quantity="mu_r", plot_name="mu_r", field_type="Fields"
328+
)
329+
330+
# ## Export field
331+
#
332+
# Export magnetic flux density B on the collector cross-section in a .fld file.
333+
334+
fld_filename = os.path.join(temp_folder.name, "Mag_B.fld")
335+
m3d.post.export_field_file(
336+
quantity="Mag_B",
337+
output_file=fld_filename,
338+
assignment=section.name,
339+
objects_type="Surf",
340+
)
341+
342+
# ## Overlay fields using PyVista
343+
#
344+
# Plot electric field using PyVista and save to an image file.
345+
# Plot the relative permeability on the collector surface at a given magnet position.
346+
# Change argument ``"show"`` to ``True`` see the permeability plot.
347+
348+
m3d["magnet_z_pos"] = "18.75mm"
349+
350+
py_vista_plot = m3d.post.plot_field(
351+
quantity="mu_r", assignment=collector.name, plot_cad_objs=True, show=False
352+
)
353+
py_vista_plot.isometric_view = True
354+
py_vista_plot.plot(
355+
export_image_path=os.path.join(temp_folder.name, "mu_r.jpg"), show=True
356+
)
357+
358+
# ## BH curve of the ferromagnetic material
359+
#
360+
# From the plot exported in the previous section, we can see the trend of the relative permeability
361+
# when the magnet gets close to the collector.
362+
# Looking at the scale of the relative permeability, we can see that the collector is far from saturation.
363+
# With a permeability peak value around 1.3E+7, the collector is still in the linear region of the BH curve.
364+
# ![BH curve and relative permeability of the ferromagnetic material](_static/BH.png)
365+
# ![Zoom in on the relative permeability of the ferromagnetic material](_static/BH_zoom_in.png)
366+
367+
# ## Release AEDT
368+
369+
m3d.save_project()
370+
m3d.release_desktop()
371+
# Wait 3 seconds to allow AEDT to shut down before cleaning the temporary directory.
372+
time.sleep(3)
373+
374+
# ## Clean up
375+
#
376+
# All project files are saved in the folder ``temp_folder.name``.
377+
# If you've run this example as a Jupyter notebook, you
378+
# can retrieve those project files. The following cell
379+
# removes all temporary files, including the project folder.
380+
381+
temp_folder.cleanup()

0 commit comments

Comments
 (0)