Hello,
I am a newbie trying to use Fenics (dolfinx) in order to study the sensitivity of Maxwell stresses for a magneto static problem.
I solve the planar case, as it is performed in the tutorial .
Then, I define my cost function the following way
normals = FacetNormal(mesh)
dArm = Measure("dS", domain=mesh, subdomain_data=facet_tags, subdomain_id=42)
maxwell = Function(W)
maxwell.interpolate( Expression(as_vector((B[0]*B[0]-B[1]*B[1], 2.*B[0]*B[1])), W.element.interpolation_points()) )
cost = 1./(2.*mu0)*inner(maxwell("-"), normals("-"))*dArm
I aim to use the adjoint method in order to compute the sensitivity of the Maxwell stresses, which in my case is a contour integral over a defined subdomain (tag, 42) of the following expression
\oint_{Gamma} \left[ (B_x^2 - B_y^2) \cdot n^x + 2 B_x B_y \cdot n^y\right] d\Gamma
However, when I compute the derivative of my cost w.r.t. the non trivial component of the vector potential A^z , dolfinx yields a zero vector
dCdAz = derivative(cost, A_z) # assembling it yield zeros
I guess I am doing something wrong.
Maybe is it related to the way I define my cost function? (which is constant per element, hence the (-)
).
I would appreciate any help coming from an advanced Fenics user
Stein
December 17, 2024, 6:56am
2
There appears to be no A_z
in cost
, hence FEniCS righfully concludes dCdAz=0
. I assume you used A_z
in the definition of B
? Yet this ‘connection’ is lost with the interpolation
. Interpolation really just determines the (numerical) values of the degrees of freedom of the associated function, without retaining knowledge on how those values are retained/relate to other functions.
I assume you want something like:
normals = FacetNormal(mesh)
dArm = Measure("dS", domain=mesh, subdomain_data=facet_tags, subdomain_id=42)
maxwell = as_vector((B[0]*B[0]-B[1]*B[1], 2.*B[0]*B[1] )
cost = 1./(2.*mu0)*inner(maxwell("-"), normals("-"))*dArm
dCdAz = derivative(cost, A_z) # assembling it yield zeros
Hello Stein. Thanks for your reply.
Indeed, B
is a Function(functionspace(mesh, ("DG", 0, (mesh.geometry.dim, ))))
that interpolates the A_z
obtained by solving the weak form
\int_{\Omega} \frac{1}{\mu} \nabla A^z \cdot \nabla v ~ d\Omega = \int_\Omega J ~v ~ d\Omega
A_z
is a a Function(functionspace(mesh, ("Lagrange", 1)))
.
The interpolation is performed as follows
B_expr = Expression(as_vector((A_z.dx(1), -A_z.dx(0))), W.element.interpolation_points())
B.interpolate(B_expr) # W = functionspace(mesh, ("DG", 0, (mesh.geometry.dim, )))
(since B = \nabla \times A )
Do I have to express my cost function as an explicit function of A_z?
dokken
December 17, 2024, 8:44am
4
Yes, you do have to use the explicit variable.
Stein
December 17, 2024, 8:44am
5
Yes, for FEniCS to be able to carry out the derivative of Cost w.r.t. Az, it must know the explicit dependency. That explicit dependency is lost when you interpolate onto a space.
Augmenting my earlier snippet, I’d expect something like:
normals = FacetNormal(mesh)
dArm = Measure("dS", domain=mesh, subdomain_data=facet_tags, subdomain_id=42)
B = as_vector((A_z.dx(1), -A_z.dx(0))
maxwell = as_vector((B[0]*B[0]-B[1]*B[1], 2.*B[0]*B[1] )
cost = 1./(2.*mu0)*inner(maxwell("-"), normals("-"))*dArm
dCdAz = derivative(cost, A_z) # assembling it yield zeros
Thanks to the both of you.
Indeed, Stein’s snippet works.