# BH curve

• lahoussaine
• New Member
• 2 months 1 week ago - 2 months 1 week ago #4629
Replied by lahoussaine on topic BH curve
Here is the code :

u, v = fes.TnT()
mu_r = {"air": 1, "magnet": 1.1, "fer1": 1000, "fer2": 1000}

# Definition des permeabilites
def nuf(u):
return IfPos(B-2.28,(1/(-0.0039954722*B**3+0.00595660*B**2+0.00646251*B + 0.001925625)), ((1902.211579*B+-4266.42343)/0.016694669))

nu_test = [nuf( if mat=="fer1" else 1.0/(mu0*mu_r[mat]) for mat in mesh.GetMaterials()]

nu = CoefficientFunction(nu_test)

a = BilinearForm(fes, symmetric=False)
...
Last edit: 2 months 1 week ago by lahoussaine.

• mrambausek
• Offline
• New Member
• 2 months 1 week ago #4630
Replied by mrambausek on topic BH curve
Is this an oversight?
Did you call a.Assemble or a.AssembleLinearization further doen behind the dots?

• lahoussaine
• New Member
• 2 months 1 week ago - 2 months 1 week ago #4631
Replied by lahoussaine on topic BH curve
Here is the reste of code

# f= LinearForm(fes)

j = CoefficientFunction(10*1e3)

a+=- (j*v) * dx("magnet")

def SimpleNewtonSolve(gfu, a, tol=1e-8, maxits=30):  res = gfu.vec.CreateVector()
du = gfu.vec.CreateVector()
fes = gfu.space
for it in range(maxits):
print("Iteration { } ".format(it), end="")
a.Apply(gfu.vec, res)
a.AssembleLinearization(gfu.vec)
du.data = a.mat.Inverse(fes.FreeDofs()) * res
gfu.vec.data -= du

# stopping criteria
stopcritval = sqrt(abs(InnerProduct(du, res)))
print("<A u", it, ", A u", it, ">_{-1}^0.5 = ", stopcritval)
if stopcritval < tol:
break
# Solve the linear system
gfa = GridFunction(fes)
SimpleNewtonSolve(gfa, a)
Last edit: 2 months 1 week ago by lahoussaine.

• mrambausek
• Offline
• New Member
• 2 months 1 week ago #4632
Replied by mrambausek on topic BH curve
Okay, there a couple of issues:

First of all, using grad(u) and grad(v) suggests that you are using the (auxiliary) scalar magnetic potential (H=-grad(u)). However, everywhere else you work like you'd use the vector potential (B=curl(A)), i.e. using nu=1/mu and j*v as loading term. So, to me, the whole formulation seems to be inconsistent. Could you recheck, please?

Second, when using a.AssembleLinearization(...), ngsolve will linearize the expressions it finds in the bilinear form in some way. However, the nu*grad(u)*grad(v) is a linearized form already.
When trying to linearize this term, you get NaN's because of a division by zero (or a very small number) resulting from the norm (at B=0).
When you work with CFs representing already "linearized" forms,
they must not depend on trial functions but grid functions only.
So nu must not depend on "u" but "gfu" in this case.

Please note that I did not try to fix the example, so there may be some things that I have overlooked (also in my own explanations). I hope they are still useful though.

Best,
Matthias
The following user(s) said Thank You: lahoussaine

• lahoussaine
• New Member
• 2 months 1 week ago - 2 months 1 week ago #4633
Replied by lahoussaine on topic BH curve
Thank you for your time, I will just try to clarify my problem one last time.
You will find below the code of the Linear solution.

Concerning the linear solution, the weak formulation has been simplified, so the equation might be not clear, sorry for that. However, this simulation has been validated both with a commercial solver and another FEA api.

My problem is not about the weak formulation but the way to carry on a NonLinear simulation, the NonLinearity coming from the nu expression which depend on B and thus on u.
The Nonlinear simulation is thus the same as the linear one but with nu( The question is : How would you perform a Non linear algorithm iterating on nu ?

You'll find below  the linear code that worked for me ...

stator = Circle(center=(0, 0), radius=10, bc="bc_rect_ext" )
magnet_f = magnet1-rotor
airgap = circle_airgap-(magnet1)
stator_f = stator-circle_airgap
# change domain name and maxh

magnet_f.Mat("magnet").Maxh(0.5)
rotor.Mat("fer1").Maxh(0.5)
stator_f.Mat("fer2").Maxh(0.5)
airgap.Mat("air").Maxh(0.5)
###
mesh = Mesh(geo.GenerateMesh(maxh=0.1))
Draw(mesh)
# FEM
fes = H1(mesh, order=3, dirichlet='bc_rect_ext')
u, v = fes.TnT()
mu_r = {"air": 1, "magnet": 1.1, "fer1": 1000, "fer2": 1000}
# Definition des permeabilites
mu0 = 4*pi*1e-7
nu_coef = [1/(mu0*mu_r[mat]) for mat in mesh.GetMaterials()]
nu = CoefficientFunction(nu_coef)
a = BilinearForm(fes)
M=80000
f = LinearForm(fes)
j = CoefficientFunction(10*1e3)
Mx = CoefficientFunction(M*cos(atan2(y,x))*1e0)
My = CoefficientFunction(0)

a.Assemble()
f.Assemble()

# Solve the linear system
gfa = GridFunction(fes)
gfa.vec.data = a.mat.Inverse(fes.FreeDofs()) * f.vec

Last edit: 2 months 1 week ago by lahoussaine.

• mrambausek
• Offline
• New Member
• 2 months 5 days ago #4636
Replied by mrambausek on topic BH curve
In my previous post, I might have had a confusion of the meaning of nu. Is the your nu "H( " or "dH/dB" evaluated for some B? I am used to work with "incremental" coefficients, ie "dH/dB". So *if you do not so*, then my second "issue" in my previous response is not valid.

Assuming that your nu if such that H = nu B, then a.AssembleLinearization(gfa.vec) will linearized it for you.
However, linearizing Norm( when B is zero, results in a division by zero. You can work around that as follows (see comments in the code below, in particular around "def nuf"):

fes = H1(mesh, order=3, dirichlet='bc_rect_ext')
u, v = fes.TnT()
mu_r = {"air": 1, "magnet": 1.1, "fer1": 1000, "fer2": 1000}
# Definition des permeabilites
mu0 = 4*pi*1e-7

def nuf(u):
# You need to avoid division by zero in the linearization! Either by perturbing the norm of by providing
#  the linearized norm for the norm being close to zero.

# Perturbation

# manual linearization
return IfPos(B-2.28,
(1/(-0.0039954722*B**3+0.00595660*B**2+0.00646251*B + 0.001925625)),
IfPos(B - 1e-8,
(1902.211579*B+-4266.42343)/0.016694669,
1902.211579/0.016694669) # linearized nu (dh/dB) for small B
)

nu_coef = [nuf(u) if mat=="fer1" else 1.0/(mu0*mu_r[mat]) for mat in mesh.GetMaterials()]

nu = CoefficientFunction(nu_coef)
a = BilinearForm(fes)
M=80000
f = LinearForm(fes)
j = CoefficientFunction(10*1e3)
Mx = CoefficientFunction(M*cos(atan2(y,x))*1e0)
My = CoefficientFunction(0)

### "SIMULATING" the first Newton step only
# define gfa upfront
gfa = GridFunction(fes)

# check that AssembleLinearization() does not give NaNs
a.AssembleLinearization(gfa.vec)
f.Assemble()

# Solve the linear system
gfa.vec.data = a.mat.Inverse(fes.FreeDofs()) * f.vec

Hope that helps!
The following user(s) said Thank You: lahoussaine