Overview

Heat Conduction in a 2D Fin Tutorial (Gmsh Mesh)

This page demonstrates solving the 2D heat conduction fin problem using a Gmsh-generated mesh. Gmsh is a powerful mesh generation tool that can create complex geometries and meshes for finite element analysis. For the mathematical formulation and theory, see the basic tutorial.

Gmsh file import

This example demonstrates how to import a Gmsh-generated mesh (.msh file format) and solve a heat conduction problem.

<body>
  <!-- ...body region... -->
  <script type="module">
    import {
      FEAScriptModel,
      importGmshMesh,
      plotInterpolatedSolution,
      printVersion,
    } from "https://core.feascript.com/dist/feascript.esm.js";

    window.addEventListener("DOMContentLoaded", async () => {
      console.log("FEAScript version:", printVersion);

      // 1. Create the model and select the physics
      const model = new FEAScriptModel();
      model.setModelConfig("heatConductionScript");

      // 2. Load the Gmsh mesh (.msh format version 4.1)
      const response = await fetch("./rect_quad.msh");
      if (!response.ok) {
        throw new Error(`Failed to load the mesh file: ${response.status} ${response.statusText}`);
      }
      const meshFile = new File([await response.text()], "rect_quad.msh");
      const mesh = await importGmshMesh(meshFile);
      model.setMeshConfig({ parsedMesh: mesh });

      // 3. Apply the boundary conditions (key = Gmsh physical group tag - 1)
      model.addBoundaryCondition("0", ["constantTemperature", 200]); // Bottom
      model.addBoundaryCondition("1", ["symmetry"]);                 // Left
      model.addBoundaryCondition("2", ["convection", 1, 20]);        // Top
      model.addBoundaryCondition("3", ["constantTemperature", 200]); // Right

      // 4. Solve
      model.setSolverMethod("lusolve");
      const result = model.solve();

      // 5. Plot the results
      plotInterpolatedSolution(model, result, "contour", "resultsCanvas");
    });
  </script>
  <!-- ...rest of body region... -->
</body>

Important notes about the Gmsh workflow:

  • Physical Groups in Gmsh: In your .geo file (see Example Gmsh .geo File), you need to define physical groups for boundaries using commands like Physical Line("bottom", 1) = {1};. These are mapped to tags in the imported mesh.
  • Boundary Condition Mapping and Tag Indexing: When using Gmsh meshes in FEAScript, you need to subtract 1 from the Gmsh physical group tag numbers. For example, if your Gmsh file has physical groups with tags "1", "2", "3", "4", you would reference them in FEAScript as "0", "1", "2", "3", respectively. For example: model.addBoundaryCondition("0", ["constantTemperature", 200]); // Gmsh physical group tag 1. This conversion is necessary because Gmsh uses 1-based indexing while FEAScript uses 0-based indexing.

You can create your own Gmsh files by writing .geo scripts or using Gmsh's GUI. For this example, we used a simple rectangular domain defined in a .geo file with specific physical groups for each boundary.

Example Gmsh .geo file

Below is the rect.geo file used in this tutorial. It defines a 4 m × 2 m rectangular domain with a physical line for each boundary edge:

rect.geo
// 2D rectangle: 4 m (width) x 2 m (height)
// Generate the mesh with: gmsh rect.geo -2 -format msh41 -o rect_quad.msh

// 1. Mesh size
lc = 0.7; // Characteristic length

// 2. Points (x, y, z, mesh size)
Point(1) = {0, 0, 0, lc}; // Bottom left
Point(2) = {4, 0, 0, lc}; // Bottom right
Point(3) = {4, 2, 0, lc}; // Top right
Point(4) = {0, 2, 0, lc}; // Top left

// 3. Lines and surface
Line(1) = {1, 2};            // Bottom
Line(2) = {2, 3};            // Right
Line(3) = {3, 4};            // Top
Line(4) = {4, 1};            // Left
Line Loop(1) = {1, 2, 3, 4}; // Closed boundary
Plane Surface(1) = {1};      // Domain

// 4. Physical groups, tagged bottom, left, top, right (the side order of FEAScript structured meshes)
Physical Line("bottom", 1) = {1};    // FEAScript boundary "0"
Physical Line("left", 2)   = {4};    // FEAScript boundary "1"
Physical Line("top", 3)    = {3};    // FEAScript boundary "2"
Physical Line("right", 4)  = {2};    // FEAScript boundary "3"
Physical Surface("domain", 5) = {1}; // Domain

// 5. Mesh
Recombine Surface{1};  // Quadrilaterals instead of triangles
Mesh.ElementOrder = 2; // Quadratic elements
Mesh 2;

Note how the physical line tags in the .geo file correspond to the boundary conditions in our FEAScript code. The tags are given in the order bottom, left, top, right, which is the side order of FEAScript's structured meshes, so the boundary keys are the same as in the basic fin tutorial:

  • Physical Line("bottom", 1) = {1}; → model.addBoundaryCondition("0", ["constantTemperature", 200]);
  • Physical Line("left", 2) = {4}; → model.addBoundaryCondition("1", ["symmetry"]);
  • Physical Line("top", 3) = {3}; → model.addBoundaryCondition("2", ["convection", 1, 20]);
  • Physical Line("right", 4) = {2}; → model.addBoundaryCondition("3", ["constantTemperature", 200]);

To generate a mesh file from this .geo script, you would run: gmsh rect.geo -2 -format msh41 -o rect_quad.msh in your terminal, which creates the rect_quad.msh file that can be imported into FEAScript.

FEAScript also supports triangular elements. To use them, remove the Recombine Surface{1}; line so that Gmsh keeps the triangles. Set Mesh.ElementOrder to 1 for linear or 2 for quadratic elements; FEAScript detects the mesh dimension and element order from the imported mesh, so there is no need to set meshDimension or elementOrder in the mesh configuration.

Generated mesh

Below is a visualization of the quadrilateral mesh generated with Gmsh. The mesh consists of 30 elements.

Quadrilateral mesh generated by Gmsh

Quadrilateral mesh (rect_quad.msh) generated using the rect.geo script with Gmsh

The unstructured mesh approach would be particularly advantageous for complex geometries, where the mapped mesh approach could not be applied effectively.

Results

Below is the 2D contour plot of the computed temperature distribution. This plot is generated in real time using FEAScript. Please note that solutions computed on unstructured meshes like this may exhibit small numerical differences compared to solutions on structured orthogonal meshes. This occurs because derivative calculations in non-orthogonal elements are inherently less precise due to the Jacobian transformation process. These small differences are expected and acceptable for most engineering applications, but may be noticeable in regions with steep temperature gradients.

See also here for a variation with a rhomboid fin.