mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: read support for EnSight single-file transient (#3154)
- the ensightReadFile init() now automatically sets up binary/ascii
(for geometry files) and checks for the transient "BEGIN TIME STEP"
marker. If found, will also populate the file offsets for each of
the timesteps. If no corresponding footer is found (which would be
very inefficient), it simply pretends that there is only a single
time step instead of performing a costly file scan.
- parsing of the ensight case file now also supports the use of
filename numbers:
as an alternative to
filename start number:
filename increment:
- improved parsing robustness of "time values:" entry.
Can now also have contents on the same line as the introducer.
ENH: base-level adjustments for writing transient single-file
- beginGeometry() is now separated out from file creation.
- in append mode, ensightFile and ensightGeoFile will attempt to
parse existing time-step information.
This commit is contained in:
committed by
Kutalmış Berçin
parent
ee895577ae
commit
dfc9a8923a
@ -1,3 +0,0 @@
|
|||||||
Test-ensightFile.C
|
|
||||||
|
|
||||||
EXE = $(FOAM_USER_APPBIN)/Test-ensightFile
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
EXE_INC = \
|
|
||||||
-I$(LIB_SRC)/fileFormats/lnInclude \
|
|
||||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
|
||||||
-I$(LIB_SRC)/conversion/lnInclude
|
|
||||||
|
|
||||||
EXE_LIBS = \
|
|
||||||
-lmeshTools \
|
|
||||||
-lconversion
|
|
||||||
3
applications/test/ensightFile1/Make/files
Normal file
3
applications/test/ensightFile1/Make/files
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Test-ensightFile1.cxx
|
||||||
|
|
||||||
|
EXE = $(FOAM_USER_APPBIN)/Test-ensightFile1
|
||||||
5
applications/test/ensightFile1/Make/options
Normal file
5
applications/test/ensightFile1/Make/options
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
EXE_INC = \
|
||||||
|
-I$(LIB_SRC)/fileFormats/lnInclude
|
||||||
|
|
||||||
|
EXE_LIBS = \
|
||||||
|
-lfileFormats
|
||||||
137
applications/test/ensightFile1/Test-ensightFile1.cxx
Normal file
137
applications/test/ensightFile1/Test-ensightFile1.cxx
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2024 OpenCFD Ltd.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Application
|
||||||
|
Test-ensightFile
|
||||||
|
|
||||||
|
Description
|
||||||
|
check cleanup of ensight file and variable names
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "argList.H"
|
||||||
|
#include "ensightFile.H"
|
||||||
|
#include "ensightGeoFile.H"
|
||||||
|
#include "Switch.H"
|
||||||
|
#include "IOstreams.H"
|
||||||
|
|
||||||
|
using namespace Foam;
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
// Main program:
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
argList::noBanner();
|
||||||
|
argList::noParallel();
|
||||||
|
argList::addBoolOption("ascii", "open as ascii instead of binary");
|
||||||
|
argList::addBoolOption("binary", "(default)");
|
||||||
|
argList::addBoolOption("clear", "force clear of time-steps");
|
||||||
|
argList::addBoolOption("no-end", "skip use of endTimeStep");
|
||||||
|
argList::addBoolOption("append", "open in append mode");
|
||||||
|
argList::addOption("geom", "geometry file");
|
||||||
|
argList::addOption("field", "field file");
|
||||||
|
|
||||||
|
#include "setRootCase.H"
|
||||||
|
|
||||||
|
const bool with_ascii = args.found("ascii") && !args.found("binary");
|
||||||
|
// const bool with_binary = args.found("binary");
|
||||||
|
const bool with_append = args.found("append");
|
||||||
|
const bool with_clear = args.found("clear");
|
||||||
|
const bool without_end = args.found("no-end");
|
||||||
|
|
||||||
|
const IOstreamOption::streamFormat fmt =
|
||||||
|
(
|
||||||
|
with_ascii
|
||||||
|
? IOstreamOption::ASCII
|
||||||
|
: IOstreamOption::BINARY
|
||||||
|
);
|
||||||
|
|
||||||
|
const IOstreamOption::appendType append =
|
||||||
|
(
|
||||||
|
with_append
|
||||||
|
? IOstreamOption::APPEND_ATE
|
||||||
|
: IOstreamOption::NO_APPEND
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
fileName file;
|
||||||
|
if (args.readIfPresent("geom", file))
|
||||||
|
{
|
||||||
|
Info<< "Open " << file << " as geometry "
|
||||||
|
<< " format:" << (with_ascii ? "ASCII" : "BINARY")
|
||||||
|
<< " append:" << Switch::name(with_append) << nl;
|
||||||
|
|
||||||
|
ensightGeoFile ensFile(append, file, fmt);
|
||||||
|
|
||||||
|
if (append)
|
||||||
|
{
|
||||||
|
ensFile.beginTimeStep();
|
||||||
|
|
||||||
|
// At the moment need to pair begin/end time-step calls
|
||||||
|
if (!without_end)
|
||||||
|
{
|
||||||
|
ensFile.endTimeStep();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (with_clear)
|
||||||
|
{
|
||||||
|
ensFile.clearTimeSteps();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.readIfPresent("field", file))
|
||||||
|
{
|
||||||
|
Info<< "Open " << file << " as field"
|
||||||
|
<< " format:" << (with_ascii ? "ASCII" : "BINARY")
|
||||||
|
<< " append:" << Switch::name(with_append) << nl;
|
||||||
|
|
||||||
|
ensightFile ensFile(append, file, fmt);
|
||||||
|
|
||||||
|
if (append)
|
||||||
|
{
|
||||||
|
ensFile.beginTimeStep();
|
||||||
|
|
||||||
|
// At the moment need to pair begin/end time-step calls
|
||||||
|
if (!without_end)
|
||||||
|
{
|
||||||
|
ensFile.endTimeStep();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (with_clear)
|
||||||
|
{
|
||||||
|
ensFile.clearTimeSteps();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Info<< "\nEnd\n" << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
3
applications/test/ensightFileName/Make/files
Normal file
3
applications/test/ensightFileName/Make/files
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Test-ensightFileName.cxx
|
||||||
|
|
||||||
|
EXE = $(FOAM_USER_APPBIN)/Test-ensightFileName
|
||||||
5
applications/test/ensightFileName/Make/options
Normal file
5
applications/test/ensightFileName/Make/options
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
EXE_INC = \
|
||||||
|
-I$(LIB_SRC)/fileFormats/lnInclude
|
||||||
|
|
||||||
|
EXE_LIBS = \
|
||||||
|
-lfileFormats
|
||||||
@ -24,10 +24,10 @@ License
|
|||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Application
|
Application
|
||||||
Test-ensightFile
|
Test-ensightFileName
|
||||||
|
|
||||||
Description
|
Description
|
||||||
check cleanup of ensight file and variable names
|
Check cleanup of ensight file and variable names
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2022-2023 OpenCFD Ltd.
|
Copyright (C) 2022-2024 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -93,29 +93,34 @@ void Foam::fileFormats::ensightMeshReader::readIDs
|
|||||||
(
|
(
|
||||||
ensightReadFile& is,
|
ensightReadFile& is,
|
||||||
const bool doRead,
|
const bool doRead,
|
||||||
const label nShapes,
|
const label elemCount,
|
||||||
labelList& foamToElem,
|
labelList& foamToElem,
|
||||||
Map<label>& elemToFoam
|
Map<label>& elemToFoam
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
const label sz = foamToElem.size();
|
const label begElem = foamToElem.size();
|
||||||
foamToElem.resize(sz+nShapes);
|
const label endElem = begElem + elemCount;
|
||||||
|
|
||||||
|
foamToElem.resize(foamToElem.size()+elemCount);
|
||||||
|
|
||||||
if (doRead)
|
if (doRead)
|
||||||
{
|
{
|
||||||
elemToFoam.reserve(elemToFoam.size()+nShapes);
|
elemToFoam.reserve(elemToFoam.size()+elemCount);
|
||||||
for (label shapei = 0; shapei < nShapes; shapei++)
|
|
||||||
|
for (label elemi = begElem; elemi < endElem; ++elemi)
|
||||||
{
|
{
|
||||||
label elemi;
|
label id;
|
||||||
is.read(elemi);
|
is.read(id);
|
||||||
foamToElem[sz+shapei] = elemi;
|
foamToElem[elemi] = id;
|
||||||
elemToFoam.insert(elemi, sz+shapei);
|
elemToFoam.insert(id, elemi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (label shapei = 0; shapei < nShapes; shapei++)
|
// identity
|
||||||
|
for (label elemi = begElem; elemi < endElem; ++elemi)
|
||||||
{
|
{
|
||||||
foamToElem[sz+shapei] = sz+shapei;
|
foamToElem[elemi] = elemi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,37 +214,54 @@ bool Foam::fileFormats::ensightMeshReader::readGoldPart
|
|||||||
// Work
|
// Work
|
||||||
DynamicList<label> verts;
|
DynamicList<label> verts;
|
||||||
|
|
||||||
string line;
|
string buffer;
|
||||||
while (is.good())
|
while (is.good())
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
is.readKeyword(line);
|
// Get entire line/string
|
||||||
|
is.read(buffer);
|
||||||
}
|
}
|
||||||
while (line.empty() && is.good());
|
while (buffer.empty() && is.good());
|
||||||
|
|
||||||
const auto split = stringOps::splitSpace(line);
|
if (!is.good())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (buffer.contains("BEGIN TIME STEP"))
|
||||||
|
{
|
||||||
|
// Graciously handle a miscued start
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (buffer.contains("END TIME STEP"))
|
||||||
|
{
|
||||||
|
// END TIME STEP is a valid means to terminate input
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const auto split = stringOps::splitSpace(buffer);
|
||||||
|
|
||||||
if (split.size() == 0)
|
if (split.empty())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (split[0] == "part")
|
const auto keyword(split[0].str());
|
||||||
|
|
||||||
|
if (keyword == "part")
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (split[0] == "node_ids")
|
else if (keyword == "node_ids")
|
||||||
{
|
{
|
||||||
const label nPoints = points.size();
|
const label nPoints = points.size();
|
||||||
// Ignore for now
|
// Ignore point ids
|
||||||
for (label i = 0; i < nPoints; i++)
|
for (label pointi = 0; pointi < nPoints; ++pointi)
|
||||||
{
|
{
|
||||||
label index;
|
label id;
|
||||||
is.read(index);
|
is.read(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (split[0] == "coordinates")
|
else if (keyword == "coordinates")
|
||||||
{
|
{
|
||||||
label nPoints;
|
label nPoints;
|
||||||
is.read(nPoints);
|
is.read(nPoints);
|
||||||
@ -257,207 +279,205 @@ bool Foam::fileFormats::ensightMeshReader::readGoldPart
|
|||||||
nodeIdToPoints
|
nodeIdToPoints
|
||||||
);
|
);
|
||||||
|
|
||||||
points.setSize(nPoints);
|
|
||||||
|
|
||||||
for (label pointi = 0; pointi < nPoints; pointi++)
|
is.readPoints(nPoints, points);
|
||||||
{
|
|
||||||
is.read(points[pointi].x());
|
|
||||||
}
|
|
||||||
for (label pointi = 0; pointi < nPoints; pointi++)
|
|
||||||
{
|
|
||||||
is.read(points[pointi].y());
|
|
||||||
}
|
|
||||||
for (label pointi = 0; pointi < nPoints; pointi++)
|
|
||||||
{
|
|
||||||
is.read(points[pointi].z());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (split[0] == "tetra4")
|
else if (keyword == "tetra4")
|
||||||
{
|
{
|
||||||
label nShapes;
|
label elemCount;
|
||||||
is.read(nShapes);
|
is.read(elemCount);
|
||||||
|
|
||||||
Pout<< indent<< "tetra4 " << nShapes
|
Pout<< indent<< "tetra4 " << elemCount
|
||||||
<< " starting at line " << is.lineNumber()
|
<< " starting at line " << is.lineNumber()
|
||||||
<< " position " << is.stdStream().tellg() << endl;
|
<< " position " << is.stdStream().tellg() << endl;
|
||||||
|
|
||||||
const label celli = cells.size();
|
|
||||||
cells.resize(celli+nShapes);
|
|
||||||
|
|
||||||
readIDs
|
readIDs
|
||||||
(
|
(
|
||||||
is,
|
is,
|
||||||
read_elem_ids,
|
read_elem_ids,
|
||||||
nShapes,
|
elemCount,
|
||||||
cellToElemIds,
|
cellToElemIds,
|
||||||
elemIdToCells
|
elemIdToCells
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Extend and fill the new trailing portion
|
||||||
|
const label startElemi = cells.size();
|
||||||
|
cells.resize(startElemi+elemCount);
|
||||||
|
faceListList::subList myElements = cells.slice(startElemi);
|
||||||
|
|
||||||
const auto& model = cellModel::ref(cellModel::TET);
|
const auto& model = cellModel::ref(cellModel::TET);
|
||||||
for (label shapei = 0; shapei < nShapes; shapei++)
|
for (auto& cellFaces : myElements)
|
||||||
{
|
{
|
||||||
readVerts(is, 4, nodeIdToPoints, verts);
|
readVerts(is, 4, nodeIdToPoints, verts);
|
||||||
if (setHandedness_)
|
if (setHandedness_)
|
||||||
{
|
{
|
||||||
setHandedness(model, verts, points);
|
setHandedness(model, verts, points);
|
||||||
}
|
}
|
||||||
const cellShape cellVerts(model, verts);
|
cellFaces = cellShape(model, verts).faces();
|
||||||
cells[celli+shapei] = cellVerts.faces();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (split[0] == "pyramid5")
|
else if (keyword == "pyramid5")
|
||||||
{
|
{
|
||||||
label nShapes;
|
label elemCount;
|
||||||
is.read(nShapes);
|
is.read(elemCount);
|
||||||
|
|
||||||
Pout<< indent<< "pyramid5 " << nShapes
|
Pout<< indent<< "pyramid5 " << elemCount
|
||||||
<< " starting at line " << is.lineNumber()
|
<< " starting at line " << is.lineNumber()
|
||||||
<< " position " << is.stdStream().tellg() << endl;
|
<< " position " << is.stdStream().tellg() << endl;
|
||||||
|
|
||||||
const label celli = cells.size();
|
|
||||||
cells.resize(celli+nShapes);
|
|
||||||
|
|
||||||
readIDs
|
readIDs
|
||||||
(
|
(
|
||||||
is,
|
is,
|
||||||
read_elem_ids,
|
read_elem_ids,
|
||||||
nShapes,
|
elemCount,
|
||||||
cellToElemIds,
|
cellToElemIds,
|
||||||
elemIdToCells
|
elemIdToCells
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Extend and fill the new trailing portion
|
||||||
|
const label startElemi = cells.size();
|
||||||
|
cells.resize(startElemi+elemCount);
|
||||||
|
faceListList::subList myElements = cells.slice(startElemi);
|
||||||
|
|
||||||
const auto& model = cellModel::ref(cellModel::PYR);
|
const auto& model = cellModel::ref(cellModel::PYR);
|
||||||
for (label shapei = 0; shapei < nShapes; shapei++)
|
for (auto& cellFaces : myElements)
|
||||||
{
|
{
|
||||||
readVerts(is, 5, nodeIdToPoints, verts);
|
readVerts(is, 5, nodeIdToPoints, verts);
|
||||||
if (setHandedness_)
|
if (setHandedness_)
|
||||||
{
|
{
|
||||||
setHandedness(model, verts, points);
|
setHandedness(model, verts, points);
|
||||||
}
|
}
|
||||||
const cellShape cellVerts(model, verts);
|
cellFaces = cellShape(model, verts).faces();
|
||||||
cells[celli+shapei] = cellVerts.faces();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (split[0] == "penta6")
|
else if (keyword == "penta6")
|
||||||
{
|
{
|
||||||
label nShapes;
|
label elemCount;
|
||||||
is.read(nShapes);
|
is.read(elemCount);
|
||||||
|
|
||||||
Pout<< indent<< "penta6 " << nShapes
|
Pout<< indent<< "penta6 " << elemCount
|
||||||
<< " starting at line " << is.lineNumber()
|
<< " starting at line " << is.lineNumber()
|
||||||
<< " position " << is.stdStream().tellg() << endl;
|
<< " position " << is.stdStream().tellg() << endl;
|
||||||
|
|
||||||
const label celli = cells.size();
|
|
||||||
cells.resize(celli+nShapes);
|
|
||||||
|
|
||||||
readIDs
|
readIDs
|
||||||
(
|
(
|
||||||
is,
|
is,
|
||||||
read_elem_ids,
|
read_elem_ids,
|
||||||
nShapes,
|
elemCount,
|
||||||
cellToElemIds,
|
cellToElemIds,
|
||||||
elemIdToCells
|
elemIdToCells
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Extend and fill the new trailing portion
|
||||||
|
const label startElemi = cells.size();
|
||||||
|
cells.resize(startElemi+elemCount);
|
||||||
|
faceListList::subList myElements = cells.slice(startElemi);
|
||||||
|
|
||||||
const auto& model = cellModel::ref(cellModel::PRISM);
|
const auto& model = cellModel::ref(cellModel::PRISM);
|
||||||
for (label shapei = 0; shapei < nShapes; shapei++)
|
for (auto& cellFaces : myElements)
|
||||||
{
|
{
|
||||||
readVerts(is, 6, nodeIdToPoints, verts);
|
readVerts(is, 6, nodeIdToPoints, verts);
|
||||||
if (setHandedness_)
|
if (setHandedness_)
|
||||||
{
|
{
|
||||||
setHandedness(model, verts, points);
|
setHandedness(model, verts, points);
|
||||||
}
|
}
|
||||||
const cellShape cellVerts(model, verts);
|
cellFaces = cellShape(model, verts).faces();
|
||||||
cells[celli+shapei] = cellVerts.faces();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (split[0] == "hexa8")
|
else if (keyword == "hexa8")
|
||||||
{
|
{
|
||||||
label nShapes;
|
label elemCount;
|
||||||
is.read(nShapes);
|
is.read(elemCount);
|
||||||
|
|
||||||
Pout<< indent<< "hexa8 " << nShapes
|
Pout<< indent<< "hexa8 " << elemCount
|
||||||
<< " starting at line " << is.lineNumber()
|
<< " starting at line " << is.lineNumber()
|
||||||
<< " position " << is.stdStream().tellg() << endl;
|
<< " position " << is.stdStream().tellg() << endl;
|
||||||
|
|
||||||
const label celli = cells.size();
|
|
||||||
cells.resize(celli+nShapes);
|
|
||||||
|
|
||||||
readIDs
|
readIDs
|
||||||
(
|
(
|
||||||
is,
|
is,
|
||||||
read_elem_ids,
|
read_elem_ids,
|
||||||
nShapes,
|
elemCount,
|
||||||
cellToElemIds,
|
cellToElemIds,
|
||||||
elemIdToCells
|
elemIdToCells
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Extend and fill the new trailing portion
|
||||||
|
const label startElemi = cells.size();
|
||||||
|
cells.resize(startElemi+elemCount);
|
||||||
|
faceListList::subList myElements = cells.slice(startElemi);
|
||||||
|
|
||||||
const auto& model = cellModel::ref(cellModel::HEX);
|
const auto& model = cellModel::ref(cellModel::HEX);
|
||||||
for (label shapei = 0; shapei < nShapes; shapei++)
|
for (auto& cellFaces : myElements)
|
||||||
{
|
{
|
||||||
readVerts(is, 8, nodeIdToPoints, verts);
|
readVerts(is, 8, nodeIdToPoints, verts);
|
||||||
if (setHandedness_)
|
if (setHandedness_)
|
||||||
{
|
{
|
||||||
setHandedness(model, verts, points);
|
setHandedness(model, verts, points);
|
||||||
}
|
}
|
||||||
const cellShape cellVerts(model, verts);
|
cellFaces = cellShape(model, verts).faces();
|
||||||
cells[celli+shapei] = cellVerts.faces();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (split[0] == "nfaced")
|
else if (keyword == "nfaced")
|
||||||
{
|
{
|
||||||
label nShapes;
|
label elemCount;
|
||||||
is.read(nShapes);
|
is.read(elemCount);
|
||||||
|
|
||||||
Pout<< indent<< "nfaced " << nShapes
|
Pout<< indent<< "nfaced " << elemCount
|
||||||
<< " starting at line " << is.lineNumber()
|
<< " starting at line " << is.lineNumber()
|
||||||
<< " position " << is.stdStream().tellg() << endl;
|
<< " position " << is.stdStream().tellg() << endl;
|
||||||
|
|
||||||
const label celli = cells.size();
|
|
||||||
cells.resize(celli+nShapes);
|
|
||||||
|
|
||||||
readIDs
|
readIDs
|
||||||
(
|
(
|
||||||
is,
|
is,
|
||||||
read_elem_ids,
|
read_elem_ids,
|
||||||
nShapes,
|
elemCount,
|
||||||
cellToElemIds,
|
cellToElemIds,
|
||||||
elemIdToCells
|
elemIdToCells
|
||||||
);
|
);
|
||||||
|
|
||||||
for (label shapei = 0; shapei < nShapes; shapei++)
|
// Extend and fill the new trailing portion
|
||||||
|
const label startElemi = cells.size();
|
||||||
|
cells.resize(startElemi+elemCount);
|
||||||
|
faceListList::subList myElements = cells.slice(startElemi);
|
||||||
|
|
||||||
|
for (auto& cellFaces : myElements)
|
||||||
{
|
{
|
||||||
label nFaces;
|
label nFaces;
|
||||||
is.read(nFaces);
|
is.read(nFaces);
|
||||||
faceList& cellFaces = cells[celli+shapei];
|
cellFaces.resize(nFaces);
|
||||||
cellFaces.setSize(nFaces);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (label shapei = 0; shapei < nShapes; shapei++)
|
for (auto& cellFaces : myElements)
|
||||||
{
|
{
|
||||||
faceList& cellFaces = cells[celli+shapei];
|
for (face& f : cellFaces)
|
||||||
forAll(cellFaces, cellFacei)
|
|
||||||
{
|
{
|
||||||
label nVerts;
|
label nVerts;
|
||||||
is.read(nVerts);
|
is.read(nVerts);
|
||||||
cellFaces[cellFacei].setSize(nVerts);
|
f.resize(nVerts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (label shapei = 0; shapei < nShapes; shapei++)
|
for (faceList& cellFaces : myElements)
|
||||||
{
|
{
|
||||||
faceList& cellFaces = cells[celli+shapei];
|
for (face& f : cellFaces)
|
||||||
forAll(cellFaces, cellFacei)
|
|
||||||
{
|
{
|
||||||
face& f = cellFaces[cellFacei];
|
|
||||||
readVerts(is, f.size(), nodeIdToPoints, verts);
|
readVerts(is, f.size(), nodeIdToPoints, verts);
|
||||||
f.labelList::operator=(verts);
|
f.labelList::operator=(verts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
forAll(f, fp)
|
// Full check
|
||||||
|
forAll(myElements, elemi)
|
||||||
|
{
|
||||||
|
for (const face& f : myElements[elemi])
|
||||||
|
{
|
||||||
|
for (label pointi : f)
|
||||||
{
|
{
|
||||||
if (f[fp] < 0 || f[fp] >= points.size())
|
if (pointi < 0 || pointi >= points.size())
|
||||||
{
|
{
|
||||||
FatalErrorInFunction<< "Face:" << shapei
|
FatalErrorInFunction
|
||||||
|
<< "Face:" << elemi
|
||||||
<< " verts:" << f
|
<< " verts:" << f
|
||||||
<< " indexes outside points:" << points.size()
|
<< " indexes outside points:" << points.size()
|
||||||
<< exit(FatalError);
|
<< exit(FatalError);
|
||||||
@ -466,107 +486,104 @@ bool Foam::fileFormats::ensightMeshReader::readGoldPart
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (split[0] == "tria3")
|
else if (keyword == "tria3")
|
||||||
{
|
{
|
||||||
label nShapes;
|
label elemCount;
|
||||||
is.read(nShapes);
|
is.read(elemCount);
|
||||||
|
|
||||||
Pout<< indent << "tria3 " << nShapes
|
Pout<< indent << "tria3 " << elemCount
|
||||||
<< " starting at line " << is.lineNumber()
|
<< " starting at line " << is.lineNumber()
|
||||||
<< " position " << is.stdStream().tellg() << endl;
|
<< " position " << is.stdStream().tellg() << endl;
|
||||||
|
|
||||||
const label facei = faces.size();
|
|
||||||
|
|
||||||
readIDs
|
readIDs
|
||||||
(
|
(
|
||||||
is,
|
is,
|
||||||
read_elem_ids,
|
read_elem_ids,
|
||||||
nShapes,
|
elemCount,
|
||||||
faceToElemIDs,
|
faceToElemIDs,
|
||||||
elemIdToFaces
|
elemIdToFaces
|
||||||
);
|
);
|
||||||
|
|
||||||
faces.setSize(facei+nShapes);
|
// Extend and fill the new trailing portion
|
||||||
|
const label startElemi = cells.size();
|
||||||
|
faces.resize(startElemi+elemCount, face(3)); // <- tria3
|
||||||
|
faceList::subList myElements = faces.slice(startElemi);
|
||||||
|
|
||||||
for (label shapei = 0; shapei < nShapes; shapei++)
|
for (face& f : myElements)
|
||||||
{
|
{
|
||||||
auto& f = faces[facei+shapei];
|
|
||||||
f.setSize(3);
|
|
||||||
readVerts(is, f.size(), nodeIdToPoints, verts);
|
readVerts(is, f.size(), nodeIdToPoints, verts);
|
||||||
f.labelList::operator=(verts);
|
f.labelList::operator=(verts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (split[0] == "quad4")
|
else if (keyword == "quad4")
|
||||||
{
|
{
|
||||||
label nShapes;
|
label elemCount;
|
||||||
is.read(nShapes);
|
is.read(elemCount);
|
||||||
|
|
||||||
Pout<< indent << "quad4 " << nShapes
|
Pout<< indent << "quad4 " << elemCount
|
||||||
<< " starting at line " << is.lineNumber()
|
<< " starting at line " << is.lineNumber()
|
||||||
<< " position " << is.stdStream().tellg() << endl;
|
<< " position " << is.stdStream().tellg() << endl;
|
||||||
|
|
||||||
const label facei = faces.size();
|
|
||||||
|
|
||||||
readIDs
|
readIDs
|
||||||
(
|
(
|
||||||
is,
|
is,
|
||||||
read_elem_ids,
|
read_elem_ids,
|
||||||
nShapes,
|
elemCount,
|
||||||
faceToElemIDs,
|
faceToElemIDs,
|
||||||
elemIdToFaces
|
elemIdToFaces
|
||||||
);
|
);
|
||||||
|
|
||||||
faces.setSize(facei+nShapes);
|
// Extend and fill the new trailing portion
|
||||||
|
const label startElemi = cells.size();
|
||||||
|
faces.resize(startElemi+elemCount, face(4)); // <- quad4
|
||||||
|
faceList::subList myElements = faces.slice(startElemi);
|
||||||
|
|
||||||
for (label shapei = 0; shapei < nShapes; shapei++)
|
for (face& f : myElements)
|
||||||
{
|
{
|
||||||
auto& f = faces[facei+shapei];
|
|
||||||
f.setSize(4);
|
|
||||||
readVerts(is, f.size(), nodeIdToPoints, verts);
|
readVerts(is, f.size(), nodeIdToPoints, verts);
|
||||||
f.labelList::operator=(verts);
|
f.labelList::operator=(verts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (split[0] == "nsided")
|
else if (keyword == "nsided")
|
||||||
{
|
{
|
||||||
label nShapes;
|
label elemCount;
|
||||||
is.read(nShapes);
|
is.read(elemCount);
|
||||||
|
|
||||||
Pout<< indent << "nsided " << nShapes
|
Pout<< indent << "nsided " << elemCount
|
||||||
<< " starting at line " << is.lineNumber()
|
<< " starting at line " << is.lineNumber()
|
||||||
<< " position " << is.stdStream().tellg() << endl;
|
<< " position " << is.stdStream().tellg() << endl;
|
||||||
|
|
||||||
const label facei = faces.size();
|
|
||||||
|
|
||||||
readIDs
|
readIDs
|
||||||
(
|
(
|
||||||
is,
|
is,
|
||||||
read_elem_ids,
|
read_elem_ids,
|
||||||
nShapes,
|
elemCount,
|
||||||
faceToElemIDs,
|
faceToElemIDs,
|
||||||
elemIdToFaces
|
elemIdToFaces
|
||||||
);
|
);
|
||||||
|
|
||||||
faces.setSize(facei+nShapes);
|
// Extend and fill the new trailing portion
|
||||||
|
const label startElemi = cells.size();
|
||||||
|
faces.resize(startElemi+elemCount);
|
||||||
|
faceList::subList myElements = faces.slice(startElemi);
|
||||||
|
|
||||||
for (label shapei = 0; shapei < nShapes; shapei++)
|
for (face& f : myElements)
|
||||||
{
|
{
|
||||||
auto& f = faces[facei+shapei];
|
|
||||||
label nVerts;
|
label nVerts;
|
||||||
is.read(nVerts);
|
is.read(nVerts);
|
||||||
f.setSize(nVerts);
|
f.resize(nVerts);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (label shapei = 0; shapei < nShapes; shapei++)
|
for (face& f : myElements)
|
||||||
{
|
{
|
||||||
auto& f = faces[facei+shapei];
|
|
||||||
readVerts(is, f.size(), nodeIdToPoints, verts);
|
readVerts(is, f.size(), nodeIdToPoints, verts);
|
||||||
f.labelList::operator=(verts);
|
f.labelList::operator=(verts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WarningInFunction << "Unhandled key " << string(split[0])
|
WarningInFunction << "Unhandled key " << keyword
|
||||||
<< " from line " << line
|
<< " from line " << buffer
|
||||||
<< " starting at line " << is.lineNumber()
|
<< " starting at line " << is.lineNumber()
|
||||||
<< " position " << is.stdStream().tellg() << endl;
|
<< " position " << is.stdStream().tellg() << endl;
|
||||||
}
|
}
|
||||||
@ -584,16 +601,21 @@ bool Foam::fileFormats::ensightMeshReader::readGeometry
|
|||||||
const scalar scaleFactor
|
const scalar scaleFactor
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
// Auto-detect ascii/binary format,
|
||||||
|
// skips any initial "BEGIN TIME STEP"
|
||||||
|
|
||||||
ensightReadFile is(geometryFile_);
|
ensightReadFile is(geometryFile_);
|
||||||
|
|
||||||
// Skip 'binary' tag
|
|
||||||
is.readBinaryHeader();
|
|
||||||
|
|
||||||
string header;
|
string buffer;
|
||||||
is.read(header);
|
|
||||||
Info<< "Ensight : " << header << endl;
|
// Ensight Geometry File
|
||||||
is.read(header);
|
is.read(buffer);
|
||||||
Info<< "Ensight : " << header << endl;
|
Info<< "Ensight : " << buffer << nl;
|
||||||
|
|
||||||
|
// Description - 1
|
||||||
|
is.read(buffer);
|
||||||
|
Info<< "Ensight : " << buffer << nl;
|
||||||
|
|
||||||
|
|
||||||
bool read_node_ids = false;
|
bool read_node_ids = false;
|
||||||
@ -623,61 +645,72 @@ bool Foam::fileFormats::ensightMeshReader::readGeometry
|
|||||||
|
|
||||||
|
|
||||||
// Parse all
|
// Parse all
|
||||||
string line;
|
SubStrings<string> split;
|
||||||
|
|
||||||
while (is.good())
|
while (is.good())
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
is.readKeyword(line);
|
// Get entire line/string
|
||||||
|
is.read(buffer);
|
||||||
}
|
}
|
||||||
while (line.empty() && is.good());
|
while (buffer.empty() && is.good());
|
||||||
const auto split = stringOps::splitSpace(line);
|
if (buffer.contains("END TIME STEP"))
|
||||||
|
{
|
||||||
|
// END TIME STEP is a valid means to terminate input
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
split = stringOps::splitSpace(buffer);
|
||||||
|
|
||||||
if (split[0] == "extents")
|
if (split.empty())
|
||||||
{
|
{
|
||||||
point min;
|
continue;
|
||||||
point max;
|
|
||||||
is.read(min.x());
|
|
||||||
is.read(max.x());
|
|
||||||
is.read(min.y());
|
|
||||||
is.read(max.y());
|
|
||||||
is.read(min.z());
|
|
||||||
is.read(max.z());
|
|
||||||
Pout<< indent
|
|
||||||
<< "Read extents " << boundBox(min, max)
|
|
||||||
<< endl;
|
|
||||||
}
|
}
|
||||||
else if (split[0] == "node")
|
|
||||||
|
const auto keyword(split[0].str());
|
||||||
|
|
||||||
|
if (keyword == "extents")
|
||||||
{
|
{
|
||||||
word id(split[1]);
|
// Optional extents (xmin, xmax, ymin, ymax, zmin, zmax)
|
||||||
word op(split[2]);
|
|
||||||
|
boundBox bb;
|
||||||
|
point& min = bb.min();
|
||||||
|
point& max = bb.max();
|
||||||
|
|
||||||
|
is.read(min.x()); is.read(max.x());
|
||||||
|
is.read(min.y()); is.read(max.y());
|
||||||
|
is.read(min.z()); is.read(max.z());
|
||||||
|
|
||||||
|
Pout<< indent << "Read extents " << bb << endl;
|
||||||
|
}
|
||||||
|
else if (keyword == "node")
|
||||||
|
{
|
||||||
|
// "node id (off|assign|given|ignore)"
|
||||||
|
std::string op(split[2]);
|
||||||
if (op == "given" || op == "ignore")
|
if (op == "given" || op == "ignore")
|
||||||
{
|
{
|
||||||
Pout<< indent << "Reading node ids" << endl;
|
Pout<< indent << "Reading node ids" << endl;
|
||||||
read_node_ids = true;
|
read_node_ids = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (split[0] == "element")
|
else if (keyword == "element")
|
||||||
{
|
{
|
||||||
word id(split[1]);
|
// "element id (off|assign|given|ignore)"
|
||||||
word op(split[2]);
|
std::string op(split[2]);
|
||||||
if (op == "given" || op == "ignore")
|
if (op == "given" || op == "ignore")
|
||||||
{
|
{
|
||||||
Pout<< indent << "Reading element ids" << endl;
|
Pout<< indent << "Reading element ids" << endl;
|
||||||
read_elem_ids = true;
|
read_elem_ids = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (split[0] == "part")
|
else if (keyword == "part")
|
||||||
{
|
{
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// Make space
|
// Read part id and name
|
||||||
partIDs.emplace_back();
|
is.read(partIDs.emplace_back());
|
||||||
is.read(partIDs.back());
|
is.read(partNames.emplace_back());
|
||||||
|
|
||||||
partNames.emplace_back();
|
|
||||||
is.read(partNames.back());
|
|
||||||
|
|
||||||
Pout<< indent
|
Pout<< indent
|
||||||
<< "Reading part " << partIDs.back()
|
<< "Reading part " << partIDs.back()
|
||||||
@ -954,7 +987,7 @@ bool Foam::fileFormats::ensightMeshReader::readGeometry
|
|||||||
const face& f = rotateFace(cFaces[cFacei], rotatedFace);
|
const face& f = rotateFace(cFaces[cFacei], rotatedFace);
|
||||||
|
|
||||||
const auto fFnd = vertsToCell.find(f);
|
const auto fFnd = vertsToCell.find(f);
|
||||||
if (fFnd)
|
if (fFnd.good())
|
||||||
{
|
{
|
||||||
// Already inserted. Internal face.
|
// Already inserted. Internal face.
|
||||||
vertsToCell.erase(fFnd);
|
vertsToCell.erase(fFnd);
|
||||||
@ -1026,7 +1059,12 @@ bool Foam::fileFormats::ensightMeshReader::readGeometry
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!cAndF)
|
if (cAndF.good())
|
||||||
|
{
|
||||||
|
partCellAndFace[patchFacei++] = cAndF.val();
|
||||||
|
vertsToCell.erase(cAndF);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
//WarningInFunction
|
//WarningInFunction
|
||||||
// << "Did not find face " << facei
|
// << "Did not find face " << facei
|
||||||
@ -1036,11 +1074,6 @@ bool Foam::fileFormats::ensightMeshReader::readGeometry
|
|||||||
// << " in part " << parti
|
// << " in part " << parti
|
||||||
// << endl;
|
// << endl;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
partCellAndFace[patchFacei++] = cAndF();
|
|
||||||
vertsToCell.erase(cAndF);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
partCellAndFace.setSize(patchFacei);
|
partCellAndFace.setSize(patchFacei);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -554,7 +554,8 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
autoPtr<ensightGeoFile> os =
|
autoPtr<ensightGeoFile> os =
|
||||||
ensCase.newGeometry(hasMovingMesh);
|
ensCase.newGeometry(hasMovingMesh);
|
||||||
ensMesh.write(os);
|
|
||||||
|
ensMesh.write(os.ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
// finite-area
|
// finite-area
|
||||||
@ -562,7 +563,8 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
autoPtr<ensightGeoFile> os =
|
autoPtr<ensightGeoFile> os =
|
||||||
ensFaCasePtr->newGeometry(hasMovingMesh);
|
ensFaCasePtr->newGeometry(hasMovingMesh);
|
||||||
ensFaMeshPtr->write(os);
|
|
||||||
|
ensFaMeshPtr->write(os.ref());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2016-2023 OpenCFD Ltd.
|
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -26,7 +26,6 @@ License
|
|||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "ensightCase.H"
|
#include "ensightCase.H"
|
||||||
#include "ensightGeoFile.H"
|
|
||||||
#include "Time.H"
|
#include "Time.H"
|
||||||
#include "cloud.H"
|
#include "cloud.H"
|
||||||
#include "IOmanip.H"
|
#include "IOmanip.H"
|
||||||
@ -42,15 +41,26 @@ const char* Foam::ensightCase::geometryName = "geometry";
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::word Foam::ensightCase::padded(const int nwidth, const label value)
|
Foam::word Foam::ensightCase::mask(const int nwidth)
|
||||||
{
|
{
|
||||||
if (nwidth < 1)
|
if (nwidth < 1)
|
||||||
{
|
{
|
||||||
return Foam::name(value);
|
return word();
|
||||||
|
}
|
||||||
|
|
||||||
|
return word(std::string(nwidth, '*'), false); // stripping=false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::word Foam::ensightCase::padded(const int nwidth, const label index)
|
||||||
|
{
|
||||||
|
if (nwidth < 1)
|
||||||
|
{
|
||||||
|
return Foam::name(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << std::setfill('0') << std::setw(nwidth) << value;
|
oss << std::setfill('0') << std::setw(nwidth) << index;
|
||||||
|
|
||||||
return word(oss.str(), false); // stripping=false
|
return word(oss.str(), false); // stripping=false
|
||||||
}
|
}
|
||||||
@ -230,7 +240,7 @@ void Foam::ensightCase::initialize()
|
|||||||
// eg, convert new results or a particular time interval
|
// eg, convert new results or a particular time interval
|
||||||
// OR remove everything
|
// OR remove everything
|
||||||
|
|
||||||
if (isDir(ensightDir_))
|
if (Foam::isDir(ensightDir_))
|
||||||
{
|
{
|
||||||
if (options_->overwrite())
|
if (options_->overwrite())
|
||||||
{
|
{
|
||||||
@ -245,7 +255,7 @@ void Foam::ensightCase::initialize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create ensight and data directories
|
// Create ensight and data directories
|
||||||
mkDir(dataDir());
|
Foam::mkDir(dataDir());
|
||||||
|
|
||||||
// The case file is always ASCII
|
// The case file is always ASCII
|
||||||
os_.reset(new OFstream(ensightDir_/caseName_, IOstreamOption::ASCII));
|
os_.reset(new OFstream(ensightDir_/caseName_, IOstreamOption::ASCII));
|
||||||
@ -508,7 +518,7 @@ Foam::ensightCase::createDataFile
|
|||||||
// Note that data/ITER is indeed a valid ensight::FileName
|
// Note that data/ITER is indeed a valid ensight::FileName
|
||||||
|
|
||||||
const fileName outdir = dataDir()/padded(timeIndex_);
|
const fileName outdir = dataDir()/padded(timeIndex_);
|
||||||
mkDir(outdir);
|
Foam::mkDir(outdir);
|
||||||
|
|
||||||
return autoPtr<ensightFile>::New(outdir, name, format());
|
return autoPtr<ensightFile>::New(outdir, name, format());
|
||||||
}
|
}
|
||||||
@ -537,7 +547,7 @@ Foam::ensightCase::createCloudFile
|
|||||||
: (dataDir() / padded(timeIndex_) / cloud::prefix / cloudName)
|
: (dataDir() / padded(timeIndex_) / cloud::prefix / cloudName)
|
||||||
);
|
);
|
||||||
|
|
||||||
mkDir(outdir); // should be unnecessary after newCloud()
|
Foam::mkDir(outdir); // should be unnecessary after newCloud()
|
||||||
|
|
||||||
return autoPtr<ensightFile>::New(outdir, name, format());
|
return autoPtr<ensightFile>::New(outdir, name, format());
|
||||||
}
|
}
|
||||||
@ -561,13 +571,7 @@ Foam::ensightCase::ensightCase
|
|||||||
caseName_(caseName + ".case"),
|
caseName_(caseName + ".case"),
|
||||||
changed_(false),
|
changed_(false),
|
||||||
timeIndex_(0),
|
timeIndex_(0),
|
||||||
timeValue_(0),
|
timeValue_(0)
|
||||||
timesUsed_(),
|
|
||||||
geomTimes_(),
|
|
||||||
cloudTimes_(),
|
|
||||||
variables_(),
|
|
||||||
nodeVariables_(),
|
|
||||||
cloudVars_()
|
|
||||||
{
|
{
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
@ -586,13 +590,7 @@ Foam::ensightCase::ensightCase
|
|||||||
caseName_(caseName + ".case"),
|
caseName_(caseName + ".case"),
|
||||||
changed_(false),
|
changed_(false),
|
||||||
timeIndex_(0),
|
timeIndex_(0),
|
||||||
timeValue_(0),
|
timeValue_(0)
|
||||||
timesUsed_(),
|
|
||||||
geomTimes_(),
|
|
||||||
cloudTimes_(),
|
|
||||||
variables_(),
|
|
||||||
nodeVariables_(),
|
|
||||||
cloudVars_()
|
|
||||||
{
|
{
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
@ -624,7 +622,7 @@ void Foam::ensightCase::setTime(const scalar value, const label index)
|
|||||||
// Note that data/ITER is indeed a valid ensight::FileName
|
// Note that data/ITER is indeed a valid ensight::FileName
|
||||||
|
|
||||||
const fileName outdir = dataDir()/padded(timeIndex_);
|
const fileName outdir = dataDir()/padded(timeIndex_);
|
||||||
mkDir(outdir);
|
Foam::mkDir(outdir);
|
||||||
|
|
||||||
// place a timestamp in the directory for future reference
|
// place a timestamp in the directory for future reference
|
||||||
OFstream timeStamp(outdir/"time");
|
OFstream timeStamp(outdir/"time");
|
||||||
@ -842,7 +840,7 @@ Foam::ensightCase::newGeometry
|
|||||||
bool moving
|
bool moving
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
autoPtr<Foam::ensightGeoFile> output;
|
autoPtr<ensightGeoFile> filePtr;
|
||||||
|
|
||||||
if (UPstream::master())
|
if (UPstream::master())
|
||||||
{
|
{
|
||||||
@ -859,14 +857,16 @@ Foam::ensightCase::newGeometry
|
|||||||
// Static mesh: write as "data/constant/geometry"
|
// Static mesh: write as "data/constant/geometry"
|
||||||
path = dataDir()/word("constant");
|
path = dataDir()/word("constant");
|
||||||
}
|
}
|
||||||
mkDir(path);
|
Foam::mkDir(path);
|
||||||
|
|
||||||
noteGeometry(moving); // note for later use
|
noteGeometry(moving); // note for later use
|
||||||
|
|
||||||
return autoPtr<ensightGeoFile>::New(path, geometryName, format());
|
filePtr.reset(new ensightGeoFile(path, geometryName, format()));
|
||||||
|
|
||||||
|
// Before 2024-05 also implicitly called beginGeometry()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return filePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -876,23 +876,24 @@ Foam::ensightCase::newCloud
|
|||||||
const word& cloudName
|
const word& cloudName
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
autoPtr<Foam::ensightFile> output;
|
autoPtr<ensightFile> filePtr;
|
||||||
|
|
||||||
if (UPstream::master())
|
if (UPstream::master())
|
||||||
{
|
{
|
||||||
output = createCloudFile(cloudName, "positions");
|
filePtr = createCloudFile(cloudName, "positions");
|
||||||
|
auto& os = filePtr();
|
||||||
|
|
||||||
// Tag binary format (just like geometry files)
|
// Tag binary format (just like geometry files)
|
||||||
output().writeBinaryHeader();
|
os.writeBinaryHeader();
|
||||||
|
|
||||||
// Description
|
// Description
|
||||||
output().write(cloud::prefix/cloudName);
|
os.write(cloud::prefix/cloudName);
|
||||||
output().newline();
|
os.newline();
|
||||||
|
|
||||||
noteCloud(cloudName); // note for later use
|
noteCloud(cloudName); // note for later use
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return filePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2016-2023 OpenCFD Ltd.
|
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -42,13 +42,11 @@ SourceFiles
|
|||||||
#define Foam_ensightCase_H
|
#define Foam_ensightCase_H
|
||||||
|
|
||||||
#include "autoPtr.H"
|
#include "autoPtr.H"
|
||||||
#include "HashSet.H"
|
|
||||||
#include "InfoProxy.H"
|
#include "InfoProxy.H"
|
||||||
#include "Map.H"
|
|
||||||
#include "HashSet.H"
|
#include "HashSet.H"
|
||||||
|
#include "Map.H"
|
||||||
#include "Pstream.H"
|
#include "Pstream.H"
|
||||||
#include "ensightGeoFile.H"
|
#include "ensightGeoFile.H"
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -195,6 +193,10 @@ private:
|
|||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Generated Methods
|
||||||
|
|
||||||
//- No copy construct
|
//- No copy construct
|
||||||
ensightCase(const ensightCase&) = delete;
|
ensightCase(const ensightCase&) = delete;
|
||||||
|
|
||||||
@ -202,8 +204,6 @@ private:
|
|||||||
void operator=(const ensightCase&) = delete;
|
void operator=(const ensightCase&) = delete;
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct from components
|
//- Construct from components
|
||||||
@ -229,8 +229,19 @@ public:
|
|||||||
|
|
||||||
// Static Functions
|
// Static Functions
|
||||||
|
|
||||||
//- Stringified zero-padded integer value
|
//- A '*' mask of specified width
|
||||||
static word padded(const int nwidth, const label value);
|
static word mask(const int nwidth);
|
||||||
|
|
||||||
|
//- Stringified zero-padded integer value of specified width
|
||||||
|
static word padded(const int nwidth, const label index);
|
||||||
|
|
||||||
|
//- Replace the '*' mask chars with zero-padded integer value
|
||||||
|
template<class StringType>
|
||||||
|
static StringType expand_mask
|
||||||
|
(
|
||||||
|
const StringType& input,
|
||||||
|
const label index
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
@ -285,6 +296,7 @@ public:
|
|||||||
// Addition of entries to case file
|
// Addition of entries to case file
|
||||||
|
|
||||||
//- Open stream for new geometry file (on master).
|
//- Open stream for new geometry file (on master).
|
||||||
|
//- Does not include beginGeometry() marker.
|
||||||
autoPtr<ensightGeoFile> newGeometry(bool moving = false) const;
|
autoPtr<ensightGeoFile> newGeometry(bool moving = false) const;
|
||||||
|
|
||||||
//- Open stream for new cloud positions (on master).
|
//- Open stream for new cloud positions (on master).
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -73,7 +73,7 @@ inline bool Foam::ensightCase::separateCloud() const
|
|||||||
|
|
||||||
inline Foam::Ostream& Foam::ensightCase::operator()() const
|
inline Foam::Ostream& Foam::ensightCase::operator()() const
|
||||||
{
|
{
|
||||||
return *os_;
|
return (os_ ? *os_ : Foam::Snull);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2016-2023 OpenCFD Ltd.
|
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -28,6 +28,35 @@ License
|
|||||||
#include "cloud.H"
|
#include "cloud.H"
|
||||||
#include "ensightPTraits.H"
|
#include "ensightPTraits.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class StringType>
|
||||||
|
StringType Foam::ensightCase::expand_mask
|
||||||
|
(
|
||||||
|
const StringType& input,
|
||||||
|
const label timeIndex
|
||||||
|
)
|
||||||
|
{
|
||||||
|
StringType result(input);
|
||||||
|
|
||||||
|
const auto nMask = std::count(input.begin(), input.end(), '*');
|
||||||
|
|
||||||
|
// If there are any '*' chars, they are assumed to be contiguous
|
||||||
|
// Eg, data/******/geometry
|
||||||
|
|
||||||
|
if (nMask)
|
||||||
|
{
|
||||||
|
result.replace
|
||||||
|
(
|
||||||
|
ensightCase::mask(nMask),
|
||||||
|
ensightCase::padded(nMask, timeIndex)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
|
|||||||
@ -27,6 +27,7 @@ License
|
|||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "ensightFile.H"
|
#include "ensightFile.H"
|
||||||
|
#include "ensightReadFile.H"
|
||||||
#include "error.H"
|
#include "error.H"
|
||||||
#include "List.H"
|
#include "List.H"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -41,6 +42,37 @@ float Foam::ensightFile::undefValue_ = Foam::floatScalarVGREAT;
|
|||||||
const char* const Foam::ensightFile::coordinates = "coordinates";
|
const char* const Foam::ensightFile::coordinates = "coordinates";
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Put integers, floats etc in binary or ascii.
|
||||||
|
template<class Type>
|
||||||
|
static inline void putPrimitive
|
||||||
|
(
|
||||||
|
const Type& value,
|
||||||
|
OFstream& os,
|
||||||
|
const int fieldWidth
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto& oss = os.stdStream();
|
||||||
|
|
||||||
|
if (os.format() == IOstreamOption::BINARY)
|
||||||
|
{
|
||||||
|
oss.write(reinterpret_cast<const char*>(&value), sizeof(Type));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oss.width(fieldWidth);
|
||||||
|
oss << value;
|
||||||
|
}
|
||||||
|
os.syncState();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
bool Foam::ensightFile::hasUndef(const UList<float>& field)
|
bool Foam::ensightFile::hasUndef(const UList<float>& field)
|
||||||
@ -82,6 +114,51 @@ void Foam::ensightFile::init()
|
|||||||
std::ios_base::floatfield
|
std::ios_base::floatfield
|
||||||
);
|
);
|
||||||
precision(5);
|
precision(5);
|
||||||
|
|
||||||
|
// Handle transient single-file timestep information
|
||||||
|
auto& oss = OFstream::stdStream();
|
||||||
|
|
||||||
|
if (OFstream::is_appending())
|
||||||
|
{
|
||||||
|
// Already positioned at the EOF (in append mode), but be certain
|
||||||
|
oss.seekp(0, std::ios_base::end);
|
||||||
|
origFileSize_ = oss.tellp();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
origFileSize_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t begin_footer(-1);
|
||||||
|
List<int64_t> offsets;
|
||||||
|
|
||||||
|
if (OFstream::is_appending())
|
||||||
|
{
|
||||||
|
// Temporarily open for reading as well.
|
||||||
|
// No race condition since no writing is done concurrently with the
|
||||||
|
// reading
|
||||||
|
IFstream is(OFstream::name(), OFstream::format());
|
||||||
|
|
||||||
|
begin_footer =
|
||||||
|
ensightReadFile::getTimeStepFooter
|
||||||
|
(
|
||||||
|
is,
|
||||||
|
offsets
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
timeStepOffsets_ = std::move(offsets);
|
||||||
|
|
||||||
|
if (OFstream::is_appending() && begin_footer > 0)
|
||||||
|
{
|
||||||
|
oss.seekp(begin_footer);
|
||||||
|
OFstream::syncState();
|
||||||
|
}
|
||||||
|
|
||||||
|
// InfoErr << "output at: " << label(begin_footer) << nl;
|
||||||
|
// InfoErr
|
||||||
|
// << "footer: " << label(begin_footer)
|
||||||
|
// << " time-steps: " << offsets.size() << nl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -89,11 +166,30 @@ void Foam::ensightFile::init()
|
|||||||
|
|
||||||
Foam::ensightFile::ensightFile
|
Foam::ensightFile::ensightFile
|
||||||
(
|
(
|
||||||
|
std::nullptr_t, // dispatch tag
|
||||||
|
IOstreamOption::appendType append,
|
||||||
const fileName& pathname,
|
const fileName& pathname,
|
||||||
IOstreamOption::streamFormat fmt
|
IOstreamOption::streamFormat fmt
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
OFstream(IOstreamOption::ATOMIC, ensight::FileName(pathname), fmt)
|
OFstream
|
||||||
|
(
|
||||||
|
(
|
||||||
|
// Only use atomic when not appending
|
||||||
|
(append == IOstreamOption::NO_APPEND)
|
||||||
|
? IOstreamOption::ATOMIC
|
||||||
|
: IOstreamOption::NON_ATOMIC
|
||||||
|
),
|
||||||
|
pathname,
|
||||||
|
fmt,
|
||||||
|
(
|
||||||
|
// Change APPEND_APP -> APPEND_ATE (file rewriting)
|
||||||
|
(append == IOstreamOption::APPEND_APP)
|
||||||
|
? IOstreamOption::APPEND_ATE
|
||||||
|
: append
|
||||||
|
)
|
||||||
|
),
|
||||||
|
origFileSize_(0)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
@ -101,14 +197,44 @@ Foam::ensightFile::ensightFile
|
|||||||
|
|
||||||
Foam::ensightFile::ensightFile
|
Foam::ensightFile::ensightFile
|
||||||
(
|
(
|
||||||
|
IOstreamOption::appendType append,
|
||||||
|
const fileName& pathname,
|
||||||
|
IOstreamOption::streamFormat fmt
|
||||||
|
)
|
||||||
|
:
|
||||||
|
ensightFile
|
||||||
|
(
|
||||||
|
nullptr,
|
||||||
|
append,
|
||||||
|
ensight::FileName(pathname),
|
||||||
|
fmt
|
||||||
|
)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::ensightFile::ensightFile
|
||||||
|
(
|
||||||
|
IOstreamOption::appendType append,
|
||||||
const fileName& path,
|
const fileName& path,
|
||||||
const fileName& name,
|
const fileName& name,
|
||||||
IOstreamOption::streamFormat fmt
|
IOstreamOption::streamFormat fmt
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
OFstream(IOstreamOption::ATOMIC, path/ensight::FileName(name), fmt)
|
ensightFile
|
||||||
|
(
|
||||||
|
nullptr,
|
||||||
|
append,
|
||||||
|
path/ensight::FileName(name),
|
||||||
|
fmt
|
||||||
|
)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::ensightFile::~ensightFile()
|
||||||
{
|
{
|
||||||
init();
|
(void) writeTimeStepFooter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -158,9 +284,11 @@ void Foam::ensightFile::writeString(const char* str, size_t len)
|
|||||||
std::copy_n(str, len, buf);
|
std::copy_n(str, len, buf);
|
||||||
std::fill_n(buf + len, (80 - len), '\0'); // Pad trailing with nul
|
std::fill_n(buf + len, (80 - len), '\0'); // Pad trailing with nul
|
||||||
|
|
||||||
|
auto& oss = stdStream();
|
||||||
|
|
||||||
if (format() == IOstreamOption::BINARY)
|
if (format() == IOstreamOption::BINARY)
|
||||||
{
|
{
|
||||||
write(buf, 80);
|
oss.write(buf, 80);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -170,9 +298,10 @@ void Foam::ensightFile::writeString(const char* str, size_t len)
|
|||||||
// char* p = ::strchr(buf, '\n');
|
// char* p = ::strchr(buf, '\n');
|
||||||
// if (p) *p = 0;
|
// if (p) *p = 0;
|
||||||
|
|
||||||
stdStream() << buf;
|
oss << buf;
|
||||||
syncState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
syncState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -209,6 +338,7 @@ Foam::Ostream& Foam::ensightFile::write(const std::string& str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Same as OFstream::writeRaw(buf, count)
|
||||||
Foam::Ostream& Foam::ensightFile::write
|
Foam::Ostream& Foam::ensightFile::write
|
||||||
(
|
(
|
||||||
const char* buf,
|
const char* buf,
|
||||||
@ -223,82 +353,56 @@ Foam::Ostream& Foam::ensightFile::write
|
|||||||
|
|
||||||
void Foam::ensightFile::writeInt(const int32_t val, const int fieldWidth)
|
void Foam::ensightFile::writeInt(const int32_t val, const int fieldWidth)
|
||||||
{
|
{
|
||||||
if (format() == IOstreamOption::BINARY)
|
putPrimitive<int32_t>(val, *this, fieldWidth);
|
||||||
{
|
|
||||||
write
|
|
||||||
(
|
|
||||||
reinterpret_cast<const char *>(&val),
|
|
||||||
sizeof(int32_t)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stdStream().width(fieldWidth);
|
|
||||||
stdStream() << val;
|
|
||||||
syncState();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::ensightFile::writeInt(const int64_t val, const int fieldWidth)
|
void Foam::ensightFile::writeInt(const int64_t val, const int fieldWidth)
|
||||||
{
|
{
|
||||||
int32_t work(narrowInt32(val));
|
putPrimitive<int32_t>(narrowInt32(val), *this, fieldWidth);
|
||||||
|
|
||||||
writeInt(work, fieldWidth);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::ensightFile::writeFloat(const float val, const int fieldWidth)
|
void Foam::ensightFile::writeFloat(const float val, const int fieldWidth)
|
||||||
{
|
{
|
||||||
if (format() == IOstreamOption::BINARY)
|
putPrimitive<float>(val, *this, fieldWidth);
|
||||||
{
|
|
||||||
write
|
|
||||||
(
|
|
||||||
reinterpret_cast<const char *>(&val),
|
|
||||||
sizeof(float)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stdStream().width(fieldWidth);
|
|
||||||
stdStream() << val;
|
|
||||||
syncState();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::ensightFile::writeFloat(const double val, const int fieldWidth)
|
void Foam::ensightFile::writeFloat(const double val, const int fieldWidth)
|
||||||
{
|
{
|
||||||
float work(narrowFloat(val));
|
putPrimitive<float>(narrowFloat(val), *this, fieldWidth);
|
||||||
|
|
||||||
writeFloat(work, fieldWidth);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::Ostream& Foam::ensightFile::write(const int32_t val)
|
Foam::Ostream& Foam::ensightFile::write(const int32_t val)
|
||||||
{
|
{
|
||||||
writeInt(val, 10);
|
putPrimitive<int32_t>(val, *this, 10);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::Ostream& Foam::ensightFile::write(const int64_t val)
|
Foam::Ostream& Foam::ensightFile::write(const int64_t val)
|
||||||
{
|
{
|
||||||
writeInt(val, 10);
|
putPrimitive<int32_t>(narrowInt32(val), *this, 10);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::Ostream& Foam::ensightFile::write(const float val)
|
Foam::Ostream& Foam::ensightFile::write(const float val)
|
||||||
{
|
{
|
||||||
writeFloat(val, 12);
|
putPrimitive<float>(val, *this, 12);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::Ostream& Foam::ensightFile::write(const double val)
|
Foam::Ostream& Foam::ensightFile::write(const double val)
|
||||||
{
|
{
|
||||||
writeFloat(val, 12);
|
putPrimitive<float>(narrowFloat(val), *this, 12);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,8 +411,7 @@ void Foam::ensightFile::newline()
|
|||||||
{
|
{
|
||||||
if (format() == IOstreamOption::ASCII)
|
if (format() == IOstreamOption::ASCII)
|
||||||
{
|
{
|
||||||
stdStream() << nl;
|
OFstream::write('\n');
|
||||||
syncState();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,22 +446,69 @@ void Foam::ensightFile::writeBinaryHeader()
|
|||||||
if (format() == IOstreamOption::BINARY)
|
if (format() == IOstreamOption::BINARY)
|
||||||
{
|
{
|
||||||
writeString("C Binary");
|
writeString("C Binary");
|
||||||
// Is binary: newline() is a no-op
|
// newline(); // A no-op in binary
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::ensightFile::beginTimeStep()
|
// Footer information looks like this
|
||||||
{
|
//
|
||||||
writeString("BEGIN TIME STEP");
|
/* |---------------|---------------|-----------------------|
|
||||||
newline();
|
* | ASCII | BINARY | element |
|
||||||
}
|
* |---------------|---------------|-----------------------|
|
||||||
|
* | "%20lld\n" | int32 | nSteps |
|
||||||
|
* | "%20lld\n" | int64 | offset step 1 |
|
||||||
|
* | "%20lld\n" | int64 | offset step 2 |
|
||||||
|
* | "%20lld\n" | .. | |
|
||||||
|
* | "%20lld\n" | int64 | offset step n |
|
||||||
|
* | "%20lld\n" | int32 | flag (unused) |
|
||||||
|
* | "%20lld\n" | int64 | offset to nSteps |
|
||||||
|
* | "%s\n" | char[80] | 'FILE_INDEX' |
|
||||||
|
* |---------------|---------------|-----------------------|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int64_t Foam::ensightFile::writeTimeStepFooter()
|
||||||
void Foam::ensightFile::endTimeStep()
|
|
||||||
{
|
{
|
||||||
writeString("END TIME STEP");
|
if (timeStepOffsets_.empty())
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& oss = OFstream::stdStream();
|
||||||
|
|
||||||
|
// The footer begin, which is also the current position
|
||||||
|
const int64_t footer_begin(oss.tellp());
|
||||||
|
|
||||||
|
// nSteps
|
||||||
|
putPrimitive<int32_t>(int32_t(timeStepOffsets_.size()), *this, 20);
|
||||||
newline();
|
newline();
|
||||||
|
|
||||||
|
// offset step 1, 2, ... N
|
||||||
|
for (int64_t off : timeStepOffsets_)
|
||||||
|
{
|
||||||
|
putPrimitive<int64_t>(off, *this, 20);
|
||||||
|
newline();
|
||||||
|
}
|
||||||
|
|
||||||
|
// flag (unused)
|
||||||
|
putPrimitive<int32_t>(0, *this, 20);
|
||||||
|
newline();
|
||||||
|
|
||||||
|
// The footer begin == position of nSteps
|
||||||
|
putPrimitive<int64_t>(footer_begin, *this, 20);
|
||||||
|
newline();
|
||||||
|
|
||||||
|
// FILE_INDEX is "%s\n", not "%79s\n"
|
||||||
|
// but our ASCII strings are truncated (nul-padded) anyhow
|
||||||
|
|
||||||
|
writeString("FILE_INDEX");
|
||||||
|
newline();
|
||||||
|
|
||||||
|
// Reposition to begin of footer so that any subsequent output
|
||||||
|
// will overwrite the footer too
|
||||||
|
oss.seekp(footer_begin);
|
||||||
|
|
||||||
|
return footer_begin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -366,6 +516,55 @@ void Foam::ensightFile::endTimeStep()
|
|||||||
// Convenience Output Methods
|
// Convenience Output Methods
|
||||||
//
|
//
|
||||||
|
|
||||||
|
int64_t Foam::ensightFile::beginTimeStep()
|
||||||
|
{
|
||||||
|
writeString("BEGIN TIME STEP");
|
||||||
|
newline();
|
||||||
|
|
||||||
|
auto& oss = OFstream::stdStream();
|
||||||
|
|
||||||
|
const int64_t curr_pos(oss.tellp());
|
||||||
|
timeStepOffsets_.push_back(curr_pos);
|
||||||
|
|
||||||
|
// To avoid partly incomplete/incorrect footer information,
|
||||||
|
// overwrite original footer if needed.
|
||||||
|
|
||||||
|
if (curr_pos >= 0 && curr_pos < origFileSize_)
|
||||||
|
{
|
||||||
|
const char fill[] = "deadbeef";
|
||||||
|
|
||||||
|
for
|
||||||
|
(
|
||||||
|
int64_t pos = curr_pos;
|
||||||
|
pos < origFileSize_ && bool(oss);
|
||||||
|
pos += 8
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Overwrite with specified "junk" to avoid/detect corrupt
|
||||||
|
// files etc. Don't worry about slightly increasing the
|
||||||
|
// file size (ie, max 7 bytes) - it's unimportant
|
||||||
|
oss.write(fill, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maintain the original output position
|
||||||
|
oss.seekp(curr_pos);
|
||||||
|
|
||||||
|
OFstream::syncState();
|
||||||
|
}
|
||||||
|
|
||||||
|
return curr_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64_t Foam::ensightFile::endTimeStep()
|
||||||
|
{
|
||||||
|
writeString("END TIME STEP");
|
||||||
|
newline();
|
||||||
|
|
||||||
|
return int64_t(stdStream().tellp());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::ensightFile::beginPart(const label index)
|
void Foam::ensightFile::beginPart(const label index)
|
||||||
{
|
{
|
||||||
writeString("part");
|
writeString("part");
|
||||||
@ -375,6 +574,28 @@ void Foam::ensightFile::beginPart(const label index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::ensightFile::beginPart
|
||||||
|
(
|
||||||
|
const label index,
|
||||||
|
const std::string& description
|
||||||
|
)
|
||||||
|
{
|
||||||
|
beginPart(index);
|
||||||
|
writeString(description);
|
||||||
|
newline();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::ensightFile::beginCoordinates(const label npoints)
|
||||||
|
{
|
||||||
|
writeString("coordinates");
|
||||||
|
newline();
|
||||||
|
|
||||||
|
write(npoints);
|
||||||
|
newline();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::ensightFile::beginParticleCoordinates(const label nparticles)
|
void Foam::ensightFile::beginParticleCoordinates(const label nparticles)
|
||||||
{
|
{
|
||||||
writeString("particle coordinates");
|
writeString("particle coordinates");
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2015 OpenFOAM Foundation
|
Copyright (C) 2011-2015 OpenFOAM Foundation
|
||||||
Copyright (C) 2016-2023 OpenCFD Ltd.
|
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -28,8 +28,8 @@ Class
|
|||||||
Foam::ensightFile
|
Foam::ensightFile
|
||||||
|
|
||||||
Description
|
Description
|
||||||
Ensight output with specialized write() for strings, integers and floats.
|
A variant of OFstream with specialised handling for Ensight writing
|
||||||
Correctly handles binary write as well.
|
of strings, integers and floats (ASCII and BINARY).
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
@ -39,6 +39,7 @@ Description
|
|||||||
#include "OFstream.H"
|
#include "OFstream.H"
|
||||||
#include "ensightFileName.H"
|
#include "ensightFileName.H"
|
||||||
#include "ensightVarName.H"
|
#include "ensightVarName.H"
|
||||||
|
#include "DynamicList.H"
|
||||||
#include "IndirectListBase.H"
|
#include "IndirectListBase.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
@ -62,17 +63,36 @@ class ensightFile
|
|||||||
//- Value to represent undef in results (default: 1e+37, floatVGREAT)
|
//- Value to represent undef in results (default: 1e+37, floatVGREAT)
|
||||||
static float undefValue_;
|
static float undefValue_;
|
||||||
|
|
||||||
|
//- Transient single-file:
|
||||||
|
//- the original file size when opened in append mode, zero otherwise
|
||||||
|
int64_t origFileSize_;
|
||||||
|
|
||||||
|
//- Transient single-file:
|
||||||
|
//- the time-step file-offsets (position after "BEGIN TIME STEP").
|
||||||
|
// Set on initial reading and added to by beginTimeStep().
|
||||||
|
DynamicList<int64_t> timeStepOffsets_;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Initialize sets the ASCII output formatting
|
//- Set the ASCII output formatting etc,
|
||||||
|
//- and handle transient single-file timestep information
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
//- No copy construct
|
|
||||||
ensightFile(const ensightFile&) = delete;
|
|
||||||
|
|
||||||
//- No copy assignment
|
// Constructors
|
||||||
void operator=(const ensightFile&) = delete;
|
|
||||||
|
//- Construct with file name, no ensight file naming adjustment.
|
||||||
|
// Created as an atomic or in append-mode (single-file format).
|
||||||
|
// In append-mode, attempts to parse existing time-step information.
|
||||||
|
// Changes APPEND_APP to APPEND_ATE (file rewriting).
|
||||||
|
ensightFile
|
||||||
|
(
|
||||||
|
std::nullptr_t, // dispatch tag
|
||||||
|
IOstreamOption::appendType append, // (NO_APPEND or APPEND_ATE)
|
||||||
|
const fileName& pathname,
|
||||||
|
IOstreamOption::streamFormat fmt
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -98,30 +118,70 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Generated Methods
|
||||||
|
|
||||||
|
//- No copy construct
|
||||||
|
ensightFile(const ensightFile&) = delete;
|
||||||
|
|
||||||
|
//- No copy assignment
|
||||||
|
void operator=(const ensightFile&) = delete;
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct from path-name.
|
//- Construct from path-name.
|
||||||
// The path-name is adjusted for valid ensight file naming.
|
// The path-name is adjusted for valid ensight file naming.
|
||||||
// Always created as an atomic
|
// Created as an atomic or in append mode (single-file format).
|
||||||
explicit ensightFile
|
// In append mode, attempts to parse existing time-step information.
|
||||||
|
ensightFile
|
||||||
(
|
(
|
||||||
|
//! Append mode: NO_APPEND or APPEND_ATE
|
||||||
|
IOstreamOption::appendType append,
|
||||||
const fileName& pathname,
|
const fileName& pathname,
|
||||||
IOstreamOption::streamFormat fmt = IOstreamOption::BINARY
|
IOstreamOption::streamFormat fmt = IOstreamOption::BINARY
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Construct from path and name.
|
//- Construct from path and name.
|
||||||
// Only the name portion is adjusted for valid ensight file naming.
|
// Only the name portion is adjusted for valid ensight file naming.
|
||||||
// Always created as an atomic
|
// Created as an atomic or in append mode (single-file format).
|
||||||
|
// In append mode, attempts to parse existing time-step information.
|
||||||
ensightFile
|
ensightFile
|
||||||
(
|
(
|
||||||
|
//! Append mode: NO_APPEND or APPEND_ATE
|
||||||
|
IOstreamOption::appendType append,
|
||||||
const fileName& path,
|
const fileName& path,
|
||||||
const fileName& name,
|
const fileName& name,
|
||||||
IOstreamOption::streamFormat fmt = IOstreamOption::BINARY
|
IOstreamOption::streamFormat fmt = IOstreamOption::BINARY
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//- Construct from path-name.
|
||||||
|
// The path-name is adjusted for valid ensight file naming.
|
||||||
|
// Created as an atomic, non-append mode.
|
||||||
|
explicit ensightFile
|
||||||
|
(
|
||||||
|
const fileName& pathname,
|
||||||
|
IOstreamOption::streamFormat fmt = IOstreamOption::BINARY
|
||||||
|
)
|
||||||
|
:
|
||||||
|
ensightFile(IOstreamOption::NO_APPEND, pathname, fmt)
|
||||||
|
{}
|
||||||
|
|
||||||
//- Destructor
|
//- Construct from path and name.
|
||||||
~ensightFile() = default;
|
// Only the name portion is adjusted for valid ensight file naming.
|
||||||
|
// Created as an atomic, non-append mode.
|
||||||
|
ensightFile
|
||||||
|
(
|
||||||
|
const fileName& path,
|
||||||
|
const fileName& name,
|
||||||
|
IOstreamOption::streamFormat fmt = IOstreamOption::BINARY
|
||||||
|
)
|
||||||
|
:
|
||||||
|
ensightFile(IOstreamOption::NO_APPEND, path, name, fmt)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor. Commits the time-step footer information (if any)
|
||||||
|
~ensightFile();
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
@ -148,12 +208,6 @@ public:
|
|||||||
//- Write "C Binary" string for binary files (eg, geometry/measured)
|
//- Write "C Binary" string for binary files (eg, geometry/measured)
|
||||||
void writeBinaryHeader();
|
void writeBinaryHeader();
|
||||||
|
|
||||||
//- Write "BEGIN TIME STEP" string and newline
|
|
||||||
void beginTimeStep();
|
|
||||||
|
|
||||||
//- Write "END TIME STEP" string and newline
|
|
||||||
void endTimeStep();
|
|
||||||
|
|
||||||
//- Write character/string content as "%79s" or as binary (max 80 chars)
|
//- Write character/string content as "%79s" or as binary (max 80 chars)
|
||||||
void writeString(const char* str, size_t len);
|
void writeString(const char* str, size_t len);
|
||||||
|
|
||||||
@ -225,11 +279,59 @@ public:
|
|||||||
void newline();
|
void newline();
|
||||||
|
|
||||||
|
|
||||||
|
// Transient single-file format
|
||||||
|
|
||||||
|
//- Write "BEGIN TIME STEP" string and newline
|
||||||
|
//- (for transient single-file format).
|
||||||
|
// \returns file position after the write
|
||||||
|
int64_t beginTimeStep();
|
||||||
|
|
||||||
|
//- Write "END TIME STEP" string and newline
|
||||||
|
//- (for transient single-file format)
|
||||||
|
// \returns file position after the write
|
||||||
|
int64_t endTimeStep();
|
||||||
|
|
||||||
|
//- Transient single-file:
|
||||||
|
//- write the time-step file-offsets as footer information.
|
||||||
|
// Maintains the current file position to allow manual use
|
||||||
|
// and seamless overwriting.
|
||||||
|
// \return the output file position at the start of the footer
|
||||||
|
int64_t writeTimeStepFooter();
|
||||||
|
|
||||||
|
//- Transient single-file:
|
||||||
|
//- forget time-step file positions (advanced use)
|
||||||
|
void clearTimeSteps() noexcept
|
||||||
|
{
|
||||||
|
timeStepOffsets_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Transient single-file:
|
||||||
|
//- the current number of time steps
|
||||||
|
label nTimes() const noexcept
|
||||||
|
{
|
||||||
|
return timeStepOffsets_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Transient single-file:
|
||||||
|
//- the current file-offsets for time steps within the file
|
||||||
|
const UList<int64_t>& timeStepOffets() const noexcept
|
||||||
|
{
|
||||||
|
return timeStepOffsets_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Convenience Output Methods
|
// Convenience Output Methods
|
||||||
|
|
||||||
//- Begin a part (0-based index internally).
|
//- Begin a part (0-based index internally).
|
||||||
void beginPart(const label index);
|
void beginPart(const label index);
|
||||||
|
|
||||||
|
//- Begin a part (0-based index internally), with a description.
|
||||||
|
//- Only used for geometry files
|
||||||
|
void beginPart(const label index, const std::string& description);
|
||||||
|
|
||||||
|
//- Begin a "coordinates" block. Only used for geometry files.
|
||||||
|
void beginCoordinates(const label nparticles);
|
||||||
|
|
||||||
//- Begin a "particle coordinates" block (measured data)
|
//- Begin a "particle coordinates" block (measured data)
|
||||||
void beginParticleCoordinates(const label nparticles);
|
void beginParticleCoordinates(const label nparticles);
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011 OpenFOAM Foundation
|
Copyright (C) 2011 OpenFOAM Foundation
|
||||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -29,15 +29,56 @@ License
|
|||||||
#include "ensightGeoFile.H"
|
#include "ensightGeoFile.H"
|
||||||
#include "foamVersion.H"
|
#include "foamVersion.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
void Foam::ensightGeoFile::init()
|
Foam::ensightGeoFile::ensightGeoFile
|
||||||
|
(
|
||||||
|
IOstreamOption::appendType append,
|
||||||
|
const fileName& pathname,
|
||||||
|
IOstreamOption::streamFormat fmt
|
||||||
|
)
|
||||||
|
:
|
||||||
|
ensightFile(append, pathname, fmt)
|
||||||
{
|
{
|
||||||
writeBinaryHeader();
|
if (!OFstream::is_appending())
|
||||||
beginGeometry();
|
{
|
||||||
|
writeBinaryHeader(); // Mandatory for geometry files
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::ensightGeoFile::ensightGeoFile
|
||||||
|
(
|
||||||
|
IOstreamOption::appendType append,
|
||||||
|
const fileName& path,
|
||||||
|
const fileName& name,
|
||||||
|
IOstreamOption::streamFormat fmt
|
||||||
|
)
|
||||||
|
:
|
||||||
|
ensightFile(append, path, name, fmt)
|
||||||
|
{
|
||||||
|
if (!OFstream::is_appending())
|
||||||
|
{
|
||||||
|
writeBinaryHeader(); // Mandatory for geometry files
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::Ostream& Foam::ensightGeoFile::writeKeyword(const keyType& key)
|
||||||
|
{
|
||||||
|
writeString(key);
|
||||||
|
newline();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Convenience Output Methods
|
||||||
|
//
|
||||||
|
|
||||||
void Foam::ensightGeoFile::beginGeometry()
|
void Foam::ensightGeoFile::beginGeometry()
|
||||||
{
|
{
|
||||||
// Description line 1
|
// Description line 1
|
||||||
@ -56,72 +97,4 @@ void Foam::ensightGeoFile::beginGeometry()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::ensightGeoFile::endGeometry()
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
Foam::ensightGeoFile::ensightGeoFile
|
|
||||||
(
|
|
||||||
const fileName& pathname,
|
|
||||||
IOstreamOption::streamFormat fmt
|
|
||||||
)
|
|
||||||
:
|
|
||||||
ensightFile(pathname, fmt)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::ensightGeoFile::ensightGeoFile
|
|
||||||
(
|
|
||||||
const fileName& path,
|
|
||||||
const fileName& name,
|
|
||||||
IOstreamOption::streamFormat fmt
|
|
||||||
)
|
|
||||||
:
|
|
||||||
ensightFile(path, name, fmt)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
Foam::Ostream& Foam::ensightGeoFile::writeKeyword(const keyType& key)
|
|
||||||
{
|
|
||||||
writeString(key);
|
|
||||||
newline();
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Convenience Output Methods
|
|
||||||
//
|
|
||||||
|
|
||||||
void Foam::ensightGeoFile::beginPart
|
|
||||||
(
|
|
||||||
const label index,
|
|
||||||
const std::string& description
|
|
||||||
)
|
|
||||||
{
|
|
||||||
beginPart(index);
|
|
||||||
writeString(description);
|
|
||||||
newline();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Foam::ensightGeoFile::beginCoordinates(const label npoints)
|
|
||||||
{
|
|
||||||
writeString(ensightFile::coordinates);
|
|
||||||
newline();
|
|
||||||
|
|
||||||
write(npoints);
|
|
||||||
newline();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2015 OpenFOAM Foundation
|
Copyright (C) 2011-2015 OpenFOAM Foundation
|
||||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -28,7 +28,8 @@ Class
|
|||||||
Foam::ensightGeoFile
|
Foam::ensightGeoFile
|
||||||
|
|
||||||
Description
|
Description
|
||||||
Specialized Ensight output with extra geometry file header
|
A variant of ensightFile (Ensight writing) that includes
|
||||||
|
the extra geometry file header information.
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
@ -50,23 +51,6 @@ class ensightGeoFile
|
|||||||
:
|
:
|
||||||
public ensightFile
|
public ensightFile
|
||||||
{
|
{
|
||||||
// Private Member Functions
|
|
||||||
|
|
||||||
//- Initialize outputs the header information and beginGeometry
|
|
||||||
void init();
|
|
||||||
|
|
||||||
//- Start of geometry information
|
|
||||||
void beginGeometry();
|
|
||||||
|
|
||||||
//- End of geometry information
|
|
||||||
void endGeometry();
|
|
||||||
|
|
||||||
//- No copy construct
|
|
||||||
ensightGeoFile(const ensightGeoFile&) = delete;
|
|
||||||
|
|
||||||
//- No copy assignment
|
|
||||||
void operator=(const ensightGeoFile&) = delete;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Static Functions
|
// Static Functions
|
||||||
@ -78,24 +62,66 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Generated Methods
|
||||||
|
|
||||||
|
//- No copy construct
|
||||||
|
ensightGeoFile(const ensightGeoFile&) = delete;
|
||||||
|
|
||||||
|
//- No copy assignment
|
||||||
|
void operator=(const ensightGeoFile&) = delete;
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct from path-name.
|
//- Construct from path-name and initialise the binary header.
|
||||||
// The path-name is adjusted for valid ensight file naming.
|
// The path-name is adjusted for valid ensight file naming.
|
||||||
explicit ensightGeoFile
|
// Created as an atomic or in append mode (single-file format).
|
||||||
|
ensightGeoFile
|
||||||
(
|
(
|
||||||
|
//! Append mode: NO_APPEND or APPEND_ATE
|
||||||
|
IOstreamOption::appendType append,
|
||||||
const fileName& pathname,
|
const fileName& pathname,
|
||||||
IOstreamOption::streamFormat fmt = IOstreamOption::BINARY
|
IOstreamOption::streamFormat fmt = IOstreamOption::BINARY
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Construct from path and name.
|
//- Construct from path / name and initialise the binary header.
|
||||||
// Only the name portion is adjusted for valid ensight file naming.
|
// Only the name portion is adjusted for valid ensight file naming.
|
||||||
|
// Created as an atomic or in append mode (single-file format).
|
||||||
|
ensightGeoFile
|
||||||
|
(
|
||||||
|
//! Append mode: NO_APPEND or APPEND_ATE
|
||||||
|
IOstreamOption::appendType append,
|
||||||
|
const fileName& path,
|
||||||
|
const fileName& name,
|
||||||
|
IOstreamOption::streamFormat fmt = IOstreamOption::BINARY
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct from path-name and initialise the binary header.
|
||||||
|
// The path-name is adjusted for valid ensight file naming.
|
||||||
|
// Created as an atomic, non-append mode.
|
||||||
|
// \note Since 2024-05 does \em not call beginGeometry() !!
|
||||||
|
explicit ensightGeoFile
|
||||||
|
(
|
||||||
|
const fileName& pathname,
|
||||||
|
IOstreamOption::streamFormat fmt = IOstreamOption::BINARY
|
||||||
|
)
|
||||||
|
:
|
||||||
|
ensightGeoFile(IOstreamOption::NO_APPEND, pathname, fmt)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//- Construct from path / name and initialise the binary header.
|
||||||
|
// Only the name portion is adjusted for valid ensight file naming.
|
||||||
|
// Created as an atomic, non-append mode.
|
||||||
|
// \note Since 2024-05 does \em not call beginGeometry() !!
|
||||||
ensightGeoFile
|
ensightGeoFile
|
||||||
(
|
(
|
||||||
const fileName& path,
|
const fileName& path,
|
||||||
const fileName& name,
|
const fileName& name,
|
||||||
IOstreamOption::streamFormat fmt = IOstreamOption::BINARY
|
IOstreamOption::streamFormat fmt = IOstreamOption::BINARY
|
||||||
);
|
)
|
||||||
|
:
|
||||||
|
ensightGeoFile(IOstreamOption::NO_APPEND, path, name, fmt)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
//- Destructor
|
||||||
@ -107,19 +133,13 @@ public:
|
|||||||
// Output
|
// Output
|
||||||
|
|
||||||
//- Write keyword with trailing newline
|
//- Write keyword with trailing newline
|
||||||
virtual Ostream& writeKeyword(const keyType& key);
|
virtual Ostream& writeKeyword(const keyType& key) override;
|
||||||
|
|
||||||
|
|
||||||
// Convenience Output Methods
|
// Convenience Output Methods
|
||||||
|
|
||||||
//- Begin a part (0-based index).
|
//- Start of geometry information
|
||||||
using ensightFile::beginPart;
|
void beginGeometry();
|
||||||
|
|
||||||
//- Begin a "part" (0-based index), with a description.
|
|
||||||
void beginPart(const label index, const std::string& description);
|
|
||||||
|
|
||||||
//- Begin a "coordinates" block
|
|
||||||
void beginCoordinates(const label npoints);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -433,6 +433,11 @@ void Foam::ensightMesh::write
|
|||||||
bool parallel
|
bool parallel
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
|
if (UPstream::master())
|
||||||
|
{
|
||||||
|
os.beginGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
// The internalMesh, cellZones
|
// The internalMesh, cellZones
|
||||||
for (const label id : cellZoneParts_.sortedToc())
|
for (const label id : cellZoneParts_.sortedToc())
|
||||||
{
|
{
|
||||||
|
|||||||
@ -217,6 +217,7 @@ public:
|
|||||||
// Output
|
// Output
|
||||||
|
|
||||||
//- Write geometry to file (normally in parallel).
|
//- Write geometry to file (normally in parallel).
|
||||||
|
//- Adds beginGeometry() marker.
|
||||||
// If all geometry is disabled, it will simply writes the mesh
|
// If all geometry is disabled, it will simply writes the mesh
|
||||||
// bounding box (to ensure that the geometry file is non-empty)
|
// bounding box (to ensure that the geometry file is non-empty)
|
||||||
void write
|
void write
|
||||||
@ -226,8 +227,8 @@ public:
|
|||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Write geometry to file (normally in parallel).
|
//- Write geometry to file (normally in parallel).
|
||||||
// If all geometry is disabled, it will simply writes the mesh
|
//- Adds beginGeometry() marker.
|
||||||
// bounding box (to ensure that the geometry file is non-empty)
|
FOAM_DEPRECATED_FOR(2024-05, "write(ensightGeoFile&, ...")
|
||||||
inline void write
|
inline void write
|
||||||
(
|
(
|
||||||
autoPtr<ensightGeoFile>& os,
|
autoPtr<ensightGeoFile>& os,
|
||||||
|
|||||||
@ -41,8 +41,8 @@ Note
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef ensightFileName_H
|
#ifndef Foam_ensightFileName_H
|
||||||
#define ensightFileName_H
|
#define Foam_ensightFileName_H
|
||||||
|
|
||||||
#include "fileName.H"
|
#include "fileName.H"
|
||||||
#include "word.H"
|
#include "word.H"
|
||||||
@ -81,6 +81,9 @@ public:
|
|||||||
//- Copy construct from std::string
|
//- Copy construct from std::string
|
||||||
inline explicit FileName(const std::string& s);
|
inline explicit FileName(const std::string& s);
|
||||||
|
|
||||||
|
//- Move construct from std::string
|
||||||
|
inline explicit FileName(std::string&& s);
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
|
|||||||
@ -46,6 +46,14 @@ inline Foam::ensight::FileName::FileName(const std::string& s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Foam::ensight::FileName::FileName(std::string&& s)
|
||||||
|
:
|
||||||
|
fileName(std::move(s), false)
|
||||||
|
{
|
||||||
|
stripInvalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
inline bool Foam::ensight::FileName::valid(char c)
|
inline bool Foam::ensight::FileName::valid(char c)
|
||||||
@ -65,11 +73,11 @@ inline void Foam::ensight::FileName::stripInvalid()
|
|||||||
|
|
||||||
// Avoid characters that upset Windows or others
|
// Avoid characters that upset Windows or others
|
||||||
string::replaceAny(":<>[]", '_');
|
string::replaceAny(":<>[]", '_');
|
||||||
removeRepeated('_');
|
string::removeRepeated('_');
|
||||||
|
|
||||||
// Minor cleanup of fileName
|
// Minor cleanup of fileName
|
||||||
removeRepeated('/');
|
string::removeRepeated('/');
|
||||||
removeEnd('/');
|
string::removeEnd('/');
|
||||||
|
|
||||||
if (empty())
|
if (empty())
|
||||||
{
|
{
|
||||||
|
|||||||
@ -41,8 +41,8 @@ Description
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef ensightVarName_H
|
#ifndef Foam_ensightVarName_H
|
||||||
#define ensightVarName_H
|
#define Foam_ensightVarName_H
|
||||||
|
|
||||||
#include "word.H"
|
#include "word.H"
|
||||||
|
|
||||||
@ -80,6 +80,9 @@ public:
|
|||||||
//- Copy construct from std::string
|
//- Copy construct from std::string
|
||||||
inline explicit VarName(const std::string& s);
|
inline explicit VarName(const std::string& s);
|
||||||
|
|
||||||
|
//- Move construct from std::string
|
||||||
|
inline explicit VarName(std::string&& s);
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
|
|||||||
@ -46,6 +46,14 @@ inline Foam::ensight::VarName::VarName(const std::string& s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Foam::ensight::VarName::VarName(std::string&& s)
|
||||||
|
:
|
||||||
|
word(std::move(s), false)
|
||||||
|
{
|
||||||
|
stripInvalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
inline bool Foam::ensight::VarName::valid(char c)
|
inline bool Foam::ensight::VarName::valid(char c)
|
||||||
@ -73,7 +81,7 @@ inline bool Foam::ensight::VarName::valid(char c)
|
|||||||
|
|
||||||
inline void Foam::ensight::VarName::stripInvalid()
|
inline void Foam::ensight::VarName::stripInvalid()
|
||||||
{
|
{
|
||||||
string::stripInvalid<VarName>(*this);
|
string::stripInvalid<ensight::VarName>(*this);
|
||||||
|
|
||||||
if (empty())
|
if (empty())
|
||||||
{
|
{
|
||||||
@ -83,10 +91,9 @@ inline void Foam::ensight::VarName::stripInvalid()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prefix with '_' to avoid starting with leading digits
|
// Prefix with '_' to avoid starting with leading digits
|
||||||
std::string::iterator iter = begin();
|
if (std::isdigit(front()))
|
||||||
if (isdigit(*iter))
|
|
||||||
{
|
{
|
||||||
insert(iter, '_');
|
insert(0, 1, '_');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -274,6 +274,7 @@ public:
|
|||||||
virtual void writeDict(Ostream& os, const bool full=false) const;
|
virtual void writeDict(Ostream& os, const bool full=false) const;
|
||||||
|
|
||||||
//- Write geometry, using a mesh reference (serial only)
|
//- Write geometry, using a mesh reference (serial only)
|
||||||
|
//- No beginGeometry() marker.
|
||||||
virtual void write
|
virtual void write
|
||||||
(
|
(
|
||||||
ensightGeoFile& os,
|
ensightGeoFile& os,
|
||||||
@ -283,6 +284,7 @@ public:
|
|||||||
|
|
||||||
//- Write bounding box geometry.
|
//- Write bounding box geometry.
|
||||||
//- All parameters are only relevant on master
|
//- All parameters are only relevant on master
|
||||||
|
//- No beginGeometry() marker.
|
||||||
static void writeBox
|
static void writeBox
|
||||||
(
|
(
|
||||||
ensightGeoFile& os,
|
ensightGeoFile& os,
|
||||||
|
|||||||
@ -54,7 +54,7 @@ namespace
|
|||||||
{
|
{
|
||||||
|
|
||||||
// Trivial shape classifier
|
// Trivial shape classifier
|
||||||
inline Foam::ensightFaces::elemType whatType(const Foam::face& f)
|
inline Foam::ensightFaces::elemType whatType(const Foam::face& f) noexcept
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
(
|
(
|
||||||
|
|||||||
@ -266,6 +266,7 @@ public:
|
|||||||
virtual void writeDict(Ostream& os, const bool full=false) const;
|
virtual void writeDict(Ostream& os, const bool full=false) const;
|
||||||
|
|
||||||
//- Write geometry, using a mesh reference
|
//- Write geometry, using a mesh reference
|
||||||
|
//- No beginGeometry() marker.
|
||||||
virtual void write
|
virtual void write
|
||||||
(
|
(
|
||||||
ensightGeoFile& os,
|
ensightGeoFile& os,
|
||||||
|
|||||||
@ -61,9 +61,7 @@ void Foam::ensightPart::decrAddressing(const label off)
|
|||||||
Foam::ensightPart::ensightPart()
|
Foam::ensightPart::ensightPart()
|
||||||
:
|
:
|
||||||
index_(0),
|
index_(0),
|
||||||
identifier_(-1),
|
identifier_(-1)
|
||||||
name_(),
|
|
||||||
address_()
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -35,8 +35,8 @@ SourceFiles
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef ensightPart_H
|
#ifndef Foam_ensightPart_H
|
||||||
#define ensightPart_H
|
#define Foam_ensightPart_H
|
||||||
|
|
||||||
#include "ensightGeoFile.H"
|
#include "ensightGeoFile.H"
|
||||||
#include "labelList.H"
|
#include "labelList.H"
|
||||||
|
|||||||
@ -42,8 +42,8 @@ SourceFiles
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef ensightOutputSurface_H
|
#ifndef Foam_ensightOutputSurface_H
|
||||||
#define ensightOutputSurface_H
|
#define Foam_ensightOutputSurface_H
|
||||||
|
|
||||||
#include "ensightFaces.H"
|
#include "ensightFaces.H"
|
||||||
|
|
||||||
@ -69,7 +69,9 @@ class ensightOutputSurface
|
|||||||
const faceList& faces_;
|
const faceList& faces_;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
public:
|
||||||
|
|
||||||
|
// Generated Methods
|
||||||
|
|
||||||
//- No copy construct
|
//- No copy construct
|
||||||
ensightOutputSurface(const ensightOutputSurface&) = delete;
|
ensightOutputSurface(const ensightOutputSurface&) = delete;
|
||||||
@ -78,8 +80,6 @@ class ensightOutputSurface
|
|||||||
void operator=(const ensightOutputSurface&) = delete;
|
void operator=(const ensightOutputSurface&) = delete;
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct from points and faces.
|
//- Construct from points and faces.
|
||||||
@ -98,7 +98,8 @@ public:
|
|||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
//- Write processor-local geometry (serial-only)
|
//- Write processor-local geometry (serial-only).
|
||||||
|
//- No beginGeometry() marker.
|
||||||
void write(ensightGeoFile& os) const;
|
void write(ensightGeoFile& os) const;
|
||||||
|
|
||||||
//- Write a field of face or point values (serial-only)
|
//- Write a field of face or point values (serial-only)
|
||||||
@ -121,7 +122,8 @@ public:
|
|||||||
|
|
||||||
// Housekeeping
|
// Housekeeping
|
||||||
|
|
||||||
//- Cannot write geometry with a mesh reference
|
//- Cannot write geometry with a mesh reference.
|
||||||
|
//- No beginGeometry() marker.
|
||||||
virtual void write(ensightGeoFile&, const polyMesh&, bool) const
|
virtual void write(ensightGeoFile&, const polyMesh&, bool) const
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -26,50 +26,300 @@ License
|
|||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "ensightReadFile.H"
|
#include "ensightReadFile.H"
|
||||||
|
#include "stringOps.H"
|
||||||
|
#include "defineDebugSwitch.H"
|
||||||
|
#include "registerSwitch.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::IOstreamOption::streamFormat
|
defineDebugSwitchWithName(Foam::ensightReadFile, "ensightReadFile", 0);
|
||||||
Foam::ensightReadFile::detectBinaryHeader(const fileName& pathname)
|
|
||||||
|
registerDebugSwitchWithName(Foam::ensightReadFile, ensight, "ensightReadFile");
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
{
|
{
|
||||||
IOstreamOption::streamFormat fmt(IOstreamOption::BINARY);
|
|
||||||
|
|
||||||
// Detect BINARY vs ASCII by testing for initial "(C|Fortran) Binary"
|
// Get integers, floats etc in binary or ascii.
|
||||||
|
template<class Type>
|
||||||
|
static inline Type getPrimitive(IFstream& is)
|
||||||
|
{
|
||||||
|
Type value(0);
|
||||||
|
|
||||||
|
auto& iss = is.stdStream();
|
||||||
|
|
||||||
|
if (is.format() == IOstreamOption::BINARY)
|
||||||
{
|
{
|
||||||
IFstream ifs(pathname, IOstreamOption::BINARY);
|
iss.read(reinterpret_cast<char*>(&value), sizeof(Type));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iss >> value;
|
||||||
|
}
|
||||||
|
is.syncState();
|
||||||
|
|
||||||
if (!ifs.good())
|
return value;
|
||||||
{
|
}
|
||||||
FatalErrorInFunction
|
|
||||||
<< "Cannot read file " << ifs.name() << nl
|
|
||||||
<< exit(FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
istream& iss = ifs.stdStream();
|
|
||||||
|
// Get an Ensight string value (binary or ascii).
|
||||||
|
static inline void readEnsightString(IFstream& is, std::string& value)
|
||||||
|
{
|
||||||
|
if (is.format() == IOstreamOption::BINARY)
|
||||||
|
{
|
||||||
|
auto& iss = is.stdStream();
|
||||||
|
|
||||||
// Binary string is *exactly* 80 characters
|
// Binary string is *exactly* 80 characters
|
||||||
string buf(size_t(80), '\0');
|
value.resize(80, '\0');
|
||||||
iss.read(&buf[0], 80);
|
iss.read(&value[0], 80);
|
||||||
const std::streamsize gcount = iss.gcount();
|
const std::streamsize gcount = iss.gcount();
|
||||||
buf.erase(gcount <= 0 ? 0 : gcount); // Truncated?
|
value.erase(gcount <= 0 ? 0 : gcount); // Truncated?
|
||||||
|
|
||||||
// Could exit on truncated input, but no real advantage
|
// Could exit on truncated input, but no real advantage
|
||||||
|
|
||||||
// Truncate at the first embedded '\0'
|
// Truncate at the first embedded '\0'
|
||||||
const auto endp = buf.find('\0');
|
const auto endp = value.find('\0');
|
||||||
|
|
||||||
if (endp != std::string::npos)
|
if (endp != std::string::npos)
|
||||||
{
|
{
|
||||||
buf.erase(endp);
|
value.erase(endp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ASCII if it does not contain "C Binary"
|
// May have been padded with trailing spaces - remove those
|
||||||
if (!buf.contains("Binary") && !buf.contains("binary"))
|
stringOps::inplaceTrimRight(value);
|
||||||
|
|
||||||
|
is.syncState();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value.clear();
|
||||||
|
while (value.empty() && !is.eof())
|
||||||
{
|
{
|
||||||
fmt = IOstreamOption::ASCII;
|
is.getLine(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return fmt;
|
|
||||||
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// Footer information looks like this
|
||||||
|
//
|
||||||
|
/* |---------------|---------------|-----------------------|
|
||||||
|
* | ASCII | BINARY | element |
|
||||||
|
* |---------------|---------------|-----------------------|
|
||||||
|
* | "%20lld\n" | int32 | nSteps |
|
||||||
|
* | "%20lld\n" | int64 | offset step 1 |
|
||||||
|
* | "%20lld\n" | int64 | offset step 2 |
|
||||||
|
* | "%20lld\n" | .. | |
|
||||||
|
* | "%20lld\n" | int64 | offset step n |
|
||||||
|
* | "%20lld\n" | int32 | flag (unused) |
|
||||||
|
* | "%20lld\n" | int64 | offset to nSteps |
|
||||||
|
* | "%s\n" | char[80] | 'FILE_INDEX' |
|
||||||
|
* |---------------|---------------|-----------------------|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int64_t Foam::ensightReadFile::getTimeStepFooter
|
||||||
|
(
|
||||||
|
IFstream& is,
|
||||||
|
// File offsets for each time step (if any)
|
||||||
|
List<int64_t>& offsets
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::string buffer;
|
||||||
|
|
||||||
|
auto& iss = is.stdStream();
|
||||||
|
const auto lineNum = is.lineNumber();
|
||||||
|
const auto curr_pos = iss.tellg();
|
||||||
|
|
||||||
|
if (curr_pos < 0)
|
||||||
|
{
|
||||||
|
// Impossible positioning - exit
|
||||||
|
is.lineNumber(lineNum); // Restore line number
|
||||||
|
offsets.clear();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss.seekg(0, std::ios_base::end);
|
||||||
|
const auto end_pos = iss.tellg();
|
||||||
|
|
||||||
|
// As a minimum, expect at least 1 time step, so have four integers
|
||||||
|
// (nSteps, offset step 1, flag, file offset) and the string (10 chars).
|
||||||
|
// Thus always at least 80+ chars.
|
||||||
|
|
||||||
|
if (end_pos <= 80)
|
||||||
|
{
|
||||||
|
// Looks quite impossible - exit
|
||||||
|
|
||||||
|
is.lineNumber(lineNum); // Restore line number
|
||||||
|
iss.seekg(curr_pos); // Restore file position
|
||||||
|
|
||||||
|
offsets.clear();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the last 80 chars as a character string
|
||||||
|
iss.seekg(-80, std::ios_base::end);
|
||||||
|
|
||||||
|
const auto fmt = is.format(IOstreamOption::BINARY);
|
||||||
|
readEnsightString(is, buffer);
|
||||||
|
is.format(fmt);
|
||||||
|
|
||||||
|
int64_t footer_begin(0);
|
||||||
|
|
||||||
|
const auto endp = buffer.find("FILE_INDEX");
|
||||||
|
|
||||||
|
if (endp == std::string::npos)
|
||||||
|
{
|
||||||
|
// Not found
|
||||||
|
|
||||||
|
is.lineNumber(lineNum); // Restore line number
|
||||||
|
iss.seekg(curr_pos); // Restore file position
|
||||||
|
|
||||||
|
offsets.clear();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (fmt == IOstreamOption::ASCII)
|
||||||
|
{
|
||||||
|
// In ASCII, the last 80 chars will also include a few integers
|
||||||
|
buffer.erase(endp); // Remove FILE_INDEX ...
|
||||||
|
auto split = stringOps::splitSpace(buffer);
|
||||||
|
|
||||||
|
if (!split.empty())
|
||||||
|
{
|
||||||
|
footer_begin = Foam::readInt64(split.back().str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Position before string (80 bytes) and int64 value (8 bytes)
|
||||||
|
iss.seekg(-88, std::ios_base::end);
|
||||||
|
footer_begin = getPrimitive<int64_t>(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// The number of steps is stored as int32 at the beginning of the footer
|
||||||
|
int32_t nSteps(0);
|
||||||
|
|
||||||
|
if (footer_begin)
|
||||||
|
{
|
||||||
|
iss.seekg(footer_begin);
|
||||||
|
nSteps = getPrimitive<int32_t>(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
offsets.resize_nocopy(nSteps);
|
||||||
|
|
||||||
|
// Next footer entries are the offsets per time-step
|
||||||
|
for (int32_t step = 0; step < nSteps; ++step)
|
||||||
|
{
|
||||||
|
offsets[step] = getPrimitive<int64_t>(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
is.lineNumber(lineNum); // Restore line number
|
||||||
|
iss.seekg(curr_pos); // Restore file position
|
||||||
|
|
||||||
|
return footer_begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::ensightReadFile::readString(std::string& value)
|
||||||
|
{
|
||||||
|
readEnsightString(*this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::ensightReadFile::init(bool detectFormat)
|
||||||
|
{
|
||||||
|
if (!IFstream::good())
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Cannot read file " << IFstream::name() << nl
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& iss = stdStream();
|
||||||
|
|
||||||
|
auto lineNum = lineNumber();
|
||||||
|
auto curr_pos = iss.tellg(); // The starting position (should be 0)
|
||||||
|
|
||||||
|
string buffer;
|
||||||
|
|
||||||
|
if (detectFormat)
|
||||||
|
{
|
||||||
|
// Read initial string as BINARY
|
||||||
|
IFstream::format(IOstreamOption::BINARY);
|
||||||
|
|
||||||
|
readEnsightString(*this, buffer);
|
||||||
|
|
||||||
|
// Detect BINARY vs ASCII by testing for initial "(C|Fortran) Binary"
|
||||||
|
if (buffer.contains("Binary") || buffer.contains("binary"))
|
||||||
|
{
|
||||||
|
// Format is BINARY
|
||||||
|
IFstream::format(IOstreamOption::BINARY);
|
||||||
|
|
||||||
|
// New backtracking point is after the initial "C Binary" string
|
||||||
|
curr_pos = iss.tellg();
|
||||||
|
|
||||||
|
// Get the next (optional) line after the "C Binary" (if any)
|
||||||
|
// and before the description.
|
||||||
|
readEnsightString(*this, buffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Not binary => ASCII
|
||||||
|
IFstream::format(IOstreamOption::ASCII);
|
||||||
|
|
||||||
|
// Rewind to the beginning again
|
||||||
|
iss.seekg(curr_pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Get the next line.
|
||||||
|
// It is either the description line or "BEGIN TIME STEP".
|
||||||
|
readEnsightString(*this, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// The buffer string now either contains the description line
|
||||||
|
// or "BEGIN TIME STEP"
|
||||||
|
|
||||||
|
if (buffer.starts_with("BEGIN TIME STEP"))
|
||||||
|
{
|
||||||
|
// Transient single file.
|
||||||
|
// File position is now after the "BEGIN TIME STEP" string
|
||||||
|
|
||||||
|
curr_pos = iss.tellg(); // Fallback value
|
||||||
|
|
||||||
|
timeStepFooterBegin_ = getTimeStepFooter(*this, timeStepOffsets_);
|
||||||
|
|
||||||
|
if (timeStepOffsets_.empty())
|
||||||
|
{
|
||||||
|
// Treat like a single time step
|
||||||
|
timeStepOffsets_.resize(1, int64_t(curr_pos));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// A description line and not "BEGIN TIME STEP"
|
||||||
|
// so backtrack to before it was read
|
||||||
|
|
||||||
|
lineNumber(lineNum); // Restore line number
|
||||||
|
iss.seekg(curr_pos); // Restore file position
|
||||||
|
|
||||||
|
timeStepFooterBegin_ = -1; // safety
|
||||||
|
timeStepOffsets_.clear(); // safety
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugInfo<< "Time-steps: " << timeStepOffsets_.size() << endl;
|
||||||
|
|
||||||
|
syncState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -80,8 +330,11 @@ Foam::ensightReadFile::ensightReadFile
|
|||||||
const fileName& pathname
|
const fileName& pathname
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
IFstream(pathname, ensightReadFile::detectBinaryHeader(pathname))
|
IFstream(pathname, IOstreamOption::BINARY), // Start as BINARY
|
||||||
{}
|
timeStepFooterBegin_(-1)
|
||||||
|
{
|
||||||
|
init(true); // detectFormat = true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::ensightReadFile::ensightReadFile
|
Foam::ensightReadFile::ensightReadFile
|
||||||
@ -90,12 +343,16 @@ Foam::ensightReadFile::ensightReadFile
|
|||||||
IOstreamOption::streamFormat fmt
|
IOstreamOption::streamFormat fmt
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
IFstream(pathname, fmt)
|
IFstream(pathname, fmt),
|
||||||
{}
|
timeStepFooterBegin_(-1)
|
||||||
|
{
|
||||||
|
init(false); // detectFormat = false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// Same as IFstream::readRaw(buf, count)
|
||||||
Foam::Istream& Foam::ensightReadFile::read
|
Foam::Istream& Foam::ensightReadFile::read
|
||||||
(
|
(
|
||||||
char* buf,
|
char* buf,
|
||||||
@ -108,113 +365,39 @@ Foam::Istream& Foam::ensightReadFile::read
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TBD
|
||||||
|
// Foam::Istream& Foam::ensightReadFile::read(word& value)
|
||||||
|
// {
|
||||||
|
// readString(value);
|
||||||
|
// string::stripInvalid<word>(value);
|
||||||
|
// return *this;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
Foam::Istream& Foam::ensightReadFile::read(string& value)
|
Foam::Istream& Foam::ensightReadFile::read(string& value)
|
||||||
{
|
{
|
||||||
if (format() == IOstreamOption::BINARY)
|
readString(value);
|
||||||
{
|
|
||||||
auto& iss = stdStream();
|
|
||||||
|
|
||||||
// Binary string is *exactly* 80 characters
|
|
||||||
value.resize(80, '\0');
|
|
||||||
iss.read(&value[0], 80);
|
|
||||||
const std::streamsize gcount = iss.gcount();
|
|
||||||
value.erase(gcount <= 0 ? 0 : gcount); // Truncated?
|
|
||||||
|
|
||||||
// Could exit on truncated input, but no real advantage
|
|
||||||
|
|
||||||
syncState();
|
|
||||||
|
|
||||||
// Truncate at the first embedded '\0'
|
|
||||||
auto endp = value.find('\0');
|
|
||||||
|
|
||||||
if (endp != std::string::npos)
|
|
||||||
{
|
|
||||||
value.erase(endp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// May have been padded with trailing spaces - remove those
|
|
||||||
endp = value.find_last_not_of(" \t\f\v\n\r");
|
|
||||||
|
|
||||||
if (endp != std::string::npos)
|
|
||||||
{
|
|
||||||
value.erase(endp + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
value.clear();
|
|
||||||
while (value.empty() && !eof())
|
|
||||||
{
|
|
||||||
getLine(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::Istream& Foam::ensightReadFile::read(label& value)
|
Foam::Istream& Foam::ensightReadFile::read(label& value)
|
||||||
{
|
{
|
||||||
int ivalue;
|
value = getPrimitive<int>(*this);
|
||||||
|
|
||||||
if (format() == IOstreamOption::BINARY)
|
|
||||||
{
|
|
||||||
read
|
|
||||||
(
|
|
||||||
reinterpret_cast<char*>(&ivalue),
|
|
||||||
sizeof(ivalue)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stdStream() >> ivalue;
|
|
||||||
syncState();
|
|
||||||
}
|
|
||||||
|
|
||||||
value = ivalue;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::Istream& Foam::ensightReadFile::read(float& value)
|
Foam::Istream& Foam::ensightReadFile::read(float& value)
|
||||||
{
|
{
|
||||||
if (format() == IOstreamOption::BINARY)
|
value = getPrimitive<float>(*this);
|
||||||
{
|
|
||||||
read
|
|
||||||
(
|
|
||||||
reinterpret_cast<char*>(&value),
|
|
||||||
sizeof(value)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stdStream() >> value;
|
|
||||||
syncState();
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::Istream& Foam::ensightReadFile::read(double& value)
|
Foam::Istream& Foam::ensightReadFile::read(double& value)
|
||||||
{
|
{
|
||||||
float fvalue;
|
value = getPrimitive<float>(*this);
|
||||||
|
|
||||||
if (format() == IOstreamOption::BINARY)
|
|
||||||
{
|
|
||||||
read
|
|
||||||
(
|
|
||||||
reinterpret_cast<char*>(&fvalue),
|
|
||||||
sizeof(fvalue)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stdStream() >> fvalue;
|
|
||||||
syncState();
|
|
||||||
}
|
|
||||||
|
|
||||||
value = fvalue;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,15 +409,79 @@ Foam::Istream& Foam::ensightReadFile::readKeyword(string& key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::Istream& Foam::ensightReadFile::readBinaryHeader()
|
void Foam::ensightReadFile::readPoints
|
||||||
|
(
|
||||||
|
const label nPoints,
|
||||||
|
List<floatVector>& points
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (format() == IOstreamOption::BINARY)
|
points.resize_nocopy(nPoints);
|
||||||
|
|
||||||
|
for (auto& p : points)
|
||||||
{
|
{
|
||||||
string buffer;
|
read(p.x());
|
||||||
read(buffer);
|
}
|
||||||
|
for (auto& p : points)
|
||||||
|
{
|
||||||
|
read(p.y());
|
||||||
|
}
|
||||||
|
for (auto& p : points)
|
||||||
|
{
|
||||||
|
read(p.z());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::ensightReadFile::readPoints
|
||||||
|
(
|
||||||
|
const label nPoints,
|
||||||
|
List<doubleVector>& points
|
||||||
|
)
|
||||||
|
{
|
||||||
|
points.resize_nocopy(nPoints);
|
||||||
|
|
||||||
|
for (auto& p : points)
|
||||||
|
{
|
||||||
|
read(p.x());
|
||||||
|
}
|
||||||
|
for (auto& p : points)
|
||||||
|
{
|
||||||
|
read(p.y());
|
||||||
|
}
|
||||||
|
for (auto& p : points)
|
||||||
|
{
|
||||||
|
read(p.z());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::ensightReadFile::seekTime(const label timeIndex)
|
||||||
|
{
|
||||||
|
if (timeIndex >= 0 && timeIndex < timeStepOffsets_.size())
|
||||||
|
{
|
||||||
|
auto& iss = stdStream();
|
||||||
|
|
||||||
|
iss.seekg(timeStepOffsets_[timeIndex]);
|
||||||
|
syncState();
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Info<< "seek time "
|
||||||
|
<< timeIndex << '/' << nTimes()
|
||||||
|
<< " offset:" << label(timeStepOffsets_[timeIndex]) << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
if (debug)
|
||||||
|
{
|
||||||
|
Info<< "seek time "
|
||||||
|
<< timeIndex << '/' << nTimes()
|
||||||
|
<< " ignored" << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2016-2023 OpenCFD Ltd.
|
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -27,9 +27,8 @@ Class
|
|||||||
Foam::ensightReadFile
|
Foam::ensightReadFile
|
||||||
|
|
||||||
Description
|
Description
|
||||||
A variant of IFstream with specialised read() for
|
A variant of IFstream with specialised handling for Ensight reading
|
||||||
strings, integers and floats.
|
of strings, integers and floats (ASCII and BINARY).
|
||||||
Correctly handles binary read as well.
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
@ -38,6 +37,7 @@ Description
|
|||||||
|
|
||||||
#include "IFstream.H"
|
#include "IFstream.H"
|
||||||
#include "IOstream.H"
|
#include "IOstream.H"
|
||||||
|
#include "vector.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -52,9 +52,28 @@ class ensightReadFile
|
|||||||
:
|
:
|
||||||
public IFstream
|
public IFstream
|
||||||
{
|
{
|
||||||
public:
|
// Private Data
|
||||||
|
|
||||||
// Generated Methods
|
//- Transient single-file:
|
||||||
|
//- beginning of time-step footer
|
||||||
|
//- as read from the file
|
||||||
|
int64_t timeStepFooterBegin_;
|
||||||
|
|
||||||
|
//- Transient single-file:
|
||||||
|
//- the time-step file-offsets (position after "BEGIN TIME STEP")
|
||||||
|
//- as read from the file
|
||||||
|
List<int64_t> timeStepOffsets_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Read string as "%80s" or as binary
|
||||||
|
void readString(std::string& value);
|
||||||
|
|
||||||
|
//- Initializes read information
|
||||||
|
//- (optional detection of "C Binary" header)
|
||||||
|
//- and scan for transient single-file format.
|
||||||
|
void init(bool detectFormat);
|
||||||
|
|
||||||
//- No copy construct
|
//- No copy construct
|
||||||
ensightReadFile(const ensightReadFile&) = delete;
|
ensightReadFile(const ensightReadFile&) = delete;
|
||||||
@ -63,10 +82,20 @@ public:
|
|||||||
void operator=(const ensightReadFile&) = delete;
|
void operator=(const ensightReadFile&) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Debug switch
|
||||||
|
static int debug;
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct from pathname, auto-detect the format
|
//- Construct a geometry reader, auto-detecting the "C Binary" header
|
||||||
explicit ensightReadFile(const fileName& pathname);
|
//- for binary files and skipping past it.
|
||||||
|
explicit ensightReadFile
|
||||||
|
(
|
||||||
|
const fileName& pathname
|
||||||
|
);
|
||||||
|
|
||||||
//- Construct from pathname, use the specified (ascii/binary) format
|
//- Construct from pathname, use the specified (ascii/binary) format
|
||||||
ensightReadFile
|
ensightReadFile
|
||||||
@ -82,11 +111,13 @@ public:
|
|||||||
|
|
||||||
// Static Functions
|
// Static Functions
|
||||||
|
|
||||||
//- Detect if the file is \em binary by testing for initial
|
//- Extract time step footer information (if any).
|
||||||
//- "(C|Fortran) Binary"
|
// \return the begin of footer position.
|
||||||
static IOstreamOption::streamFormat detectBinaryHeader
|
static int64_t getTimeStepFooter
|
||||||
(
|
(
|
||||||
const fileName& pathname
|
IFstream& is,
|
||||||
|
//! [out] File offsets for each time step (if any)
|
||||||
|
List<int64_t>& offsets
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@ -101,7 +132,7 @@ public:
|
|||||||
//- Read string as "%80s" or as binary
|
//- Read string as "%80s" or as binary
|
||||||
virtual Istream& read(string& value) override;
|
virtual Istream& read(string& value) override;
|
||||||
|
|
||||||
//- Read integer as "%10d" or as binary
|
//- Read integer as "%10d" or as binary (narrowed) int
|
||||||
virtual Istream& read(label& value) override;
|
virtual Istream& read(label& value) override;
|
||||||
|
|
||||||
//- Read floating-point as "%12.5e" or as binary
|
//- Read floating-point as "%12.5e" or as binary
|
||||||
@ -113,8 +144,68 @@ public:
|
|||||||
//- Read element keyword. Currently the same as read(string)
|
//- Read element keyword. Currently the same as read(string)
|
||||||
Istream& readKeyword(string& key);
|
Istream& readKeyword(string& key);
|
||||||
|
|
||||||
//- Read "C Binary" for binary files (eg, geometry/measured)
|
|
||||||
Istream& readBinaryHeader();
|
// Special Read Functions
|
||||||
|
|
||||||
|
//- Component-wise reading of points/coordinates.
|
||||||
|
//- Read all x components, y components and z components.
|
||||||
|
void readPoints(const label nPoints, List<floatVector>& points);
|
||||||
|
|
||||||
|
//- Component-wise reading of points/coordinates.
|
||||||
|
//- Reads x components, y components and z components.
|
||||||
|
void readPoints(const label nPoints, List<doubleVector>& points);
|
||||||
|
|
||||||
|
//- Read and discard specified number of elements
|
||||||
|
template<class Type>
|
||||||
|
void skip(label n = 1)
|
||||||
|
{
|
||||||
|
Type dummy;
|
||||||
|
for (; n > 0; --n)
|
||||||
|
{
|
||||||
|
this->read(dummy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Transient single-file format
|
||||||
|
|
||||||
|
//- Transient single-file:
|
||||||
|
//- the position of the FILE_INDEX footer
|
||||||
|
int64_t timeStepFooterBegin() const noexcept
|
||||||
|
{
|
||||||
|
return timeStepFooterBegin_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Transient single-file:
|
||||||
|
//- the number of time steps within the file
|
||||||
|
label nTimes() const noexcept
|
||||||
|
{
|
||||||
|
return timeStepOffsets_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Transient single-file:
|
||||||
|
//- the file-offsets for time steps within the file
|
||||||
|
const UList<int64_t>& timeStepOffets() const noexcept
|
||||||
|
{
|
||||||
|
return timeStepOffsets_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Transient single-file:
|
||||||
|
//- seek to the file position corresponding to the given time index.
|
||||||
|
bool seekTime(const label timeIndex);
|
||||||
|
|
||||||
|
|
||||||
|
// Housekeeping
|
||||||
|
|
||||||
|
//- Detect if the file is \em binary by testing for initial
|
||||||
|
//- "(C|Fortran) Binary"
|
||||||
|
FOAM_DEPRECATED_FOR(2024-05, "detected on construct")
|
||||||
|
static IOstreamOption::streamFormat
|
||||||
|
detectBinaryHeader(const fileName& pathname)
|
||||||
|
{
|
||||||
|
ensightReadFile reader(pathname);
|
||||||
|
return reader.format();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2021-2022 OpenCFD Ltd.
|
Copyright (C) 2021-2024 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -125,6 +125,11 @@ void Foam::ensightFaMesh::write
|
|||||||
bool parallel
|
bool parallel
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
|
if (UPstream::master())
|
||||||
|
{
|
||||||
|
os.beginGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
// Area meshes (currently only one)
|
// Area meshes (currently only one)
|
||||||
// const label areaId = 0;
|
// const label areaId = 0;
|
||||||
areaPart_.write(os, mesh_.mesh(), parallel);
|
areaPart_.write(os, mesh_.mesh(), parallel);
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2021-2022 OpenCFD Ltd.
|
Copyright (C) 2021-2024 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -147,14 +147,17 @@ public:
|
|||||||
|
|
||||||
// Output
|
// Output
|
||||||
|
|
||||||
//- Write geometry to file. Normally in parallel
|
//- Write geometry to file (normally in parallel).
|
||||||
|
//- Adds beginGeometry() marker.
|
||||||
void write
|
void write
|
||||||
(
|
(
|
||||||
ensightGeoFile& os,
|
ensightGeoFile& os,
|
||||||
bool parallel = UPstream::parRun()
|
bool parallel = UPstream::parRun()
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Write geometry to file. Normally in parallel
|
//- Write geometry to file (normally in parallel).
|
||||||
|
//- Adds beginGeometry() marker.
|
||||||
|
FOAM_DEPRECATED_FOR(2024-05, "write(ensightGeoFile&, ...")
|
||||||
inline void write
|
inline void write
|
||||||
(
|
(
|
||||||
autoPtr<ensightGeoFile>& os,
|
autoPtr<ensightGeoFile>& os,
|
||||||
|
|||||||
@ -391,6 +391,11 @@ bool Foam::functionObjects::ensightCloudWriteObject::write()
|
|||||||
// Generate a (non-moving) dummy geometry
|
// Generate a (non-moving) dummy geometry
|
||||||
// - ParaView ensight-reader needs this, and usually ensight does too
|
// - ParaView ensight-reader needs this, and usually ensight does too
|
||||||
autoPtr<ensightGeoFile> os = ensCase().newGeometry(false);
|
autoPtr<ensightGeoFile> os = ensCase().newGeometry(false);
|
||||||
|
|
||||||
|
if (os)
|
||||||
|
{
|
||||||
|
os->beginGeometry();
|
||||||
|
}
|
||||||
ensightCells::writeBox(os.ref(), mesh_.bounds());
|
ensightCells::writeBox(os.ref(), mesh_.bounds());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -237,7 +237,7 @@ bool Foam::functionObjects::ensightWrite::write()
|
|||||||
// Treat all geometry as moving, since we do not know a priori
|
// Treat all geometry as moving, since we do not know a priori
|
||||||
// if the simulation has mesh motion later on.
|
// if the simulation has mesh motion later on.
|
||||||
autoPtr<ensightGeoFile> os = ensCase_().newGeometry(true);
|
autoPtr<ensightGeoFile> os = ensCase_().newGeometry(true);
|
||||||
ensMesh_().write(os);
|
ensMesh_().write(os.ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -92,9 +92,9 @@ Foam::fileName Foam::coordSetWriters::ensightWriter::writeCollated
|
|||||||
merge();
|
merge();
|
||||||
|
|
||||||
{
|
{
|
||||||
if (!isDir(outputFile.path()))
|
if (!Foam::isDir(outputFile.path()))
|
||||||
{
|
{
|
||||||
mkDir(outputFile.path());
|
Foam::mkDir(outputFile.path());
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool stateChanged =
|
const bool stateChanged =
|
||||||
@ -131,12 +131,12 @@ Foam::fileName Foam::coordSetWriters::ensightWriter::writeCollated
|
|||||||
);
|
);
|
||||||
|
|
||||||
// As per mkdir -p "data/00000000"
|
// As per mkdir -p "data/00000000"
|
||||||
mkDir(dataDir);
|
Foam::mkDir(dataDir);
|
||||||
|
|
||||||
|
|
||||||
const fileName geomFile(baseDir/geometryName);
|
const fileName geomFile(baseDir/geometryName);
|
||||||
|
|
||||||
if (!exists(geomFile))
|
if (!Foam::exists(geomFile))
|
||||||
{
|
{
|
||||||
if (verbose_)
|
if (verbose_)
|
||||||
{
|
{
|
||||||
@ -151,6 +151,7 @@ Foam::fileName Foam::coordSetWriters::ensightWriter::writeCollated
|
|||||||
caseOpts_.format()
|
caseOpts_.format()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
osGeom.beginGeometry();
|
||||||
writeGeometry(osGeom, elemOutput);
|
writeGeometry(osGeom, elemOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +177,12 @@ Foam::fileName Foam::coordSetWriters::ensightWriter::writeCollated
|
|||||||
// Update case file
|
// Update case file
|
||||||
if (stateChanged)
|
if (stateChanged)
|
||||||
{
|
{
|
||||||
OFstream osCase(outputFile, IOstreamOption::ASCII);
|
OFstream osCase
|
||||||
|
(
|
||||||
|
IOstreamOption::ATOMIC,
|
||||||
|
outputFile,
|
||||||
|
IOstreamOption::ASCII
|
||||||
|
);
|
||||||
ensightCase::setTimeFormat(osCase, caseOpts_); // time-format
|
ensightCase::setTimeFormat(osCase, caseOpts_); // time-format
|
||||||
|
|
||||||
if (verbose_)
|
if (verbose_)
|
||||||
|
|||||||
@ -91,9 +91,9 @@ Foam::fileName Foam::coordSetWriters::ensightWriter::writeUncollated
|
|||||||
merge();
|
merge();
|
||||||
|
|
||||||
{
|
{
|
||||||
if (!isDir(outputFile.path()))
|
if (!Foam::isDir(outputFile.path()))
|
||||||
{
|
{
|
||||||
mkDir(outputFile.path());
|
Foam::mkDir(outputFile.path());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Two-argument form for path-name to avoid validating base-dir
|
// Two-argument form for path-name to avoid validating base-dir
|
||||||
@ -110,6 +110,7 @@ Foam::fileName Foam::coordSetWriters::ensightWriter::writeUncollated
|
|||||||
caseOpts_.format()
|
caseOpts_.format()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
osGeom.beginGeometry();
|
||||||
writeGeometry(osGeom, elemOutput);
|
writeGeometry(osGeom, elemOutput);
|
||||||
|
|
||||||
// Write field (serial only)
|
// Write field (serial only)
|
||||||
@ -118,7 +119,12 @@ Foam::fileName Foam::coordSetWriters::ensightWriter::writeUncollated
|
|||||||
|
|
||||||
// Update case file
|
// Update case file
|
||||||
{
|
{
|
||||||
OFstream osCase(outputFile, IOstreamOption::ASCII);
|
OFstream osCase
|
||||||
|
(
|
||||||
|
IOstreamOption::ATOMIC,
|
||||||
|
outputFile,
|
||||||
|
IOstreamOption::ASCII
|
||||||
|
);
|
||||||
ensightCase::setTimeFormat(osCase, caseOpts_); // time-format
|
ensightCase::setTimeFormat(osCase, caseOpts_); // time-format
|
||||||
|
|
||||||
osCase
|
osCase
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2015-2022 OpenCFD Ltd.
|
Copyright (C) 2015-2024 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -44,54 +44,57 @@ namespace Foam
|
|||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
// Read and discard specified number of elements
|
// Extract timeset and fileset from split line information
|
||||||
template<class Type>
|
// when the minElements has been satisfied.
|
||||||
static inline void discard(label n, ensightReadFile& is)
|
// For example,
|
||||||
|
// ----
|
||||||
|
// model: 1 some-geometry
|
||||||
|
// model: 1 1 some-geometry
|
||||||
|
// ----
|
||||||
|
// would be split *after* the 'model:' resulting in these sub-strings:
|
||||||
|
//
|
||||||
|
// ("1" "some-geometry")
|
||||||
|
// ("1" "1" some-geometry")
|
||||||
|
//
|
||||||
|
// thus call extractTimeset with minElements == 2
|
||||||
|
//
|
||||||
|
template<class StringType>
|
||||||
|
static inline labelPair extractTimeset
|
||||||
|
(
|
||||||
|
const SubStrings<StringType>& split,
|
||||||
|
const std::size_t minElements
|
||||||
|
)
|
||||||
{
|
{
|
||||||
Type val;
|
ISpanStream is;
|
||||||
|
|
||||||
while (n > 0)
|
labelPair result(-1, -1);
|
||||||
|
if (split.size() >= minElements)
|
||||||
{
|
{
|
||||||
is.read(val);
|
is.reset(split[0]);
|
||||||
--n;
|
is >> result.first();
|
||||||
|
|
||||||
|
if (split.size() > minElements)
|
||||||
|
{
|
||||||
|
is.reset(split[1]);
|
||||||
|
is >> result.second();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * Protected Static Member Functions * * * * * * * * * * //
|
||||||
|
|
||||||
void Foam::ensightSurfaceReader::skip(const label n, Istream& is) const
|
bool Foam::ensightSurfaceReader::readLine(ISstream& is, std::string& line)
|
||||||
{
|
|
||||||
label i = 0;
|
|
||||||
token tok;
|
|
||||||
while (is.good() && (i < n))
|
|
||||||
{
|
|
||||||
is >> tok;
|
|
||||||
++i;
|
|
||||||
|
|
||||||
DebugInfo
|
|
||||||
<< "Skipping token " << tok << nl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i != n)
|
|
||||||
{
|
|
||||||
WarningInFunction
|
|
||||||
<< "Requested to skip " << n << " tokens, but stream exited after "
|
|
||||||
<< i << " tokens. Last token read: " << tok
|
|
||||||
<< nl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Foam::ensightSurfaceReader::readLine(ISstream& is, string& line) const
|
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
is.getLine(line);
|
is.getLine(line);
|
||||||
|
|
||||||
// Trim out any '#' comments
|
// Trim out any '#' comments (trailing or otherwise)
|
||||||
const auto pos = line.find('#');
|
const auto pos = line.find('#');
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos)
|
||||||
{
|
{
|
||||||
@ -100,6 +103,32 @@ void Foam::ensightSurfaceReader::readLine(ISstream& is, string& line) const
|
|||||||
stringOps::inplaceTrimRight(line);
|
stringOps::inplaceTrimRight(line);
|
||||||
}
|
}
|
||||||
while (line.empty() && is.good());
|
while (line.empty() && is.good());
|
||||||
|
|
||||||
|
return !line.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::ensightSurfaceReader::checkSection
|
||||||
|
(
|
||||||
|
const word& expected,
|
||||||
|
const string& buffer,
|
||||||
|
const ISstream& is
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Be more generous with our expectations.
|
||||||
|
// Eg, ensight specifies the "VARIABLE" entry,
|
||||||
|
// but accepts "VARIABLES" as well.
|
||||||
|
|
||||||
|
if (!expected.empty() && !buffer.starts_with(expected))
|
||||||
|
{
|
||||||
|
FatalIOErrorInFunction(is)
|
||||||
|
<< "Expected section header '" << expected
|
||||||
|
<< "' but read " << buffer << nl
|
||||||
|
<< exit(FatalIOError);
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugInfo
|
||||||
|
<< "Read section header: " << buffer.c_str() << nl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -107,54 +136,23 @@ void Foam::ensightSurfaceReader::debugSection
|
|||||||
(
|
(
|
||||||
const word& expected,
|
const word& expected,
|
||||||
ISstream& is
|
ISstream& is
|
||||||
) const
|
|
||||||
{
|
|
||||||
string actual;
|
|
||||||
readLine(is, actual);
|
|
||||||
|
|
||||||
if (expected != actual)
|
|
||||||
{
|
|
||||||
FatalIOErrorInFunction(is)
|
|
||||||
<< "Expected section header '" << expected
|
|
||||||
<< "' but read " << actual << nl
|
|
||||||
<< exit(FatalIOError);
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugInfo
|
|
||||||
<< "Read section header: " << expected << nl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::fileName Foam::ensightSurfaceReader::replaceMask
|
|
||||||
(
|
|
||||||
const fileName& fName,
|
|
||||||
const label timeIndex
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
fileName result(fName);
|
string buffer;
|
||||||
|
readLine(is, buffer);
|
||||||
|
|
||||||
const auto nMask = stringOps::count(fName, '*');
|
checkSection(expected, buffer, is);
|
||||||
|
|
||||||
// If there are any '*' chars, they are assumed to be contiguous
|
|
||||||
// Eg, data/******/geometry
|
|
||||||
|
|
||||||
if (nMask)
|
|
||||||
{
|
|
||||||
const std::string maskStr(nMask, '*');
|
|
||||||
const Foam::word indexStr(ensightCase::padded(nMask, timeIndex));
|
|
||||||
result.replace(maskStr, indexStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::Pair<Foam::ensightSurfaceReader::idTypes>
|
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||||
Foam::ensightSurfaceReader::readGeometryHeader(ensightReadFile& is) const
|
|
||||||
{
|
|
||||||
// Binary flag string if applicable
|
|
||||||
is.readBinaryHeader();
|
|
||||||
|
|
||||||
|
Foam::Pair<Foam::ensightSurfaceReader::idTypes>
|
||||||
|
Foam::ensightSurfaceReader::readGeometryHeader
|
||||||
|
(
|
||||||
|
ensightReadFile& is
|
||||||
|
) const
|
||||||
|
{
|
||||||
string buffer;
|
string buffer;
|
||||||
|
|
||||||
Pair<idTypes> idHandling(idTypes::NONE, idTypes::NONE);
|
Pair<idTypes> idHandling(idTypes::NONE, idTypes::NONE);
|
||||||
@ -203,17 +201,17 @@ Foam::ensightSurfaceReader::readGeometryHeader(ensightReadFile& is) const
|
|||||||
// Optional extents - read and discard 6 floats
|
// Optional extents - read and discard 6 floats
|
||||||
// (xmin, xmax, ymin, ymax, zmin, zmax)
|
// (xmin, xmax, ymin, ymax, zmin, zmax)
|
||||||
|
|
||||||
discard<scalar>(6, is);
|
is.skip<scalar>(6);
|
||||||
|
|
||||||
// Part
|
// "part"
|
||||||
is.read(buffer);
|
is.read(buffer);
|
||||||
DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
|
DebugInfo<< "buffer [" << buffer.length() << "] " << buffer << nl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The part number
|
// The part number
|
||||||
label ivalue;
|
label intValue;
|
||||||
is.read(ivalue);
|
is.read(intValue);
|
||||||
DebugInfo<< "ivalue: " << ivalue << nl;
|
DebugInfo<< "part number: " << intValue << nl;
|
||||||
|
|
||||||
// Part description / name
|
// Part description / name
|
||||||
is.read(buffer);
|
is.read(buffer);
|
||||||
@ -231,6 +229,8 @@ void Foam::ensightSurfaceReader::readCase(ISstream& is)
|
|||||||
{
|
{
|
||||||
DebugInFunction << endl;
|
DebugInFunction << endl;
|
||||||
|
|
||||||
|
enum ParseSection { UNKNOWN, FORMAT, GEOMETRY, VARIABLE, TIME, FILE };
|
||||||
|
|
||||||
if (!is.good())
|
if (!is.good())
|
||||||
{
|
{
|
||||||
FatalErrorInFunction
|
FatalErrorInFunction
|
||||||
@ -239,99 +239,366 @@ void Foam::ensightSurfaceReader::readCase(ISstream& is)
|
|||||||
}
|
}
|
||||||
|
|
||||||
string buffer;
|
string buffer;
|
||||||
|
SubStrings<string> split;
|
||||||
|
|
||||||
// Read the file
|
ParseSection parseState = ParseSection::UNKNOWN;
|
||||||
|
|
||||||
|
// FORMAT
|
||||||
|
// ~~~~~~
|
||||||
|
|
||||||
debugSection("FORMAT", is);
|
debugSection("FORMAT", is);
|
||||||
readLine(is, buffer); // type: ensight gold
|
readLine(is, buffer); // type: ensight gold
|
||||||
|
parseState = ParseSection::FORMAT;
|
||||||
|
|
||||||
|
// GEOMETRY
|
||||||
|
// ~~~~~~~~
|
||||||
debugSection("GEOMETRY", is);
|
debugSection("GEOMETRY", is);
|
||||||
readLine(is, buffer);
|
parseState = ParseSection::GEOMETRY;
|
||||||
|
|
||||||
// GEOMETRY with any of these
|
do
|
||||||
// model: 1 xxx.0000.mesh
|
{
|
||||||
// model: xxx.0000.mesh
|
readLine(is, buffer);
|
||||||
// model: data/directory/geometry
|
|
||||||
//
|
|
||||||
// - use the last entry
|
|
||||||
meshFileName_ = stringOps::splitSpace(buffer).back().str();
|
|
||||||
|
|
||||||
DebugInfo << "mesh file:" << meshFileName_ << endl;
|
if (buffer.starts_with("VARIABLE"))
|
||||||
|
{
|
||||||
|
parseState = ParseSection::VARIABLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
debugSection("VARIABLE", is);
|
if (buffer.contains("change_coords_only"))
|
||||||
|
{
|
||||||
|
FatalIOErrorInFunction(is)
|
||||||
|
<< "No support for moving points, only topology change" << nl
|
||||||
|
<< exit(FatalIOError);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract filename from GEOMETRY section
|
||||||
|
// ====
|
||||||
|
// model: [ts] [fs] filename [change_coords_only [cstep]]
|
||||||
|
//
|
||||||
|
// ====
|
||||||
|
|
||||||
|
// TBD:
|
||||||
|
// check for "model:" vs "measured:" ?
|
||||||
|
|
||||||
|
const auto pos_colon = buffer.find(':');
|
||||||
|
|
||||||
|
if
|
||||||
|
(
|
||||||
|
(pos_colon == std::string::npos)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
FatalIOErrorInFunction(is)
|
||||||
|
<< "Error reading geometry 'model:'" << nl
|
||||||
|
<< exit(FatalIOError);
|
||||||
|
}
|
||||||
|
|
||||||
|
split = stringOps::splitSpace(buffer, pos_colon+1);
|
||||||
|
|
||||||
|
if (split.empty())
|
||||||
|
{
|
||||||
|
FatalIOErrorInFunction(is)
|
||||||
|
<< "Error reading geometry 'model:'" << nl
|
||||||
|
<< exit(FatalIOError);
|
||||||
|
}
|
||||||
|
|
||||||
|
// With timeset? - need at least 2 entries
|
||||||
|
meshTimeset_ = extractTimeset(split, 2);
|
||||||
|
meshFileName_ = split[split.size()-1].str();
|
||||||
|
|
||||||
|
DebugInfo << "mesh file:" << meshFileName_ << endl;
|
||||||
|
}
|
||||||
|
while (false);
|
||||||
|
|
||||||
|
|
||||||
|
if (parseState != ParseSection::VARIABLE)
|
||||||
|
{
|
||||||
|
debugSection("VARIABLE", is);
|
||||||
|
parseState = ParseSection::VARIABLE;
|
||||||
|
}
|
||||||
|
|
||||||
// Read the field description
|
// Read the field description
|
||||||
DynamicList<word> fieldNames(16);
|
DynamicList<labelPair> dynFieldTimesets(16);
|
||||||
DynamicList<string> fieldFileNames(16);
|
DynamicList<word> dynFieldNames(16);
|
||||||
|
DynamicList<string> dynFieldFileNames(16);
|
||||||
|
|
||||||
|
// VARIABLE
|
||||||
|
// ~~~~~~~~
|
||||||
|
|
||||||
while (is.good())
|
while (is.good())
|
||||||
{
|
{
|
||||||
readLine(is, buffer);
|
readLine(is, buffer);
|
||||||
|
|
||||||
if (buffer == "TIME")
|
if (buffer.starts_with("TIME"))
|
||||||
{
|
{
|
||||||
|
parseState = ParseSection::TIME;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the field name and associated file name. Eg,
|
// Read the field name and associated file name.
|
||||||
// scalar per element: 1 p data/********/p
|
// Eg,
|
||||||
|
// scalar per element: [ts] [fs] p data/********/p
|
||||||
|
// but ignore
|
||||||
|
// scalar per node: [ts] [fs] other data/********/other
|
||||||
|
|
||||||
const auto parsed = stringOps::splitSpace(buffer);
|
const auto pos_colon = buffer.find(':');
|
||||||
|
|
||||||
if (!buffer.contains(':') || parsed.size() < 4)
|
if (pos_colon == std::string::npos)
|
||||||
|
{
|
||||||
|
DebugInfo<< "ignore variable line: " << buffer << nl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO? handle variable descriptions with spaces (they are quoted)
|
||||||
|
|
||||||
|
split = stringOps::splitSpace(buffer, pos_colon+1);
|
||||||
|
|
||||||
|
if (split.size() < 2)
|
||||||
{
|
{
|
||||||
WarningInFunction
|
WarningInFunction
|
||||||
<< "Error reading field file name. Current buffer: "
|
<< "Error reading field file name, variable line: "
|
||||||
<< buffer << endl;
|
<< buffer << endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (debug)
|
|
||||||
|
auto pos_key = buffer.find("element");
|
||||||
|
if ((pos_key == std::string::npos) || (pos_colon < pos_key))
|
||||||
{
|
{
|
||||||
Info<< "variable line: " << parsed.size();
|
DebugInfo<< "ignore variable line: " << buffer << nl;
|
||||||
for (const auto& s : parsed)
|
continue;
|
||||||
{
|
|
||||||
Info<< " " << s.str();
|
|
||||||
}
|
|
||||||
Info<< nl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldNames.push_back(parsed[parsed.size()-2].str());
|
DebugInfo<< "variable line: " << buffer << nl;
|
||||||
fieldFileNames.push_back(parsed.back().str());
|
|
||||||
|
// With timeset? - need at least 3 entries
|
||||||
|
dynFieldTimesets.push_back(extractTimeset(split, 3));
|
||||||
|
|
||||||
|
dynFieldNames.push_back(split[split.size()-2].str());
|
||||||
|
dynFieldFileNames.push_back(split[split.size()-1].str());
|
||||||
}
|
}
|
||||||
fieldNames_.transfer(fieldNames);
|
fieldTimesets_.transfer(dynFieldTimesets);
|
||||||
fieldFileNames_.transfer(fieldFileNames);
|
fieldNames_.transfer(dynFieldNames);
|
||||||
|
fieldFileNames_.transfer(dynFieldFileNames);
|
||||||
|
|
||||||
DebugInfo
|
DebugInfo
|
||||||
<< "fieldNames: " << fieldNames_ << nl
|
<< "fieldNames: " << fieldNames_ << nl
|
||||||
<< "fieldFileNames: " << fieldFileNames_ << nl;
|
<< "fieldFileNames: " << fieldFileNames_ << nl;
|
||||||
|
|
||||||
// Start reading time information
|
|
||||||
readLine(is, buffer); // time set: <int>
|
|
||||||
|
|
||||||
readLine(is, buffer);
|
if (parseState != ParseSection::TIME)
|
||||||
readFromLine(3, buffer, nTimeSteps_); // number of steps: <int>
|
{
|
||||||
readLine(is, buffer);
|
FatalIOErrorInFunction(is)
|
||||||
readFromLine(3, buffer, timeStartIndex_); // filename start number: <int>
|
<< "Did not find section header 'TIME'" << nl
|
||||||
readLine(is, buffer);
|
<< exit(FatalIOError);
|
||||||
readFromLine(2, buffer, timeIncrement_); // filename increment: <int>
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Determine which unique timeset or fileset to expect
|
||||||
|
|
||||||
|
labelHashSet expectTimeset;
|
||||||
|
labelHashSet expectFileset;
|
||||||
|
|
||||||
|
expectTimeset.insert(meshTimeset_.first());
|
||||||
|
expectFileset.insert(meshTimeset_.second());
|
||||||
|
|
||||||
|
for (const auto& tup : fieldTimesets_)
|
||||||
|
{
|
||||||
|
expectTimeset.insert(tup.first());
|
||||||
|
expectFileset.insert(tup.second());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove placeholders
|
||||||
|
expectTimeset.erase(-1);
|
||||||
|
expectFileset.erase(-1);
|
||||||
|
|
||||||
|
|
||||||
DebugInfo
|
DebugInfo
|
||||||
<< "nTimeSteps: " << nTimeSteps_ << nl
|
<< "expect timesets: " << flatOutput(expectTimeset) << nl
|
||||||
<< "timeStartIndex: " << timeStartIndex_ << nl
|
<< "expect filesets: " << flatOutput(expectFileset) << nl;
|
||||||
<< "timeIncrement: " << timeIncrement_ << nl;
|
|
||||||
|
|
||||||
// Read the time values
|
|
||||||
readLine(is, buffer); // time values:
|
// TIME
|
||||||
timeValues_.resize_nocopy(nTimeSteps_);
|
// ~~~~
|
||||||
for (label i = 0; i < nTimeSteps_; ++i)
|
// style 1:
|
||||||
|
// ====
|
||||||
|
// time set: <int> [description]
|
||||||
|
// number of steps: <int>
|
||||||
|
// filename start number: <int>
|
||||||
|
// filename increment: <int>
|
||||||
|
// time values: time_1 .. time_N
|
||||||
|
// ====
|
||||||
|
//
|
||||||
|
// style 2:
|
||||||
|
// ====
|
||||||
|
// time set: <int> [description]
|
||||||
|
// number of steps: <int>
|
||||||
|
// filename numbers: int_1 .. int_N
|
||||||
|
// time values: time_1 .. time_N
|
||||||
|
// ====
|
||||||
|
//
|
||||||
|
// style 3:
|
||||||
|
// ====
|
||||||
|
// time set: <int> [description]
|
||||||
|
// number of steps: <int>
|
||||||
|
// filename numbers file: <filename>
|
||||||
|
// time values file: <filename>
|
||||||
|
// ====
|
||||||
|
|
||||||
|
|
||||||
|
// Currently only handling style 1, style 2
|
||||||
|
// and only a single time set
|
||||||
|
|
||||||
|
// time set = 1
|
||||||
{
|
{
|
||||||
scalar t(readScalar(is));
|
// time set: <int>
|
||||||
|
{
|
||||||
|
readLine(is, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
timeValues_[i].value() = t;
|
// number of steps: <int>
|
||||||
// TODO: use character representation of t directly instead of
|
label nTimes = 0;
|
||||||
// regenerating from scalar value
|
{
|
||||||
timeValues_[i].name() = Foam::name(t);
|
readLine(is, buffer);
|
||||||
|
split = stringOps::splitSpace(buffer);
|
||||||
|
readFrom(split.back(), nTimes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// filename start number: <int>
|
||||||
|
// filename increment: <int>
|
||||||
|
//
|
||||||
|
// OR:
|
||||||
|
// filename numbers: ...
|
||||||
|
|
||||||
|
readLine(is, buffer);
|
||||||
|
auto pos_colon = buffer.find(':');
|
||||||
|
|
||||||
|
if (buffer.contains("numbers:"))
|
||||||
|
{
|
||||||
|
// Split out trailing values...
|
||||||
|
split = stringOps::splitSpace(buffer, pos_colon+1);
|
||||||
|
|
||||||
|
fileNumbers_.resize_nocopy(nTimes);
|
||||||
|
|
||||||
|
label numRead = 0;
|
||||||
|
while (numRead < nTimes)
|
||||||
|
{
|
||||||
|
for (const auto& chunk : split)
|
||||||
|
{
|
||||||
|
std::string str(chunk.str());
|
||||||
|
|
||||||
|
if (!Foam::readLabel(str, fileNumbers_[numRead]))
|
||||||
|
{
|
||||||
|
FatalIOErrorInFunction(is)
|
||||||
|
<< "Could not parse label: " << str << nl
|
||||||
|
<< exit(FatalIOError);
|
||||||
|
}
|
||||||
|
++numRead;
|
||||||
|
|
||||||
|
if (numRead == nTimes)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get more input
|
||||||
|
if (numRead < nTimes)
|
||||||
|
{
|
||||||
|
readLine(is, buffer);
|
||||||
|
split = stringOps::splitSpace(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
timeStartIndex_ = 0;
|
||||||
|
timeIncrement_ = 0;
|
||||||
|
fileNumbers_.resize(numRead);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// filename start number: <int>
|
||||||
|
split = stringOps::splitSpace(buffer);
|
||||||
|
readFrom(split.back(), timeStartIndex_);
|
||||||
|
|
||||||
|
// filename increment: <int>
|
||||||
|
readLine(is, buffer);
|
||||||
|
split = stringOps::splitSpace(buffer);
|
||||||
|
readFrom(split.back(), timeIncrement_);
|
||||||
|
|
||||||
|
fileNumbers_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugInfo
|
||||||
|
<< "nTimes: " << nTimes
|
||||||
|
<< " start-index: " << timeStartIndex_
|
||||||
|
<< " increment: " << timeIncrement_
|
||||||
|
<< " file numbers: " << flatOutput(fileNumbers_) << nl;
|
||||||
|
|
||||||
|
|
||||||
|
// time values: time_1 .. time_N
|
||||||
|
readLine(is, buffer);
|
||||||
|
|
||||||
|
// Split out trailing values...
|
||||||
|
{
|
||||||
|
const auto pos_colon = buffer.find(':');
|
||||||
|
const auto pos_key = buffer.find("values");
|
||||||
|
|
||||||
|
if
|
||||||
|
(
|
||||||
|
(pos_colon == std::string::npos)
|
||||||
|
|| (pos_key == std::string::npos) || (pos_colon < pos_key)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
split.clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
split = stringOps::splitSpace(buffer, pos_colon+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
timeValues_.resize_nocopy(nTimes);
|
||||||
|
|
||||||
|
label numRead = 0;
|
||||||
|
while (numRead < nTimes)
|
||||||
|
{
|
||||||
|
for (const auto& chunk : split)
|
||||||
|
{
|
||||||
|
auto& inst = timeValues_[numRead];
|
||||||
|
|
||||||
|
// Retain character representation
|
||||||
|
inst.name() = word(chunk.str());
|
||||||
|
|
||||||
|
if (!Foam::readScalar(inst.name(), inst.value()))
|
||||||
|
{
|
||||||
|
FatalIOErrorInFunction(is)
|
||||||
|
<< "Could not parse scalar: " << inst.name() << nl
|
||||||
|
<< exit(FatalIOError);
|
||||||
|
}
|
||||||
|
++numRead;
|
||||||
|
|
||||||
|
if (numRead == nTimes)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get more input
|
||||||
|
if (numRead < nTimes)
|
||||||
|
{
|
||||||
|
readLine(is, buffer);
|
||||||
|
split = stringOps::splitSpace(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
timeValues_.resize(numRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Not yet:
|
||||||
|
|
||||||
|
// FILE
|
||||||
|
// ~~~~
|
||||||
|
// file set: <int>
|
||||||
|
// filename index: <int> - file index number in the file name
|
||||||
|
// number of steps: <int>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -351,14 +618,9 @@ Foam::ensightSurfaceReader::ensightSurfaceReader
|
|||||||
),
|
),
|
||||||
readFormat_(IOstreamOption::ASCII), // Placeholder value
|
readFormat_(IOstreamOption::ASCII), // Placeholder value
|
||||||
baseDir_(fName.path()),
|
baseDir_(fName.path()),
|
||||||
meshFileName_(),
|
meshTimeset_(-1,-1),
|
||||||
fieldNames_(),
|
|
||||||
fieldFileNames_(),
|
|
||||||
nTimeSteps_(0),
|
|
||||||
timeStartIndex_(0),
|
timeStartIndex_(0),
|
||||||
timeIncrement_(1),
|
timeIncrement_(1)
|
||||||
timeValues_(),
|
|
||||||
surfPtr_(nullptr)
|
|
||||||
{
|
{
|
||||||
if (options.getOrDefault("debug", false))
|
if (options.getOrDefault("debug", false))
|
||||||
{
|
{
|
||||||
@ -376,12 +638,14 @@ Foam::ensightSurfaceReader::ensightSurfaceReader
|
|||||||
Pstream::broadcasts
|
Pstream::broadcasts
|
||||||
(
|
(
|
||||||
UPstream::worldComm,
|
UPstream::worldComm,
|
||||||
|
meshTimeset_,
|
||||||
meshFileName_,
|
meshFileName_,
|
||||||
|
fieldTimesets_,
|
||||||
fieldNames_,
|
fieldNames_,
|
||||||
fieldFileNames_,
|
fieldFileNames_,
|
||||||
nTimeSteps_,
|
|
||||||
timeStartIndex_,
|
timeStartIndex_,
|
||||||
timeIncrement_,
|
timeIncrement_,
|
||||||
|
fileNumbers_,
|
||||||
timeValues_
|
timeValues_
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -392,7 +656,8 @@ Foam::ensightSurfaceReader::ensightSurfaceReader
|
|||||||
|
|
||||||
Foam::meshedSurface Foam::ensightSurfaceReader::readGeometry
|
Foam::meshedSurface Foam::ensightSurfaceReader::readGeometry
|
||||||
(
|
(
|
||||||
const fileName& geometryFile
|
const fileName& geometryFile,
|
||||||
|
const label timeIndex
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
DebugInFunction << endl;
|
DebugInFunction << endl;
|
||||||
@ -404,6 +669,9 @@ Foam::meshedSurface Foam::ensightSurfaceReader::readGeometry
|
|||||||
// Format detected from the geometry
|
// Format detected from the geometry
|
||||||
readFormat_ = is.format();
|
readFormat_ = is.format();
|
||||||
|
|
||||||
|
// For transient single-file
|
||||||
|
is.seekTime(timeIndex);
|
||||||
|
|
||||||
DebugInfo
|
DebugInfo
|
||||||
<< "File: " << is.name()
|
<< "File: " << is.name()
|
||||||
<< " format: "
|
<< " format: "
|
||||||
@ -433,52 +701,59 @@ Foam::meshedSurface Foam::ensightSurfaceReader::readGeometry
|
|||||||
<< "Ignore " << nPoints << " node ids" << nl;
|
<< "Ignore " << nPoints << " node ids" << nl;
|
||||||
|
|
||||||
// Read and discard labels
|
// Read and discard labels
|
||||||
discard<label>(nPoints, is);
|
is.skip<label>(nPoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
pointField points(nPoints);
|
pointField points;
|
||||||
for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt)
|
is.readPoints(nPoints, points);
|
||||||
{
|
|
||||||
for (point& p : points)
|
|
||||||
{
|
|
||||||
is.read(p[cmpt]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Read faces - may be a mix of tria3, quad4, nsided
|
// Read faces - may be a mix of tria3, quad4, nsided
|
||||||
DynamicList<face> dynFaces(nPoints/3);
|
DynamicList<face> dynFaces(nPoints/3);
|
||||||
DynamicList<faceInfoTuple> faceTypeInfo(16);
|
DynamicList<faceInfoTuple> faceTypeInfo(16);
|
||||||
|
|
||||||
string faceType;
|
string buffer;
|
||||||
label faceCount = 0;
|
|
||||||
|
|
||||||
while (is.good()) // (is.peek() != EOF)
|
while (is.good())
|
||||||
{
|
{
|
||||||
// The element type
|
// The element type
|
||||||
is.read(faceType);
|
is.read(buffer);
|
||||||
|
|
||||||
if (!is.good())
|
if (!is.good())
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if (buffer.contains("BEGIN TIME STEP"))
|
||||||
|
{
|
||||||
|
// Graciously handle a miscued start
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (buffer.contains("END TIME STEP"))
|
||||||
|
{
|
||||||
|
// END TIME STEP is a valid means to terminate input
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if
|
if
|
||||||
(
|
(
|
||||||
faceType
|
buffer
|
||||||
== ensightFaces::elemNames[ensightFaces::elemType::TRIA3]
|
== ensightFaces::elemNames[ensightFaces::elemType::TRIA3]
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
is.read(faceCount);
|
label elemCount;
|
||||||
|
is.read(elemCount);
|
||||||
|
|
||||||
faceTypeInfo.push_back
|
faceTypeInfo.emplace_back
|
||||||
(
|
(
|
||||||
faceInfoTuple(ensightFaces::elemType::TRIA3, faceCount)
|
ensightFaces::elemType::TRIA3,
|
||||||
|
elemCount
|
||||||
);
|
);
|
||||||
|
|
||||||
DebugInfo
|
DebugInfo
|
||||||
<< "faceType <" << faceType.c_str() << "> count: "
|
<< "faceType <"
|
||||||
<< faceCount << nl;
|
<< ensightFaces::elemNames[ensightFaces::elemType::TRIA3]
|
||||||
|
<< "> count: "
|
||||||
|
<< elemCount << nl;
|
||||||
|
|
||||||
if
|
if
|
||||||
(
|
(
|
||||||
@ -487,39 +762,45 @@ Foam::meshedSurface Foam::ensightSurfaceReader::readGeometry
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
DebugInfo
|
DebugInfo
|
||||||
<< "Ignore " << faceCount << " element ids" << nl;
|
<< "Ignore " << elemCount << " element ids" << nl;
|
||||||
|
|
||||||
// Read and discard labels
|
// Read and discard labels
|
||||||
discard<label>(faceCount, is);
|
is.skip<label>(elemCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (label facei = 0; facei < faceCount; ++facei)
|
// Extend and fill the new trailing portion
|
||||||
|
const label startElemi = dynFaces.size();
|
||||||
|
dynFaces.resize(startElemi+elemCount, face(3)); // tria3
|
||||||
|
faceList::subList myElements = dynFaces.slice(startElemi);
|
||||||
|
|
||||||
|
for (auto& f : myElements)
|
||||||
{
|
{
|
||||||
face f(3);
|
|
||||||
for (label& fp : f)
|
for (label& fp : f)
|
||||||
{
|
{
|
||||||
is.read(fp);
|
is.read(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
dynFaces.push_back(std::move(f));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if
|
else if
|
||||||
(
|
(
|
||||||
faceType
|
buffer
|
||||||
== ensightFaces::elemNames[ensightFaces::elemType::QUAD4]
|
== ensightFaces::elemNames[ensightFaces::elemType::QUAD4]
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
is.read(faceCount);
|
label elemCount;
|
||||||
|
is.read(elemCount);
|
||||||
|
|
||||||
faceTypeInfo.push_back
|
faceTypeInfo.emplace_back
|
||||||
(
|
(
|
||||||
faceInfoTuple(ensightFaces::elemType::QUAD4, faceCount)
|
ensightFaces::elemType::QUAD4,
|
||||||
|
elemCount
|
||||||
);
|
);
|
||||||
|
|
||||||
DebugInfo
|
DebugInfo
|
||||||
<< "faceType <" << faceType.c_str() << "> count: "
|
<< "faceType <"
|
||||||
<< faceCount << nl;
|
<< ensightFaces::elemNames[ensightFaces::elemType::QUAD4]
|
||||||
|
<< "> count: "
|
||||||
|
<< elemCount << nl;
|
||||||
|
|
||||||
if
|
if
|
||||||
(
|
(
|
||||||
@ -528,39 +809,44 @@ Foam::meshedSurface Foam::ensightSurfaceReader::readGeometry
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
DebugInfo
|
DebugInfo
|
||||||
<< "Ignore " << faceCount << " element ids" << nl;
|
<< "Ignore " << elemCount << " element ids" << nl;
|
||||||
|
|
||||||
// Read and discard labels
|
// Read and discard labels
|
||||||
discard<label>(faceCount, is);
|
is.skip<label>(elemCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (label facei = 0; facei < faceCount; ++facei)
|
// Extend and fill the new trailing portion
|
||||||
|
const label startElemi = dynFaces.size();
|
||||||
|
dynFaces.resize(startElemi + elemCount, face(4)); // quad4
|
||||||
|
faceList::subList myElements = dynFaces.slice(startElemi);
|
||||||
|
|
||||||
|
for (auto& f : myElements)
|
||||||
{
|
{
|
||||||
face f(4);
|
|
||||||
for (label& fp : f)
|
for (label& fp : f)
|
||||||
{
|
{
|
||||||
is.read(fp);
|
is.read(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
dynFaces.push_back(std::move(f));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if
|
else if
|
||||||
(
|
(
|
||||||
faceType
|
buffer
|
||||||
== ensightFaces::elemNames[ensightFaces::elemType::NSIDED]
|
== ensightFaces::elemNames[ensightFaces::elemType::NSIDED]
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
is.read(faceCount);
|
label elemCount;
|
||||||
|
is.read(elemCount);
|
||||||
|
|
||||||
faceTypeInfo.push_back
|
faceTypeInfo.emplace_back
|
||||||
(
|
(
|
||||||
faceInfoTuple(ensightFaces::elemType::NSIDED, faceCount)
|
ensightFaces::elemType::NSIDED,
|
||||||
|
elemCount
|
||||||
);
|
);
|
||||||
|
|
||||||
DebugInfo
|
DebugInfo
|
||||||
<< "faceType <" << faceType.c_str() << "> count: "
|
<< "faceType <"
|
||||||
<< faceCount << nl;
|
<< ensightFaces::elemNames[ensightFaces::elemType::NSIDED]
|
||||||
|
<< "> count: " << elemCount << nl;
|
||||||
|
|
||||||
if
|
if
|
||||||
(
|
(
|
||||||
@ -569,26 +855,31 @@ Foam::meshedSurface Foam::ensightSurfaceReader::readGeometry
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
DebugInfo
|
DebugInfo
|
||||||
<< "Ignore " << faceCount << " element ids" << nl;
|
<< "Ignore " << elemCount << " element ids" << nl;
|
||||||
|
|
||||||
// Read and discard labels
|
// Read and discard labels
|
||||||
discard<label>(faceCount, is);
|
is.skip<label>(elemCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
labelList np(faceCount);
|
// Extend and fill the new trailing portion
|
||||||
for (label facei = 0; facei < faceCount; ++facei)
|
const label startElemi = dynFaces.size();
|
||||||
|
dynFaces.resize(startElemi + elemCount);
|
||||||
|
faceList::subList myElements = dynFaces.slice(startElemi);
|
||||||
|
|
||||||
|
for (auto& f : myElements)
|
||||||
{
|
{
|
||||||
is.read(np[facei]);
|
label nVerts;
|
||||||
|
is.read(nVerts);
|
||||||
|
|
||||||
|
f.resize(nVerts);
|
||||||
}
|
}
|
||||||
for (label facei = 0; facei < faceCount; ++facei)
|
|
||||||
|
for (auto& f : myElements)
|
||||||
{
|
{
|
||||||
face f(np[facei]);
|
|
||||||
for (label& fp : f)
|
for (label& fp : f)
|
||||||
{
|
{
|
||||||
is.read(fp);
|
is.read(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
dynFaces.push_back(std::move(f));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -596,7 +887,7 @@ Foam::meshedSurface Foam::ensightSurfaceReader::readGeometry
|
|||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
WarningInFunction
|
WarningInFunction
|
||||||
<< "Unknown face type: <" << faceType.c_str()
|
<< "Unknown face type: <" << buffer.c_str()
|
||||||
<< ">. Stopping read and continuing with current "
|
<< ">. Stopping read and continuing with current "
|
||||||
<< "elements only" << endl;
|
<< "elements only" << endl;
|
||||||
}
|
}
|
||||||
@ -605,7 +896,7 @@ Foam::meshedSurface Foam::ensightSurfaceReader::readGeometry
|
|||||||
}
|
}
|
||||||
|
|
||||||
// From 1-based Ensight addressing to 0-based OF addressing
|
// From 1-based Ensight addressing to 0-based OF addressing
|
||||||
for (face& f : dynFaces)
|
for (auto& f : dynFaces)
|
||||||
{
|
{
|
||||||
for (label& fp : f)
|
for (label& fp : f)
|
||||||
{
|
{
|
||||||
@ -637,11 +928,15 @@ const Foam::meshedSurface& Foam::ensightSurfaceReader::geometry
|
|||||||
surfPtr_.reset(new meshedSurface);
|
surfPtr_.reset(new meshedSurface);
|
||||||
auto& surf = *surfPtr_;
|
auto& surf = *surfPtr_;
|
||||||
|
|
||||||
fileName geomFile(baseDir_/replaceMask(meshFileName_, timeIndex));
|
fileName geomFile
|
||||||
|
(
|
||||||
|
baseDir_
|
||||||
|
/ ensightCase::expand_mask(meshFileName_, timeIndex)
|
||||||
|
);
|
||||||
|
|
||||||
if (!masterOnly_ || UPstream::master(UPstream::worldComm))
|
if (!masterOnly_ || UPstream::master(UPstream::worldComm))
|
||||||
{
|
{
|
||||||
surf = readGeometry(geomFile);
|
surf = readGeometry(geomFile, timeIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (masterOnly_ && UPstream::parRun())
|
if (masterOnly_ && UPstream::parRun())
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2015-2022 OpenCFD Ltd.
|
Copyright (C) 2015-2024 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -57,6 +57,7 @@ SourceFiles
|
|||||||
#define Foam_ensightSurfaceReader_H
|
#define Foam_ensightSurfaceReader_H
|
||||||
|
|
||||||
#include "surfaceReader.H"
|
#include "surfaceReader.H"
|
||||||
|
#include "ensightCase.H"
|
||||||
#include "ensightFaces.H"
|
#include "ensightFaces.H"
|
||||||
#include "ensightReadFile.H"
|
#include "ensightReadFile.H"
|
||||||
#include "Pair.H"
|
#include "Pair.H"
|
||||||
@ -103,24 +104,30 @@ protected:
|
|||||||
//- Base directory
|
//- Base directory
|
||||||
fileName baseDir_;
|
fileName baseDir_;
|
||||||
|
|
||||||
|
//- The timeset/fileset (if any) associated with the mesh
|
||||||
|
labelPair meshTimeset_;
|
||||||
|
|
||||||
//- Name of mesh file, including any subdirectory
|
//- Name of mesh file, including any subdirectory
|
||||||
fileName meshFileName_;
|
fileName meshFileName_;
|
||||||
|
|
||||||
|
//- The timeset/fileset (if any) associated with fields
|
||||||
|
List<labelPair> fieldTimesets_;
|
||||||
|
|
||||||
//- Field names
|
//- Field names
|
||||||
List<word> fieldNames_;
|
List<word> fieldNames_;
|
||||||
|
|
||||||
//- Field file names
|
//- Field file names
|
||||||
List<string> fieldFileNames_;
|
List<string> fieldFileNames_;
|
||||||
|
|
||||||
//- Number of time steps
|
|
||||||
label nTimeSteps_;
|
|
||||||
|
|
||||||
//- Start time index
|
//- Start time index
|
||||||
label timeStartIndex_;
|
label timeStartIndex_;
|
||||||
|
|
||||||
//- Time increment
|
//- Time increment
|
||||||
label timeIncrement_;
|
label timeIncrement_;
|
||||||
|
|
||||||
|
//- Numbers for files
|
||||||
|
labelList fileNumbers_;
|
||||||
|
|
||||||
//- Times
|
//- Times
|
||||||
instantList timeValues_;
|
instantList timeValues_;
|
||||||
|
|
||||||
@ -131,23 +138,30 @@ protected:
|
|||||||
List<faceInfoTuple> faceTypeInfo_;
|
List<faceInfoTuple> faceTypeInfo_;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Static Member Functions
|
||||||
|
|
||||||
//- Helper function to skip forward n steps in stream
|
//- Helper function to read an ascii line from file,
|
||||||
void skip(const label n, Istream& is) const;
|
//- skipping blank lines and comments.
|
||||||
|
// \return True if reading was successful
|
||||||
|
static bool readLine(ISstream& is, std::string& line);
|
||||||
|
|
||||||
//- Helper function to read an ascii line from file
|
//- Check a section header
|
||||||
void readLine(ISstream& is, string& buffer) const;
|
static void checkSection
|
||||||
|
(
|
||||||
|
const word& expected,
|
||||||
|
const string& buffer,
|
||||||
|
const ISstream& is // For errors
|
||||||
|
);
|
||||||
|
|
||||||
//- Read and check a section header
|
//- Read and check a section header
|
||||||
void debugSection(const word& expected, ISstream& is) const;
|
static void debugSection(const word& expected, ISstream& is);
|
||||||
|
|
||||||
//- Replace the '*' mask chars with a 0 padded string.
|
//- Helper function to return Type from string
|
||||||
static fileName replaceMask
|
template<class Type>
|
||||||
(
|
static void readFrom(const std::string& buffer, Type& value);
|
||||||
const fileName& fName,
|
|
||||||
const label timeIndex
|
|
||||||
);
|
// Protected Member Functions
|
||||||
|
|
||||||
//- Read (and discard) geometry file header.
|
//- Read (and discard) geometry file header.
|
||||||
// \return information about node/element id handling
|
// \return information about node/element id handling
|
||||||
@ -157,27 +171,20 @@ protected:
|
|||||||
void readCase(ISstream& is);
|
void readCase(ISstream& is);
|
||||||
|
|
||||||
//- Read and return surface geometry. Updates faceTypeInfo_
|
//- Read and return surface geometry. Updates faceTypeInfo_
|
||||||
meshedSurface readGeometry(const fileName& geometryFile);
|
meshedSurface readGeometry
|
||||||
|
|
||||||
//- Helper function to return Type after skipping n tokens
|
|
||||||
template<class Type>
|
|
||||||
void readFromLine(const label nSkip, Istream& is, Type& value) const;
|
|
||||||
|
|
||||||
//- Helper function to return Type after skipping n tokens
|
|
||||||
template<class Type>
|
|
||||||
void readFromLine
|
|
||||||
(
|
(
|
||||||
const label nSkip,
|
const fileName& geometryFile,
|
||||||
const string& buffer,
|
//! Optional index for transient single-file format
|
||||||
Type& value
|
const label timeIndex = 0
|
||||||
) const;
|
);
|
||||||
|
|
||||||
//- Helper function to return a field
|
//- Helper function to return a field
|
||||||
template<class Type>
|
template<class Type>
|
||||||
tmp<Field<Type>> readField
|
tmp<Field<Type>> readField
|
||||||
(
|
(
|
||||||
const fileName& dataFile,
|
const fileName& dataFile,
|
||||||
const word& fieldName
|
const word& fieldName,
|
||||||
|
const label timeIndex = 0
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Helper function to return a field
|
//- Helper function to return a field
|
||||||
@ -191,6 +198,15 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
// Generated Methods
|
||||||
|
|
||||||
|
//- No copy construct
|
||||||
|
ensightSurfaceReader(const ensightSurfaceReader&) = delete;
|
||||||
|
|
||||||
|
//- No copy assignment
|
||||||
|
void operator=(const ensightSurfaceReader&) = delete;
|
||||||
|
|
||||||
|
|
||||||
//- Runtime type information
|
//- Runtime type information
|
||||||
TypeName("ensight");
|
TypeName("ensight");
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2015-2022 OpenCFD Ltd.
|
Copyright (C) 2015-2024 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -28,41 +28,28 @@ License
|
|||||||
#include "SpanStream.H"
|
#include "SpanStream.H"
|
||||||
#include "ensightPTraits.H"
|
#include "ensightPTraits.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * Protected Static Member Functions * * * * * * * * * * //
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
void Foam::ensightSurfaceReader::readFromLine
|
void Foam::ensightSurfaceReader::readFrom
|
||||||
(
|
(
|
||||||
const label nSkip,
|
const std::string& buffer,
|
||||||
Istream& is,
|
|
||||||
Type& value
|
Type& value
|
||||||
) const
|
)
|
||||||
{
|
{
|
||||||
skip(nSkip, is);
|
ISpanStream is(buffer.data(), buffer.size());
|
||||||
|
|
||||||
is >> value;
|
is >> value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class Type>
|
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||||
void Foam::ensightSurfaceReader::readFromLine
|
|
||||||
(
|
|
||||||
const label nSkip,
|
|
||||||
const string& buffer,
|
|
||||||
Type& value
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
ISpanStream is(buffer.data(), buffer.length());
|
|
||||||
|
|
||||||
readFromLine(nSkip, is, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
Foam::tmp<Foam::Field<Type>> Foam::ensightSurfaceReader::readField
|
Foam::tmp<Foam::Field<Type>> Foam::ensightSurfaceReader::readField
|
||||||
(
|
(
|
||||||
const fileName& dataFile,
|
const fileName& dataFile,
|
||||||
const word& fieldName
|
const word& fieldName,
|
||||||
|
const label timeIndex
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
auto tfield = tmp<Field<Type>>::New(surfPtr_->nFaces(), Zero);
|
auto tfield = tmp<Field<Type>>::New(surfPtr_->nFaces(), Zero);
|
||||||
@ -81,6 +68,10 @@ Foam::tmp<Foam::Field<Type>> Foam::ensightSurfaceReader::readField
|
|||||||
<< exit(FatalError);
|
<< exit(FatalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If transient single-file
|
||||||
|
is.seekTime(timeIndex);
|
||||||
|
|
||||||
|
|
||||||
// Check that data type is as expected
|
// Check that data type is as expected
|
||||||
// (assuming OpenFOAM generated the data set)
|
// (assuming OpenFOAM generated the data set)
|
||||||
string primitiveType;
|
string primitiveType;
|
||||||
@ -104,11 +95,11 @@ Foam::tmp<Foam::Field<Type>> Foam::ensightSurfaceReader::readField
|
|||||||
}
|
}
|
||||||
|
|
||||||
string strValue;
|
string strValue;
|
||||||
label iValue;
|
label intValue;
|
||||||
|
|
||||||
// Read header info: part index, e.g. part 1
|
// Read header info: part index, e.g. part 1
|
||||||
is.read(strValue);
|
is.read(strValue);
|
||||||
is.read(iValue);
|
is.read(intValue);
|
||||||
|
|
||||||
label begFace = 0;
|
label begFace = 0;
|
||||||
|
|
||||||
@ -183,11 +174,18 @@ Foam::tmp<Foam::Field<Type>> Foam::ensightSurfaceReader::readField
|
|||||||
}
|
}
|
||||||
|
|
||||||
const word& fieldName = fieldNames_[fieldIndex];
|
const word& fieldName = fieldNames_[fieldIndex];
|
||||||
const label fileIndex = timeStartIndex_ + timeIndex*timeIncrement_;
|
|
||||||
|
const label fileIndex =
|
||||||
|
(
|
||||||
|
(timeIndex >= 0 && timeIndex < fileNumbers_.size())
|
||||||
|
? fileNumbers_[timeIndex]
|
||||||
|
: (timeStartIndex_ + timeIndex*timeIncrement_)
|
||||||
|
);
|
||||||
|
|
||||||
const fileName dataFile
|
const fileName dataFile
|
||||||
(
|
(
|
||||||
baseDir_/replaceMask(fieldFileNames_[fieldIndex], fileIndex)
|
baseDir_
|
||||||
|
/ ensightCase::expand_mask(fieldFileNames_[fieldIndex], fileIndex)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
@ -196,7 +194,7 @@ Foam::tmp<Foam::Field<Type>> Foam::ensightSurfaceReader::readField
|
|||||||
<< dataFile << endl;
|
<< dataFile << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return readField<Type>(dataFile, fieldName);
|
return readField<Type>(dataFile, fieldName, timeIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -99,9 +99,9 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated
|
|||||||
|
|
||||||
if (UPstream::master() || !parallel_)
|
if (UPstream::master() || !parallel_)
|
||||||
{
|
{
|
||||||
if (!isDir(outputFile.path()))
|
if (!Foam::isDir(outputFile.path()))
|
||||||
{
|
{
|
||||||
mkDir(outputFile.path());
|
Foam::mkDir(outputFile.path());
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool stateChanged =
|
const bool stateChanged =
|
||||||
@ -138,7 +138,7 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated
|
|||||||
);
|
);
|
||||||
|
|
||||||
// As per mkdir -p "data/00000000"
|
// As per mkdir -p "data/00000000"
|
||||||
mkDir(dataDir);
|
Foam::mkDir(dataDir);
|
||||||
|
|
||||||
|
|
||||||
const fileName geomFile(baseDir/geometryName);
|
const fileName geomFile(baseDir/geometryName);
|
||||||
@ -151,7 +151,7 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated
|
|||||||
geomFile.name()
|
geomFile.name()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!exists(geomFile))
|
if (!Foam::exists(geomFile))
|
||||||
{
|
{
|
||||||
if (verbose_)
|
if (verbose_)
|
||||||
{
|
{
|
||||||
@ -165,7 +165,9 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated
|
|||||||
geomFile.name(),
|
geomFile.name(),
|
||||||
caseOpts_.format()
|
caseOpts_.format()
|
||||||
);
|
);
|
||||||
part.write(osGeom); // serial
|
|
||||||
|
osGeom.beginGeometry();
|
||||||
|
part.write(osGeom); // serial
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write field
|
// Write field
|
||||||
@ -190,7 +192,12 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated
|
|||||||
// Update case file
|
// Update case file
|
||||||
if (stateChanged)
|
if (stateChanged)
|
||||||
{
|
{
|
||||||
OFstream osCase(outputFile, IOstreamOption::ASCII);
|
OFstream osCase
|
||||||
|
(
|
||||||
|
IOstreamOption::ATOMIC,
|
||||||
|
outputFile,
|
||||||
|
IOstreamOption::ASCII
|
||||||
|
);
|
||||||
ensightCase::setTimeFormat(osCase, caseOpts_); // time-format
|
ensightCase::setTimeFormat(osCase, caseOpts_); // time-format
|
||||||
|
|
||||||
if (verbose_)
|
if (verbose_)
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2014 OpenFOAM Foundation
|
Copyright (C) 2011-2014 OpenFOAM Foundation
|
||||||
Copyright (C) 2015-2023 OpenCFD Ltd.
|
Copyright (C) 2015-2024 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -64,11 +64,20 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeUncollated()
|
|||||||
|
|
||||||
if (UPstream::master() || !parallel_)
|
if (UPstream::master() || !parallel_)
|
||||||
{
|
{
|
||||||
if (!isDir(outputDir))
|
if (!Foam::isDir(outputDir))
|
||||||
{
|
{
|
||||||
mkDir(outputDir);
|
Foam::mkDir(outputDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The geometry
|
||||||
|
ensightOutputSurface part
|
||||||
|
(
|
||||||
|
surf.points(),
|
||||||
|
surf.faces(),
|
||||||
|
baseName
|
||||||
|
);
|
||||||
|
|
||||||
|
// Two-argument form for path-name to avoid validating outputDir
|
||||||
ensightGeoFile osGeom
|
ensightGeoFile osGeom
|
||||||
(
|
(
|
||||||
outputDir,
|
outputDir,
|
||||||
@ -76,16 +85,16 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeUncollated()
|
|||||||
caseOpts_.format()
|
caseOpts_.format()
|
||||||
);
|
);
|
||||||
|
|
||||||
ensightOutputSurface part
|
osGeom.beginGeometry();
|
||||||
(
|
part.write(osGeom); // serial
|
||||||
surf.points(),
|
|
||||||
surf.faces(),
|
|
||||||
osGeom.name().name()
|
|
||||||
);
|
|
||||||
part.write(osGeom); // serial
|
|
||||||
|
|
||||||
// Update case file
|
// Update case file
|
||||||
OFstream osCase(outputFile, IOstreamOption::ASCII);
|
OFstream osCase
|
||||||
|
(
|
||||||
|
IOstreamOption::ATOMIC,
|
||||||
|
outputFile,
|
||||||
|
IOstreamOption::ASCII
|
||||||
|
);
|
||||||
ensightCase::setTimeFormat(osCase, caseOpts_); // time-format
|
ensightCase::setTimeFormat(osCase, caseOpts_); // time-format
|
||||||
|
|
||||||
osCase
|
osCase
|
||||||
@ -168,11 +177,19 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeUncollated
|
|||||||
|
|
||||||
if (UPstream::master() || !parallel_)
|
if (UPstream::master() || !parallel_)
|
||||||
{
|
{
|
||||||
if (!isDir(outputFile.path()))
|
if (!Foam::isDir(outputFile.path()))
|
||||||
{
|
{
|
||||||
mkDir(outputFile.path());
|
Foam::mkDir(outputFile.path());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The geometry
|
||||||
|
ensightOutputSurface part
|
||||||
|
(
|
||||||
|
surf.points(),
|
||||||
|
surf.faces(),
|
||||||
|
baseName
|
||||||
|
);
|
||||||
|
|
||||||
// Two-argument form for path-name to avoid validating base-dir
|
// Two-argument form for path-name to avoid validating base-dir
|
||||||
ensightGeoFile osGeom
|
ensightGeoFile osGeom
|
||||||
(
|
(
|
||||||
@ -187,14 +204,8 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeUncollated
|
|||||||
caseOpts_.format()
|
caseOpts_.format()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Ensight Geometry
|
osGeom.beginGeometry();
|
||||||
ensightOutputSurface part
|
part.write(osGeom); // serial
|
||||||
(
|
|
||||||
surf.points(),
|
|
||||||
surf.faces(),
|
|
||||||
osGeom.name().name()
|
|
||||||
);
|
|
||||||
part.write(osGeom); // serial
|
|
||||||
|
|
||||||
// Write field (serial)
|
// Write field (serial)
|
||||||
osField.write(ensightPTraits<Type>::typeName);
|
osField.write(ensightPTraits<Type>::typeName);
|
||||||
@ -204,7 +215,12 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeUncollated
|
|||||||
|
|
||||||
// Update case file
|
// Update case file
|
||||||
{
|
{
|
||||||
OFstream osCase(outputFile, IOstreamOption::ASCII);
|
OFstream osCase
|
||||||
|
(
|
||||||
|
IOstreamOption::ATOMIC,
|
||||||
|
outputFile,
|
||||||
|
IOstreamOption::ASCII
|
||||||
|
);
|
||||||
ensightCase::setTimeFormat(osCase, caseOpts_); // time-format
|
ensightCase::setTimeFormat(osCase, caseOpts_); // time-format
|
||||||
|
|
||||||
osCase
|
osCase
|
||||||
|
|||||||
Reference in New Issue
Block a user