Ferrite.jl Stokes Flow Example: Windows-Specific File Locking Issue

Hello everyone, I’m a begineer to Julia!

I’m working through the Stokes flow tutorial using Ferrite.jl and encountering an issue specifically on my Windows machine. The example code stokes-flow.jl runs fine on Linux (e.g., Google Colab), but fails on Windows with a Base.IOError.

The error occurs during the mesh generation phase, specifically when writing and reading the mesh file within the setup_grid function. The error message is:

Warning: Failed to clean up temporary path "C:\\Users\\summer\\AppData\\Local\\Temp\\jl_nkR4Ag"
│ Base.IOError("unlink(\"C:\\\\Users\\\\summer\\\\AppData\\\\Local\\\\Temp\\\\jl_nkR4Ag\\\\mesh.msh\"): resource busy or locked (EBUSY)", -4082)

Here’s the complete setup_grid function where the error occurs:

function setup_grid(h = 0.05)
    # Initialize gmsh
    Gmsh.initialize()
    gmsh.option.set_number("General.Verbosity", 2)

    # Add the points
    o = gmsh.model.geo.add_point(0.0, 0.0, 0.0, h)
    p1 = gmsh.model.geo.add_point(0.5, 0.0, 0.0, h)
    p2 = gmsh.model.geo.add_point(1.0, 0.0, 0.0, h)
    p3 = gmsh.model.geo.add_point(0.0, 1.0, 0.0, h)
    p4 = gmsh.model.geo.add_point(0.0, 0.5, 0.0, h)

    # Add the lines
    l1 = gmsh.model.geo.add_line(p1, p2)
    l2 = gmsh.model.geo.add_circle_arc(p2, o, p3)
    l3 = gmsh.model.geo.add_line(p3, p4)
    l4 = gmsh.model.geo.add_circle_arc(p4, o, p1)

    # Create the closed curve loop and the surface
    loop = gmsh.model.geo.add_curve_loop([l1, l2, l3, l4])
    surf = gmsh.model.geo.add_plane_surface([loop])

    # Synchronize the model
    gmsh.model.geo.synchronize()

    # Create the physical domains
    gmsh.model.add_physical_group(1, [l1], -1, "Γ1")
    gmsh.model.add_physical_group(1, [l2], -1, "Γ2")
    gmsh.model.add_physical_group(1, [l3], -1, "Γ3")
    gmsh.model.add_physical_group(1, [l4], -1, "Γ4")
    gmsh.model.add_physical_group(2, [surf])

    # Add the periodicity constraint using 4x4 affine transformation matrix,
    # see https://en.wikipedia.org/wiki/Transformation_matrix#Affine_transformations
    transformation_matrix = zeros(4, 4)
    transformation_matrix[1, 2] = 1  # -sin(-pi/2)
    transformation_matrix[2, 1] = -1 #  cos(-pi/2)
    transformation_matrix[3, 3] = 1
    transformation_matrix[4, 4] = 1
    transformation_matrix = vec(transformation_matrix')
    gmsh.model.mesh.set_periodic(1, [l1], [l3], transformation_matrix)

    # Generate a 2D mesh
    gmsh.model.mesh.generate(2)

    # Save the mesh, and read back in as a Ferrite Grid
    grid = mktempdir() do dir
        path = joinpath(dir, "mesh.msh")
        gmsh.write(path)
        togrid(path)
    end

    # # Finalize the Gmsh library
    Gmsh.finalize()

    
    return grid
end

The problematic part seems to be within the mktempdir() block where the mesh.msh file is written and then read back in using togrid(). The error suggests that the file is locked or busy when the mktempdir() tries to clean up.

Has anyone experienced this specific issue on Windows when working with Gmsh and Ferrite.jl for mesh generation? Any suggestions for resolving this file locking problem would be greatly appreciated. The full error message is below:

Error: mktempdir cleanup
│   exception =
│    IOError: unlink("C:\\Users\\summer\\AppData\\Local\\Temp\\jl_nkR4Ag\\mesh.msh"): resource busy or locked (EBUSY)
│    Stacktrace:
│      [1] uv_error
│        @ .\libuv.jl:100 [inlined]
│      [2] unlink(p::String)
│        @ Base.Filesystem .\file.jl:978
│      [3] rm(path::String; force::Bool, recursive::Bool)
│        @ Base.Filesystem .\file.jl:283
│      [4] rm(path::String; force::Bool, recursive::Bool)
│        @ Base.Filesystem .\file.jl:294
│      [5] rm
│        @ .\file.jl:273 [inlined]
│      [6] mktempdir(fn::var"#1#2", parent::String; prefix::String)
│        @ Base.Filesystem .\file.jl:771
│      [7] mktempdir (repeats 2 times)
│        @ .\file.jl:762 [inlined]
│      [8] setup_grid(h::Float64)
│        @ Main d:\Users\summer\Desktop\5\stokes-flow(plain).jl:49
│      [9] main()
│        @ Main d:\Users\summer\Desktop\5\stokes-flow(plain).jl:198
│     [10] top-level scope
│        @ d:\Users\summer\Desktop\5\stokes-flow(plain).jl:228
│     [11] include(mod::Module, _path::String)
│        @ Base .\Base.jl:495
│     [12] exec_options(opts::Base.JLOptions)
│        @ Base .\client.jl:323
│     [13] _start()
│        @ Base .\client.jl:557
└ @ Base.Filesystem file.jl:774
ERROR: LoadError: 
Stacktrace:
  [1] error(s::String)
    @ Base .\error.jl:35
  [2] open(fileName::String)
    @ Gmsh.gmsh D:\MySoftware\Julia\packages\artifacts\649584fb27316a4395dbb47fde904c83626feae5\lib\gmsh.jl:113
  [3] togrid(filename::String; domain::String)
    @ FerriteGmsh D:\MySoftware\Julia\packages\packages\FerriteGmsh\MH6r7\src\FerriteGmsh.jl:185
  [4] togrid
    @ D:\MySoftware\Julia\packages\packages\FerriteGmsh\MH6r7\src\FerriteGmsh.jl:176 [inlined]
  [5] #1
    @ d:\Users\summer\Desktop\5\stokes-flow(plain).jl:52 [inlined]
  [6] mktempdir(fn::var"#1#2", parent::String; prefix::String)
    @ Base.Filesystem .\file.jl:766
  [7] mktempdir (repeats 2 times)
    @ .\file.jl:762 [inlined]
  [8] setup_grid(h::Float64)
    @ Main d:\Users\summer\Desktop\5\stokes-flow(plain).jl:49
  [9] main()
    @ Main d:\Users\summer\Desktop\5\stokes-flow(plain).jl:198
 [10] top-level scope
    @ d:\Users\summer\Desktop\5\stokes-flow(plain).jl:228
in expression starting at d:\Users\summer\Desktop\5\stokes-flow(plain).jl:228        
┌ Warning: Failed to clean up temporary path "C:\\Users\\summer\\AppData\\Local\\Temp\\jl_nkR4Ag"
│ Base.IOError("unlink(\"C:\\\\Users\\\\summer\\\\AppData\\\\Local\\Temp\\jl_nkR4Ag\\\\mesh.msh\"): resource busy or locked (EBUSY)", -4082)
└ @ Base.Filesystem file.jl:549

I hope someone can help! Thanks in advance.

The total code can be found in Ferrite → Tutorials → Stokes flow

Welcome @sumor !

Unfortunately, Gmsh.jl is still not stable on Windows as far as I know. But it is possible to use WSL.