Mesh

You can specify simple geometries using FEniCS DOLFIN built in mesh generators, and also load a mesh from file. For realistic cases using something like gmsh to generate meshes is recommended. The meshio program can be used to convert between different mesh file formats and also loading these formats directly, see below.

Simple geometries

Example: 2D rectangle

mesh:
    type: Rectangle
    Nx: 64
    Ny: 64
    diagonal: left/right  # defaults to 'right'
    startx: 0             # defaults to 0
    endx:   2             # defaults to 1
    # you can also give starty and endy

Example: 3D box

mesh:
    type: Box
    Nx: 64
    Ny: 64
    Nz: 15
    startx: 0  # defaults to 0
    endx:   2  # defaults to 1
    # you can also give starty and endy, startz and endz

Example: 2D disc

mesh:
    type: UnitDisc
    N: 20
    degree: 1  # defaults to 1 (degree of mesh elements)
startx, starty, startz, endx, endy, endz

Geometry descriptions for the simple geometries. Defaults coordinate ranges are [0, 1] in each direction.

Nx, Ny, Nz, N

The number of mesh cells in each direction. N is used for the radial direction for UnitDisc meshes.

degree

Mesh cell degree. Using higher order (order 2) will be slower to assemble, the default is order 1 (facets are straight lines or flat planes).

diagonal

The same options as accepted by FEniCS dolfin mesh generators: right, left, crossed, right/left, left/right. This controls how squares are split into triangles in 2D.

Mesh file formats

Example: using meshio to load all its supported formats (RECOMMENDED)

mesh:
    type: meshio
    mesh_file: mesh.msh
    meshio_type: gmsh

The supported format specifiers in meshio as of January 2019 are (from the meshio source code on github): ansys, ansys-ascii, ansys-binary, gmsh, gmsh-ascii, gmsh-binary, gmsh2, gmsh2-ascii, gmsh2-binary, gmsh4, gmsh4-ascii, gmsh4-binary, med, medit, dolfin-xml, permas, moab, off, stl, stl-ascii, stl-binary, vtu-ascii, vtu-binary, vtk-ascii, vtk-binary, xdmf, exodus, abaqus, mdpa.

Example: legacy DOLFIN XML format

mesh:
    type: XML
    mesh_file: mesh.xml
    facet_region_file: regions.xml  # not required

Ocellaris will look for the xml files first as absolute paths, then as paths relative to the current working directory and last as paths relative to the directory of the input file. If it cannot find the file in any of these places you will get an error message and Ocellaris will quit.

A sample mesh xml file and facet marker file is included in the demo/files directory. The mesh ocellaris_mesh.xml.gz and the facet regions ocellaris_facet_regions.xml.gz. You can load these files without unzipping them. The flow around Ocellaris demo shows how it is done.

Example: XDMF format

mesh:
    type: XDMF
    mesh_file: mesh.xdmf

Example: Ocellaris HDF5 restart file format

mesh:
    type: HDF5
    mesh_file: ocellaris_savepoint000010.h5

This will only load the mesh and (possibly) facet regions. You can also start the simulation from a restart file instead of an input file. Then the mesh and the function values from that save point are used, allowing you to restart the simulation more or less like it was never stopped.

Moving the mesh

Ocellaris can move the mesh right after it has been created or read from file. To move the mesh in order to refine, skew, scale, rotate or translate it you must specify a C++ description of the mesh displacement from the initial position (which was specified in the input file or in the loaded mesh file).

An example is the following 140 meter long 2D wave tank which is 10 m high. To refine the mesh in the y-direction such that it is finest around x[1] = 7 meters—where the free surface is to be located—a function is specified which is zero on the boundaries (to avoid changing the domain size) and non-zero in the interior in order to move the nodes closer to the free surface. No’ refinement is performed in the x-direction (x[0]).

mesh:
    type: Rectangle
    Nx: 140
    Ny: 20
    endx: 140
    endy: 20
    move: ['0', '0.0297619048*pow(x[1], 3) - 0.520833333*pow(x[1], 2) + 2.23214286*x[1] + 3.55271368e-15']

In order to develop and check the mesh refinement function it can be beneficial to generate and plot it, e.g., using matplotlib in jupyter or using similar interactive tools. The above refinement was developed using polynomial fitting in numpy:

from matplotlib import pyplot
import numpy

# Find a polynomial that refines the mesh
y_target = [0, 4, 7.5, 10]
dy_target = [0, 2.5, 0, 0]  # zero at the boundary
P = numpy.polyfit(y_target, dy_target, 3)

# Realise the polynomial
y = numpy.linspace(0, 10, 20)
dy = numpy.polyval(P, y)

# Plot the results
for ypos in (y + dy):
    pyplot.plot([0, 1], [ypos, ypos], '-k', lw=1)
pyplot.axhline(7, c='b', ls=':')
pyplot.axhline(6, c='b', ls=':', lw=1)
pyplot.axhline(8, c='b', ls=':', lw=1)

print('%.9g*pow(x[1], 3) + %.10g*pow(x[1], 2) + %.10g*x[1] + %.10g' % tuple(P))

For more complicated meshes it is recommended to perform mesh grading and other mesh operation in an external mesh generator such as gmsh.

There is also some (not much used, hence possibly buggy) support for ALE where the mesh moves every timestep, but that is not covered by the mesh section of the input file.