v2206: New and improved post-processing

Re-write of sampled sets

TOP

The very old writer class has been replaced with a new coordSetWriter class that uses similar concepts to the previously updated surface writers. Changes are largely transparent for the end-user, except that in some cases the output filenames for raw format will be slightly different.

Changes include:

  • Sample/write a field in a single step; this allows use of the writers for streaming operations.

  • Collect multiple field types, e.g. scalar, vector etc. into a single output. This is especially noticeable for VTK and Ensight formats where the number of generated files is reduced.

  • Direct writing of the raw format as unbuffered output, with a file layout consistent with the raw format for surface writers.

  • Support for sampleOnExecute to obtain values at execution intervals without writing. This allows internal sampling for use in functionObject controls without thrashing the disk with unnecessary IO operations.

  • Support sets input as a dictionary entry (as well as a list), similar to the changes for sampled-surface, and permits use of changeDictionary to modify content.

  • sampleSet results (properties) are now qualified with the name of the set, allowing multiple subsets to be addressed.

    This potentially represents a breaking change for some workflows, but corrects deficiencies in the the previous version. For example:

    sample1
    {
        scalar
        {
            average(line,T) 349.96521;
            min(line,T)     349.9544281;
            max(line,T)     350;
            average(cells,T) 349.9854619;
            min(cells,T)    349.6589286;
            max(cells,T)    350.4967271;
            average(line,epsilon) 0.04947733869;
            min(line,epsilon) 0.04449639927;
            max(line,epsilon) 0.06452856475;
        }
        label
        {
            size(line,T)    79;
            size(cells,T)   1720;
            size(line,epsilon) 79;
        }
    }

    Note: since values are scoped by the name of the set itself, e.g. average(line,T) for the average temperature of the 'line' set, existing workflows will break.

    Unqualified names now correspond to ensemble values of all the sub-sets. This means that if the existing workflow only had a single sub-set the net change will be non-breaking. It is, however, advisable to use the more precise specification to future-proof your workflow.

    average(p)    // Ensemble average of all listed sets
  • sampledSets have an additional special-purpose probes setFormat that collects all of the specified sampled location points into a single, aggregate ensemble output with a raw probed format.

    This can be useful when it is more convenient to specify probe locations in terms of arrays/lines instead of individual points.

Source code

Improved probes function object

TOP

Probes have an additional sampleOnExecute option which supports sampling/probing of values to obtain min/max/average/size at execution intervals without writing any output or generating output directories.

Source code

Improved sampled surfaces

TOP

Sampled surfaces have received multiple updates, including:

  • Removed support for sampling onto an internal surfMesh. This was a rarely used feature that was a stop-gap measure before the more flexible polySurface sample/storage was added (FEB-2019);

  • enhanced output for sampled surfaces; and

  • improved point merging.

The surface writers now support field scaling and geometric transformations. The fieldLevel is useful to add or remove a uniform shift prior to applying any fieldScale, e.g.:

fieldLevel
{
    "p.*"   1e5;        // Absolute -> gauge [Pa]
    T       273.15;     // [K] -> [C]
    U       #eval{ 10/sqrt(3) };  // Uniform mag(U)=10
}

After the fieldLevel has been removed, any fieldScale is applied, e.g.:

fieldScale
{
    "p.*"   0.01;       // [Pa] -> [mbar]
}

This is particularly useful to gain more output precision for pressure fields, e.g. when using EnSight-format which is intrinsically limited to single-precision.

The new optional transform entry allows the "relocation" of sampled surfaces. For example, to reposition into a different coordinate system for importing into CAD, e.g.:

formatOptions
{
    vtk
    {
        scale 1000;  // m -> mm
        transform
        {
            origin  (0.05 0 0);
            rotation axisAngle;
            axis    (0 0 1);
            angle   -45;
        }
    }
}

This will transform vector or tensor fields according to the geometric rotation.

Improved runTimeControl function object

TOP

The runTimeControl function object activates further function objects using triggers. Previously the trigger index could only advance; this change set allows users to set smaller values to enable function object recycling, e.g.

Repeat for N cycles:

  1. average the pressure at a point in space
  2. when the average stabilises, run for a further 100 iterations
  3. set a new patch inlet velocity
  4. back to (1)

This release also includes a none condition that acts as a pass-through/no-op with the option to set a new trigger value.

Tutorials

Source code

Improved multiFieldValue function object

TOP

The multiFieldValue function object now operates on any function object that generates result entries, removing the restriction of only using fieldValue-type function objects.

For example, it is now possible to average the results of surfaceFieldValue and valueAverage function objects as follows:

averagePressure
{
    type    multiFieldValue;
    libs    (fieldFunctionObjects);

    operation   average;

    functions
    {
        inlet
        {
            type            surfaceFieldValue;
            operation       areaAverage;
            regionType      patch;
            name            inlet;
            fields          (p);

            writeFields     no;
            writeToFile     no;
            log             no;
        }
        outlet
        {
            type            surfaceFieldValue;
            operation       areaAverage;
            regionType      patch;
            name            outlet;
            fields          (p);

            writeFields     no;
            writeToFile     no;
            log             no;
        }
        average 
        {
            type            valueAverage;
            functionObject  testSample1;
            fields          (average(p));
            writeToFile     no;
            log             no;
        }
    }
}

The output has also been updated for clarity:

  1 # Group0          
  2 #   - averagePressure:inlet:areaAverage(inlet,p)
  3 #   - averagePressure:outlet:areaAverage(outlet,p)
  4 #   - averagePressure:average:average(p)Mean
  5 # Operation       : add
  6 # Time              Group0            
  7 0.00120482          3.4483824485e+05
  8 0.00265769          3.0352523946e+05
  9 0.00439595          3.0338969991e+05

Additional groups are labelled Group1, Group2 ... GroupN etc.

Tutorials

Source code

Improved force and forceCoeffs function objects

TOP

The force and forces function objects have been refactored, to reduce code complexity and improve code maintenance. The binning functionality has been removed, and now available as a separate binField function object.

Users have more control when requesting force coefficients; previously, all contributions were written - these can now be selected using the optional 'coefficients' entry:

coefficients    (Cd Cl(f) Cl(r));

The full list of coefficients comprise:

  • Cd, Cd(f), Cd(r) : drag force, (front and rear)
  • Cs, Cs(f), Cs(r) : side force, (front and rear)
  • Cl, Cl(f), Cl(r) : lift force, (front and rear)
  • CmRoll : roll moment
  • CmPitch : pitch moment
  • CmYaw : yaw moment

If omitted, all coefficients will be written.

Tutorials

Source code

New binField function object

TOP

The new binField function object calculates binned data, where specified patches and cell zones are divided into segments to enable spatially-localised information to be output for each segment.

Two bin models are available:

  • singleDirectionUniformBin: calculates binned data in a specified direction; and
  • uniformBin: calculates binned data in multiple segments according to a specified Cartesian or cylindrical coordinate system.

Output variables include:

  • total: the sum of patch and internal
  • patch: patch data
  • internal: e.g. porous data from specified cell zones
  • normal and tangential: orthogonal components of the patch data

As an example, to recover the previous binning behaviour of the forceCoeffs function object:

forceCoeffs1
{
    type            forceCoeffs;
    libs            (forces);
    writeControl    writeTime;
    writeFields     true;

    patches         (body);
    p               p;
    U               U;
    rho             rhoInf;      // Indicates incompressible
    log             true;
    rhoInf          1;           // Required when rho = rhoInf
    liftDir         (0 1 0);
    dragDir         (1 0 0);
    CofR            (3.5 0 0);  // Axle midpoint on ground
    pitchAxis       (0 0 1);
    magUInf         10;
    lRef            4;          // Wheelbase length
    Aref            1;          // Estimated
    porosity        on;
}

binField1
{
    type                    binField;
    libs                    (fieldFunctionObjects);
    binModel                singleDirectionUniformBin;
    fields                  (forceCoeff);
    patches                 (body);
    decomposePatchValues    yes;
    CofR                    ${..forceCoeffs1.CofR};
    cellZones               (porousZone);

    binData
    {
        nBin        20;          // output data into 20 bins
        direction   (1 0 0);     // bin direction
        cumulative  yes;
    }
    writeControl            writeTime;
}

Tutorials

Source code

Improved Dynamic Mode Decomposition (DMD) tools

TOP

The Dynamic Mode Decomposition function object has been extended to enable users to specify multiple patches in DMD calculations:

DMD1
{
    // Optional entries

        // Option-1
        patch               <word>;

        // Option-2
        patches             (<wordRes>);
}

Performance has also been improved, whereby the most expensive parts of the STDMD implementation were identified and refactored, resulting in reduced run-times. For example, the timing of the standard "cylinder2D" tutorial, i.e. where all STDMD function objects are active, the duration of the parallel, 12-processor simulation, reduced by approximately 60%.

Source code

Tutorial

Merge request

New particleZoneInfo cloud function object

TOP

The new particleZoneInfo cloud function object generates statistics for particles crossing a cellZone. It is specified in the cloudFunctions sub-dictionary of the cloud properties file, e.g.:

cloudFunctions
{
    particleZoneInfo1
    {
        type            particleZoneInfo;
        cellZone        leftFluid;

        // Optional entries
        writer          vtk; // vtk, raw, none
    }
}

If the optional writer entry is supplied, cloud data is written in the specified format. Statistics generated include the particle:

  • index and its originating processor
  • time, diameter and mass when first entering the cellZone
  • current position, diameter and mass
  • time spent in the cellZone

During the run, the object writes after the cloud solution, e.g.:

particleZoneInfo:
    Cell zone                       = leftFluid
    Contributions                   = 257

Here, Contributions refers to the number of incremental particle-move contributions recorded during this time step. At write times, the output is extended, e.g.:

particleZoneInfo:
    Cell zone                       = leftFluid
    Contributions                   = 822
    Number of particles             = 199
    Written data to "postProcessing/lagrangian/reactingCloud1/particleZoneInfo1/0.7/particles.dat"

The particles.dat file contains the particle statistics, e.g.:

# cellZone        : leftFluid
# time            : 1.0000000000e+00
#
# origID            origProc    (x y z)    time0    age    d0    d    mass0    mass
2 0 (1.2403730063e+00 6.3907929681e-01 5.0000000000e-02) 5.0400000000e-01 5.0400000000e-01 1.0000000000e-03 9.9733169015e-04 5.2359877560e-07 5.1941857822e-07
3 0 (1.2294005030e+00 7.1626530229e-01 5.0000000000e-02) 5.0400000000e-01 5.0225000000e-01 1.0000000000e-03 9.9733162350e-04 5.2359877560e-07 5.1941847408e-07
4 0 (1.2265565036e+00 6.5308628366e-01 5.0000000000e-02) 5.0400000000e-01 5.0100000000e-01 1.0000000000e-03 9.9733541220e-04 5.2359877560e-07 5.1942439366e-07

Tutorials

Source code

Improved cloudInfo cloud function object

TOP

The cloudInfo is a simple cloud function object that reports some basic parcel information such as

  • number of parcels
  • mass in system
  • maximum diameter
  • D10 diameter
  • D32 diameter

It is now extended to support a restricted selection of parcels to analyse. The selection mechanism is identical to the vtkCloud function object, e.g.

selection
{
    all
    {
        action  all;
    }

    T
    {
        action  subset;
        source  field;
        field   T;
        accept  (greater 280) and (less 300);
    }

    Umin
    {
        action  subtract;
        source  field;
        field   U;
        accept  (less 0.1);
    }
}

Tutorials

Source code

New particle doses cloud function object

TOP

The new doses cloud function object calculates the dose absorbed by a particle as the time integral of the particle track along the radiation field G [w/m2].

The function object is specified as:

cloudFunctions
{
    ParticleDose1
    {
        type             ParticleDose;
        GName            G;
    }
}

Tutorials

Source code

New norm function object

TOP

The new norm function object normalises an input field with a chosen norm, and writes a new normalised field.

A minimal example usage follows:

norm1
{
    // Mandatory entries
    type            norm;
    libs            (fieldFunctionObjects);
    field           <word>;
    norm            <word>;

    // Conditional entries

        // when norm == Lp
        p               <scalar>;

        // when norm == composite
        divisor         <Function1<scalar>>;

        // when norm == divisorField
        divisorField    <word>;

    // Inherited entries
    ...
}

for which the following norm entries are available:

  • L1 : L1/Taxicab norm
  • L2 : L2/Euclidean norm
  • Lp : p norm
  • max : Maximum norm
  • composite : Composite norm comprising Function1 divisor
  • divisorField : Normalise by a given field

Source code

Tutorial

Merge request

Improved finite area support for foamToVTK and foamToEnsight

TOP

Finite-area fields are now detected and converted in both foamToEnsight and foamToVTK by default. If required, this can be suppressed with the -no-finite-area option; the old -finite-area option is now ignored.

The foamToEnsight and foamToVTK utilities have additional -exclude-fields and -no-fields options for more precise control over conversions.