Mesh Creation
How to create and load meshes in Rodin.
Rodin provides multiple ways to create meshes: loading from files, programmatic generation, or building custom meshes from scratch.
Generating Uniform Grids
The simplest way to create a mesh is using the UniformGrid static method, which generates structured grids of various polytope types.
2D Uniform Grids
#include <Rodin/Geometry.h> using namespace Rodin; using namespace Rodin::Geometry; int main() { Mesh mesh; // Triangular mesh with 16x16 grid mesh = mesh.UniformGrid(Polytope::Type::Triangle, {16, 16}); // Quadrilateral mesh with 32x32 grid mesh = mesh.UniformGrid(Polytope::Type::Quadrilateral, {32, 32}); return 0; }
3D Uniform Grids
Mesh mesh; // Tetrahedral mesh with 8x8x8 grid mesh = mesh.UniformGrid(Polytope::Type::Tetrahedron, {8, 8, 8}); // Hexahedral mesh with 16x16x16 grid mesh = mesh.UniformGrid(Polytope::Type::Hexahedron, {16, 16, 16}); // Wedge (prism) mesh with 10x10x10 grid mesh = mesh.UniformGrid(Polytope::Type::Wedge, {10, 10, 10});
Domain
By default, UniformGrid generates meshes on the unit square or unit cube . The grid parameters specify the number of subdivisions in each direction.
Loading from Files
Rodin supports loading meshes from various file formats.
Supported Formats
- MFEM (
.mesh) - MFEM native format (default) - MEDIT (
.mesh) - MEDIT format from INRIA - GMSH (
.msh,.gmsh) - Gmsh format
Loading Meshes
#include <Rodin/Geometry.h> #include <Rodin/IO.h> using namespace Rodin; using namespace Rodin::Geometry; int main() { Mesh mesh; // Load from MFEM format (default) mesh.load("domain.mesh"); // Explicitly specify format mesh.load("domain.mesh", IO::FileFormat::MFEM); mesh.load("domain.msh", IO::FileFormat::GMSH); // Alternatively, use constructor Mesh mesh2("domain.mesh", IO::FileFormat::MFEM); return 0; }
Building Custom Meshes
For complete control, use the Mesh::Builder to construct meshes programmatically.
Simple Example
#include <Rodin/Geometry.h> using namespace Rodin; using namespace Rodin::Geometry; int main() { // Create a simple triangular mesh Mesh mesh = Mesh::Build() .initialize(2) // 2D space .nodes(4) // 4 vertices .vertex({0.0, 0.0}) // Vertex 0 .vertex({1.0, 0.0}) // Vertex 1 .vertex({1.0, 1.0}) // Vertex 2 .vertex({0.0, 1.0}) // Vertex 3 .triangle({0, 1, 2}) // Triangle 1 .triangle({0, 2, 3}) // Triangle 2 .finalize(); std::cout << "Created mesh with " << mesh.getCellCount() << " cells" << std::endl; return 0; }
Setting Attributes
Attributes are used to mark different regions or boundaries:
Mesh mesh = Mesh::Build() .initialize(2) .nodes(6) .vertex({0.0, 0.0}) .vertex({1.0, 0.0}) .vertex({2.0, 0.0}) .vertex({0.0, 1.0}) .vertex({1.0, 1.0}) .vertex({2.0, 1.0}) .triangle({0, 1, 4}) .attribute({2, 0}, 1) // Set triangle 0 attribute to 1 .triangle({0, 4, 3}) .attribute({2, 1}, 1) // Set triangle 1 attribute to 1 .triangle({1, 2, 5}) .attribute({2, 2}, 2) // Set triangle 2 attribute to 2 .triangle({1, 5, 4}) .attribute({2, 3}, 2) // Set triangle 3 attribute to 2 .finalize(); // Query volumes by attribute std::cout << "Volume of region 1: " << mesh.getVolume(1) << std::endl; std::cout << "Volume of region 2: " << mesh.getVolume(2) << std::endl;
Mixed Element Types
The builder supports meshes with different element types:
Mesh mesh = Mesh::Build() .initialize(2) .nodes(6) .vertex({0.0, 0.0}) .vertex({1.0, 0.0}) .vertex({2.0, 0.0}) .vertex({0.0, 1.0}) .vertex({1.0, 1.0}) .vertex({2.0, 1.0}) // Left region: triangles .triangle({0, 1, 4}) .triangle({0, 4, 3}) // Right region: quadrilateral .quadrilateral({1, 2, 5, 4}) .finalize();
Box Meshes
The Box method is similar to UniformGrid but allows specifying the domain bounds:
// Create mesh on domain [0, 2] x [0, 3] // Implementation depends on Rodin version Mesh mesh = Mesh::Box(Polytope::Type::Triangle, {16, 16});
Empty Meshes
Create an empty mesh and populate it later:
Mesh mesh; // Empty mesh if (mesh.isEmpty()) { std::cout << "Mesh is empty" << std::endl; } // Load or build the mesh later mesh.load("domain.mesh");
Copying Meshes
Mesh mesh1; mesh1 = mesh1.UniformGrid(Polytope::Type::Triangle, {16, 16}); // Copy constructor Mesh mesh2(mesh1); // Move constructor Mesh mesh3(std::move(mesh1));
Complete Example
#include <Rodin/Geometry.h> #include <Rodin/IO.h> using namespace Rodin; using namespace Rodin::Geometry; int main() { // Method 1: Generate uniform grid Mesh mesh1; mesh1 = mesh1.UniformGrid(Polytope::Type::Triangle, {32, 32}); mesh1.save("grid.mesh", IO::FileFormat::MEDIT); // Method 2: Load from file Mesh mesh2; mesh2.load("domain.mesh", IO::FileFormat::MFEM); // Method 3: Build programmatically Mesh mesh3 = Mesh::Build() .initialize(2) .nodes(3) .vertex({0.0, 0.0}) .vertex({1.0, 0.0}) .vertex({0.5, 0.866}) .triangle({0, 1, 2}) .finalize(); std::cout << "Mesh 1 cells: " << mesh1.getCellCount() << std::endl; std::cout << "Mesh 2 cells: " << mesh2.getCellCount() << std::endl; std::cout << "Mesh 3 cells: " << mesh3.getCellCount() << std::endl; return 0; }
See Also
- Mesh I/O
- Meshes overview
- Mesh class reference
- Example: examples/Geometry/UniformGrid.cpp