From 1b017938c30ddc83e69ff5a1efc9d9b69e0db1ae Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Mon, 2 Dec 2019 09:42:52 +0100 Subject: [PATCH] ENH: be more forgiving when reading ensight surface files (#1511) - The case files may contain #... comment lines - The geometry file may contain an optional "extents" entry - Properly handle element id specifications (off|assign|ignore|given). - Partially handle node id specifications (off|assign|ignore|given). Treat "given" like "ignore", since results in the lightest amount of coding and in many cases the "given" node ids are in fact 1-based contiguous values and thus no different than "ignore" for our purposes. --- .../readers/ensight/ensightSurfaceReader.C | 176 +++++++++++++++--- .../readers/ensight/ensightSurfaceReader.H | 16 +- 2 files changed, 161 insertions(+), 31 deletions(-) diff --git a/src/sampling/sampledSurface/readers/ensight/ensightSurfaceReader.C b/src/sampling/sampledSurface/readers/ensight/ensightSurfaceReader.C index ce95050bfaf..eefcf1d2835 100644 --- a/src/sampling/sampledSurface/readers/ensight/ensightSurfaceReader.C +++ b/src/sampling/sampledSurface/readers/ensight/ensightSurfaceReader.C @@ -37,6 +37,29 @@ namespace Foam } +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Read and discard specified number of elements +template<class Type> +static inline void discard(label n, ensightReadFile& is) +{ + Type val; + + while (n > 0) + { + is.read(val); + --n; + } +} + +} // End namespace Foam + + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + void Foam::ensightSurfaceReader::skip(const label n, Istream& is) const { label i = 0; @@ -53,20 +76,28 @@ void Foam::ensightSurfaceReader::skip(const label n, Istream& is) const if (i != n) { WarningInFunction - << "Requested to skip " << n << "tokens, but stream exited after " + << "Requested to skip " << n << " tokens, but stream exited after " << i << " tokens. Last token read: " << tok << nl; } } -void Foam::ensightSurfaceReader::readLine(IFstream& is, string& buffer) const +void Foam::ensightSurfaceReader::readLine(IFstream& is, string& line) const { - buffer.clear(); - while (is.good() && buffer.empty()) + do { - is.getLine(buffer); + is.getLine(line); + + // Trim out any '#' comments + const auto pos = line.find('#'); + if (pos != std::string::npos) + { + line.erase(pos); + } + stringOps::inplaceTrimRight(line); } + while (line.empty() && is.good()); } @@ -83,7 +114,7 @@ void Foam::ensightSurfaceReader::debugSection { FatalIOErrorInFunction(is) << "Expected section header '" << expected - << "' but read the word '" << actual << "'" + << "' but read " << actual << nl << exit(FatalIOError); } @@ -92,13 +123,16 @@ void Foam::ensightSurfaceReader::debugSection } -void Foam::ensightSurfaceReader::readGeometryHeader(ensightReadFile& is) const +Foam::Pair<Foam::ensightSurfaceReader::idTypes> +Foam::ensightSurfaceReader::readGeometryHeader(ensightReadFile& is) const { // Binary flag string if applicable is.readBinaryHeader(); string buffer; + Pair<idTypes> idHandling(idTypes::NONE, idTypes::NONE); + // Ensight Geometry File is.read(buffer); DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl; @@ -107,30 +141,63 @@ void Foam::ensightSurfaceReader::readGeometryHeader(ensightReadFile& is) const is.read(buffer); DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl; - // Node info + // "node id (off|assign|given|ignore)" - "given" is not actually supported is.read(buffer); DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl; - // Element info + if (buffer.find("ignore") != std::string::npos) + { + idHandling.first() = idTypes::IGNORE; + } + else if (buffer.find("given") != std::string::npos) + { + idHandling.first() = idTypes::GIVEN; + } + + // "element id (off|assign|given|ignore)" is.read(buffer); DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl; - // Part + if (buffer.find("ignore") != std::string::npos) + { + idHandling.second() = idTypes::IGNORE; + } + else if (buffer.find("given") != std::string::npos) + { + idHandling.second() = idTypes::GIVEN; + } + + + // "part" - but could also be an optional "extents" is.read(buffer); DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl; - // Part number - label ibuffer; - is.read(ibuffer); - DebugInfo<< "ibuffer: " << ibuffer << nl; + if (buffer.find("extents") != std::string::npos) + { + // Optional extents - read and discard 6 floats + // (xmin, xmax, ymin, ymax, zmin, zmax) + + discard<scalar>(6, is); + + // Part + is.read(buffer); + DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl; + } + + // The part number + label ivalue; + is.read(ivalue); + DebugInfo<< "ivalue: " << ivalue << nl; - // Description - 2 + // Part description / name is.read(buffer); DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl; - // Coordinates + // "coordinates" is.read(buffer); DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl; + + return idHandling; } @@ -166,8 +233,8 @@ void Foam::ensightSurfaceReader::readCase(IFstream& is) debugSection("VARIABLE", is); // Read the field description - DynamicList<word> fieldNames(10); - DynamicList<string> fieldFileNames(10); + DynamicList<word> fieldNames(16); + DynamicList<string> fieldFileNames(16); while (is.good()) { @@ -228,7 +295,7 @@ void Foam::ensightSurfaceReader::readCase(IFstream& is) // Read the time values readLine(is, buffer); // time values: timeValues_.setSize(nTimeSteps_); - for (label i = 0; i < nTimeSteps_; i++) + for (label i = 0; i < nTimeSteps_; ++i) { scalar t(readScalar(is)); @@ -329,7 +396,7 @@ const Foam::meshedSurface& Foam::ensightSurfaceReader::geometry() DebugInfo << "File: " << is.name() << nl; - readGeometryHeader(is); + Pair<idTypes> idHandling = readGeometryHeader(is); label nPoints; is.read(nPoints); @@ -337,17 +404,31 @@ const Foam::meshedSurface& Foam::ensightSurfaceReader::geometry() DebugInfo << "nPoints: " << nPoints << nl; + if (idHandling.first() == idTypes::GIVEN) + { + WarningInFunction + << "Treating node id 'given' as being 'ignore'" << nl + << "If something fails, this could be the reason" << nl + << endl; + + idHandling.first() = idTypes::IGNORE; + } + + if (idHandling.first() == idTypes::IGNORE) + { + DebugInfo + << "Ignore " << nPoints << " node ids" << nl; + + // Read and discard labels + discard<label>(nPoints, is); + } + pointField points(nPoints); + for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt) { - scalarField x(nPoints); - for (label dir = 0; dir < 3; dir++) + for (point& pt : points) { - forAll(points, pointI) - { - is.read(x[pointI]); - } - - points.replace(dir, x); + is.read(pt[cmpt]); } } @@ -375,6 +456,19 @@ const Foam::meshedSurface& Foam::ensightSurfaceReader::geometry() << "faceType <" << faceType.c_str() << "> count: " << nFace << nl; + if + ( + idHandling.second() == idTypes::IGNORE + || idHandling.second() == idTypes::GIVEN + ) + { + DebugInfo + << "Ignore " << nFace << " element ids" << nl; + + // Read and discard labels + discard<label>(nFace, is); + } + face f(3); for (label facei = 0; facei < nFace; ++facei) { @@ -394,6 +488,19 @@ const Foam::meshedSurface& Foam::ensightSurfaceReader::geometry() << "faceType <" << faceType.c_str() << "> count: " << nFace << nl; + if + ( + idHandling.second() == idTypes::IGNORE + || idHandling.second() == idTypes::GIVEN + ) + { + DebugInfo + << "Ignore " << nFace << " element ids" << nl; + + // Read and discard labels + discard<label>(nFace, is); + } + face f(4); for (label facei = 0; facei < nFace; ++facei) { @@ -413,6 +520,19 @@ const Foam::meshedSurface& Foam::ensightSurfaceReader::geometry() << "faceType <" << faceType.c_str() << "> count: " << nFace << nl; + if + ( + idHandling.second() == idTypes::IGNORE + || idHandling.second() == idTypes::GIVEN + ) + { + DebugInfo + << "Ignore " << nFace << " element ids" << nl; + + // Read and discard labels + discard<label>(nFace, is); + } + labelList np(nFace); for (label facei = 0; facei < nFace; ++facei) { diff --git a/src/sampling/sampledSurface/readers/ensight/ensightSurfaceReader.H b/src/sampling/sampledSurface/readers/ensight/ensightSurfaceReader.H index 376fda35141..5b30eceebde 100644 --- a/src/sampling/sampledSurface/readers/ensight/ensightSurfaceReader.H +++ b/src/sampling/sampledSurface/readers/ensight/ensightSurfaceReader.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2015-2016 OpenCFD Ltd. + Copyright (C) 2015-2019 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -40,6 +40,7 @@ SourceFiles #include "surfaceReader.H" #include "ensightReadFile.H" #include "StringStream.H" +#include "Pair.H" #include "Tuple2.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -59,6 +60,14 @@ protected: // Protected Data + //- Handling of node/element id types (off, assign, ignore, given) + enum idTypes : unsigned char + { + NONE = 0, //!< "off", "assign" + IGNORE = 1, //!< Read but "ignore" + GIVEN = 2 //!< Use "given" values (not supported) + }; + //- Format flag IOstream::streamFormat streamFormat_; @@ -103,8 +112,9 @@ protected: //- Read and check a section header void debugSection(const word& expected, IFstream& is) const; - //- Read (and throw away) geometry file header - void readGeometryHeader(ensightReadFile& is) const; + //- Read (and discard) geometry file header. + // \return information about node/element id handling + Pair<idTypes> readGeometryHeader(ensightReadFile& is) const; //- Read the case file void readCase(IFstream& is); -- GitLab