Please forgive my inexperience in this field. I’m trying to setup a workflow to simulate magnet arrays (brushless motor rotors) to predict how (small) geometric changes will affect the field shape and strength. I’d like to make use of periodic (rotational) symmetry to decrease setup time / effort.
I have a simple test setup based on one of the site examples. This setup generates fields lines which look good, but as soon as I cut the model in a pie-shape and tag the cut faces as symmetry face pairs the simulation results are inaccurate:
The bit of code used to cut-up the model and ‘tag’ the appropriate faces:
def slice_pie(shape, axis = occ.Z, count = 6, start = 30.0):
bb = shape.bounding_box
pmin = bb[0]
pmax = bb[1]
direction = occ.Pnt(axis.z, axis.x, axis.y)
center = occ.Pnt(\
(pmin.x + pmax.x) / 2, \
(pmin.y + pmax.y) / 2, \
(pmin.z + pmax.z) / 2 \
)
size = max(pmax.x - pmin.x, pmax.y - pmin.y, pmax.z - pmin.z)
disp = occ.Vec( \
direction.x * size - center.x, \
direction.y * size - center.y, \
direction.z * size - center.z \
)
rot_axis = occ.Axis((0,0,0), axis)
bb1 = bb2 = occ.Box(\
( -size, -size, -size ),
( size, size, size )
).Move(disp).Rotate(rot_axis, 180 + start)
bb2 = bb2.Rotate(rot_axis, 180 - 360 / count)
sliced = shape - bb1
i = 0
pairs = []
for face in sliced.faces:
if face.name is None:
pairs.append(face)
face.name = f"A_{i}"
i += 1
sliced = sliced - bb2
i = 0
for face in sliced.faces:
if face.name is None:
pairs[i] = (pairs[i], face)
face.name = f"B_{i}"
i += 1
return (sliced, pairs)
shape, pairs = slice_pie(shape, magnet_axis, magnet_sections)
for pair in pairs:
pair[1].Identify(pair[0], "periodic", occ.IdentificationType.PERIODIC) # tried this in reverse order too
geo = occ.OCCGeometry(shape)
The code for calculating the magnetic field:
magnet_mask = ng.CoefficientFunction([0 if mat == 'magnet' else 1 for mat in mesh.GetMaterials()])
fes = ng.HCurl(mesh, order=3, dirichlet="outer", noGrads=True)
print ("ndof =", fes.ndof)
u = fes.TrialFunction()
v = fes.TestFunction()
mu0 = 4 * pi * 1e-7
mur = mesh.MaterialCF({"magnet" : 1000}, default=1) # What unit is used here? Gauss?
nu = 1 / (mu0 * mur)
a = ng.BilinearForm(fes)
a += nu * ng.curl(u) * ng.curl(v) * ng.dx + 1e-8 * nu * u * v * ng.dx
c = ng.Preconditioner(a, "bddc")
f = ng.LinearForm(fes)
mag = mesh.MaterialCF({"magnet" : (magnet_axis.x, magnet_axis.y, magnet_axis.z)}, default=(0,0,0)) # What exactly is (0,0,1) here? The normal for the magnetization direction?
f += mag * ng.curl(v) * ng.dx("magnet")
with ng.TaskManager():
a.Assemble()
f.Assemble()
gfu = ng.GridFunction(fes)
with ng.TaskManager():
solution = ng.solvers.CG(sol=gfu.vec, rhs=f.vec, mat=a.mat, pre=c.mat, maxsteps=256, printrates=True)
ng.Draw (ng.curl(gfu) * magnet_mask, mesh, "B-field")
I suppose I’m missing something here to account for the periodic mesh. How can I make this work as intended?