mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: vtk::seriesWriter to encapsulate writing file series (issue #926)
This commit is contained in:
3
applications/test/vtkSeriesWriter/Make/files
Normal file
3
applications/test/vtkSeriesWriter/Make/files
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Test-vtkSeriesWriter.C
|
||||||
|
|
||||||
|
EXE = $(FOAM_APPBIN)/Test-vtkSeriesWriter
|
||||||
5
applications/test/vtkSeriesWriter/Make/options
Normal file
5
applications/test/vtkSeriesWriter/Make/options
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
EXE_INC = \
|
||||||
|
-I$(LIB_SRC)/fileFormats/lnInclude
|
||||||
|
|
||||||
|
EXE_LIBS = \
|
||||||
|
-lfileFormats
|
||||||
118
applications/test/vtkSeriesWriter/Test-vtkSeriesWriter.C
Normal file
118
applications/test/vtkSeriesWriter/Test-vtkSeriesWriter.C
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
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-vtkSeriesWriter
|
||||||
|
|
||||||
|
Description
|
||||||
|
Basic functionality tests for vtk::seriesWriter
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "foamVtkSeriesWriter.H"
|
||||||
|
#include "argList.H"
|
||||||
|
|
||||||
|
using namespace Foam;
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
argList::addBoolOption("sort", "Sort value / name");
|
||||||
|
argList::addBoolOption("check", "Check for existence of files");
|
||||||
|
argList::addOption("time", "value", "Filter based on given time");
|
||||||
|
argList::addOption("scan", "series", "Scan directory to create series");
|
||||||
|
|
||||||
|
argList args(argc, argv, false, true);
|
||||||
|
|
||||||
|
const scalar currTime = args.lookupOrDefault<scalar>("time", GREAT);
|
||||||
|
|
||||||
|
Info<< "Using currTime = " << currTime << nl
|
||||||
|
<< "when loading " << (args.size()-1) << " files" << nl << nl;
|
||||||
|
|
||||||
|
for (label argi=1; argi < args.size(); ++argi)
|
||||||
|
{
|
||||||
|
const auto& input = args[argi];
|
||||||
|
|
||||||
|
Info << "load from " << input << nl;
|
||||||
|
|
||||||
|
vtk::seriesWriter writer;
|
||||||
|
writer.load(input);
|
||||||
|
|
||||||
|
writer.print(Info);
|
||||||
|
Info<< nl << nl;
|
||||||
|
|
||||||
|
if (writer.removeNewer(currTime))
|
||||||
|
{
|
||||||
|
Info<< "removed entries with time >= " << currTime << nl;
|
||||||
|
writer.print(Info);
|
||||||
|
Info<< nl << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.found("sort"))
|
||||||
|
{
|
||||||
|
writer.sort();
|
||||||
|
|
||||||
|
Info<< "sorted" << nl;
|
||||||
|
writer.print(Info);
|
||||||
|
Info<< nl << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.found("check"))
|
||||||
|
{
|
||||||
|
writer.load(input, true);
|
||||||
|
|
||||||
|
Info<< "reload, checking the existance of files" << nl;
|
||||||
|
writer.print(Info);
|
||||||
|
Info<< nl << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (writer.empty())
|
||||||
|
{
|
||||||
|
Info<< "No entries" << nl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Info<< writer.size() << " entries" << nl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.found("scan"))
|
||||||
|
{
|
||||||
|
vtk::seriesWriter writer;
|
||||||
|
|
||||||
|
writer.scan(args.opt<fileName>("scan"));
|
||||||
|
|
||||||
|
Info<< "scanned for files" << nl;
|
||||||
|
writer.print(Info);
|
||||||
|
Info<< nl << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Info<< "\nEnd\n" << nl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
4
applications/test/vtkSeriesWriter/file.vtm
Normal file
4
applications/test/vtkSeriesWriter/file.vtm
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version='1.0'?>
|
||||||
|
<!-- case='abc' time='0' index='0' -->
|
||||||
|
<VTKFile type='vtkMultiBlockDataSet' version='1.0' byte_order='LittleEndian' header_type='UInt64'>
|
||||||
|
<vtkMultiBlockDataSet>
|
||||||
4
applications/test/vtkSeriesWriter/file_00000679.vtm
Normal file
4
applications/test/vtkSeriesWriter/file_00000679.vtm
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version='1.0'?>
|
||||||
|
<!-- case='abc' time='0.00125' index='679' -->
|
||||||
|
<VTKFile type='vtkMultiBlockDataSet' version='1.0' byte_order='LittleEndian' header_type='UInt64'>
|
||||||
|
<vtkMultiBlockDataSet>
|
||||||
4
applications/test/vtkSeriesWriter/file_00001025.vtm
Normal file
4
applications/test/vtkSeriesWriter/file_00001025.vtm
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version='1.0'?>
|
||||||
|
<!-- case='abc' time="0.5250" index='1025' -->
|
||||||
|
<VTKFile type='vtkMultiBlockDataSet' version='1.0' byte_order='LittleEndian' header_type='UInt64'>
|
||||||
|
<vtkMultiBlockDataSet>
|
||||||
4
applications/test/vtkSeriesWriter/file_00001234.vtm
Normal file
4
applications/test/vtkSeriesWriter/file_00001234.vtm
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version='1.0'?>
|
||||||
|
<!-- note="no time entry" -->
|
||||||
|
<VTKFile type='vtkMultiBlockDataSet' version='1.0' byte_order='LittleEndian' header_type='UInt64'>
|
||||||
|
<vtkMultiBlockDataSet>
|
||||||
4
applications/test/vtkSeriesWriter/file_00005680.vtm
Normal file
4
applications/test/vtkSeriesWriter/file_00005680.vtm
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version='1.0'?>
|
||||||
|
<!-- case='abc' time= index='1234' note="degenerate time entry" -->
|
||||||
|
<VTKFile type='vtkMultiBlockDataSet' version='1.0' byte_order='LittleEndian' header_type='UInt64'>
|
||||||
|
<vtkMultiBlockDataSet>
|
||||||
4
applications/test/vtkSeriesWriter/file_23.vtm
Normal file
4
applications/test/vtkSeriesWriter/file_23.vtm
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version='1.0'?>
|
||||||
|
<!-- case='abc' time=0.0145 index='1234' note="unquoted time entry" -->
|
||||||
|
<VTKFile type='vtkMultiBlockDataSet' version='1.0' byte_order='LittleEndian' header_type='UInt64'>
|
||||||
|
<vtkMultiBlockDataSet>
|
||||||
20
applications/test/vtkSeriesWriter/test1.vtm.series
Normal file
20
applications/test/vtkSeriesWriter/test1.vtm.series
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"file-series-version" : "1.0",
|
||||||
|
"files": [
|
||||||
|
{ "name" : "file_00001742.vtm", "time" : 50 },
|
||||||
|
{ "name" : "file_00001025.vtm", "time" : 30 },
|
||||||
|
{
|
||||||
|
"time" : 40,
|
||||||
|
"name" : "file_00001380.vtm", ,,,,
|
||||||
|
},
|
||||||
|
{ "name" : "file_00000679.vtm", "time" : 20 },
|
||||||
|
{ "name" : "file_00002110.vtm", "time" : 60 },
|
||||||
|
{ "name" : "file_00001234.vtm", "time" : 60 },
|
||||||
|
{ "name" : "file_00001742.vtm", "time" : 150 },
|
||||||
|
{ "name" : "file_00001742.vtm", "time" : 5 },
|
||||||
|
|
||||||
|
{ "name" : "file_1000.vtm", "badTime" : 60 },
|
||||||
|
{ "" : "", "" : 60, "" : false },
|
||||||
|
{ "name" : "", "time" : 10 },
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -17,6 +17,7 @@ stl/STLAsciiParseManual.C
|
|||||||
stl/STLAsciiParseRagel.C
|
stl/STLAsciiParseRagel.C
|
||||||
|
|
||||||
vtk/file/foamVtkFileWriter.C
|
vtk/file/foamVtkFileWriter.C
|
||||||
|
vtk/file/foamVtkSeriesWriter.C
|
||||||
vtk/file/foamVtmWriter.C
|
vtk/file/foamVtmWriter.C
|
||||||
vtk/core/foamVtkCore.C
|
vtk/core/foamVtkCore.C
|
||||||
vtk/core/foamVtkPTraits.C
|
vtk/core/foamVtkPTraits.C
|
||||||
|
|||||||
753
src/fileFormats/vtk/file/foamVtkSeriesWriter.C
Normal file
753
src/fileFormats/vtk/file/foamVtkSeriesWriter.C
Normal file
@ -0,0 +1,753 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
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/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "foamVtkSeriesWriter.H"
|
||||||
|
#include "Fstream.H"
|
||||||
|
#include "ListOps.H"
|
||||||
|
#include "stringOpsSort.H"
|
||||||
|
#include "OSspecific.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
// Get any single token.
|
||||||
|
static inline bool getToken(ISstream& is, token& tok)
|
||||||
|
{
|
||||||
|
return (!is.read(tok).bad() && tok.good());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get two tokens.
|
||||||
|
// The first one must be a ':' token, the second one is any value
|
||||||
|
//
|
||||||
|
// This corrsponds to the JSON "key" : value syntax,
|
||||||
|
// we trigger after reading the "key".
|
||||||
|
static inline bool getValueToken(ISstream& is, token& tok)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(
|
||||||
|
// Token 1 = ':' separator
|
||||||
|
(
|
||||||
|
getToken(is, tok)
|
||||||
|
&& tok.isPunctuation() && tok.pToken() == token::COLON
|
||||||
|
)
|
||||||
|
|
||||||
|
// Token 2 is the value
|
||||||
|
&& getToken(is, tok)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Sorting for fileNameInstant
|
||||||
|
// 1. sort by value (time)
|
||||||
|
// 2. natural sort (name)
|
||||||
|
struct seriesLess
|
||||||
|
{
|
||||||
|
bool operator()(const fileNameInstant a, const fileNameInstant b) const
|
||||||
|
{
|
||||||
|
scalar val = compareOp<scalar>()(a.value(), b.value());
|
||||||
|
if (val == 0)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
stringOps::natural_sort::compare(a.name(), b.name()) < 0;
|
||||||
|
}
|
||||||
|
return val < 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Check if value is less than upper, with some tolerance.
|
||||||
|
static inline bool lessThan(const scalar& val, const scalar& upper)
|
||||||
|
{
|
||||||
|
return (val < upper && Foam::mag(val - upper) > ROOTVSMALL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::fileName Foam::vtk::seriesWriter::base
|
||||||
|
(
|
||||||
|
const fileName& outputName,
|
||||||
|
char sep
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const auto dash = outputName.rfind(sep);
|
||||||
|
|
||||||
|
// No separator? Or separator in path() instead of name()?
|
||||||
|
if
|
||||||
|
(
|
||||||
|
std::string::npos == dash
|
||||||
|
|| std::string::npos != outputName.find('/', dash)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Warn?
|
||||||
|
return outputName;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto dot = outputName.find('.', dash);
|
||||||
|
|
||||||
|
if (std::string::npos == dot)
|
||||||
|
{
|
||||||
|
return outputName.substr(0, dash);
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputName.substr(0, dash) + outputName.substr(dot);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::word Foam::vtk::seriesWriter::suffix
|
||||||
|
(
|
||||||
|
const fileName& file,
|
||||||
|
char sep
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const auto dash = file.rfind(sep);
|
||||||
|
|
||||||
|
// No separator? Or separator in path() instead of name()?
|
||||||
|
if
|
||||||
|
(
|
||||||
|
std::string::npos == dash
|
||||||
|
|| std::string::npos != file.find('/', dash)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Warn?
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto dot = file.find('.', dash);
|
||||||
|
|
||||||
|
if (std::string::npos == dot)
|
||||||
|
{
|
||||||
|
return file.substr(dash);
|
||||||
|
}
|
||||||
|
|
||||||
|
return file.substr(dash, (dot-dash));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::Ostream& Foam::vtk::seriesWriter::print
|
||||||
|
(
|
||||||
|
Ostream& os,
|
||||||
|
const fileName& base,
|
||||||
|
const UList<instant>& series,
|
||||||
|
const char sep
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Split the base into (stem, ext) components
|
||||||
|
//
|
||||||
|
// base = "path/file.vtm"
|
||||||
|
//
|
||||||
|
// stem = "file"
|
||||||
|
// ext = ".vtm"
|
||||||
|
|
||||||
|
const word stem = base.nameLessExt();
|
||||||
|
const word ext = "." + base.ext();
|
||||||
|
|
||||||
|
// Begin file-series (JSON)
|
||||||
|
os << "{\n \"file-series-version\" : \"1.0\",\n \"files\" : [\n";
|
||||||
|
|
||||||
|
// Track how many entries are remaining
|
||||||
|
// - trailing commas on all but the final entry (JSON requirement)
|
||||||
|
label nremain = series.size();
|
||||||
|
|
||||||
|
// Each entry
|
||||||
|
// { "name" : "<stem><sep>name<ext>", "time" : value }
|
||||||
|
|
||||||
|
for (const instant& inst : series)
|
||||||
|
{
|
||||||
|
os << " { \"name\" : \""
|
||||||
|
<< stem << sep << inst.name() << ext
|
||||||
|
<< "\", \"time\" : " << inst.value() << " }";
|
||||||
|
|
||||||
|
if (--nremain)
|
||||||
|
{
|
||||||
|
os << ',';
|
||||||
|
}
|
||||||
|
os << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
os << " ]\n}\n";
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::Ostream& Foam::vtk::seriesWriter::print
|
||||||
|
(
|
||||||
|
Ostream& os,
|
||||||
|
const UList<fileNameInstant>& series
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Begin file-series (JSON)
|
||||||
|
os << "{\n \"file-series-version\" : \"1.0\",\n \"files\" : [\n";
|
||||||
|
|
||||||
|
// Track how many entries are remaining
|
||||||
|
// - trailing commas on all but the final entry (JSON requirement)
|
||||||
|
label nremain = series.size();
|
||||||
|
|
||||||
|
// Each entry
|
||||||
|
// { "name" : "<file>", "time" : <value> }
|
||||||
|
|
||||||
|
for (const fileNameInstant& inst : series)
|
||||||
|
{
|
||||||
|
os << " { \"name\" : \""
|
||||||
|
<< inst.name().name()
|
||||||
|
<< "\", \"time\" : " << inst.value() << " }";
|
||||||
|
|
||||||
|
if (--nremain)
|
||||||
|
{
|
||||||
|
os << ',';
|
||||||
|
}
|
||||||
|
os << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
os << " ]\n}\n";
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::vtk::seriesWriter::write
|
||||||
|
(
|
||||||
|
const fileName& seriesName,
|
||||||
|
const UList<instant>& series,
|
||||||
|
const char sep
|
||||||
|
)
|
||||||
|
{
|
||||||
|
mkDir(seriesName.path());
|
||||||
|
|
||||||
|
autoPtr<OFstream> osPtr =
|
||||||
|
(
|
||||||
|
seriesName.hasExt("series")
|
||||||
|
? autoPtr<OFstream>::New(seriesName)
|
||||||
|
: autoPtr<OFstream>::New(seriesName + ".series")
|
||||||
|
);
|
||||||
|
|
||||||
|
print(*osPtr, seriesName, series, sep);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::vtk::seriesWriter::write
|
||||||
|
(
|
||||||
|
const fileName& seriesName,
|
||||||
|
const UList<fileNameInstant>& series
|
||||||
|
)
|
||||||
|
{
|
||||||
|
mkDir(seriesName.path());
|
||||||
|
|
||||||
|
autoPtr<OFstream> osPtr =
|
||||||
|
(
|
||||||
|
seriesName.hasExt("series")
|
||||||
|
? autoPtr<OFstream>::New(seriesName)
|
||||||
|
: autoPtr<OFstream>::New(seriesName + ".series")
|
||||||
|
);
|
||||||
|
|
||||||
|
print(*osPtr, series);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool Foam::vtk::seriesWriter::appendCheck(fileNameInstant inst)
|
||||||
|
{
|
||||||
|
if (inst.name().empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto iter = existing_.find(inst.name());
|
||||||
|
|
||||||
|
if (iter.found())
|
||||||
|
{
|
||||||
|
for (fileNameInstant& dst : entries_)
|
||||||
|
{
|
||||||
|
if (dst.name() == inst.name())
|
||||||
|
{
|
||||||
|
// Replace value
|
||||||
|
dst.value() = inst.value();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entries_.append(inst);
|
||||||
|
existing_.insert(inst.name());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::vtk::seriesWriter::removeDuplicates()
|
||||||
|
{
|
||||||
|
const label nElem = entries_.size();
|
||||||
|
|
||||||
|
HashTable<label, fileName> filesSeen(2*nElem);
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
for (label elemi=0; elemi < nElem; ++elemi)
|
||||||
|
{
|
||||||
|
fileNameInstant& inst = entries_[elemi];
|
||||||
|
|
||||||
|
if (inst.name().empty())
|
||||||
|
{
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto iter = filesSeen.find(inst.name());
|
||||||
|
|
||||||
|
if (iter.found())
|
||||||
|
{
|
||||||
|
// Mark previous location as being superseded
|
||||||
|
entries_[*iter].name().clear();
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
*iter = elemi; // The latest with this name
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
filesSeen.insert(inst.name(), elemi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
{
|
||||||
|
label dsti = 0;
|
||||||
|
for (label elemi=0; elemi < nElem; ++elemi)
|
||||||
|
{
|
||||||
|
fileNameInstant& src = entries_[elemi];
|
||||||
|
|
||||||
|
if (!src.name().empty())
|
||||||
|
{
|
||||||
|
if (dsti != elemi)
|
||||||
|
{
|
||||||
|
entries_[dsti] = std::move(src);
|
||||||
|
}
|
||||||
|
++dsti;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entries_.resize(dsti);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (nElem != entries_.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::label Foam::vtk::seriesWriter::load
|
||||||
|
(
|
||||||
|
const fileName& seriesName,
|
||||||
|
const bool checkFiles,
|
||||||
|
const scalar restartTime
|
||||||
|
)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
|
||||||
|
fileName seriesFile(seriesName);
|
||||||
|
if (!seriesFile.hasExt("series"))
|
||||||
|
{
|
||||||
|
seriesFile.ext("series");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isFile(seriesFile))
|
||||||
|
{
|
||||||
|
return size();
|
||||||
|
}
|
||||||
|
|
||||||
|
HashSet<fileName> filesOnDisk;
|
||||||
|
|
||||||
|
if (checkFiles)
|
||||||
|
{
|
||||||
|
filesOnDisk.insert(Foam::readDir(seriesFile.path()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Parse JSON content:
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// "file-series-version" : "1.0",
|
||||||
|
// "files" : [
|
||||||
|
// { "name" : "abc", "time" : 123 },
|
||||||
|
// { "name" : "def", "time" : 345 }
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Parsing states
|
||||||
|
enum parse
|
||||||
|
{
|
||||||
|
NONE, // Looking for "files"
|
||||||
|
FILES_ARRAY, // Saw "file" : '['
|
||||||
|
ENTRY, // Parsing in { "name" : ... }
|
||||||
|
DONE, // Saw a ']' while in FILES_ARRAY
|
||||||
|
FAIL // Something bad happened
|
||||||
|
};
|
||||||
|
|
||||||
|
// Track if "file" and "time" keys have been located
|
||||||
|
unsigned instStatus = 0;
|
||||||
|
fileNameInstant inst;
|
||||||
|
|
||||||
|
token tok;
|
||||||
|
|
||||||
|
IFstream is(seriesFile);
|
||||||
|
|
||||||
|
for
|
||||||
|
(
|
||||||
|
parse state = parse::NONE;
|
||||||
|
(state != parse::DONE && state != parse::FAIL)
|
||||||
|
&& getToken(is, tok);
|
||||||
|
/*nil*/
|
||||||
|
)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
// Still scanning for initial "files" entry
|
||||||
|
case parse::NONE :
|
||||||
|
{
|
||||||
|
if (tok.isString() && tok.stringToken() == "files")
|
||||||
|
{
|
||||||
|
// Expect "files" : [ ...
|
||||||
|
|
||||||
|
if
|
||||||
|
(
|
||||||
|
getValueToken(is, tok)
|
||||||
|
&& tok.isPunctuation()
|
||||||
|
&& tok.pToken() == token::BEGIN_SQR
|
||||||
|
)
|
||||||
|
{
|
||||||
|
state = parse::FILES_ARRAY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = parse::FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Parsing entries within "files" array
|
||||||
|
case parse::FILES_ARRAY :
|
||||||
|
{
|
||||||
|
if (tok.isPunctuation())
|
||||||
|
{
|
||||||
|
switch (tok.pToken())
|
||||||
|
{
|
||||||
|
// ',' - keep going (another entry)
|
||||||
|
case token::COMMA :
|
||||||
|
break;
|
||||||
|
|
||||||
|
// '{' - begin entry
|
||||||
|
case token::BEGIN_BLOCK :
|
||||||
|
state = parse::ENTRY;
|
||||||
|
instStatus = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// ']' - done array
|
||||||
|
case token::END_SQR :
|
||||||
|
state = parse::DONE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
state = parse::FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = parse::FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Parsing an individual entry within "files"
|
||||||
|
case parse::ENTRY :
|
||||||
|
{
|
||||||
|
if (tok.isPunctuation())
|
||||||
|
{
|
||||||
|
switch (tok.pToken())
|
||||||
|
{
|
||||||
|
// ',' - keep going (another key/value pair)
|
||||||
|
case token::COMMA :
|
||||||
|
break;
|
||||||
|
|
||||||
|
// '}'
|
||||||
|
case token::END_BLOCK :
|
||||||
|
{
|
||||||
|
// Verify instant was properly parsed and
|
||||||
|
// is also valid
|
||||||
|
if
|
||||||
|
(
|
||||||
|
instStatus == 0x03
|
||||||
|
&& lessThan(inst.value(), restartTime)
|
||||||
|
&&
|
||||||
|
(
|
||||||
|
checkFiles
|
||||||
|
? filesOnDisk.found(inst.name())
|
||||||
|
: true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
appendCheck(inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
state = parse::FILES_ARRAY;
|
||||||
|
instStatus = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
state = parse::FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tok.isString())
|
||||||
|
{
|
||||||
|
// Expect "key" : value
|
||||||
|
|
||||||
|
const string key(tok.stringToken());
|
||||||
|
|
||||||
|
if (getValueToken(is, tok))
|
||||||
|
{
|
||||||
|
if ("name" == key)
|
||||||
|
{
|
||||||
|
if (tok.isString())
|
||||||
|
{
|
||||||
|
inst.name() = tok.stringToken();
|
||||||
|
instStatus |= 0x01;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = parse::FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ("time" == key)
|
||||||
|
{
|
||||||
|
if (tok.isNumber())
|
||||||
|
{
|
||||||
|
inst.value() = tok.number();
|
||||||
|
instStatus |= 0x02;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = parse::FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = parse::FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = parse::FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::label Foam::vtk::seriesWriter::scan
|
||||||
|
(
|
||||||
|
const fileName& seriesName,
|
||||||
|
const scalar restartTime
|
||||||
|
)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
|
||||||
|
const fileName path = seriesName.path();
|
||||||
|
|
||||||
|
if (!isDir(path))
|
||||||
|
{
|
||||||
|
return size();
|
||||||
|
}
|
||||||
|
|
||||||
|
fileName seriesFile(seriesName);
|
||||||
|
|
||||||
|
if (seriesName.hasExt("series"))
|
||||||
|
{
|
||||||
|
seriesFile.removeExt();
|
||||||
|
}
|
||||||
|
|
||||||
|
const word stem = seriesFile.nameLessExt();
|
||||||
|
const word ext = seriesFile.ext();
|
||||||
|
|
||||||
|
// Accept "fileN.ext", "fileNN.ext", but reject "file.ext"
|
||||||
|
const auto minLen = stem.length() + ext.length() + 1;
|
||||||
|
|
||||||
|
const auto acceptName =
|
||||||
|
[=](const fileName& file) -> bool
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(
|
||||||
|
minLen < file.length()
|
||||||
|
&& file.hasExt(ext) && file.startsWith(stem)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
fileNameList files = subsetList(Foam::readDir(path), acceptName);
|
||||||
|
|
||||||
|
// Names sorted so warnings appear less random
|
||||||
|
Foam::sort(files, stringOps::natural_sort());
|
||||||
|
|
||||||
|
// Scratch space for reading some of the file
|
||||||
|
std::string header;
|
||||||
|
|
||||||
|
scalar timeValue;
|
||||||
|
|
||||||
|
bool warnings = false;
|
||||||
|
|
||||||
|
for (const fileName& file : files)
|
||||||
|
{
|
||||||
|
std::ifstream is(path/file);
|
||||||
|
|
||||||
|
if (!is)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read directly into the string
|
||||||
|
// 1024 (12 lines of 80 chars) is plenty for all comments
|
||||||
|
|
||||||
|
header.resize(1024);
|
||||||
|
is.read(&(header.front()), header.size());
|
||||||
|
header.resize(is.gcount());
|
||||||
|
|
||||||
|
// DebugInfo
|
||||||
|
// << "got header:\n=====\n" << header << "\n=====\n" << nl;
|
||||||
|
|
||||||
|
|
||||||
|
// Look for time="...", time='...', or even time=... attribute
|
||||||
|
|
||||||
|
auto begAttr = header.find("time=");
|
||||||
|
|
||||||
|
if (string::npos == begAttr)
|
||||||
|
{
|
||||||
|
if (!warnings)
|
||||||
|
{
|
||||||
|
Info<< "No 'time=' comment attribute found:\n(" << nl;
|
||||||
|
warnings = true;
|
||||||
|
}
|
||||||
|
Info<< " " << file << nl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip past the 'time='
|
||||||
|
begAttr += 5;
|
||||||
|
const char quote = header[begAttr];
|
||||||
|
|
||||||
|
// Info<< "have time=" << int(begAttr) << nl;
|
||||||
|
|
||||||
|
auto endAttr =
|
||||||
|
(
|
||||||
|
(quote == '"' || quote == '\'')
|
||||||
|
?
|
||||||
|
// Quoted
|
||||||
|
header.find(quote, ++begAttr)
|
||||||
|
:
|
||||||
|
// Unquoted
|
||||||
|
header.find_first_of("\t\n\v\f\r ", begAttr)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
if
|
||||||
|
(
|
||||||
|
string::npos != endAttr && begAttr < endAttr
|
||||||
|
&& readScalar
|
||||||
|
(
|
||||||
|
header.substr(begAttr, endAttr-begAttr),
|
||||||
|
timeValue
|
||||||
|
)
|
||||||
|
&& lessThan(timeValue, restartTime)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Success
|
||||||
|
append(timeValue, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (warnings)
|
||||||
|
{
|
||||||
|
Info<< ")" << nl << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't trust the order. Sort by time and name instead.
|
||||||
|
this->sort();
|
||||||
|
|
||||||
|
return size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::vtk::seriesWriter::removeNewer(const scalar timeValue)
|
||||||
|
{
|
||||||
|
// Rebuild hash as side-effect
|
||||||
|
existing_.clear();
|
||||||
|
|
||||||
|
label dsti = 0;
|
||||||
|
|
||||||
|
const label nElem = entries_.size();
|
||||||
|
|
||||||
|
for (label elemi=0; elemi < nElem; ++elemi)
|
||||||
|
{
|
||||||
|
fileNameInstant& src = entries_[elemi];
|
||||||
|
|
||||||
|
if (!src.name().empty() && lessThan(src.value(), timeValue))
|
||||||
|
{
|
||||||
|
if (dsti != elemi)
|
||||||
|
{
|
||||||
|
entries_[dsti] = std::move(src);
|
||||||
|
existing_.insert(entries_[dsti].name());
|
||||||
|
}
|
||||||
|
++dsti;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entries_.resize(dsti);
|
||||||
|
|
||||||
|
return (nElem != entries_.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::vtk::seriesWriter::sort()
|
||||||
|
{
|
||||||
|
Foam::sort(entries_, seriesLess());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
276
src/fileFormats/vtk/file/foamVtkSeriesWriter.H
Normal file
276
src/fileFormats/vtk/file/foamVtkSeriesWriter.H
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
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/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::vtk::seriesWriter
|
||||||
|
|
||||||
|
Description
|
||||||
|
Provides a means of accumulating and generating VTK file series.
|
||||||
|
|
||||||
|
The VTK file series format is a simple JSON format with the following
|
||||||
|
type of content:
|
||||||
|
\verbatim
|
||||||
|
{
|
||||||
|
"file-series-version" : "1.0",
|
||||||
|
"files": [
|
||||||
|
{ "name" : "file1.vtk", "time" : 10 },
|
||||||
|
{ "name" : "file2.vtk", "time" : 20 },
|
||||||
|
{ "name" : "file3.vtk", "time" : 30 },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
The append() operations include various sanity checks.
|
||||||
|
Entries with an empty name are ignored.
|
||||||
|
If an entry with an identical name already exists, its place
|
||||||
|
will be overwritten with the new time value.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
foamVtkSeriesWriter.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef foamVtkSeriesWriter_H
|
||||||
|
#define foamVtkSeriesWriter_H
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include "foamVtkOutputOptions.H"
|
||||||
|
#include "instant.H"
|
||||||
|
#include "fileNameInstant.H"
|
||||||
|
#include "DynamicList.H"
|
||||||
|
#include "HashSet.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
namespace vtk
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class vtk::seriesWriter Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class seriesWriter
|
||||||
|
{
|
||||||
|
// Private Member Data
|
||||||
|
|
||||||
|
//- A list of file/time entries
|
||||||
|
DynamicList<fileNameInstant> entries_;
|
||||||
|
|
||||||
|
//- Hash of existing (known) file names
|
||||||
|
HashSet<fileName> existing_;
|
||||||
|
|
||||||
|
//- Append the specified file/time instant.
|
||||||
|
// Overwrites existing entry that has the same name,
|
||||||
|
// does not append empty names.
|
||||||
|
bool appendCheck(fileNameInstant inst);
|
||||||
|
|
||||||
|
//- Remove duplicate filename entries. Keeping the last one seen.
|
||||||
|
bool removeDuplicates();
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct an empty series
|
||||||
|
seriesWriter() = default;
|
||||||
|
|
||||||
|
//- Copy construct
|
||||||
|
seriesWriter(const seriesWriter&) = default;
|
||||||
|
|
||||||
|
//- Move construct
|
||||||
|
seriesWriter(seriesWriter&&) = default;
|
||||||
|
|
||||||
|
//- Copy assignment
|
||||||
|
seriesWriter& operator=(const seriesWriter&) = default;
|
||||||
|
|
||||||
|
//- Move assignment
|
||||||
|
seriesWriter& operator=(seriesWriter&&) = default;
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
~seriesWriter() = default;
|
||||||
|
|
||||||
|
|
||||||
|
// Static Member Functions
|
||||||
|
|
||||||
|
//- Extract the base name for a file series
|
||||||
|
//
|
||||||
|
// \param outputName The name of the data output file
|
||||||
|
// Eg, "somefile_0001.vtk" would extract to "somefile.vtk"
|
||||||
|
// \param sep The separator used between file stem and suffix.
|
||||||
|
static fileName base(const fileName& outputName, char sep = '_');
|
||||||
|
|
||||||
|
//- Extract the time-varying ending of files
|
||||||
|
//
|
||||||
|
// \param file The name of the file
|
||||||
|
// Eg, "somefile_0001.vtk" would extract to "0001"
|
||||||
|
// \param sep The separator used between file stem and suffix.
|
||||||
|
static word suffix(const fileName& file, char sep = '_');
|
||||||
|
|
||||||
|
//- Print file series (JSON format) for specified time instances
|
||||||
|
//
|
||||||
|
// \param os The output stream
|
||||||
|
// \param base The name for the series (eg, "path/file.vtk")
|
||||||
|
// \param series The list of suffix/value entries
|
||||||
|
// \param sep The separator used between file stem and suffix.
|
||||||
|
static Ostream& print
|
||||||
|
(
|
||||||
|
Ostream& os,
|
||||||
|
const fileName& seriesName,
|
||||||
|
const UList<instant>& series,
|
||||||
|
const char sep = '_'
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Write file series (JSON format) to disk, for specified instances
|
||||||
|
//
|
||||||
|
// \param base The name for the series (eg, "path/file.vtk")
|
||||||
|
// \param series The list of suffix/value entries
|
||||||
|
// \param sep The separator used between file stem and suffix.
|
||||||
|
static void write
|
||||||
|
(
|
||||||
|
const fileName& base,
|
||||||
|
const UList<instant>& series,
|
||||||
|
const char sep = '_'
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Print file series (JSON format) for specified time instances.
|
||||||
|
// Since the VTK file series does not currently (OCT-2018) support
|
||||||
|
// sub-directories, these will be stripped on output.
|
||||||
|
//
|
||||||
|
// \param os The output stream
|
||||||
|
// \param series The list of filename/value entries
|
||||||
|
static Ostream& print
|
||||||
|
(
|
||||||
|
Ostream& os,
|
||||||
|
const UList<fileNameInstant>& series
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Write file series (JSON format) to disk, for specified instances
|
||||||
|
//
|
||||||
|
// \param seriesName The name for the series (eg, "path/file.vtk")
|
||||||
|
// \param series The list of filename/value entries
|
||||||
|
static void write
|
||||||
|
(
|
||||||
|
const fileName& seriesName,
|
||||||
|
const UList<fileNameInstant>& series
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
//- True if there are no data sets
|
||||||
|
inline bool empty() const;
|
||||||
|
|
||||||
|
//- The number of data sets
|
||||||
|
inline label size() const;
|
||||||
|
|
||||||
|
|
||||||
|
// Content Management
|
||||||
|
|
||||||
|
//- Clear entries
|
||||||
|
inline void clear();
|
||||||
|
|
||||||
|
//- Append the specified file instant
|
||||||
|
inline bool append(const fileNameInstant& inst);
|
||||||
|
|
||||||
|
//- Append the specified file instant
|
||||||
|
inline bool append(fileNameInstant&& inst);
|
||||||
|
|
||||||
|
//- Append the specified file instant.
|
||||||
|
inline bool append(scalar timeValue, const fileName& file);
|
||||||
|
|
||||||
|
//- Append the specified file instant.
|
||||||
|
inline bool append(scalar timeValue, fileName&& file);
|
||||||
|
|
||||||
|
//- Clear contents and reload by parsing the specified file.
|
||||||
|
//
|
||||||
|
// \param seriesName the base name of the series to scan, without
|
||||||
|
// the ".series" ending.
|
||||||
|
// \param checkFiles verify that the files also exist
|
||||||
|
// \param restartTime ignore entries with a time greater/equal
|
||||||
|
// to the specified restart time.
|
||||||
|
//
|
||||||
|
// \return the number of entries
|
||||||
|
label load
|
||||||
|
(
|
||||||
|
const fileName& seriesName,
|
||||||
|
const bool checkFiles = false,
|
||||||
|
const scalar restartTime = ROOTVGREAT
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Clear contents and scan directory for files.
|
||||||
|
//
|
||||||
|
// The expected xml header content is a comment with the following:
|
||||||
|
// \verbatim
|
||||||
|
// <!-- ... time='3.14159' ... -->
|
||||||
|
// \endverbatim
|
||||||
|
//
|
||||||
|
// \param seriesName the base name of the series to scan, without
|
||||||
|
// the ".series" ending.
|
||||||
|
// \param restartTime ignore entries with a time greater/equal
|
||||||
|
// to the specified restart time.
|
||||||
|
//
|
||||||
|
// \return the number of entries
|
||||||
|
label scan
|
||||||
|
(
|
||||||
|
const fileName& seriesName,
|
||||||
|
const scalar restartTime = ROOTVGREAT
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Remove entries that are greater_equal the time value.
|
||||||
|
//
|
||||||
|
// \return True if the contents changed
|
||||||
|
bool removeNewer(const scalar timeValue);
|
||||||
|
|
||||||
|
//- Sort by time value and by file name
|
||||||
|
void sort();
|
||||||
|
|
||||||
|
|
||||||
|
// Writing
|
||||||
|
|
||||||
|
//- Print file series as (JSON format)
|
||||||
|
inline void print(Ostream& os) const;
|
||||||
|
|
||||||
|
//- Write file series as (JSON format) to disk
|
||||||
|
inline void write(const fileName& seriesName) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace vtk
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#include "foamVtkSeriesWriterI.H"
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
99
src/fileFormats/vtk/file/foamVtkSeriesWriterI.H
Normal file
99
src/fileFormats/vtk/file/foamVtkSeriesWriterI.H
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
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/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
inline bool Foam::vtk::seriesWriter::empty() const
|
||||||
|
{
|
||||||
|
return entries_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Foam::label Foam::vtk::seriesWriter::size() const
|
||||||
|
{
|
||||||
|
return entries_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void Foam::vtk::seriesWriter::clear()
|
||||||
|
{
|
||||||
|
entries_.clear();
|
||||||
|
existing_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Foam::vtk::seriesWriter::append(const fileNameInstant& inst)
|
||||||
|
{
|
||||||
|
// Strip out path before saving
|
||||||
|
return appendCheck(fileNameInstant(inst.value(), inst.name().name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Foam::vtk::seriesWriter::append(fileNameInstant&& inst)
|
||||||
|
{
|
||||||
|
// Strip out path before saving
|
||||||
|
inst.name().removePath();
|
||||||
|
|
||||||
|
return appendCheck(inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Foam::vtk::seriesWriter::append
|
||||||
|
(
|
||||||
|
scalar timeValue,
|
||||||
|
const fileName& file
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Strip out path before saving
|
||||||
|
return appendCheck(fileNameInstant(timeValue, file.name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Foam::vtk::seriesWriter::append
|
||||||
|
(
|
||||||
|
scalar timeValue,
|
||||||
|
fileName&& file
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Strip out path before saving
|
||||||
|
file.removePath();
|
||||||
|
|
||||||
|
return appendCheck(fileNameInstant(timeValue, std::move(file)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void Foam::vtk::seriesWriter::print(Ostream& os) const
|
||||||
|
{
|
||||||
|
seriesWriter::print(os, entries_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void Foam::vtk::seriesWriter::write(const fileName& seriesName) const
|
||||||
|
{
|
||||||
|
seriesWriter::write(seriesName, entries_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
Reference in New Issue
Block a user