Transient heat equation on hex mesh¶

Open In Colab Binder

Solving the transient heat eqaution on a hexahedron mesh.

In [1]:
import meshio as mo
import pyvista as pv
import torch

from torchfem import SolidHeat
from torchfem.data import get_data
from torchfem.materials import IsotropicConductivity3D
from torchfem.plot_utils import embed_pyvista_animation

# Set default data type to double precision
torch.set_default_dtype(torch.float64)

3D unstructured mesh with linear hexahedrons read from Abaqus input file¶

In [2]:
kappa, rho, cp = 500.0, 7850.0, 500.0
In [3]:
inp_path = get_data("extruded_hex_mesh.inp")


# material
material = IsotropicConductivity3D(kappa=kappa, rho=rho * cp)


mesh = mo.read(inp_path)
# Create model
nodes = torch.tensor(mesh.points) * 1.0e-3  # SI
elements = torch.tensor(mesh.cells_dict["hexahedron"])
box_heat = SolidHeat(nodes, elements, material)


# Assign boundary conditions
box_heat.constraints[mesh.point_sets["temp_left"]] = True
box_heat.constraints[mesh.point_sets["temp_right"]] = True
# box_heat.constraints[mesh.point_sets["insulation"]] = True
box_heat.temperatures[mesh.point_sets["temp_left"], 0] = 0.0
box_heat.temperatures[mesh.point_sets["temp_right"], 0] = 20.0
# box_heat.heat_flux[nodes[:, 1] == 1.0, 0] = 0.0
# box_heat.heat_flux[mesh.point_sets["insulation"]] = 5.0

# solver settings
end_time = 5.0
delta_t = 0.2

# Results are returned at exactly these times
times = torch.arange(0.0, end_time + delta_t, delta_t)

# Solve
temp, rfl, hf, temp_grad, _ = box_heat.time_integration(times, delta_t, verbose=True)
────────────────────────────────────────────────────────────────────────────────────────
 model    SolidHeat · 360 elem · 584 dof · float64
 machine  x86_64 · 2 threads · 16 GB RAM
 solver   direct · scipy · cpu
 newton   rtol 1e-08 · atol 1e-06 · <=100 it · dt <= 0.2
────────────────────────────────────────────────────────────────────────────────────────
  Time step         Time  Steps  Newton  Krylov  Residual  Wall time
          1          0.2      1       1       -  8.66e-15     0.01 s
          2          0.4      1       1       -  5.74e-15     0.01 s
          3          0.6      1       1       -  4.80e-15     0.01 s
          4          0.8      1       1       -  3.46e-15     0.01 s
          5            1      1       1       -  3.60e-15     0.01 s
          6          1.2      1       1       -  3.41e-15     0.01 s
          7          1.4      1       1       -  2.75e-15     0.01 s
          8          1.6      1       1       -  3.56e-15     0.01 s
          9          1.8      1       1       -  3.35e-15     0.01 s
         10            2      1       1       -  3.28e-15     0.01 s
         11          2.2      1       1       -  2.84e-15     0.01 s
         12          2.4      1       1       -  3.03e-15     0.01 s
         13          2.6      1       1       -  3.03e-15     0.01 s
         14          2.8      1       1       -  2.94e-15     0.01 s
         15            3      1       1       -  3.35e-15     0.01 s
         16          3.2      1       1       -  3.14e-15     0.01 s
         17          3.4      1       1       -  2.95e-15     0.01 s
         18          3.6      1       1       -  3.22e-15     0.01 s
         19          3.8      1       1       -  3.51e-15     0.01 s
         20            4      1       1       -  3.23e-15     0.01 s
         21          4.2      1       1       -  3.05e-15     0.01 s
         22          4.4      1       1       -  3.34e-15     0.01 s
         23          4.6      1       1       -  3.18e-15     0.01 s
         24          4.8      1       1       -  3.44e-15     0.01 s
         25            5      1       1       -  3.32e-15     0.01 s
────────────────────────────────────────────────────────────────────────────────────────
 converged · 25 time steps · 25 Newton iterations · 0.16 s

Plot the animated results.

In [4]:
pl = pv.Plotter()


def animate_temp(i):
    pl.clear()
    box_heat.plot(
        node_property={"Temperature": temp[i]},
        show_undeformed=True,
        opacity=torch.linspace(0.2, 1.0, len(temp)),
        colormap="magma",
        clim=[temp.min(), temp.max()],
        plotter=pl,
        lighting=False,
    )


frames = range(len(temp))
embed_pyvista_animation(pl, animate_temp, frames)
Out[4]:
No description has been provided for this image