Skip to content

Feature mixed precision

Mark OLESEN requested to merge feature-mixedPrecision into develop

This set of changes makes it easier to identify and manage binary reading from different representations. For example, a binary file written from an OpenFOAM installation with WM_SP, WM_LABEL_SIZE=32 can be read back as WM_DP and/or WM_LABEL_SIZE=64. This is managed internally by using the "arch" information that is included in the binary output files. For example,

FoamFile
{
    version     2.0;
    format      binary;
    class       vectorField;
    arch        "LSB;label=32;scalar=64";
    location    "constant/polyMesh";
    object      points;
}

On reading, the size information is used to determine if the label/scalar sizes in the file correspond to the native version of the currently active OpenFOAM installation. If the values are identical, the binary file reading is as always. If, however, there is a discrepancy between the label/scalar sizes in the file and the current OpenFOAM sizes, the values will be read in the raw format and converted on-the-fly. This adds no additional memory overhead, but can potentially result in somewhat lower reading speeds. There are some additional operations when narrowing the representation (eg, reading in double but saving as float) to avoid underflow and overflow, but it cannot work magic. If your input file has 1e10 faces, the addressing will not fit into a signed or unsigned 32-bit integer.

To manage the reading, the new trait structures is_contiguous, is_contiguous_label, is_contiguous_scalar are used. For data payloads that comprise homogenous base types (ie, the lowest level component is entirely scalar or label) the Detail::readContiguous is used for managing the reading in a uniform manner. For heterogeneous data types, the author of the class must address this individually. This is typically in the following form:

if (is.format() == IOstream::ASCII)
{
    is >> start_ >> end_ >> level_ >> i_ >> j_ >> k_;
}
else if (!is.checkLabelSize<>() || !is.checkScalarSize<>())
{
    // Non-native label or scalar size
    is.beginRawRead();

    readRawScalar(is, start_.data(), vector::nComponents);
    readRawScalar(is, end_.data(), vector::nComponents);
    readRawLabel(is, &level_);
    readRawLabel(is, &i_);
    readRawLabel(is, &j_);
    readRawLabel(is, &k_);

    is.endRawRead();
}
else
{
    is.read
    (
        reinterpret_cast<char*>(&start_),
        sizeofFields_
    );
}

Limitation

Changes in the endian type are not handled.

Edited by Mark OLESEN

Merge request reports