64 const std::size_t minElements
70 if (
split.size() >= minElements)
75 if (
split.size() > minElements)
97 const auto pos = line.find(
'#');
98 if (
pos != std::string::npos)
104 while (
line.empty() && is.good());
106 return !
line.empty();
112 const word& expected,
113 const string& buffer,
121 if (!expected.empty() && !buffer.
starts_with(expected))
124 <<
"Expected section header '" << expected
125 <<
"' but read " << buffer <<
nl 130 <<
"Read section header: " << buffer.c_str() <<
nl;
136 const word& expected,
141 readLine(is, buffer);
143 checkSection(expected, buffer, is);
173 idHandling.
first() = idTypes::IGNORE;
177 idHandling.
first() = idTypes::GIVEN;
186 idHandling.
second() = idTypes::IGNORE;
190 idHandling.
second() = idTypes::GIVEN;
231 enum ParseSection { UNKNOWN, FORMAT, GEOMETRY, VARIABLE, TIME, FILE };
236 <<
"Cannot read file " << is.
name()
243 ParseSection parseState = ParseSection::UNKNOWN;
248 debugSection(
"FORMAT", is);
249 readLine(is, buffer);
250 parseState = ParseSection::FORMAT;
254 debugSection(
"GEOMETRY", is);
255 parseState = ParseSection::GEOMETRY;
259 readLine(is, buffer);
261 if (buffer.starts_with(
"VARIABLE"))
263 parseState = ParseSection::VARIABLE;
267 if (buffer.contains(
"change_coords_only"))
270 <<
"No support for moving points, only topology change" <<
nl 283 const auto pos_colon = buffer.find(
':');
287 (pos_colon == std::string::npos)
291 <<
"Error reading geometry 'model:'" <<
nl 300 <<
"Error reading geometry 'model:'" <<
nl 313 if (parseState != ParseSection::VARIABLE)
315 debugSection(
"VARIABLE", is);
316 parseState = ParseSection::VARIABLE;
320 DynamicList<labelPair> dynFieldTimesets(16);
321 DynamicList<word> dynFieldNames(16);
322 DynamicList<string> dynFieldFileNames(16);
329 readLine(is, buffer);
331 if (buffer.starts_with(
"TIME"))
333 parseState = ParseSection::TIME;
343 const auto pos_colon = buffer.find(
':');
345 if (pos_colon == std::string::npos)
347 DebugInfo<<
"ignore variable line: " << buffer <<
nl;
355 if (
split.size() < 2)
358 <<
"Error reading field file name, variable line: " 363 auto pos_key = buffer.find(
"element");
364 if ((pos_key == std::string::npos) || (pos_colon < pos_key))
366 DebugInfo<<
"ignore variable line: " << buffer <<
nl;
375 dynFieldNames.push_back(
split[
split.size()-2].str());
376 dynFieldFileNames.push_back(
split[
split.size()-1].str());
378 fieldTimesets_.transfer(dynFieldTimesets);
379 fieldNames_.transfer(dynFieldNames);
380 fieldFileNames_.transfer(dynFieldFileNames);
383 <<
"fieldNames: " << fieldNames_ <<
nl 384 <<
"fieldFileNames: " << fieldFileNames_ <<
nl;
387 if (parseState != ParseSection::TIME)
390 <<
"Did not find section header 'TIME'" <<
nl 400 expectTimeset.
insert(meshTimeset_.first());
401 expectFileset.insert(meshTimeset_.second());
403 for (
const auto& tup : fieldTimesets_)
405 expectTimeset.insert(tup.first());
406 expectFileset.insert(tup.second());
410 expectTimeset.erase(-1);
411 expectFileset.erase(-1);
415 <<
"expect timesets: " <<
flatOutput(expectTimeset) <<
nl 416 <<
"expect filesets: " <<
flatOutput(expectFileset) <<
nl;
454 readLine(is, buffer);
460 readLine(is, buffer);
462 readFrom(
split.back(), nTimes);
471 readLine(is, buffer);
472 auto pos_colon = buffer.find(
':');
474 if (buffer.contains(
"numbers:"))
479 fileNumbers_.resize_nocopy(nTimes);
482 while (numRead < nTimes)
484 for (
const auto& chunk :
split)
486 std::string str(chunk.str());
491 <<
"Could not parse label: " << str <<
nl 496 if (numRead == nTimes)
503 if (numRead < nTimes)
505 readLine(is, buffer);
512 fileNumbers_.resize(numRead);
518 readFrom(
split.back(), timeStartIndex_);
521 readLine(is, buffer);
523 readFrom(
split.back(), timeIncrement_);
525 fileNumbers_.clear();
529 <<
"nTimes: " << nTimes
530 <<
" start-index: " << timeStartIndex_
531 <<
" increment: " << timeIncrement_
536 readLine(is, buffer);
540 const auto pos_colon = buffer.find(
':');
541 const auto pos_key = buffer.find(
"values");
545 (pos_colon == std::string::npos)
546 || (pos_key == std::string::npos) || (pos_colon < pos_key)
557 timeValues_.resize_nocopy(nTimes);
560 while (numRead < nTimes)
562 for (
const auto& chunk :
split)
564 auto& inst = timeValues_[numRead];
567 inst.name() = word(chunk.str());
569 if (!Foam::readScalar(inst.name(), inst.value()))
572 <<
"Could not parse scalar: " << inst.name() <<
nl 577 if (numRead == nTimes)
584 if (numRead < nTimes)
586 readLine(is, buffer);
591 timeValues_.resize(numRead);
616 && options.getOrDefault(
"masterOnly", false)
619 baseDir_(fName.
path()),
658 const fileName& geometryFile,
666 ensightReadFile is(geometryFile);
669 readFormat_ = is.format();
675 <<
"File: " << is.name()
679 Pair<idTypes> idHandling = readGeometryHeader(is);
687 if (idHandling.first() == idTypes::GIVEN)
690 <<
"Treating node id 'given' as being 'ignore'" <<
nl 691 <<
"If something fails, this could be the reason" <<
nl 694 idHandling.first() = idTypes::IGNORE;
697 if (idHandling.first() == idTypes::IGNORE)
700 <<
"Ignore " <<
nPoints <<
" node ids" <<
nl;
711 DynamicList<face> dynFaces(
nPoints/3);
712 DynamicList<faceInfoTuple> faceTypeInfo(16);
725 else if (buffer.contains(
"BEGIN TIME STEP"))
730 else if (buffer.contains(
"END TIME STEP"))
745 faceTypeInfo.emplace_back
747 ensightFaces::elemType::TRIA3,
759 idHandling.second() == idTypes::IGNORE
760 || idHandling.second() == idTypes::GIVEN
764 <<
"Ignore " << elemCount <<
" element ids" <<
nl;
767 is.skip<label>(elemCount);
771 const label startElemi = dynFaces.size();
772 dynFaces.resize(startElemi+elemCount, face(3));
775 for (
auto&
f : myElements)
792 faceTypeInfo.emplace_back
794 ensightFaces::elemType::QUAD4,
806 idHandling.second() == idTypes::IGNORE
807 || idHandling.second() == idTypes::GIVEN
811 <<
"Ignore " << elemCount <<
" element ids" <<
nl;
814 is.skip<label>(elemCount);
818 const label startElemi = dynFaces.size();
819 dynFaces.resize(startElemi + elemCount, face(4));
822 for (
auto&
f : myElements)
839 faceTypeInfo.emplace_back
841 ensightFaces::elemType::NSIDED,
848 <<
"> count: " << elemCount <<
nl;
852 idHandling.second() == idTypes::IGNORE
853 || idHandling.second() == idTypes::GIVEN
857 <<
"Ignore " << elemCount <<
" element ids" <<
nl;
860 is.skip<label>(elemCount);
864 const label startElemi = dynFaces.size();
865 dynFaces.resize(startElemi + elemCount);
868 for (
auto&
f : myElements)
876 for (
auto&
f : myElements)
889 <<
"Unknown face type: <" << buffer.c_str()
890 <<
">. Stopping read and continuing with current " 891 <<
"elements only" <<
endl;
898 for (
auto&
f : dynFaces)
906 faceTypeInfo_.transfer(faceTypeInfo);
907 faceList faces(std::move(dynFaces));
910 <<
"read nFaces: " << faces.size() <<
nl 911 <<
"file schema: " << faceTypeInfo_ <<
nl;
928 auto& surf = *surfPtr_;
938 surf = readGeometry(geomFile,
timeIndex);
970 const label fieldIndex,
971 const scalar& refValue
974 return readField<scalar>(
timeIndex, fieldIndex);
981 const label fieldIndex,
985 return readField<vector>(
timeIndex, fieldIndex);
993 const label fieldIndex,
997 return readField<sphericalTensor>(
timeIndex, fieldIndex);
1004 const label fieldIndex,
1008 return readField<symmTensor>(
timeIndex, fieldIndex);
1015 const label fieldIndex,
1019 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)
Foam::SubStrings splitSpace(const std::string &str, std::string::size_type pos=0)
Split string into sub-strings at whitespace (TAB, NL, VT, FF, CR, SPC)
static const char * elemNames[nTypes]
The ensight 'Face' element type names.
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 void broadcasts(const int communicator, Type &value, Args &&... values)
Broadcast multiple items to all communicator ranks. Does nothing in non-parallel. ...
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.
static labelPair extractTimeset(const SubStrings &split, const std::size_t minElements)
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.
void inplaceTrimRight(std::string &s)
Trim trailing whitespace inplace.
static void broadcast(Type &value, const int communicator=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all communicator ranks. Does nothing in non-paral...
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.
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)
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)
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.
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 ...