61 template<
class StringType>
65 const std::size_t minElements
71 if (
split.size() >= minElements)
76 if (
split.size() > minElements)
98 const auto pos = line.find(
'#');
99 if (
pos != std::string::npos)
105 while (
line.empty() && is.good());
107 return !
line.empty();
113 const word& expected,
114 const string& buffer,
122 if (!expected.empty() && !buffer.
starts_with(expected))
125 <<
"Expected section header '" << expected
126 <<
"' but read " << buffer <<
nl 131 <<
"Read section header: " << buffer.c_str() <<
nl;
137 const word& expected,
142 readLine(is, buffer);
144 checkSection(expected, buffer, is);
174 idHandling.
first() = idTypes::IGNORE;
178 idHandling.
first() = idTypes::GIVEN;
187 idHandling.
second() = idTypes::IGNORE;
191 idHandling.
second() = idTypes::GIVEN;
232 enum ParseSection { UNKNOWN, FORMAT, GEOMETRY, VARIABLE, TIME, FILE };
237 <<
"Cannot read file " << is.
name()
242 SubStrings<string>
split;
244 ParseSection parseState = ParseSection::UNKNOWN;
249 debugSection(
"FORMAT", is);
250 readLine(is, buffer);
251 parseState = ParseSection::FORMAT;
255 debugSection(
"GEOMETRY", is);
256 parseState = ParseSection::GEOMETRY;
260 readLine(is, buffer);
262 if (buffer.starts_with(
"VARIABLE"))
264 parseState = ParseSection::VARIABLE;
268 if (buffer.contains(
"change_coords_only"))
271 <<
"No support for moving points, only topology change" <<
nl 284 const auto pos_colon = buffer.find(
':');
288 (pos_colon == std::string::npos)
292 <<
"Error reading geometry 'model:'" <<
nl 301 <<
"Error reading geometry 'model:'" <<
nl 314 if (parseState != ParseSection::VARIABLE)
316 debugSection(
"VARIABLE", is);
317 parseState = ParseSection::VARIABLE;
321 DynamicList<labelPair> dynFieldTimesets(16);
322 DynamicList<word> dynFieldNames(16);
323 DynamicList<string> dynFieldFileNames(16);
330 readLine(is, buffer);
332 if (buffer.starts_with(
"TIME"))
334 parseState = ParseSection::TIME;
344 const auto pos_colon = buffer.find(
':');
346 if (pos_colon == std::string::npos)
348 DebugInfo<<
"ignore variable line: " << buffer <<
nl;
356 if (
split.size() < 2)
359 <<
"Error reading field file name, variable line: " 364 auto pos_key = buffer.find(
"element");
365 if ((pos_key == std::string::npos) || (pos_colon < pos_key))
367 DebugInfo<<
"ignore variable line: " << buffer <<
nl;
376 dynFieldNames.push_back(
split[
split.size()-2].str());
377 dynFieldFileNames.push_back(
split[
split.size()-1].str());
379 fieldTimesets_.transfer(dynFieldTimesets);
380 fieldNames_.transfer(dynFieldNames);
381 fieldFileNames_.transfer(dynFieldFileNames);
384 <<
"fieldNames: " << fieldNames_ <<
nl 385 <<
"fieldFileNames: " << fieldFileNames_ <<
nl;
388 if (parseState != ParseSection::TIME)
391 <<
"Did not find section header 'TIME'" <<
nl 401 expectTimeset.
insert(meshTimeset_.first());
402 expectFileset.insert(meshTimeset_.second());
404 for (
const auto& tup : fieldTimesets_)
406 expectTimeset.insert(tup.first());
407 expectFileset.insert(tup.second());
411 expectTimeset.erase(-1);
412 expectFileset.erase(-1);
416 <<
"expect timesets: " <<
flatOutput(expectTimeset) <<
nl 417 <<
"expect filesets: " <<
flatOutput(expectFileset) <<
nl;
455 readLine(is, buffer);
461 readLine(is, buffer);
463 readFrom(
split.back(), nTimes);
472 readLine(is, buffer);
473 auto pos_colon = buffer.find(
':');
475 if (buffer.contains(
"numbers:"))
480 fileNumbers_.resize_nocopy(nTimes);
483 while (numRead < nTimes)
485 for (
const auto& chunk :
split)
487 std::string str(chunk.str());
492 <<
"Could not parse label: " << str <<
nl 497 if (numRead == nTimes)
504 if (numRead < nTimes)
506 readLine(is, buffer);
513 fileNumbers_.resize(numRead);
519 readFrom(
split.back(), timeStartIndex_);
522 readLine(is, buffer);
524 readFrom(
split.back(), timeIncrement_);
526 fileNumbers_.clear();
530 <<
"nTimes: " << nTimes
531 <<
" start-index: " << timeStartIndex_
532 <<
" increment: " << timeIncrement_
537 readLine(is, buffer);
541 const auto pos_colon = buffer.find(
':');
542 const auto pos_key = buffer.find(
"values");
546 (pos_colon == std::string::npos)
547 || (pos_key == std::string::npos) || (pos_colon < pos_key)
558 timeValues_.resize_nocopy(nTimes);
561 while (numRead < nTimes)
563 for (
const auto& chunk :
split)
565 auto& inst = timeValues_[numRead];
568 inst.name() = word(chunk.str());
570 if (!Foam::readScalar(inst.name(), inst.value()))
573 <<
"Could not parse scalar: " << inst.name() <<
nl 578 if (numRead == nTimes)
585 if (numRead < nTimes)
587 readLine(is, buffer);
592 timeValues_.resize(numRead);
617 && options.getOrDefault(
"masterOnly", false)
620 baseDir_(fName.
path()),
659 const fileName& geometryFile,
667 ensightReadFile is(geometryFile);
670 readFormat_ = is.format();
676 <<
"File: " << is.name()
680 Pair<idTypes> idHandling = readGeometryHeader(is);
688 if (idHandling.first() == idTypes::GIVEN)
691 <<
"Treating node id 'given' as being 'ignore'" <<
nl 692 <<
"If something fails, this could be the reason" <<
nl 695 idHandling.first() = idTypes::IGNORE;
698 if (idHandling.first() == idTypes::IGNORE)
701 <<
"Ignore " <<
nPoints <<
" node ids" <<
nl;
712 DynamicList<face> dynFaces(
nPoints/3);
713 DynamicList<faceInfoTuple> faceTypeInfo(16);
726 else if (buffer.contains(
"BEGIN TIME STEP"))
731 else if (buffer.contains(
"END TIME STEP"))
746 faceTypeInfo.emplace_back
748 ensightFaces::elemType::TRIA3,
760 idHandling.second() == idTypes::IGNORE
761 || idHandling.second() == idTypes::GIVEN
765 <<
"Ignore " << elemCount <<
" element ids" <<
nl;
768 is.skip<label>(elemCount);
772 const label startElemi = dynFaces.size();
773 dynFaces.resize(startElemi+elemCount, face(3));
776 for (
auto&
f : myElements)
793 faceTypeInfo.emplace_back
795 ensightFaces::elemType::QUAD4,
807 idHandling.second() == idTypes::IGNORE
808 || idHandling.second() == idTypes::GIVEN
812 <<
"Ignore " << elemCount <<
" element ids" <<
nl;
815 is.skip<label>(elemCount);
819 const label startElemi = dynFaces.size();
820 dynFaces.resize(startElemi + elemCount, face(4));
823 for (
auto&
f : myElements)
840 faceTypeInfo.emplace_back
842 ensightFaces::elemType::NSIDED,
849 <<
"> count: " << elemCount <<
nl;
853 idHandling.second() == idTypes::IGNORE
854 || idHandling.second() == idTypes::GIVEN
858 <<
"Ignore " << elemCount <<
" element ids" <<
nl;
861 is.skip<label>(elemCount);
865 const label startElemi = dynFaces.size();
866 dynFaces.resize(startElemi + elemCount);
869 for (
auto&
f : myElements)
877 for (
auto&
f : myElements)
890 <<
"Unknown face type: <" << buffer.c_str()
891 <<
">. Stopping read and continuing with current " 892 <<
"elements only" <<
endl;
899 for (
auto&
f : dynFaces)
907 faceTypeInfo_.transfer(faceTypeInfo);
908 faceList faces(std::move(dynFaces));
911 <<
"read nFaces: " << faces.size() <<
nl 912 <<
"file schema: " << faceTypeInfo_ <<
nl;
929 auto& surf = *surfPtr_;
939 surf = readGeometry(geomFile,
timeIndex);
971 const label fieldIndex,
972 const scalar& refValue
975 return readField<scalar>(
timeIndex, fieldIndex);
982 const label fieldIndex,
986 return readField<vector>(
timeIndex, fieldIndex);
994 const label fieldIndex,
998 return readField<sphericalTensor>(
timeIndex, fieldIndex);
1005 const label fieldIndex,
1009 return readField<symmTensor>(
timeIndex, fieldIndex);
1016 const label fieldIndex,
1020 return readField<tensor>(
timeIndex, fieldIndex);
const T & first() const noexcept
Access the first element.
virtual wordList fieldNames(const label timeIndex) const
Return a list of the available fields at a given time.
virtual Istream & read(char *buf, std::streamsize count) override
Binary read.
static std::string::size_type length(const char *s)
Length of the character sequence (with nullptr protection)
A class for handling file names.
bool contains(char c) const noexcept
True if string contains given character (cf. C++23)
errorManipArg< error, int > exit(error &err, const int errNo=1)
static const char * elemNames[nTypes]
The ensight 'Face' element type names.
static labelPair extractTimeset(const SubStrings< StringType > &split, const std::size_t minElements)
void resize(const label len)
Adjust allocated size of list.
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
static StringType expand_mask(const StringType &input, const label index)
Replace the '*' mask chars with zero-padded integer value.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
instantList timeValues_
Times.
static bool readLine(ISstream &is, std::string &line)
Helper function to read an ascii line from file, skipping blank lines and comments.
virtual tmp< Field< scalar > > field(const label timeIndex, const label fieldIndex, const scalar &refValue=pTraits< scalar >::zero) const
Return a scalar field at a given time.
void reset(const char *buffer, size_t nbytes)
Reset input area, position to buffer start and clear errors.
constexpr char nl
The newline '\n' character (0x0a)
static const Enum< streamFormat > formatNames
Stream format names (ascii, binary)
void skip(label n=1)
Read and discard specified number of elements.
List< string > fieldFileNames_
Field file names.
Ostream & endl(Ostream &os)
Add newline and flush stream.
static bool & parRun() noexcept
Test if this a parallel run.
bool masterOnly_
Read on master and broadcast (in parallel)
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
List< word > fieldNames_
Field names.
A simple container for options an IOstream can normally have.
SubList< face > subList
Declare type of subList.
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
static void debugSection(const word &expected, ISstream &is)
Read and check a section header.
Sub-ranges of a string with a structure similar to std::match_results, but without the underlying reg...
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Macros for easy insertion into run-time selection tables.
static void broadcast(Type &value, const label comm=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all communicator ranks. Does nothing in non-paral...
fileName meshFileName_
Name of mesh file, including any subdirectory.
static void checkSection(const word &expected, const string &buffer, const ISstream &is)
Check a section header.
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
List< face > faceList
List of faces.
dimensionedScalar pos(const dimensionedScalar &ds)
void inplaceTrimRight(std::string &s)
Trim trailing whitespace inplace.
vectorField pointField
pointField is a vectorField.
A class for handling words, derived from Foam::string.
MeshedSurface< face > meshedSurface
#define DebugInFunction
Report an information message using Foam::Info.
A variant of IFstream with specialised handling for Ensight reading of strings, integers and floats (...
virtual const fileName & name() const override
The name of the input serial stream. (eg, the name of the Fstream file name)
#define DebugInfo
Report an information message using Foam::Info.
label timeStartIndex_
Start time index.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
int debug
Static debugging option.
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
label timeIncrement_
Time increment.
defineTypeNameAndDebug(combustionModel, 0)
static void broadcasts(const label comm, Type &arg1, Args &&... args)
Broadcast multiple items to all communicator ranks. Does nothing in non-parallel. ...
List< labelPair > fieldTimesets_
The timeset/fileset (if any) associated with fields.
virtual instantList times() const
Return a list of the available times.
static bool split(const std::string &line, std::string &key, std::string &val)
bool starts_with(char c) const
True if string starts with given character (cf. C++20)
Generic input stream using a standard (STL) stream.
#define WarningInFunction
Report a warning using Foam::Warning.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
bool good() const noexcept
True if next operation might succeed.
virtual const meshedSurface & geometry(const label timeIndex)
Return a reference to the surface geometry.
Pair< idTypes > readGeometryHeader(ensightReadFile &is) const
Read (and discard) geometry file header.
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
labelList fileNumbers_
Numbers for files.
void readCase(ISstream &is)
Read the case file.
labelPair meshTimeset_
The timeset/fileset (if any) associated with the mesh.
ensightSurfaceReader(const ensightSurfaceReader &)=delete
No copy construct.
Foam::SubStrings< StringType > splitSpace(const StringType &str, std::string::size_type pos=0)
Split string into sub-strings at whitespace (TAB, NL, VT, FF, CR, SPC)
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
A class for managing temporary objects.
const T & second() const noexcept
Access the second element.
Tensor of scalars, i.e. Tensor<scalar>.
Abstract base class for surface readers with fields.
Similar to IStringStream but using an externally managed buffer for its input. This allows the input ...
Inter-processor communications stream.
meshedSurface readGeometry(const fileName &geometryFile, const label timeIndex=0)
Read and return surface geometry. Updates faceTypeInfo_.
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...