OrthOpt: a mesh orthogonality optimizer
Optimize a tetrahedral mesh to minimize its mean non-orthogonality (possibly weighted).
This implementation is naive but sufficient for demonstration purpose, but can still optimize a 1M elements mesh in few minutes. If you had time to optimize it, feel free to contribute!
Features
- Decompose the mesh (i.e. finding its internal faces) and compute statistic on non-orthogonality and skewness.
- Mesh non orthogonality is defined by the dot product of face normal and vector defined by the two cell centers sharing the face.
- Optimize the non-orthogonality distribution in the mesh according to a gradient based method using the LBGFS algorithm (from LBFGS++ library) by moving its vertices.
- Optimize vertices shared by only tetrahedra (e.g. if the vertices belong to one hex element and 100 tetrahedra, it is NOT optimized).
- Control the non-orthogonality distribution in the mesh by applying penalization function to the non-orthogonality (power function, inverse function, log function, exponential function).
- Read and write mesh in various formats (Medit, TetGen, PFLOTRAN for instance)
- Parallelization of the optimization process through OpenMP
Installation
- Install dependencies:
sudo apt install libeigen3-dev
- Clone this repository
git clone https://github.com/MoiseRousseau/Mesh-Orthogonality-Optimizer.git OrthOpt && cd OrthOpt
- Create a build directory:
mkdir build && cd build
- Configure with CMake:
cmake ..
- Build with
make
Use
Please see OrthOpt launching OrthOpt without arguments (e.g. ./OrthOpt
)
For example, for a mesh in Medit format (extension .mesh
), the command
./OrthOpt -optimize -m in.mesh -o out.mesh -function_type 0 -penalizing_power 5 -maxit 100
optimize the vertices position of the mesh stored in the file in.mesh
(Medit format) considering a power weigthing function with a penalization power of 5 with a maximum of 100 iteration.
Optimized mesh is saved in Medit format in the file out.mesh
.
Salome plugin
A plugin for the CAD software Salome plugin is also available. The plugin export the mesh in a PFLOTRAN-like format, automatically call the optimizer, and reimport the optimize mesh in Salome.
Installation is done in three step:
- Copy the content or the folder
salome_plugin
in this repository to a newly created folder nammedOrthOpt
in the directory$HOME/.config/salome/Plugins/
- Add the following two lines at the end of
smesh_plugins.py
file located in the previous directory:
import OrthOpt
salome_pluginsmanager.AddFunction('OrthOpt', ' ',
OrthOpt.OrthOpt_opt)
- Copy the
OrthOpt
executable in the$HOME/.config/salome/Plugins/OrthOpt/
folder.
You are ready to go. The plugin is located in the MESH module under the Mesh/SMESH Plugins/OrthOpt
.
Examples
Example of the optimization of a mesh composed of nearly 25000 nodes and 125000 tetrahedra for simulation the flow around a cylinder as this OpenFOAM tutorial.
Mesh was generated using Salome and the NETGEN algorithm with default optimization parameters and refined near the cylinder.
Mesh was further optimized using OrthOpt considering a power law penalization function with various penalization power n
.
The table below summarizes the mesh statistics and the total number of iteration for the linear solver with the orthogonal correction for the Laplacian to converge (with tolerance 1e-6 and 1e-12).
Mesh | Mean non-orthogonality (°) | Max non-orthogonality (°) | Solver iteration (1e-6) | Solver iteration (1e-12) |
---|---|---|---|---|
OrthOpt n=0.5 | 11.2 | 70.8 | 34 | > 100 |
OrthOpt n=1 | 11.7 | 56.9 | 31 | 78 |
Netgen default | 12.4 | 50.7 | 29 | 68 |
OrthOpt n=3 | 13.6 | 44.1 | 29 | 59 |
OrthOpt n=5 | 14.5 | 42.6 | 28 | 52 |
The figure below also shows the distribution of non-orthogonality angle within the internal faces of the meshes.
In details, increasing the penalization power increase the mean non-orthogonality, but decrease its maximum. Decrease of the maximum resulted in fewer iteration for the solver to converge, especially for a tolerance of 1e-12.
TODO
- Parallel decomposition of mesh (maybe use some dedicaced library)
- Some code optimization (e.g. store vertices coordinate as one table, and not as a structure)
- More IO format
- Add more examples
- Tests
- Write a paper ?
Python Wrapper
Rather some note for me than to be used.
- Open makefile and add option
-fPIC to TARGET
- Compile the binder:
g++ -c -fPIC binding.cpp -o binding.o -I/usr/include/eigen3
- Create the shared library:
g++ -shared -Wl,--no-undefined,-soname,lib.so -o lib.so ../../build/obj/Mesh.o ../../build/obj/OrthOpt.o binding.o -fopenmp