OpenFOAM® v1912: New and improved pre-processing


New expressions syntax

OpenFOAM-v1912 now implements expressions, which use ideas pioneered by swak4Foam (Bernhard Gschaider). By expressions we mean the processing of string-like input as mathematical or field evaluations within OpenFOAM. This addition permeates various parts of OpenFOAM i.e. dictionary syntax, string evaluations, boundary conditions, set fields, and can be expected to grow in the future.

For example, the expressions make it possible to embed mathematical evaluation into regular string expansions:

#include "<system>/sampling${{ round(${flowRate:-5} * 100) }}";

At its core the expressions functionality uses:

Source code

Inline expressions in dictionaries

A major change for dictionary input is provided by the new #eval directive, which is associated with the addition of expressions. In many case it can directly replace #calc for a significant gain in speed. As a comparison, 10 evaluations of the following reported a time of 16 seconds for #calc versus only 0.02 seconds for #eval.

This capability will change the way you view dictionaries.

kgh     700;
split   0.4;

    type            flowRateInletVelocity;
    massFlowRate    constant #eval{ $split * $kgh / 3600 };

    type            flowRateInletVelocity;
    massFlowRate    constant #eval{ (1-$split) * $kgh / 3600 };
Further examples are provided in the v1912 User Upgrade Guide

Source code
All tutorials that previously used #calc now use #eval.

New expressions-based setFields utility

The expressions support the new utilities setExprFields and setExprBoundaryFields, which serve a similar purpose to the swak4Foam funky utilities of similar names.

Instead of using shapes and selection to set the fields, the setExprFields uses the combination of a condition and an expression. Only when the condition is valid will the result of the expression be applied. For example, the following will adjust the temperature within the defined zone:

        field       T;
        dimensions  [0 0 0 1 0 0 0];

            centre (0.21 0 0.01);

            "radius = 0.1"

            // Within the radius
            (mag(pos() - $[(vector)constants.centre]) < radius)

            // but only +ve y!
          && bool(pos((pos() - $[(vector)constants.centre]).y()))

          + 200 * (1 - mag(pos() - $[(vector)constants.centre]) / radius)

The setExprBoundaryFields utility serves a similar purpose for custom modification of boundary field entries.


New set fields utility for PDRFoam

The new PDRsetFields utility computes the tensorial resistances of blockages for use by the PDRFoam solver. The geometry is input in the form of primitive shapes using a PDRsetFieldsDict file, taking the form:

// Data dictionary for PDRsetFields

// Replace by the relevant names

obsFileDir      "<case>/geometry";

obsFileNames    (obstaclesDict);

// legacyObsSpec   true;
// obsFileNames    (position.obs base.obs);
Obstacles are provided in separate files listed under the obsFileNames entry. Various obstacle types are supported, including:
  • cylinder
  • diagonal beam
  • cuboid
  • grating
  • louvre
  • patch

An example set of obstacles is shown below:

PDRsetFields obstacles example

Source code

Wall distance output from checkMesh

The checkMesh utility option -writeAllFields has been extended to write the wall distance as a field wallDistance. It requir es the wall distance method to have been selected in system/fvSchemes dictionary:

    method meshWave;
The wallDistance is set to SMALL (1e-15) on the wall patches, and can be post processed in e.g.paraFoam:


Source code

snappyHexMesh : automatic closure of thin gaps

In meshing complicated geometries there might be thin gaps where the user does not want a mesh. In this release snappyHexMesh allows a per-surface, per-surface-region specification of a blockLevel which specifies the minimum size of a gap to mesh. Any cell inside a gap smaller than this indicated size gets deleted (and consequently there will be no cells in the gap).

The extension is enabled using the following syntax:

        // Surface-wise min and max refinement level
        level       (2 2);

        // From cell level 2 onwards start checking
        // for opposite surfaces
        blockLevel  2;

The blockLevel setting determines

  • whether the surface is used at all in the gap detection
  • an idealised size of the gap: 2 * cellsize; where cellsize is determined from the initial cell size refined blockLevel times

After all surface refinement snappyHexMesh but before any shell/volume refinement, determine for all cells the nearest two surfaces. If the cell is

  • in between two surfaces, or disconnected regions of the same surface
  • and the distance between the opposite points is less than the gap size

the cell will get deleted.

The tutorial opposite_walls is a simple block with two surfaces that form a thin gap.