Yes there is a feature for that:
Code:
from netgen.csg import *
from ngsolve import *
ngsglobals.msg_level = 0
geo = CSGeometry()
block = OrthoBrick(Pnt(-1,-1,-1), Pnt(1,1,1))
sphere = Sphere(Pnt(0,0,0),0.5)
geo.Add((block-sphere).mat("air"))
geo.Add(sphere.mat("metal").bc("metalbc"))
mesh = Mesh(geo.GenerateMesh())
Draw(mesh)
dom_nrs_metal = [1 if mat == "metal" else 0 for mat in mesh.GetMaterials()]
order = 3
full_fes = HCurl(mesh, order=order)
nograds_fes = HCurl(mesh, order=order, nograds=True)
domainwisegrad_fes = HCurl(mesh, order=order, gradientdomains=dom_nrs_metal)
ndofs = {"air" : {}, "metal" : {}}
for el in domainwisegrad_fes.Elements(VOL):
if len(el.dofs) not in ndofs[el.mat]:
ndofs[el.mat][len(el.dofs)] = 1
else:
ndofs[el.mat][len(el.dofs)] += 1
print(ndofs)
print("ndof full = ", full_fes.ndof)
print("reduce all = ", nograds_fes.ndof)
print("gradient domains =", domainwisegrad_fes.ndof)
Results in
Code:
{'air': {41: 188, 32: 156, 29: 100, 35: 6, 50: 2}, 'metal': {60: 142}}
ndof full = 15164
reduce all = 8639
gradient domains = 11124
So you can see, that the gradients are only in the metal and on the boundary to the metal (thats why some of the air elements have some gradients as well). You can ignore the warning about the undocumented flag.
Best
Christopher