# Creating 3D Mesh from stl files with gmsh

After long hours of searching for an answer I thought it might be better to ask the community.

The problem I have is that I need to convert STL files to mesh files. I know that I therefore need to add a volume to the surfaces from the STL file.

When I do it manually in gmsh

Modules->Geometry->Elementary entities->Add->Volume->klick on the surface-mesh->pressing 'e'->pressing 'q')

that works very well.

Since I have to do this process for multiple hundreds of .stl-files I can't do it manually with the gui. Therefore I created a script which uses command line arguments to do the above and avoids opening the gui. Up until now I have:

gmsh input.stl -string "Surface Loop(2)={1}; Volume(3)={2};" -3 -o output.msh


When I run this I get the error, that the surface 1 is unknown. But when I inspect the STL file manually in the gui and do nothing but opening this STL file it shows me that the surface has id 1. So why is the surface in the script-version unknown? Is there maybe a better way to add a volume to a surface-mesh with gmsh?

P.S.: I can't use a .geo-file for the commands since I am using a shell script to iterate through my files (with variables in the file names). Using a .geo-file would not allow me to use the variables anymore.

P.P.S.: Here is the script I'm now using:

#!/bin/bash

# amount of files to be processed
endVal=400

# amount of slices per timestep to be processed
sliceCount=2

# create output folders for .msh and remeshed .stl files, if necessary
cd Slices/

# save current working directory to a variable
cwd=$(pwd) # folder structure should be: # / the Slices folder, created by the user or another script # MSH/ after running the script it should contain the meshes created by gmsh # Remeshed/ after running the script it should contain the remeshed meshes generated by mmg # STL/ should contain the .stl files # STL_Remeshed/ after running it should contain the remeshed meshes converted back to the .stl format by gmsh if [[ ! -d MSH/ ]]; then mkdir -p MSH/Remeshed fi if [[ ! -d STL_Remeshed/ ]]; then mkdir STL_Remeshed fi for ((a = 0; a < $$sliceCount; a++)) do for ((i = 0; i <$$endVal; i++)) do # convert .stl to .msh /Volumes/User/Gmsh.app/Contents/MacOS/gmsh $$cwd/STL/slice$$a.$$i.stl -string "Merge '$$cwd/STL/slice$$a.$$i.stl'; Surface Loop(2)={1}; Volume(3)={2};" -3 -o $$cwd/MSH/slice$$a.$i.msh -format "msh22"

# remesh
/Volumes/User/mmg/mmg3d_debug -in $$cwd/MSH/slice$$a.$$i.msh -out$$cwd/MSH/Remeshed/slice$$a.$$i.msh -hausd 0.00005

# convert remeshed .msh to .stl
/Volumes/User/Gmsh.app/Contents/MacOS/gmsh $$cwd/MSH/Remeshed/slice$$a.$$i.msh -0 -o$$cwd/STL_Remeshed/slice$$a.$$i.stl
done
done


I am not entirely sure what is going wrong in your version of the command-line approach. However, I think it works on my test STL file (with gmsh 4.0.7) with the following line:

gmsh -string "Merge 'input.stl'; Surface Loop(2)={1}; Volume(3)={2};" -3 -o output.msh


It might be also easier to use the full path of the input file to avoid gmsh "running around".

My guess would be that opening an STL (your command-line) vs merging it (my proposition) has a different effect.

• I had finally time to try this. The command doesn't result in errors. But when I inspect the resulting file in the gmsh gui, there is no volume added. So it seems, that the command line doesn't do anything. – A.M. May 21 '19 at 15:03
• I also added the script that I use to the above posting. The line with mmg3d and the command after that won't work because the first command with gmsh is the problem. But maybe the error that I get from mmg is helpful: currently I get "Check that your mesh contains tetrahedra." I think this is because of the missing volume. – A.M. May 21 '19 at 15:13
• @A.M. have you tried adding some physical ids? The default GMSH behaviour is to only output tagged entities. – origimbo May 21 '19 at 16:16
• @origimbo Yes, I've tried that. To no effect. There is still no volume added when I manually inspect the resulting .msh-file in the gmsh gui. – A.M. May 22 '19 at 11:27

I solved my problem now. Despite initially not wanting to do that, I now generate .geo-files in my script. I do it with

echo "Merge '$$cwd/STL/slice$$a.$$i.stl';\nSurface Loop(1) = {1};\nVolume(1) = {1};" >$$cwd/GEO/slice$$a.$$i.geo
# convert .stl to .msh
/Volumes/User/Gmsh.app/Contents/MacOS/gmsh $$cwd/GEO/slice$$a.$$i.geo -3 -o$$cwd/MSH/slice$$a.$$i.msh -format "msh22"


The first line generates .geo-files for each of my .stl-files individually. After that I can just run the .geo-file and get what I initially wanted.

I think the problem was that in the original script I posted above all commands were written in one single line:

/Volumes/User/Gmsh.app/Contents/MacOS/gmsh $$cwd/STL/slice$$a.$$i.stl -string "Merge '$$cwd/STL/slice$$a.$$i.stl'; Surface Loop(2)={1}; Volume(3)={2};" -3 -o $$cwd/MSH/slice$$a.\$i.msh -format "msh22"


Gmsh seems to only execute the first of the three commands (the merge command) and ignores the rest. I also tried to write all the commands in the .geo-file in one line (so the echo command from above just without the linebreaks). That also lead to .msh-files without the added volume. The same happend when I wrote everything manually in one line directly in the .geo-file with explicit linebreaks (\n between the commands). It seems that the command parser from gmsh parses line-wise only until it encounters the first semicolon. Everything after that gets ignored.

Thanks again to all who helped me here.

P.S.: Since I didn't write it anywhere else: I used Gmsh 4.3.0

• Maybe the problem with the single line command is some inadequate/archaic 128 character limit, it's 191 characters long... – Tobias Kienzler Sep 8 '20 at 6:47
• @TobiasKienzler Maybe that's the case. Unfortunately, I can't test it because I'm working elsewhere and do not have the resources to test that. But wouldn't it be a problem, when the string isn't properly closed? The second double quote comes after the 128 character limit. I think that would cause a different error or no output at all. – A.M. Sep 9 '20 at 11:35
• Ah true, and shell limits are around 1e5. Then maybe it's a bug (or design decission) that gmsh only performs the first command passed via -string – Tobias Kienzler Sep 9 '20 at 11:47