Chi-Tech
The structure of meshes

General structure of meshes

Mesh generation can be classified into 4 basic levels difficulty.

  1. Orthogonal. The simplest mesh generation is undoubtedly the generation of orthogonal meshes.
  2. Reading meshes. Minimal repackaging of pre-generated meshes.
  3. Semi-generated meshes. Extruded meshes and other similar operations.
  4. Internally generated meshes. Pipe dream for now, but having the ability to generate tetrahedral meshes would open a lot of doors. From there I would like to have polyhedral meshes generation then hexahedral mesh generation.

What is the grid?

The grid is an instance of the chi_mesh::MeshContinuum class. It has 3 members of primary interest namely:

_

Easily access an existing grid

We will explain the different elements of a mesh in more detail in sections below but as a quick primer we can say that mesh entities are loaded into chi_mesh::MeshHandler.

You can get the current mesh-handler using:

auto cur_handler = chi_mesh::GetCurrentHandler();
MeshHandler & GetCurrentHandler()

The computational grid is contained in a chi_mesh::MeshContinuum object which you can obtain with:

auto grid_ptr = cur_handler->GetGrid();

If there is no existing grid then one can be created as detailed in

_

More detail on Mesh data structures

chi_mesh::MeshHandler

Meshes and mesh operations are all handled under the umbrella of a chi_mesh::MeshHandler. Mesh handlers are loaded onto the global variable chi_meshhandler_stack and the "current" handler is tracked by another global variable, chi_current_mesh_handler. If any mesh operation is performed it should push newly created objects to a stack in a handler. The figure below shows a generalized architecture.

Figure 1: Overview of the mesh hierarchy.

Even though we already showed how to obtain the handler, the "current" handler can always be obtained with:

auto cur_handler = chi_mesh::GetCurrentHandler();

_

chi_mesh::SurfaceMesher and chi_mesh::VolumeMesher

Each mesh-handler is outfitted with one surface mesher and one volume mesher, both initially undefined. The surface meshing step can be thought of a preprocessing step. For those who are used to STAR-CCM+, this step is analogous to the remeshing of a CAD surface into a format more conducive to volume meshing.

There are various types of surface meshers:

  • chi_mesh::SurfaceMesherPredefined. Pass through pre-processor. Does not perform any meshing.
  • chi_mesh::SurfaceMesherDelaunay. Remeshes a surface mesh using Delaunay triangulation.
  • chi_mesh::SurfaceMesherTriangle. Remeshes a surface mesh using Triangle 1.6.

Similarly there are also various types of volume meshers:

  • chi_mesh::VolumeMesherLinemesh1D. Converts line meshes into slabs.
  • chi_mesh::VolumeMesherPredefined2D. Converts predefined surface meshes into 2D triangles, quadrilaterals or polygons.
  • chi_mesh::VolumeMesherExtruder. Extrudes predefined surface meshes into 3D triangular prisms, hexahedrals or polyhedrons.
  • chi_mesh::VolumeMesherPredefined3D. Converts loaded 3D meshes to 3D tetrahedrals, hexahedrals or polyhedrons.
  • chi_mesh::VolumeMesherPredefinedUnpartitioned. Converts a ligthweight unpartitioned mesh to a proper full detail partitioned mesh. This mesher allows much flexibility for reading meshes from external sources.

Surface meshers and volume meshers are assigned to a handler as:

cur_handler->surface_mesher = new chi_mesh::SurfaceMesherPredefined;
cur_handler->volume_mesher = new chi_mesh::VolumeMesherPredefined3D;

To execute the surface meshers simply do:

cur_handler->surface_mesher->Execute();
cur_handler->volume_mesher->Execute();

_

chi_mesh::MeshContinuum (or if you like ... THE GRID!)

A chi_mesh::MeshContinuum object is the business-end of meshes. The execution of a volume mesher ultimately results in the creation of a grid. To obtain a reference to a grid simply execute:

auto grid = cur_handler->GetGrid();

This command will retrieve the latest grid from the latest region within the current mesh handler.

_

chi_mesh::Cell

Cells in Chi-Tech are the basic building blocks for mesh-based scientific computing. Some of the mesh types are shown in Figure 2 below and are defined by the enumeration they hold as defined by chi_mesh::CellType. The cell types supported right now are:

Figure 2: Types of cells.

_

Accessing cells (the pain of parallel programs)

Cells live in the local_cells member of a grid, which is of object type chi_mesh::MeshContinuum::LocalCells, under the auspices of either native_cells or foreign_cells. Local cells are guaranteed to be fully defined (i.e. not ghost cells) whilst non-local cells are most likely to be ghost-cells. The fastest way to access a cell is by means of its local id

auto cell = grid->local_cells[cell_local_id];

The local_cells object also facilitates an iterator.

for (auto cell = grid->local_cells.begin();
cell != grid->local-cells.end();
++cell)
{//do stuff}

and also a range based iterator

for (auto& cell : grid->local_cells)
{ //do stuff}

Alternatively, a more expensive way to access a cell is by means of its global index via the grid's cells member. This member is a utility object that will search the native_cells and foreign_cells for the cell with the associated global id

auto cell = grid->cells[cell_global_id];

Because of the search operation it is not recommended to repeatedly access cells by their global ids.

Figure 3: Cell mapping logic.