Effective thermal conductivity#
Usually, after the design of the circuitry, the empty space on chips gets filled with equally spaced small rectangles in each layer. Optically, these structures are supposed to be far enough away that their influence on the structures can be neglected. But for thermal considerations, those fill structures can have an impact on the temperature distribution on the chip and thus e.g. on the crosstalk between thermal phase shifters. As it’s computationally challenging to include all the small cuboids in the model (which is especially for the meshing a major challenge), a preferable approach is to consider the filled area as a homogenous area of higher thermal conductivity. For this, we calculate the effective thermal conductivity of the filled area by examining a single unit cell.
To have an intuitively understandable problem, we consider half of the unit cell to be filled with a highly thermally conductive material (metal/silicon) surrounded by a material with low thermal conductance (e.g. silicon dioxide) Let’s start with the mesh!
unitcell_width = 0.8
unitcell_length = 0.8
unitcell_thickness = 0.387
fill_width = 0.4
fill_length = 0.4
fill_thickness = 0.22
0.22
Show code cell source
using PyCall
np = pyimport("numpy")
shapely = pyimport("shapely")
shapely.affinity = pyimport("shapely.affinity")
OrderedDict = pyimport("collections").OrderedDict
meshwell = pyimport("meshwell")
Prism = pyimport("meshwell.prism").Prism
Model = pyimport("meshwell.model").Model
model = Model()
fill_polygon = shapely.box(
xmin = unitcell_length / 2 - fill_length / 2,
ymin = unitcell_width / 2 - fill_width / 2,
xmax = unitcell_length / 2 + fill_length / 2,
ymax = unitcell_width / 2 + fill_width / 2,
)
fill = Prism(
polygons = fill_polygon,
buffers = Dict(
unitcell_thickness / 2 - fill_thickness / 2 => 0.0,
unitcell_thickness / 2 + fill_thickness / 2 => 0.0,
),
model = model,
physical_name = "fill",
mesh_order = 1,
resolution = Dict("resolution" => 0.05, "SizeMax" => 0.2, "DistMax" => 1),
)
unitcell_polygon =
shapely.box(xmin = 0, ymin = 0, xmax = unitcell_length, ymax = unitcell_width)
unitcell_buffer = Dict(0 => 0.0, unitcell_thickness => 0.0)
unitcell = Prism(
polygons = unitcell_polygon,
buffers = unitcell_buffer,
model = model,
physical_name = "unitcell",
mesh_order = 2,
)
"""
BOUNDARIES
"""
right_polygon = shapely.box(
xmin = unitcell_length,
ymin = 0,
xmax = unitcell_length + 1,
ymax = unitcell_width,
)
right = Prism(
polygons = right_polygon,
buffers = unitcell_buffer,
model = model,
physical_name = "right",
mesh_bool = false,
mesh_order = 0,
)
left_polygon = shapely.box(xmin = -1, ymin = 0, xmax = 0, ymax = unitcell_width)
left = Prism(
polygons = left_polygon,
buffers = unitcell_buffer,
model = model,
physical_name = "left",
mesh_bool = false,
mesh_order = 0,
)
up_polygon = shapely.box(
xmin = 0,
ymin = unitcell_width,
xmax = unitcell_length,
ymax = unitcell_width + 1,
)
up = Prism(
polygons = up_polygon,
buffers = unitcell_buffer,
model = model,
physical_name = "up",
mesh_bool = false,
mesh_order = 0,
)
down_polygon = shapely.box(xmin = 0, ymin = -1, xmax = unitcell_length, ymax = 0)
down = Prism(
polygons = down_polygon,
buffers = unitcell_buffer,
model = model,
physical_name = "down",
mesh_bool = false,
mesh_order = 0,
)
above_buffer = Dict(unitcell_thickness => 0.0, unitcell_thickness + 1 => 0.0)
above = Prism(
polygons = unitcell_polygon,
buffers = above_buffer,
model = model,
physical_name = "above",
mesh_bool = false,
mesh_order = 0,
)
below_buffer = Dict(-1 => 0.0, 0 => 0.0)
below = Prism(
polygons = unitcell_polygon,
buffers = below_buffer,
model = model,
physical_name = "below",
mesh_bool = false,
mesh_order = 0,
)
"""
ASSEMBLE AND NAME ENTITIES
"""
entities = [unitcell, fill, up, down, left, right, above, below]
mesh = model.mesh(
entities_list = entities,
verbosity = 0,
filename = "mesh.msh",
default_characteristic_length = 0.2,
)
Info : [ 0%] Difference
Info : [ 10%] Difference - Performing intersection of shapes
Info : [ 80%] Difference
Info : [ 90%] Difference - Splitting solids
Info : [ 0%] Fragments
Info : [ 10%] Fragments - Performing intersection of shapes
Info : [ 80%] Fragments
Info : [ 90%] Fragments - Splitting solids
Info : [ 0%] Difference
Info : [ 10%] Difference
Info : [ 20%] Difference
Info : [ 30%] Difference
Info : [ 40%] Difference
Info : [ 50%] Difference
Info : [ 60%] Difference
Info : [ 70%] Difference
Info : [ 80%] Difference - Splitting faces
Info : [ 90%] Difference
Info : [ 0%] Fragments
Info : [ 10%] Fragments
Info : [ 20%] Fragments
Info : [ 30%] Fragments
Info : [ 40%] Fragments
Info : [ 50%] Fragments
Info : [ 60%] Fragments
Info : [ 70%] Fragments
Info : [ 80%] Fragments - Splitting faces
Info : [ 90%] Fragments
Info : [ 0%] Difference
Info : [ 10%] Difference - Performing Vertex-Face intersection
Info : [ 20%] Difference
Info : [ 30%] Difference
Info : [ 40%] Difference
Info : [ 50%] Difference
Info : [ 60%] Difference
Info : [ 70%] Difference - Filling splits of vertices
Info : [ 80%] Difference - Splitting faces
Info : [ 90%] Difference
Info : [ 0%] Fragments
Info : [ 10%] Fragments - Performing Vertex-Face intersection
Info : [ 20%] Fragments
Info : [ 30%] Fragments
Info : [ 40%] Fragments
Info : [ 50%] Fragments
Info : [ 60%] Fragments
Info : [ 70%] Fragments - Filling splits of vertices
Info : [ 80%] Fragments - Splitting faces
Info : [ 90%] Fragments
Info : [ 0%] Difference
Info : [ 10%] Difference
Info : [ 20%] Difference
Info : [ 30%] Difference
Info : [ 40%] Difference
Info : [ 50%] Difference
Info : [ 60%] Difference
Info : [ 70%] Difference - Filling splits of edges
Info : [ 80%] Difference - Splitting faces
Info : [ 90%] Difference
Info : [ 0%] Fragments
Info : [ 10%] Fragments
Info : [ 20%] Fragments
Info : [ 30%] Fragments
Info : [ 40%] Fragments
Info : [ 50%] Fragments
Info : [ 60%] Fragments
Info : [ 70%] Fragments - Filling splits of edges
Info : [ 80%] Fragments - Splitting faces
Info : [ 90%] Fragments
Info : [ 0%] Difference
Info : [ 10%] Difference
Info : [ 20%] Difference
Info : [ 30%] Difference
Info : [ 40%] Difference
Info : [ 50%] Difference
Info : [ 60%] Difference
Info : [ 70%] Difference
Info : [ 80%] Difference - Splitting faces
Info : [ 90%] Difference
Info : [ 0%] Fragments
Info : [ 10%] Fragments
Info : [ 20%] Fragments
Info : [ 30%] Fragments
Info : [ 40%] Fragments
Info : [ 50%] Fragments
Info : [ 60%] Fragments
Info : [ 70%] Fragments
Info : [ 80%] Fragments - Splitting faces
Info : [ 90%] Fragments
Info : [ 0%] Difference
Info : [ 10%] Difference
Info : [ 20%] Difference
Info : [ 30%] Difference
Info : [ 40%] Difference
Info : [ 50%] Difference
Info : [ 60%] Difference
Info : [ 70%] Difference - Building splits of containers
Info : [ 80%] Difference - Splitting faces
Info : [ 90%] Difference
Info : [ 0%] Fragments
Info : [ 10%] Fragments
Info : [ 20%] Fragments
Info : [ 30%] Fragments
Info : [ 40%] Fragments
Info : [ 50%] Fragments
Info : [ 60%] Fragments
Info : [ 70%] Fragments - Building splits of containers
Info : [ 80%] Fragments - Splitting faces
Info : [ 90%] Fragments
Info : [ 0%] Difference
Info : [ 10%] Difference
Info : [ 20%] Difference
Info : [ 30%] Difference
Info : [ 40%] Difference
Info : [ 50%] Difference
Info : [ 60%] Difference
Info : [ 70%] Difference - Filling splits of vertices
Info : [ 80%] Difference - Splitting faces
Info : [ 90%] Difference
Info : [ 0%] Fragments
Info : [ 10%] Fragments
Info : [ 20%] Fragments
Info : [ 30%] Fragments
Info : [ 40%] Fragments
Info : [ 50%] Fragments
Info : [ 60%] Fragments
Info : [ 70%] Fragments - Filling splits of vertices
Info : [ 80%] Fragments - Splitting faces
Info : [ 90%] Fragments
Info : Meshing 1D...
Info : [ 0%] Meshing curve 126 (Line)
Info : [ 0%] Meshing curve 124 (Line)
Info : [ 0%] Meshing curve 125 (Line)
Info : [ 0%] Meshing curve 123 (Line)
Info : [ 10%] Meshing curve 127 (Line)
Info : [ 10%] Meshing curve 128 (Line)
Info : [ 10%] Meshing curve 129 (Line)
Info : [ 10%] Meshing curve 130 (Line)
Info : [ 30%] Meshing curve 131 (Line)
Info : [ 30%] Meshing curve 132 (Line)
Info : [ 30%] Meshing curve 133 (Line)
Info : [ 30%] Meshing curve 134 (Line)
Info : [ 30%] Meshing curve 135 (Line)
Info : [ 50%] Meshing curve 142 (Line)
Info : [ 50%] Meshing curve 145 (Line)
Info : [ 50%] Meshing curve 146 (Line)
Info : [ 60%] Meshing curve 148 (Line)
Info : [ 60%] Meshing curve 151 (Line)
Info : [ 70%] Meshing curve 152 (Line)
Info : [ 70%] Meshing curve 153 (Line)
Info : [ 70%] Meshing curve 159 (Line)
Info : [ 70%] Meshing curve 160 (Line)
Info : [ 80%] Meshing curve 175 (Line)
Info : [ 80%] Meshing curve 176 (Line)
Info : Done meshing 1D (Wall 0.0149352s, CPU 0.047695s)
Info : Meshing 2D...
Info : [ 0%] Meshing surface 75 (Plane, Frontal-Delaunay)
Info : [ 0%] Meshing surface 73 (Plane, Frontal-Delaunay)
Info : [ 0%] Meshing surface 74 (Plane, Frontal-Delaunay)
Info : [ 0%] Meshing surface 76 (Plane, Frontal-Delaunay)
Info : [ 0%] Meshing surface 77 (Plane, Frontal-Delaunay)
Info : [ 0%] Meshing surface 78 (Plane, Frontal-Delaunay)
Info : [ 30%] Meshing surface 82 (Plane, Frontal-Delaunay)
Info : [ 30%] Meshing surface 86 (Plane, Frontal-Delaunay)
Info : [ 50%] Meshing surface 91 (Plane, Frontal-Delaunay)
Info : [ 50%] Meshing surface 99 (Plane, Frontal-Delaunay)
Info : [ 50%] Meshing surface 107 (Plane, Frontal-Delaunay)
Info : [ 70%] Meshing surface 114 (Plane, Frontal-Delaunay)
Info : Done meshing 2D (Wall 0.0158348s, CPU 0.063735s)
Info : Meshing 3D...
Info : 3D Meshing 2 volumes with 1 connected component
Info : Tetrahedrizing 948 nodes...
Info : Done tetrahedrizing 956 nodes (Wall 0.0114474s, CPU 0.034906s)
Info : Reconstructing mesh...
Info : - Creating surface mesh
Info : - Identifying boundary edges
Info : - Recovering boundary
Info : Done reconstructing mesh (Wall 0.0221463s, CPU 0.057591s)
Info : Found volume 7
Info : Found volume 8
Info : It. 0 - 0 nodes created - worst tet radius 2.5504 (nodes removed 0 0)
Info : 3D refinement terminated (1315 nodes total):
Info : - 0 Delaunay cavities modified for star shapeness
Info : - 0 nodes could not be inserted
Info : - 6276 tetrahedra created in 0.0195223 sec. (321477 tets/s)
Info : 0 node relocations
Info : Done meshing 3D (Wall 0.0702698s, CPU 0.105712s)
Info : Optimizing mesh...
Info : Optimizing volume 7
Info : Optimization starts (volume = 0.0352) with worst = 0.0371703 / average = 0.763886:
Info : 0.00 < quality < 0.10 : 5 elements
Info : 0.10 < quality < 0.20 : 12 elements
Info : 0.20 < quality < 0.30 : 20 elements
Info : 0.30 < quality < 0.40 : 17 elements
Info : 0.40 < quality < 0.50 : 25 elements
Info : 0.50 < quality < 0.60 : 87 elements
Info : 0.60 < quality < 0.70 : 241 elements
Info : 0.70 < quality < 0.80 : 443 elements
Info : 0.80 < quality < 0.90 : 476 elements
Info : 0.90 < quality < 1.00 : 263 elements
Info : 37 edge swaps, 0 node relocations (volume = 0.0352): worst = 0.306628 / average = 0.779068 (Wall 0.000527918s, CPU 0.000528s)
Info : No ill-shaped tets in the mesh :-)
Info : 0.00 < quality < 0.10 : 0 elements
Info : 0.10 < quality < 0.20 : 0 elements
Info : 0.20 < quality < 0.30 : 0 elements
Info : 0.30 < quality < 0.40 : 18 elements
Info : 0.40 < quality < 0.50 : 24 elements
Info : 0.50 < quality < 0.60 : 82 elements
Info : 0.60 < quality < 0.70 : 243 elements
Info : 0.70 < quality < 0.80 : 438 elements
Info : 0.80 < quality < 0.90 : 483 elements
Info : 0.90 < quality < 1.00 : 266 elements
Info : Optimizing volume 8
Info : Optimization starts (volume = 0.21248) with worst = 0.0290494 / average = 0.733132:
Info : 0.00 < quality < 0.10 : 9 elements
Info : 0.10 < quality < 0.20 : 39 elements
Info : 0.20 < quality < 0.30 : 89 elements
Info : 0.30 < quality < 0.40 : 99 elements
Info : 0.40 < quality < 0.50 : 188 elements
Info : 0.50 < quality < 0.60 : 321 elements
Info : 0.60 < quality < 0.70 : 805 elements
Info : 0.70 < quality < 0.80 : 1349 elements
Info : 0.80 < quality < 0.90 : 1251 elements
Info : 0.90 < quality < 1.00 : 537 elements
Info : 133 edge swaps, 5 node relocations (volume = 0.21248): worst = 0.183989 / average = 0.749034 (Wall 0.00193871s, CPU 0.001939s)
Info : 135 edge swaps, 5 node relocations (volume = 0.21248): worst = 0.300295 / average = 0.749167 (Wall 0.00228048s, CPU 0.002281s)
Info : No ill-shaped tets in the mesh :-)
Info : 0.00 < quality < 0.10 : 0 elements
Info : 0.10 < quality < 0.20 : 0 elements
Info : 0.20 < quality < 0.30 : 0 elements
Info : 0.30 < quality < 0.40 : 98 elements
Info : 0.40 < quality < 0.50 : 185 elements
Info : 0.50 < quality < 0.60 : 327 elements
Info : 0.60 < quality < 0.70 : 810 elements
Info : 0.70 < quality < 0.80 : 1344 elements
Info : 0.80 < quality < 0.90 : 1266 elements
Info : 0.90 < quality < 1.00 : 542 elements
Info : Done optimizing mesh (Wall 0.00850473s, CPU 0.008504s)
Info : 1315 nodes 8214 elements
Info : Writing 'mesh.msh'...
Info : Done writing 'mesh.msh'
Info : Writing '/tmp/tmp7s74x_hn/mesh.msh'...
Info : Done writing '/tmp/tmp7s74x_hn/mesh.msh'
PyObject <meshio mesh object>
Number of points: 1315
Number of cells:
triangle: 162
triangle: 98
triangle: 98
triangle: 98
triangle: 98
triangle: 162
triangle: 128
triangle: 128
triangle: 128
triangle: 128
triangle: 330
triangle: 330
tetra: 1554
tetra: 4572
Cell sets: up___unitcell, down___unitcell, left___unitcell, right___unitcell, above___unitcell, below___unitcell, fill___unitcell, up___None, down___None, left___None, right___None, above___None, below___None, fill___None, unitcell___None, up, down, left, right, above, below, fill, unitcell, gmsh:bounding_entities
Point data: gmsh:dim_tags
Cell data: gmsh:physical, gmsh:geometrical
Field data: up___unitcell, down___unitcell, left___unitcell, right___unitcell, above___unitcell, below___unitcell, fill___unitcell, up___None, down___None, left___None, right___None, above___None, below___None, fill___None, unitcell___None, up, down, left, right, above, below, fill, unitcell
Show code cell source
using Gridap
using GridapGmsh
using Gridap.Geometry
using GridapMakie, CairoMakie
using Femwell.Maxwell.Electrostatic
using Femwell.Thermal
For simplicity, we define the thermal conductivity of the unitcell to be 1 and the thermal conductivity of the fill to be 100, which is almost negligible in comparison.
thermal_conductivities = ["unitcell" => 1.4, "fill" => 400]
model = GmshDiscreteModel("mesh.msh")
Ω = Triangulation(model)
dΩ = Measure(Ω, 1)
labels = get_face_labeling(model)
tags = get_face_tag(labels, num_cell_dims(model))
τ = CellField(tags, Ω)
thermal_conductivities =
Dict(get_tag_from_name(labels, u) => v for (u, v) in thermal_conductivities)
ϵ_conductivities(tag) = thermal_conductivities[tag]
Info : Reading 'mesh.msh'...
Info : 54 entities
Info : 1315 nodes
Info : 8014 elements
Info : Done reading 'mesh.msh'
ϵ_conductivities (generic function with 1 method)
We define the temperatures at both sides of the unitcell to define the direction in which we want to estimate the thermal conductivity. In other directions the boundaries are considered to be insulating/mirroring.
We start with calculating the temperature distribution. From this, we calculate, analog to how we calculate resistances for electrical simulations first the integral $\int σ \left|\frac{\mathrm{d}T}{\mathrm{d}\vec{x}}\right|^2 dA which gives an equivalent of the power and calculate from this the effective thermal conductivity. We expect the thermal conductivity almost twice as high as the thermal conductivity of the material with lower thermal conductivity.
boundary_temperatures = Dict("left___unitcell" => 100.0, "right___unitcell" => 0.0)
T0 = calculate_temperature(
ϵ_conductivities ∘ τ,
CellField(x -> 0, Ω),
boundary_temperatures,
order = 2,
)
temperature_difference = abs(sum(values(boundary_temperatures) .* [-1, 1]))
power = abs(
sum(
∫(gradient(temperature(T0)) ⋅ (ϵ_conductivities ∘ τ) ⋅ gradient(temperature(T0)))dΩ,
),
)
println(
"Effective thermal conductivity: ",
(power / temperature_difference^2) /
((unitcell_thickness * unitcell_width) / unitcell_length),
)
boundary_temperatures = Dict("above___unitcell" => 100.0, "below___unitcell" => 0.0)
T0 = calculate_temperature(
ϵ_conductivities ∘ τ,
CellField(x -> 0, Ω),
boundary_temperatures,
order = 2,
)
temperature_difference = abs(sum(values(boundary_temperatures) .* [-1, 1]))
power = abs(
sum(
∫(gradient(temperature(T0)) ⋅ (ϵ_conductivities ∘ τ) ⋅ gradient(temperature(T0)))dΩ,
),
)
println(
"Effective thermal conductivity: ",
(power / temperature_difference^2) /
((unitcell_length * unitcell_width) / unitcell_thickness),
)
Effective thermal conductivity: 2.258192811043174
Effective thermal conductivity:
2.0649540412834715