Heat conduction¶
A cooling fin in one dimension¶
The equation \(-u'' + 400\,u = 0\) on \((0, 0.05)\) with \(u(0) = 300\) and \(u'(L) + 2u(L) = 0\) is Example 5.3.1 of the book. It shows the three ingredients of every problem — kernels, boundary conditions, and a solve — and the recovery of the secondary variable at the fixed end.
# SPDX-License-Identifier: LGPL-2.1-or-later
"""Reddy, Example 5.3.1: a cooling fin, -u'' + 400 u = 0 on (0, 0.05).
u(0) = 300, and at x = L the fin loses heat to the surroundings:
u'(L) + 2 u(L) = 0. The example prints the nodal temperatures, the heat flow
into the fin at the fixed end (the secondary variable), and the same solution
computed with the finite element method for comparison.
"""
import dualmesh as dm
def solve(num_elements, method="dmcdm"):
mesh = dm.generate_line_mesh(start=0.0, end=0.05, num_elements=num_elements)
problem = dm.Problem(mesh, method=method)
problem.add_variable("temperature")
problem.add_kernel("Diffusion", variable="temperature")
problem.add_kernel("Reaction", variable="temperature", coefficient=400.0)
problem.add_boundary_condition(
"DirichletBC", variable="temperature", boundary="left", value=300.0
)
problem.add_boundary_condition(
"RobinBC", variable="temperature", boundary="right", transfer_coefficient=2.0
)
problem.solve()
return problem
if __name__ == "__main__":
for method in ("dmcdm", "fem"):
problem = solve(5, method)
values = problem.values("temperature")
print(f"{method:6s} u = " + " ".join(f"{v:8.3f}" for v in values))
print(f"{method:6s} Q(0) = {problem.total_reaction('temperature', 'left'):.1f}")
print("book (DMCDM): 300.00 257.62 225.59 202.64 187.83 180.57, Q(0) = 4817")
Running it prints
dmcdm u = 300.000 257.618 225.593 202.637 187.827 180.568
dmcdm Q(0) = 4817.0
fem u = 300.000 257.567 225.507 202.527 187.703 180.437
which are the values of Table 5.3.1 of the book. Note how little separates the
two methods: only the method argument of dualmesh.Problem.
A bus bar in two dimensions¶
Example 5.4.3 adds internal heat generation and a convective boundary. The same problem is also available as an input file (Input files).
# Reddy, Example 5.4.3: a bus bar with internal heat generation, fixed
# temperatures on the sides, an insulated bottom, and convection on top.
mesh:
type: rectangle
x_min: 0.0
x_max: 0.1
y_min: 0.0
y_max: 0.05
num_x_elements: 10
num_y_elements: 5
problem:
method: dmcdm
variables:
temperature: {initial_condition: 0.0}
kernels:
conduction:
type: HeatConduction
variable: temperature
thermal_conductivity: 20.0
heating:
type: HeatSource
variable: temperature
heat_source: 1.0e6
boundary_conditions:
left:
type: DirichletBC
variable: temperature
boundary: left
value: 40.0
right:
type: DirichletBC
variable: temperature
boundary: right
value: 10.0
top:
type: ConvectiveHeatFluxBC
variable: temperature
boundary: top
heat_transfer_coefficient: 75.0
ambient_temperature: 0.0
executioner:
type: steady
outputs:
vtu: bus_bar.vtu
reactions: [[temperature, left], [temperature, right]]
point_values: [[temperature, 0.05, 0.0], [temperature, 0.05, 0.05]]
Things worth noticing¶
An insulated boundary needs no boundary condition at all: a zero natural condition is the default, which in the dual mesh method means that the boundary face of the control domain simply contributes nothing.
total_reactionreturns the heat flow through a boundary, computed from the equations that the Dirichlet conditions replaced — not by differentiating the solution afterwards.A temperature-dependent conductivity \(k = k_0 (1 + k_1 T)\) needs only
temperature_polynomial=[1.0, k1]on theHeatConductionkernel; the problem then solves by Newton’s method with the exact Jacobian, or by direct iteration withnonlinear_solver="picard".