3. Variable Coefficients#
\(\DeclareMathOperator{\opdiv}{div}\) A setup with varying heat-conductivity is modeled by the equation
where \(\lambda : \Omega \rightarrow {\mathbb R}^+\) is the heat-conductivity, relating the heat-flux
to the temperature gradient \(\nabla u\).
In the case of discontinuous \(\lambda\), the equation is understood in distributional sense. This includes the interface conditions: The temperature on the left and right side are equal, and the heat flux leaving the left side enters the right side:
The variational form is: find \(u \in H^1(\Omega)\)
There is no issue with discontinuous coefficients. Both interface conditions are included:
continuity of temperature \(u\) by the continuity of the trial space
continuity of the heat flux in weak sense, similar as Neumann boundary conditions
from ngsolve import *
from ngsolve.webgui import Draw
Create a 2D geometric model:
from netgen.occ import *
box = Rectangle(1,1).Face()
circ1 = Circle((0.3,0.7), 0.1).Face()
circ2 = Circle((0.7,0.7), 0.1).Face()
bar = MoveTo(0.2,0.2).Rectangle(0.6,0.1).Face()
air = box-circ1-circ2-bar
circ1.faces.name = "left"
circ2.faces.name = "right"
air.faces.name = "air"
bar.faces.name = "bar"
air.edges.Min(Y).name ='b'
air.edges.Max(X).name ='r'
shape = Glue([air,circ1, circ2,bar])
Draw (shape);
geo = OCCGeometry(shape, dim=2)
mesh = Mesh(geo.GenerateMesh(maxh=0.05)).Curve(3)
Draw (mesh);
print (mesh.GetMaterials())
('air', 'left', 'right', 'bar')
print (mesh.GetBoundaries())
('b', 'default', 'r', 'default', 'default', 'default', 'default', 'default', 'default', 'default')
fes = H1(mesh, order=3, dirichlet="b|r")
u,v = fes.TnT()
make a coefficient function taking one constant, or even another coefficient function per material:
lam = mesh.MaterialCF({ "bar" : 5, "left" : 2.5, "right" : 2.5 }, default=1 )
Draw (lam, mesh, "lambda");
use conductivity in bilinear-form:
a = BilinearForm(lam*grad(u)*grad(v)*dx).Assemble()
f = LinearForm(50*v*dx("left")).Assemble()
reg = mesh.Materials("left|bar")
print (type(reg))
print ("volume or boundary=", reg.VB())
print ("bitmask =", reg.Mask())
<class 'ngsolve.comp.Region'>
volume or boundary= VorB.VOL
bitmask = 0: 0101
gfu = GridFunction(fes)
gfu.vec.data = a.mat.Inverse(fes.FreeDofs()) * f.vec
Draw (gfu, mesh);
The gradient is small in regions with high conductivity:
Draw (grad(gfu), mesh, "gradient");
The heat-flux is large in highly conductive materials:
Draw (-lam*grad(gfu), mesh, vectors={"grid_size":30});
Exercise:
experiment with different (positive!) values for the conductivity coefficients