Integrate a field quantity along a line in 3D

Is there a method for integrating a field along a line? For example, is it possible to compute the integral for Ampere’s Law in 3D?
I = \oint \mathbf{H}\cdot d\mathbf{l}

The path can lie on a boundary or be just inside the volumetric region, the idea being the calculation of current in a conductor immersed in an electromagnetic field.
Cheers!

1 Like

Hello!

You can integrate along arbitrary lines using ufl.Measure.
The main idea is to mark your line in Gmsh using Physical Line and then use the line ID in a custom measure.

For example, in 2D I want to integrate constant function u(x,y)=1 along the red line.

For this I create a custom measure dS where I specify MeshTags for it to use

dS = ufl.Measure('dS', domain=mesh, subdomain_data=boundaries)

After that I could select appropriate line by supplying its ID as a measure argument. In this example red line’s ID is 2.

print(dolfinx.fem.assemble_scalar(u * dS(2)))

This particular line computes \int_L\operatorname{u}dS. You could use this measure in other forms as well.

Gmsh script for this example (Conversion between .msh and .xdmf is described here.):

Geometry.OCCTargetUnit = "M";

r1 = 0.5;
r2 = 1;
dx1 = 0;
dy1 = 0;
dx2 = 0;
dy2 = 0;
mesh1 = 0.04;
mesh2 = 0.04;

p0 = newp; Point(p0) = {dx1,dy1,0,mesh1};
p1 = newp; Point(p1) = {r1+dx1,dy1,0,mesh1};
p2 = newp; Point(p2) = {dx1,r1+dy1,0,mesh1};
p3 = newp; Point(p3) = {-r1+dx1,dy1,0,mesh1};
p4 = newp; Point(p4) = {dx1,-r1+dy1,0,mesh1};
l1 = newl; Circle(l1) = {p1,p0,p2};
l2 = newl; Circle(l2) = {p2,p0,p3};
l3 = newl; Circle(l3) = {p3,p0,p4};
l4 = newl; Circle(l4) = {p4,p0,p1};
ll1 = newll; Line loop(ll1) = {l1,l2,l3,l4};
s1 = news; Surface(s1) = {ll1};

p00 = newp; Point(p00) = {dx2,dy2,0,mesh2};
p10 = newp; Point(p10) = {r2+dx2,dy2,0,mesh2};
p20 = newp; Point(p20) = {dx2,r2+dy2,0,mesh2};
p30 = newp; Point(p30) = {-r2+dx2,dy2,0,mesh2};
p40 = newp; Point(p40) = {dx2,-r2+dy2,0,mesh2};
l10 = newl; Circle(l10) = {p10,p00,p20};
l20 = newl; Circle(l20) = {p20,p00,p30};
l30 = newl; Circle(l30) = {p30,p00,p40};
l40 = newl; Circle(l40) = {p40,p00,p10};
ll10 = newll; Line loop(ll10) = {l10,l20,l30,l40};
s10 = news; Surface(s10) = {ll10, ll1};

// Assign IDs to the mesh regions
Physical Surface(1) = {s10,s1};
Physical Line(2) = {l1,l2};

DolfinX code:

import dolfinx
import dolfinx.io
import ufl
from mpi4py import MPI


# Read mesh and meshtags
with dolfinx.io.XDMFFile(MPI.COMM_WORLD, "mesh.xdmf", "r") as xdmf:
    mesh = xdmf.read_mesh(name="Grid")
mesh.topology.create_connectivity(mesh.topology.dim-1, mesh.topology.dim)
with dolfinx.io.XDMFFile(MPI.COMM_WORLD, "mesh_boundary.xdmf", "r") as xdmf:
    boundaries = xdmf.read_meshtags(mesh, name="Grid")

V = dolfinx.FunctionSpace(mesh, ("Lagrange", 1))

# Set constant function
u = dolfinx.Function(V)
with u.vector.localForm() as loc:
    loc.set(1)

# Create measure
dS = ufl.Measure('dS', domain=mesh, subdomain_data=boundaries)

# Integrate
print(dolfinx.fem.assemble_scalar(u * dS(2)))