mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: refactor coordSet writers (#2347)
- the very old 'writer' class was fully stateless and always templated on an particular output type. This is now replaced with a 'coordSetWriter' with similar concepts as previously introduced for surface writers (#1206). - writers change from being a generic state-less set of routines to more properly conforming to the normal notion of a writer. - Parallel data is done *outside* of the writers, since they are used in a wide variety of contexts and the caller is currently still in a better position for deciding how to combine parallel data. ENH: update sampleSets to sample on per-field basis (#2347) - sample/write a field in a single step. - support for 'sampleOnExecute' to obtain values at execution intervals without writing. - support 'sets' input as a dictionary entry (as well as a list), which is similar to the changes for sampled-surface and permits use of changeDictionary to modify content. - globalIndex for gather to reduce parallel communication, less code - qualify the sampleSet results (properties) with the name of the set. The sample results were previously without a qualifier, which meant that only the last property value was actually saved (previous ones overwritten). For example, ``` sample1 { scalar { average(line,T) 349.96521; min(line,T) 349.9544281; max(line,T) 350; average(cells,T) 349.9854619; min(cells,T) 349.6589286; max(cells,T) 350.4967271; average(line,epsilon) 0.04947733869; min(line,epsilon) 0.04449639927; max(line,epsilon) 0.06452856475; } label { size(line,T) 79; size(cells,T) 1720; size(line,epsilon) 79; } } ``` ENH: update particleTracks application - use globalIndex to manage original parcel addressing and for gathering. Simplify code by introducing a helper class, storing intermediate fields in hash tables instead of separate lists. ADDITIONAL NOTES: - the regionSizeDistribution largely retains separate writers since the utility of placing sum/dev/count for all fields into a single file is questionable. - the streamline writing remains a "soft" upgrade, which means that scalar and vector fields are still collected a priori and not on-the-fly. This is due to how the streamline infrastructure is currently handled (should be upgraded in the future).
This commit is contained in:
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2020 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -40,7 +40,7 @@ Description
|
||||
#include "IOdictionary.H"
|
||||
#include "searchableSurfaces.H"
|
||||
#include "conformalVoronoiMesh.H"
|
||||
#include "vtkSetWriter.H"
|
||||
#include "vtkCoordSetWriter.H"
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
@ -106,8 +106,10 @@ int main(int argc, char *argv[])
|
||||
foamyHexMeshDict.getOrDefault("singleRegionName", true)
|
||||
);
|
||||
|
||||
autoPtr<coordSetWriter> setWriterPtr(new coordSetWriters::vtkWriter());
|
||||
|
||||
// Write some stats
|
||||
allGeometry.writeStats(List<wordList>(0), Info);
|
||||
allGeometry.writeStats(List<wordList>(), Info);
|
||||
// Check topology
|
||||
allGeometry.checkTopology(true);
|
||||
// Check geometry
|
||||
@ -115,7 +117,7 @@ int main(int argc, char *argv[])
|
||||
(
|
||||
100.0, // max size ratio
|
||||
1e-9, // intersection tolerance
|
||||
autoPtr<writer<scalar>>(new vtkSetWriter<scalar>()),
|
||||
setWriterPtr,
|
||||
0.01, // min triangle quality
|
||||
true
|
||||
);
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2021 OpenCFD Ltd.
|
||||
Copyright (C) 2015-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -51,7 +51,7 @@ Description
|
||||
#include "refinementParameters.H"
|
||||
#include "snapParameters.H"
|
||||
#include "layerParameters.H"
|
||||
#include "vtkSetWriter.H"
|
||||
#include "vtkCoordSetWriter.H"
|
||||
#include "faceSet.H"
|
||||
#include "motionSmoother.H"
|
||||
#include "polyTopoChange.H"
|
||||
@ -854,19 +854,25 @@ int main(int argc, char *argv[])
|
||||
|
||||
const bool keepPatches(meshDict.getOrDefault("keepPatches", false));
|
||||
|
||||
// format to be used for writing lines
|
||||
const word setFormat
|
||||
(
|
||||
meshDict.getOrDefault<word>
|
||||
// Writer for writing lines
|
||||
autoPtr<coordSetWriter> setFormatter;
|
||||
{
|
||||
const word setFormat
|
||||
(
|
||||
"setFormat",
|
||||
vtkSetWriter<scalar>::typeName
|
||||
)
|
||||
);
|
||||
const autoPtr<writer<scalar>> setFormatter
|
||||
(
|
||||
writer<scalar>::New(setFormat)
|
||||
);
|
||||
meshDict.getOrDefault<word>
|
||||
(
|
||||
"setFormat",
|
||||
coordSetWriters::vtkWriter::typeName // Default: "vtk"
|
||||
)
|
||||
);
|
||||
|
||||
setFormatter = coordSetWriter::New
|
||||
(
|
||||
setFormat,
|
||||
meshDict.subOrEmptyDict("formatOptions").optionalSubDict(setFormat)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
const scalar maxSizeRatio
|
||||
(
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
#include "checkTools.H"
|
||||
#include "functionObject.H"
|
||||
|
||||
#include "vtkSetWriter.H"
|
||||
#include "vtkCoordSetWriter.H"
|
||||
#include "vtkSurfaceWriter.H"
|
||||
|
||||
#include "cyclicACMIPolyPatch.H"
|
||||
@ -537,7 +537,7 @@ Foam::label Foam::checkGeometry
|
||||
const polyMesh& mesh,
|
||||
const bool allGeometry,
|
||||
autoPtr<surfaceWriter>& surfWriter,
|
||||
const autoPtr<writer<scalar>>& setWriter
|
||||
autoPtr<coordSetWriter>& setWriter
|
||||
)
|
||||
{
|
||||
label noFailedChecks = 0;
|
||||
@ -594,7 +594,7 @@ Foam::label Foam::checkGeometry
|
||||
<< nonAlignedPoints.name() << endl;
|
||||
nonAlignedPoints.instance() = mesh.pointsInstance();
|
||||
nonAlignedPoints.write();
|
||||
if (setWriter)
|
||||
if (setWriter && setWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*setWriter, nonAlignedPoints);
|
||||
}
|
||||
@ -628,7 +628,7 @@ Foam::label Foam::checkGeometry
|
||||
<< " non closed cells to set " << cells.name() << endl;
|
||||
cells.instance() = mesh.pointsInstance();
|
||||
cells.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, cells);
|
||||
}
|
||||
@ -644,7 +644,7 @@ Foam::label Foam::checkGeometry
|
||||
<< aspectCells.name() << endl;
|
||||
aspectCells.instance() = mesh.pointsInstance();
|
||||
aspectCells.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, aspectCells);
|
||||
}
|
||||
@ -665,7 +665,7 @@ Foam::label Foam::checkGeometry
|
||||
<< " zero area faces to set " << faces.name() << endl;
|
||||
faces.instance() = mesh.pointsInstance();
|
||||
faces.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, faces);
|
||||
}
|
||||
@ -687,7 +687,7 @@ Foam::label Foam::checkGeometry
|
||||
<< " zero volume cells to set " << cells.name() << endl;
|
||||
cells.instance() = mesh.pointsInstance();
|
||||
cells.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, cells);
|
||||
}
|
||||
@ -710,7 +710,7 @@ Foam::label Foam::checkGeometry
|
||||
<< " non-orthogonal faces to set " << faces.name() << endl;
|
||||
faces.instance() = mesh.pointsInstance();
|
||||
faces.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, faces);
|
||||
}
|
||||
@ -732,7 +732,7 @@ Foam::label Foam::checkGeometry
|
||||
<< faces.name() << endl;
|
||||
faces.instance() = mesh.pointsInstance();
|
||||
faces.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, faces);
|
||||
}
|
||||
@ -754,7 +754,7 @@ Foam::label Foam::checkGeometry
|
||||
<< " skew faces to set " << faces.name() << endl;
|
||||
faces.instance() = mesh.pointsInstance();
|
||||
faces.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, faces);
|
||||
}
|
||||
@ -778,7 +778,7 @@ Foam::label Foam::checkGeometry
|
||||
<< faces.name() << endl;
|
||||
faces.instance() = mesh.pointsInstance();
|
||||
faces.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, faces);
|
||||
}
|
||||
@ -811,7 +811,7 @@ Foam::label Foam::checkGeometry
|
||||
<< "decomposition tets to set " << faces.name() << endl;
|
||||
faces.instance() = mesh.pointsInstance();
|
||||
faces.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, faces);
|
||||
}
|
||||
@ -836,7 +836,7 @@ Foam::label Foam::checkGeometry
|
||||
<< endl;
|
||||
points.instance() = mesh.pointsInstance();
|
||||
points.write();
|
||||
if (setWriter)
|
||||
if (setWriter && setWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*setWriter, points);
|
||||
}
|
||||
@ -859,7 +859,7 @@ Foam::label Foam::checkGeometry
|
||||
<< " apart) points to set " << nearPoints.name() << endl;
|
||||
nearPoints.instance() = mesh.pointsInstance();
|
||||
nearPoints.write();
|
||||
if (setWriter)
|
||||
if (setWriter && setWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*setWriter, nearPoints);
|
||||
}
|
||||
@ -883,7 +883,7 @@ Foam::label Foam::checkGeometry
|
||||
<< endl;
|
||||
faces.instance() = mesh.pointsInstance();
|
||||
faces.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, faces);
|
||||
}
|
||||
@ -906,7 +906,7 @@ Foam::label Foam::checkGeometry
|
||||
<< " warped faces to set " << faces.name() << endl;
|
||||
faces.instance() = mesh.pointsInstance();
|
||||
faces.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, faces);
|
||||
}
|
||||
@ -927,7 +927,7 @@ Foam::label Foam::checkGeometry
|
||||
<< " under-determined cells to set " << cells.name() << endl;
|
||||
cells.instance() = mesh.pointsInstance();
|
||||
cells.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, cells);
|
||||
}
|
||||
@ -947,7 +947,7 @@ Foam::label Foam::checkGeometry
|
||||
<< " concave cells to set " << cells.name() << endl;
|
||||
cells.instance() = mesh.pointsInstance();
|
||||
cells.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, cells);
|
||||
}
|
||||
@ -968,7 +968,7 @@ Foam::label Foam::checkGeometry
|
||||
<< faces.name() << endl;
|
||||
faces.instance() = mesh.pointsInstance();
|
||||
faces.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, faces);
|
||||
}
|
||||
@ -989,7 +989,7 @@ Foam::label Foam::checkGeometry
|
||||
<< faces.name() << endl;
|
||||
faces.instance() = mesh.pointsInstance();
|
||||
faces.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, faces);
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ namespace Foam
|
||||
// Forward Declarations
|
||||
class polyMesh;
|
||||
class wedgePolyPatch;
|
||||
template<class T> class writer;
|
||||
class coordSetWriter;
|
||||
class surfaceWriter;
|
||||
|
||||
label findOppositeWedge(const polyMesh&, const wedgePolyPatch&);
|
||||
@ -47,6 +47,6 @@ namespace Foam
|
||||
const polyMesh& mesh,
|
||||
const bool allGeometry,
|
||||
autoPtr<surfaceWriter>& surfWriter,
|
||||
const autoPtr<writer<scalar>>& setWriter
|
||||
autoPtr<coordSetWriter>& setWriter
|
||||
);
|
||||
}
|
||||
|
||||
@ -74,7 +74,7 @@ Usage
|
||||
#include "Time.H"
|
||||
#include "fvMesh.H"
|
||||
#include "globalMeshData.H"
|
||||
#include "vtkSetWriter.H"
|
||||
#include "vtkCoordSetWriter.H"
|
||||
#include "vtkSurfaceWriter.H"
|
||||
#include "IOdictionary.H"
|
||||
#include "regionProperties.H"
|
||||
@ -262,11 +262,11 @@ int main(int argc, char *argv[])
|
||||
|
||||
|
||||
autoPtr<surfaceWriter> surfWriter;
|
||||
autoPtr<writer<scalar>> setWriter;
|
||||
autoPtr<coordSetWriter> setWriter;
|
||||
if (writeSets)
|
||||
{
|
||||
surfWriter = surfaceWriter::New(surfaceFormat);
|
||||
setWriter = writer<scalar>::New(vtkSetWriter<scalar>::typeName);
|
||||
setWriter = coordSetWriter::New(coordSetWriters::vtkWriter::typeName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ License
|
||||
#include "faceSet.H"
|
||||
#include "cellSet.H"
|
||||
#include "Time.H"
|
||||
#include "writer.H"
|
||||
#include "coordSetWriter.H"
|
||||
#include "surfaceWriter.H"
|
||||
#include "syncTools.H"
|
||||
#include "globalIndex.H"
|
||||
@ -417,7 +417,7 @@ void Foam::mergeAndWrite
|
||||
|
||||
void Foam::mergeAndWrite
|
||||
(
|
||||
const writer<scalar>& writer,
|
||||
coordSetWriter& writer,
|
||||
const pointSet& set
|
||||
)
|
||||
{
|
||||
@ -441,39 +441,26 @@ void Foam::mergeAndWrite
|
||||
}
|
||||
|
||||
|
||||
// Write with scalar pointID
|
||||
// Write with pointID
|
||||
if (Pstream::master())
|
||||
{
|
||||
scalarField scalarPointIDs(mergedIDs.size());
|
||||
forAll(mergedIDs, i)
|
||||
{
|
||||
scalarPointIDs[i] = 1.0*mergedIDs[i];
|
||||
}
|
||||
coordSet coords(set.name(), "distance", mergedPts, mag(mergedPts));
|
||||
|
||||
coordSet points(set.name(), "distance", mergedPts, mag(mergedPts));
|
||||
// Output. E.g. pointSet p0 -> postProcessing/<time>/p0.vtk
|
||||
|
||||
List<const scalarField*> flds(1, &scalarPointIDs);
|
||||
|
||||
wordList fldNames(1, "pointID");
|
||||
|
||||
// Output e.g. pointSet p0 to
|
||||
// postProcessing/<time>/p0.vtk
|
||||
fileName outputDir
|
||||
fileName outputPath
|
||||
(
|
||||
set.time().globalPath()
|
||||
/ functionObject::outputPrefix
|
||||
/ mesh.pointsInstance()
|
||||
// set.name()
|
||||
/ set.name()
|
||||
);
|
||||
outputDir.clean(); // Remove unneeded ".."
|
||||
mkDir(outputDir);
|
||||
outputPath.clean(); // Remove unneeded ".."
|
||||
|
||||
fileName outputFile(outputDir/writer.getFileName(points, wordList()));
|
||||
//fileName outputFile(outputDir/set.name());
|
||||
|
||||
OFstream os(outputFile);
|
||||
|
||||
writer.write(points, fldNames, flds, os);
|
||||
writer.open(coords, outputPath);
|
||||
writer.nFields(1);
|
||||
writer.write("pointID", mergedIDs);
|
||||
writer.close(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ namespace Foam
|
||||
class cellSet;
|
||||
class fileName;
|
||||
class polyMesh;
|
||||
template<class T> class writer;
|
||||
class coordSetWriter;
|
||||
class surfaceWriter;
|
||||
|
||||
void printMeshStats(const polyMesh& mesh, const bool allTopology);
|
||||
@ -36,7 +36,7 @@ namespace Foam
|
||||
|
||||
//- Write vtk representation of (assembled) pointSet to 'set' file in
|
||||
// postProcessing/ directory
|
||||
void mergeAndWrite(const writer<scalar>& writer, const pointSet& set);
|
||||
void mergeAndWrite(coordSetWriter& writer, const pointSet& set);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ License
|
||||
#include "IOmanip.H"
|
||||
#include "emptyPolyPatch.H"
|
||||
#include "processorPolyPatch.H"
|
||||
#include "vtkSetWriter.H"
|
||||
#include "vtkCoordSetWriter.H"
|
||||
#include "vtkSurfaceWriter.H"
|
||||
#include "checkTools.H"
|
||||
#include "treeBoundBox.H"
|
||||
@ -117,7 +117,7 @@ Foam::label Foam::checkTopology
|
||||
const bool allTopology,
|
||||
const bool allGeometry,
|
||||
autoPtr<surfaceWriter>& surfWriter,
|
||||
const autoPtr<writer<scalar>>& setWriter
|
||||
autoPtr<coordSetWriter>& setWriter
|
||||
)
|
||||
{
|
||||
label noFailedChecks = 0;
|
||||
@ -203,7 +203,7 @@ Foam::label Foam::checkTopology
|
||||
<< " illegal cells to set " << cells.name() << endl;
|
||||
cells.instance() = mesh.pointsInstance();
|
||||
cells.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, cells);
|
||||
}
|
||||
@ -227,7 +227,7 @@ Foam::label Foam::checkTopology
|
||||
<< " unused points to set " << points.name() << endl;
|
||||
points.instance() = mesh.pointsInstance();
|
||||
points.write();
|
||||
if (setWriter)
|
||||
if (setWriter && setWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*setWriter, points);
|
||||
}
|
||||
@ -249,7 +249,7 @@ Foam::label Foam::checkTopology
|
||||
<< " unordered faces to set " << faces.name() << endl;
|
||||
faces.instance() = mesh.pointsInstance();
|
||||
faces.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, faces);
|
||||
}
|
||||
@ -269,7 +269,7 @@ Foam::label Foam::checkTopology
|
||||
<< faces.name() << endl;
|
||||
faces.instance() = mesh.pointsInstance();
|
||||
faces.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, faces);
|
||||
}
|
||||
@ -290,11 +290,10 @@ Foam::label Foam::checkTopology
|
||||
<< endl;
|
||||
cells.instance() = mesh.pointsInstance();
|
||||
cells.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, cells);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -314,7 +313,7 @@ Foam::label Foam::checkTopology
|
||||
<< faces.name() << endl;
|
||||
faces.instance() = mesh.pointsInstance();
|
||||
faces.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, faces);
|
||||
}
|
||||
@ -369,7 +368,7 @@ Foam::label Foam::checkTopology
|
||||
<< endl;
|
||||
oneCells.instance() = mesh.pointsInstance();
|
||||
oneCells.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, oneCells);
|
||||
}
|
||||
@ -385,7 +384,7 @@ Foam::label Foam::checkTopology
|
||||
<< endl;
|
||||
twoCells.instance() = mesh.pointsInstance();
|
||||
twoCells.write();
|
||||
if (surfWriter)
|
||||
if (surfWriter && surfWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*surfWriter, twoCells);
|
||||
}
|
||||
@ -530,7 +529,7 @@ Foam::label Foam::checkTopology
|
||||
<< " points that are in multiple regions to set "
|
||||
<< points.name() << endl;
|
||||
points.write();
|
||||
if (setWriter)
|
||||
if (setWriter && setWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*setWriter, points);
|
||||
}
|
||||
@ -641,7 +640,7 @@ Foam::label Foam::checkTopology
|
||||
<< " conflicting points to set " << points.name() << endl;
|
||||
points.instance() = mesh.pointsInstance();
|
||||
points.write();
|
||||
if (setWriter)
|
||||
if (setWriter && setWriter->enabled())
|
||||
{
|
||||
mergeAndWrite(*setWriter, points);
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ namespace Foam
|
||||
// Forward Declarations
|
||||
class polyMesh;
|
||||
class pointSet;
|
||||
template<class T> class writer;
|
||||
class coordSetWriter;
|
||||
class surfaceWriter;
|
||||
|
||||
template<class PatchType>
|
||||
@ -24,6 +24,6 @@ namespace Foam
|
||||
const bool allTopology,
|
||||
const bool allGeometry,
|
||||
autoPtr<surfaceWriter>& surfWriter,
|
||||
const autoPtr<writer<scalar>>& setWriter
|
||||
autoPtr<coordSetWriter>& setWriter
|
||||
);
|
||||
}
|
||||
|
||||
@ -17,7 +17,12 @@ label maxTracks(propsDict.getOrDefault<label>("maxTracks", -1));
|
||||
word setFormat(propsDict.getOrDefault<word>("setFormat", "vtk"));
|
||||
|
||||
// Optional - if empty, select all
|
||||
const wordRes fieldNames(propsDict.getOrDefault<wordRes>("fields", wordRes()));
|
||||
wordRes acceptFields;
|
||||
propsDict.readIfPresent("fields", acceptFields);
|
||||
|
||||
// Optional
|
||||
wordRes excludeFields;
|
||||
propsDict.readIfPresent("exclude", excludeFields);
|
||||
|
||||
const word UName(propsDict.getOrDefault<word>("U", "U"));
|
||||
|
||||
|
||||
@ -42,199 +42,34 @@ Description
|
||||
#include "fvMesh.H"
|
||||
#include "Time.H"
|
||||
#include "timeSelector.H"
|
||||
#include "OFstream.H"
|
||||
#include "coordSetWriter.H"
|
||||
#include "passiveParticleCloud.H"
|
||||
#include "writer.H"
|
||||
#include "ListOps.H"
|
||||
#include "particleTracksSampler.H"
|
||||
|
||||
#define createTrack(field, trackValues) \
|
||||
createTrackField \
|
||||
( \
|
||||
field, \
|
||||
sampleFrequency, \
|
||||
maxPositions, \
|
||||
startIds, \
|
||||
allOrigProcs, \
|
||||
allOrigIds, \
|
||||
trackValues \
|
||||
);
|
||||
|
||||
#define setFields(fields, fieldNames) \
|
||||
setTrackFields \
|
||||
( \
|
||||
obr, \
|
||||
fields, \
|
||||
fieldNames, \
|
||||
nTracks, \
|
||||
startIds, \
|
||||
allOrigProcs, \
|
||||
allOrigIds, \
|
||||
maxPositions, \
|
||||
sampleFrequency \
|
||||
);
|
||||
|
||||
#define writeFields(fields, fieldNames, tracks, times, dirs) \
|
||||
writeTrackFields \
|
||||
( \
|
||||
fields, \
|
||||
fieldNames, \
|
||||
tracks, \
|
||||
times, \
|
||||
dirs, \
|
||||
setFormat, \
|
||||
formatOptions, \
|
||||
cloudName \
|
||||
);
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
template<class Type>
|
||||
void createTrackField
|
||||
(
|
||||
const Field<Type>& values,
|
||||
const label sampleFrequency,
|
||||
const label maxPositions,
|
||||
const labelList& startIds,
|
||||
const List<labelField>& allOrigProcs,
|
||||
const List<labelField>& allOrigIds,
|
||||
List<DynamicList<Type>>& trackValues
|
||||
)
|
||||
{
|
||||
List<Field<Type>> procField(Pstream::nProcs());
|
||||
procField[Pstream::myProcNo()] = values;
|
||||
Pstream::gatherList(procField);
|
||||
|
||||
if (!Pstream::master())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const label nTracks = trackValues.size();
|
||||
|
||||
forAll(procField, proci)
|
||||
{
|
||||
forAll(procField[proci], i)
|
||||
{
|
||||
const label globalId =
|
||||
startIds[allOrigProcs[proci][i]] + allOrigIds[proci][i];
|
||||
|
||||
if (globalId % sampleFrequency == 0)
|
||||
{
|
||||
const label trackId = globalId/sampleFrequency;
|
||||
|
||||
if
|
||||
(
|
||||
trackId < nTracks
|
||||
&& trackValues[trackId].size() < maxPositions
|
||||
)
|
||||
{
|
||||
trackValues[trackId].append(procField[proci][i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void writeTrackFields
|
||||
(
|
||||
List<List<DynamicList<Type>>>& fieldValues,
|
||||
const wordList& fieldNames,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const List<scalarField>& times,
|
||||
const List<vectorField>& dirs,
|
||||
const word& setFormat,
|
||||
const dictionary& formatOptions,
|
||||
const word& cloudName
|
||||
coordSetWriter& writer,
|
||||
HashTable<List<DynamicList<Type>>>& fieldTable
|
||||
)
|
||||
{
|
||||
if (fieldValues.empty())
|
||||
for (const word& fieldName : fieldTable.sortedToc())
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Steal and reshape from List<DynamicList> to List<Field>
|
||||
auto& input = fieldTable[fieldName];
|
||||
|
||||
auto writerPtr = writer<Type>::New(setFormat, formatOptions);
|
||||
|
||||
const fileName outFile(writerPtr().getFileName(tracks[0], wordList(0)));
|
||||
|
||||
const fileName outPath
|
||||
(
|
||||
functionObject::outputPrefix/cloud::prefix/cloudName/"particleTracks"
|
||||
);
|
||||
mkDir(outPath);
|
||||
|
||||
OFstream os(outPath/(pTraits<Type>::typeName & "tracks." + outFile.ext()));
|
||||
|
||||
Info<< "Writing " << pTraits<Type>::typeName << " particle tracks in "
|
||||
<< setFormat << " format to " << os.name() << endl;
|
||||
|
||||
|
||||
List<List<Field<Type>>> fields(fieldValues.size());
|
||||
forAll(fields, fieldi)
|
||||
{
|
||||
fields[fieldi].setSize(fieldValues[fieldi].size());
|
||||
forAll(fields[fieldi], tracki)
|
||||
List<Field<Type>> fields(input.size());
|
||||
forAll(input, tracki)
|
||||
{
|
||||
fields[fieldi][tracki].transfer(fieldValues[fieldi][tracki]);
|
||||
fields[tracki].transfer(input[tracki]);
|
||||
}
|
||||
|
||||
writer.write(fieldName, fields);
|
||||
}
|
||||
|
||||
writerPtr().write(true, times, tracks, fieldNames, fields, os);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::label setTrackFields
|
||||
(
|
||||
const objectRegistry& obr,
|
||||
List<List<DynamicList<Type>>>& fields,
|
||||
List<word>& fieldNames,
|
||||
const label nTracks,
|
||||
const labelList& startIds,
|
||||
const List<labelField>& allOrigProcs,
|
||||
const List<labelField>& allOrigIds,
|
||||
const label maxPositions,
|
||||
const label sampleFrequency
|
||||
)
|
||||
{
|
||||
const auto availableFieldPtrs = obr.lookupClass<IOField<Type>>();
|
||||
|
||||
fieldNames = availableFieldPtrs.toc();
|
||||
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
Pstream::combineGather(fieldNames, ListOps::uniqueEqOp<word>());
|
||||
Pstream::combineScatter(fieldNames);
|
||||
Foam::sort(fieldNames);
|
||||
}
|
||||
|
||||
const label nFields = fieldNames.size();
|
||||
|
||||
if (fields.empty())
|
||||
{
|
||||
fields.setSize(nFields);
|
||||
fieldNames.setSize(nFields);
|
||||
forAll(fields, i)
|
||||
{
|
||||
fields[i].setSize(nTracks);
|
||||
}
|
||||
}
|
||||
|
||||
forAll(fieldNames, fieldi)
|
||||
{
|
||||
const word& fieldName = fieldNames[fieldi];
|
||||
|
||||
const auto* fldPtr = obr.cfindObject<IOField<Type>>(fieldName);
|
||||
|
||||
createTrack
|
||||
(
|
||||
fldPtr ? static_cast<const Field<Type>>(*fldPtr) : Field<Type>(),
|
||||
fields[fieldi]
|
||||
);
|
||||
}
|
||||
|
||||
return nFields;
|
||||
}
|
||||
|
||||
|
||||
@ -267,6 +102,14 @@ int main(int argc, char *argv[])
|
||||
"Override the sample-frequency"
|
||||
);
|
||||
argList::addOption
|
||||
(
|
||||
"fields",
|
||||
"wordRes",
|
||||
"Specify single or multiple fields to write "
|
||||
"(default: all or 'fields' from dictionary)\n"
|
||||
"Eg, 'T' or '( \"U.*\" )'"
|
||||
);
|
||||
argList::addOption
|
||||
(
|
||||
"format",
|
||||
"name",
|
||||
@ -285,137 +128,147 @@ int main(int argc, char *argv[])
|
||||
|
||||
#include "createControls.H"
|
||||
|
||||
args.readListIfPresent<wordRe>("fields", acceptFields);
|
||||
args.readIfPresent("format", setFormat);
|
||||
|
||||
args.readIfPresent("stride", sampleFrequency);
|
||||
sampleFrequency = max(1, sampleFrequency); // sanity
|
||||
|
||||
// Setup the writer
|
||||
auto writerPtr =
|
||||
coordSetWriter::New
|
||||
(
|
||||
setFormat,
|
||||
formatOptions.optionalSubDict(setFormat, keyType::LITERAL)
|
||||
);
|
||||
|
||||
writerPtr().useTracks(true);
|
||||
|
||||
if (args.verbose())
|
||||
{
|
||||
writerPtr().verbose(true);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
const fileName vtkPath(runTime.rootPath()/runTime.globalCaseName()/"VTK");
|
||||
mkDir(vtkPath);
|
||||
particleTracksSampler trackSampler;
|
||||
|
||||
Info<< "Scanning times to determine track data for cloud " << cloudName
|
||||
<< nl << endl;
|
||||
|
||||
labelList maxIds(Pstream::nProcs(), -1);
|
||||
forAll(timeDirs, timei)
|
||||
{
|
||||
runTime.setTime(timeDirs[timei], timei);
|
||||
Info<< "Time = " << runTime.timeName() << endl;
|
||||
|
||||
Info<< " Reading particle positions" << endl;
|
||||
passiveParticleCloud myCloud(mesh, cloudName);
|
||||
|
||||
Info<< " Read " << returnReduce(myCloud.size(), sumOp<label>())
|
||||
<< " particles" << endl;
|
||||
|
||||
for (const passiveParticle& p : myCloud)
|
||||
labelList maxIds(Pstream::nProcs(), -1);
|
||||
forAll(timeDirs, timei)
|
||||
{
|
||||
const label origId = p.origId();
|
||||
const label origProc = p.origProc();
|
||||
runTime.setTime(timeDirs[timei], timei);
|
||||
Info<< "Time = " << runTime.timeName() << endl;
|
||||
|
||||
// Handle case where we are processing particle data generated in
|
||||
// parallel using more cores than when running this application.
|
||||
if (origProc >= maxIds.size())
|
||||
passiveParticleCloud myCloud(mesh, cloudName);
|
||||
|
||||
Info<< " Read " << returnReduce(myCloud.size(), sumOp<label>())
|
||||
<< " particles" << endl;
|
||||
|
||||
for (const passiveParticle& p : myCloud)
|
||||
{
|
||||
maxIds.setSize(origProc+1, -1);
|
||||
}
|
||||
const label origId = p.origId();
|
||||
const label origProc = p.origProc();
|
||||
|
||||
maxIds[origProc] = max(maxIds[origProc], origId);
|
||||
// Handle case where processing particle data generated in
|
||||
// parallel using more cores than for this application.
|
||||
if (origProc >= maxIds.size())
|
||||
{
|
||||
maxIds.resize(origProc+1, -1);
|
||||
}
|
||||
|
||||
maxIds[origProc] = max(maxIds[origProc], origId);
|
||||
}
|
||||
}
|
||||
|
||||
const label maxNProcs = returnReduce(maxIds.size(), maxOp<label>());
|
||||
maxIds.resize(maxNProcs, -1);
|
||||
|
||||
Pstream::listCombineGather(maxIds, maxEqOp<label>());
|
||||
Pstream::listCombineScatter(maxIds);
|
||||
|
||||
// From ids to count
|
||||
const labelList numIds = maxIds + 1;
|
||||
|
||||
// Set parcel addressing
|
||||
trackSampler.reset(numIds);
|
||||
|
||||
Info<< nl
|
||||
<< "Detected particles originating from "
|
||||
<< maxNProcs << " processors." << nl
|
||||
<< "Particle statistics:" << endl;
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
const globalIndex& parcelAddr = trackSampler.parcelAddr();
|
||||
|
||||
for (const label proci : parcelAddr.allProcs())
|
||||
{
|
||||
Info<< " Found " << parcelAddr.localSize(proci)
|
||||
<< " particles originating"
|
||||
<< " from processor " << proci << nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
label maxNProcs = returnReduce(maxIds.size(), maxOp<label>());
|
||||
|
||||
Info<< "Detected particles originating from " << maxNProcs
|
||||
<< " processors." << nl << endl;
|
||||
|
||||
maxIds.setSize(maxNProcs, -1);
|
||||
|
||||
Pstream::listCombineGather(maxIds, maxEqOp<label>());
|
||||
Pstream::listCombineScatter(maxIds);
|
||||
|
||||
labelList numIds = maxIds + 1;
|
||||
|
||||
Info<< nl << "Particle statistics:" << endl;
|
||||
forAll(maxIds, proci)
|
||||
{
|
||||
Info<< " Found " << numIds[proci] << " particles originating"
|
||||
<< " from processor " << proci << endl;
|
||||
}
|
||||
Info<< nl << endl;
|
||||
|
||||
|
||||
// Calculate starting ids for particles on each processor
|
||||
labelList startIds(numIds.size(), Zero);
|
||||
for (label i = 0; i < numIds.size()-1; ++i)
|
||||
{
|
||||
startIds[i+1] += startIds[i] + numIds[i];
|
||||
}
|
||||
label nParticle = startIds.last() + numIds[startIds.size()-1];
|
||||
trackSampler.setSampleRate(sampleFrequency, maxPositions, maxTracks);
|
||||
|
||||
|
||||
// Number of tracks to generate
|
||||
const label nTracks =
|
||||
maxTracks > 0
|
||||
? min(nParticle/sampleFrequency, maxTracks)
|
||||
: nParticle/sampleFrequency;
|
||||
const label nTracks = trackSampler.nTracks();
|
||||
|
||||
|
||||
// Storage for all particle tracks
|
||||
List<DynamicList<vector>> allTracks(nTracks);
|
||||
List<DynamicList<point>> allTrackPos(nTracks);
|
||||
List<DynamicList<scalar>> allTrackTimes(nTracks);
|
||||
|
||||
// Lists of field, tracki, trackValues
|
||||
//List<List<DynamicList<label>>> labelFields;
|
||||
List<List<DynamicList<scalar>>> scalarFields;
|
||||
List<List<DynamicList<vector>>> vectorFields;
|
||||
List<List<DynamicList<sphericalTensor>>> sphTensorFields;
|
||||
List<List<DynamicList<symmTensor>>> symTensorFields;
|
||||
List<List<DynamicList<tensor>>> tensorFields;
|
||||
//List<word> labelFieldNames;
|
||||
List<word> scalarFieldNames;
|
||||
List<word> vectorFieldNames;
|
||||
List<word> sphTensorFieldNames;
|
||||
List<word> symTensorFieldNames;
|
||||
List<word> tensorFieldNames;
|
||||
// Track field values by name/type
|
||||
HashTable<List<DynamicList<label>>> labelFields; // <- mostly unused
|
||||
HashTable<List<DynamicList<scalar>>> scalarFields;
|
||||
HashTable<List<DynamicList<vector>>> vectorFields;
|
||||
HashTable<List<DynamicList<sphericalTensor>>> sphericalTensorFields;
|
||||
HashTable<List<DynamicList<symmTensor>>> symmTensorFields;
|
||||
HashTable<List<DynamicList<tensor>>> tensorFields;
|
||||
|
||||
Info<< "\nGenerating " << nTracks << " particle tracks for cloud "
|
||||
<< cloudName << nl << endl;
|
||||
Info<< nl
|
||||
<< "Generating " << nTracks
|
||||
<< " particle tracks for cloud " << cloudName << nl << endl;
|
||||
|
||||
forAll(timeDirs, timei)
|
||||
{
|
||||
runTime.setTime(timeDirs[timei], timei);
|
||||
Info<< "Time = " << runTime.timeName() << endl;
|
||||
Info<< "Time = " << runTime.timeName() << " (processing)" << endl;
|
||||
|
||||
// Read particles. Will be size 0 if no particles.
|
||||
Info<< " Reading particle positions" << endl;
|
||||
passiveParticleCloud myCloud(mesh, cloudName);
|
||||
|
||||
pointField localPositions(myCloud.size(), Zero);
|
||||
scalarField localTimes(myCloud.size(), Zero);
|
||||
pointField localPositions(myCloud.size());
|
||||
scalarField localTimes(myCloud.size(), runTime.value());
|
||||
|
||||
List<labelField> allOrigIds(Pstream::nProcs());
|
||||
List<labelField> allOrigProcs(Pstream::nProcs());
|
||||
|
||||
// Collect the track data on all processors that have positions
|
||||
allOrigIds[Pstream::myProcNo()].setSize(myCloud.size(), Zero);
|
||||
allOrigProcs[Pstream::myProcNo()].setSize(myCloud.size(), Zero);
|
||||
|
||||
label i = 0;
|
||||
for (const passiveParticle& p : myCloud)
|
||||
// Gather track data from all processors that have positions
|
||||
trackSampler.resetCloud(myCloud.size());
|
||||
{
|
||||
allOrigIds[Pstream::myProcNo()][i] = p.origId();
|
||||
allOrigProcs[Pstream::myProcNo()][i] = p.origProc();
|
||||
localPositions[i] = p.position();
|
||||
localTimes[i] = runTime.value();
|
||||
++i;
|
||||
labelField& origIds = trackSampler.origParcelIds_;
|
||||
labelField& origProcs = trackSampler.origProcIds_;
|
||||
|
||||
label np = 0;
|
||||
for (const passiveParticle& p : myCloud)
|
||||
{
|
||||
origIds[np] = p.origId();
|
||||
origProcs[np] = p.origProc();
|
||||
localPositions[np] = p.position();
|
||||
++np;
|
||||
}
|
||||
|
||||
trackSampler.gatherInplace(origIds);
|
||||
trackSampler.gatherInplace(origProcs);
|
||||
}
|
||||
|
||||
// Collect the track data on the master processor
|
||||
Pstream::gatherList(allOrigIds);
|
||||
Pstream::gatherList(allOrigProcs);
|
||||
|
||||
// Read cloud fields (from disk) into object registry
|
||||
objectRegistry obr
|
||||
(
|
||||
IOobject
|
||||
@ -426,63 +279,122 @@ int main(int argc, char *argv[])
|
||||
)
|
||||
);
|
||||
|
||||
myCloud.readFromFiles(obr, fieldNames);
|
||||
myCloud.readFromFiles(obr, acceptFields, excludeFields);
|
||||
|
||||
// Create track positions and track time fields
|
||||
// (not registered as IOFields)
|
||||
// Note: createTrack is a local #define to reduce arg count...
|
||||
createTrack(localPositions, allTracks);
|
||||
createTrack(localTimes, allTrackTimes);
|
||||
|
||||
trackSampler.createTrackField(localPositions, allTrackPos);
|
||||
trackSampler.createTrackField(localTimes, allTrackTimes);
|
||||
|
||||
// Create the track fields
|
||||
// Note: setFields is a local #define to reduce arg count...
|
||||
//setFields(labelFields, labelFieldNames);
|
||||
setFields(scalarFields, scalarFieldNames);
|
||||
setFields(vectorFields, vectorFieldNames);
|
||||
setFields(sphTensorFields, sphTensorFieldNames);
|
||||
setFields(symTensorFields, symTensorFieldNames);
|
||||
setFields(tensorFields, tensorFieldNames);
|
||||
///trackSampler.setTrackFields(obr, labelFields);
|
||||
trackSampler.setTrackFields(obr, scalarFields);
|
||||
trackSampler.setTrackFields(obr, vectorFields);
|
||||
trackSampler.setTrackFields(obr, sphericalTensorFields);
|
||||
trackSampler.setTrackFields(obr, symmTensorFields);
|
||||
trackSampler.setTrackFields(obr, tensorFields);
|
||||
}
|
||||
|
||||
const label nFields =
|
||||
(
|
||||
labelFields.size()
|
||||
+ scalarFields.size()
|
||||
+ vectorFields.size()
|
||||
+ sphericalTensorFields.size()
|
||||
+ symmTensorFields.size()
|
||||
+ tensorFields.size()
|
||||
);
|
||||
|
||||
Info<< nl
|
||||
<< "Extracted " << nFields << " cloud fields" << nl;
|
||||
|
||||
if (nFields)
|
||||
{
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(FieldContent) \
|
||||
if (!FieldContent.empty()) \
|
||||
{ \
|
||||
Info<< " "; \
|
||||
for (const word& fieldName : FieldContent.sortedToc()) \
|
||||
{ \
|
||||
Info<< ' ' << fieldName; \
|
||||
} \
|
||||
Info<< nl; \
|
||||
}
|
||||
|
||||
doLocalCode(labelFields);
|
||||
doLocalCode(scalarFields);
|
||||
doLocalCode(vectorFields);
|
||||
doLocalCode(sphericalTensorFields);
|
||||
doLocalCode(symmTensorFields);
|
||||
doLocalCode(tensorFields);
|
||||
#undef doLocalCode
|
||||
}
|
||||
|
||||
Info<< nl
|
||||
<< "Writing particle tracks (" << setFormat << " format)" << nl;
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
PtrList<coordSet> tracks(allTracks.size());
|
||||
List<scalarField> times(tracks.size());
|
||||
PtrList<coordSet> tracks(allTrackPos.size());
|
||||
List<scalarField> times(allTrackPos.size());
|
||||
forAll(tracks, tracki)
|
||||
{
|
||||
tracks.set
|
||||
(
|
||||
tracki,
|
||||
new coordSet("track" + Foam::name(tracki), "distance")
|
||||
new coordSet("track" + Foam::name(tracki), "xyz")
|
||||
);
|
||||
tracks[tracki].transfer(allTracks[tracki]);
|
||||
tracks[tracki].transfer(allTrackPos[tracki]);
|
||||
times[tracki].transfer(allTrackTimes[tracki]);
|
||||
|
||||
if (!tracki) tracks[0].rename("tracks");
|
||||
}
|
||||
|
||||
Info<< nl;
|
||||
/// Currently unused
|
||||
/// List<vectorField> dirs(nTracks);
|
||||
/// const auto Uiter = vectorFields.cfind(UName);
|
||||
/// if (Uiter.found())
|
||||
/// {
|
||||
/// const auto& UTracks = *Uiter;
|
||||
/// forAll(UTracks, tracki)
|
||||
/// {
|
||||
/// const auto& U = UTracks[tracki];
|
||||
/// dirs[tracki] = U/(mag(U) + ROOTVSMALL);
|
||||
/// }
|
||||
/// }
|
||||
|
||||
const label Uid = vectorFieldNames.find(UName);
|
||||
List<vectorField> dirs(nTracks);
|
||||
|
||||
if (Uid != -1)
|
||||
// Write tracks with fields
|
||||
if (nFields)
|
||||
{
|
||||
const auto& UTracks = vectorFields[Uid];
|
||||
forAll(UTracks, tracki)
|
||||
{
|
||||
const auto& U = UTracks[tracki];
|
||||
dirs[tracki] = U/(mag(U) + ROOTVSMALL);
|
||||
}
|
||||
}
|
||||
auto& writer = *writerPtr;
|
||||
|
||||
// Write track fields
|
||||
// Note: writeFields is a local #define to reduce arg count...
|
||||
//writeFields(allLabelFields, labelFieldNames, tracks);
|
||||
writeFields(scalarFields, scalarFieldNames, tracks, times, dirs);
|
||||
writeFields(vectorFields, vectorFieldNames, tracks, times, dirs);
|
||||
writeFields(sphTensorFields, sphTensorFieldNames, tracks, times, dirs);
|
||||
writeFields(symTensorFields, symTensorFieldNames, tracks, times, dirs);
|
||||
writeFields(tensorFields, tensorFieldNames, tracks, times, dirs);
|
||||
const fileName outputPath
|
||||
(
|
||||
functionObject::outputPrefix/cloud::prefix/cloudName
|
||||
/ "particleTracks" / "tracks"
|
||||
);
|
||||
|
||||
Info<< " "
|
||||
<< runTime.relativePath(outputPath) << endl;
|
||||
|
||||
writer.open(tracks, outputPath);
|
||||
writer.setTrackTimes(times);
|
||||
writer.nFields(nFields);
|
||||
|
||||
///writeTrackFields(writer, labelFields);
|
||||
writeTrackFields(writer, scalarFields);
|
||||
writeTrackFields(writer, vectorFields);
|
||||
writeTrackFields(writer, sphericalTensorFields);
|
||||
writeTrackFields(writer, symmTensorFields);
|
||||
writeTrackFields(writer, tensorFields);
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "Warning: no fields, did not write" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
Info<< nl << "End\n" << endl;
|
||||
|
||||
@ -0,0 +1,190 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 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/>.
|
||||
|
||||
Class
|
||||
Foam::particleTracksSampler
|
||||
|
||||
Description
|
||||
Helper class when generating particle tracks.
|
||||
The interface is fairly rudimentary.
|
||||
|
||||
SourceFiles
|
||||
particleTracksSamplerTemplates.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_particleTracksSampler_H
|
||||
#define Foam_particleTracksSampler_H
|
||||
|
||||
#include "globalIndex.H"
|
||||
#include "fieldTypes.H"
|
||||
#include "IOField.H"
|
||||
#include "labelField.H"
|
||||
#include "DynamicList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward Declarations
|
||||
class objectRegistry;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class particleTracksSampler Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class particleTracksSampler
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- The sampling interval
|
||||
label stride_ = 1;
|
||||
|
||||
//- The number of tracks
|
||||
label nTracks_ = 1;
|
||||
|
||||
//- Upper limit for number of track positions
|
||||
label maxPositions_ = 10000;
|
||||
|
||||
//- The bin for sampled parcels.
|
||||
labelField trackIds_;
|
||||
|
||||
//- The addressing for gathering cloud fields etc
|
||||
globalIndex cloudGather_;
|
||||
|
||||
//- The originating parcel addressing
|
||||
globalIndex origParcelAddr_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Data Members
|
||||
|
||||
//- The originating parcel ids
|
||||
labelField origParcelIds_;
|
||||
|
||||
//- The originating processor ids
|
||||
labelField origProcIds_;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- The original parcel addressing
|
||||
const globalIndex& parcelAddr() const noexcept
|
||||
{
|
||||
return origParcelAddr_;
|
||||
}
|
||||
|
||||
//- Total number of particles
|
||||
label nParticle() const
|
||||
{
|
||||
return origParcelAddr_.totalSize();
|
||||
}
|
||||
|
||||
//- Number of tracks to generate
|
||||
label nTracks() const noexcept
|
||||
{
|
||||
return nTracks_;
|
||||
}
|
||||
|
||||
//- Define the orig parcel mappings
|
||||
void reset(const labelUList& origParcelCounts)
|
||||
{
|
||||
origParcelAddr_.reset(origParcelCounts);
|
||||
origParcelIds_.clear();
|
||||
origProcIds_.clear();
|
||||
trackIds_.clear();
|
||||
}
|
||||
|
||||
//- Set the sampling stride, upper limits
|
||||
// \return Number of tracks to generate
|
||||
label setSampleRate
|
||||
(
|
||||
const label sampleFreq,
|
||||
const label maxPositions,
|
||||
const label maxTracks = -1
|
||||
)
|
||||
{
|
||||
// numTracks = numParticles/stride
|
||||
|
||||
stride_ = max(1, sampleFreq);
|
||||
maxPositions_ = maxPositions;
|
||||
nTracks_ = (origParcelAddr_.totalSize()/stride_);
|
||||
|
||||
if (maxTracks > 0)
|
||||
{
|
||||
nTracks_ = min(nTracks_, maxTracks);
|
||||
}
|
||||
|
||||
return nTracks_;
|
||||
}
|
||||
|
||||
void resetCloud(const label localCloudSize)
|
||||
{
|
||||
cloudGather_.reset(localCloudSize, globalIndex::gatherOnly{});
|
||||
origParcelIds_.resize_nocopy(localCloudSize);
|
||||
origProcIds_.resize_nocopy(localCloudSize);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void gatherInplace(List<Type>& fld) const
|
||||
{
|
||||
cloudGather_.gatherInplace(fld);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
void createTrackField
|
||||
(
|
||||
const UList<Type>& values,
|
||||
List<DynamicList<Type>>& trackValues
|
||||
) const;
|
||||
|
||||
|
||||
template<class Type>
|
||||
label setTrackFields
|
||||
(
|
||||
const objectRegistry& obr,
|
||||
HashTable<List<DynamicList<Type>>>& fieldTable
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "particleTracksSamplerTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,108 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "objectRegistry.H"
|
||||
#include "ListOps.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
void Foam::particleTracksSampler::createTrackField
|
||||
(
|
||||
const UList<Type>& values,
|
||||
List<DynamicList<Type>>& trackValues
|
||||
) const
|
||||
{
|
||||
List<Type> allValues(cloudGather_.gather(values));
|
||||
|
||||
const label nTracks = trackValues.size();
|
||||
|
||||
forAll(allValues, i)
|
||||
{
|
||||
const label globalId =
|
||||
origParcelAddr_.toGlobal(origProcIds_[i], origParcelIds_[i]);
|
||||
|
||||
if (globalId % stride_ == 0)
|
||||
{
|
||||
const label trackId = globalId/stride_;
|
||||
|
||||
if
|
||||
(
|
||||
trackId < nTracks
|
||||
&& trackValues[trackId].size() < maxPositions_
|
||||
)
|
||||
{
|
||||
trackValues[trackId].append(allValues[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::label Foam::particleTracksSampler::setTrackFields
|
||||
(
|
||||
const objectRegistry& obr,
|
||||
HashTable<List<DynamicList<Type>>>& fieldTable
|
||||
) const
|
||||
{
|
||||
// First time - obtain field names and populate storage locations
|
||||
if (fieldTable.empty())
|
||||
{
|
||||
wordList fieldNames = obr.names<IOField<Type>>();
|
||||
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
Pstream::combineGather(fieldNames, ListOps::uniqueEqOp<word>());
|
||||
Pstream::combineScatter(fieldNames);
|
||||
}
|
||||
|
||||
for (const word& fieldName : fieldNames)
|
||||
{
|
||||
fieldTable(fieldName).resize(nTracks());
|
||||
}
|
||||
}
|
||||
|
||||
// Process in parallel-consistent order
|
||||
for (const word& fieldName : fieldTable.sortedToc())
|
||||
{
|
||||
auto& output = fieldTable[fieldName];
|
||||
|
||||
const auto* ptr = obr.cfindObject<IOField<Type>>(fieldName);
|
||||
|
||||
this->createTrackField
|
||||
(
|
||||
ptr ? static_cast<const UList<Type>&>(*ptr) : UList<Type>::null(),
|
||||
output
|
||||
);
|
||||
}
|
||||
|
||||
return fieldTable.size();
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -8,7 +8,12 @@ IOdictionary propsDict(dictIO);
|
||||
|
||||
const word cloudName(propsDict.get<word>("cloud"));
|
||||
|
||||
List<word> userFields(propsDict.lookup("fields"));
|
||||
// Mandatory - if empty, select none
|
||||
wordRes acceptFields(propsDict.get<wordRes>("fields"));
|
||||
|
||||
// Optional
|
||||
wordRes excludeFields;
|
||||
propsDict.readIfPresent("exclude", excludeFields);
|
||||
|
||||
const dictionary formatOptions
|
||||
(
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -45,73 +46,112 @@ Description
|
||||
#include "Time.H"
|
||||
#include "timeSelector.H"
|
||||
#include "OFstream.H"
|
||||
#include "passiveParticleCloud.H"
|
||||
#include "labelPairHashes.H"
|
||||
#include "SortableList.H"
|
||||
#include "IOField.H"
|
||||
#include "IOobjectList.H"
|
||||
#include "PtrList.H"
|
||||
#include "Field.H"
|
||||
#include "SortableList.H"
|
||||
#include "passiveParticleCloud.H"
|
||||
#include "steadyParticleTracksTemplates.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
label validateFields
|
||||
// Extract list of IOobjects, modifying the input IOobjectList in the
|
||||
// process
|
||||
IOobjectList preFilterFields
|
||||
(
|
||||
const List<word>& userFields,
|
||||
const IOobjectList& cloudObjs
|
||||
IOobjectList& cloudObjects,
|
||||
const wordRes& acceptFields,
|
||||
const wordRes& excludeFields
|
||||
)
|
||||
{
|
||||
List<bool> ok(userFields.size(), false);
|
||||
IOobjectList filteredObjects(cloudObjects.capacity());
|
||||
DynamicList<label> missed(acceptFields.size());
|
||||
|
||||
forAll(userFields, i)
|
||||
{
|
||||
ok[i] = ok[i] || fieldOk<label>(cloudObjs, userFields[i]);
|
||||
ok[i] = ok[i] || fieldOk<scalar>(cloudObjs, userFields[i]);
|
||||
ok[i] = ok[i] || fieldOk<vector>(cloudObjs, userFields[i]);
|
||||
ok[i] = ok[i] || fieldOk<sphericalTensor>(cloudObjs, userFields[i]);
|
||||
ok[i] = ok[i] || fieldOk<symmTensor>(cloudObjs, userFields[i]);
|
||||
ok[i] = ok[i] || fieldOk<tensor>(cloudObjs, userFields[i]);
|
||||
}
|
||||
// Selection here is slighly different than usual
|
||||
// - an empty accept filter means "ignore everything"
|
||||
|
||||
label nOk = 0;
|
||||
forAll(ok, i)
|
||||
if (!acceptFields.empty())
|
||||
{
|
||||
if (ok[i])
|
||||
const wordRes::filter pred(acceptFields, excludeFields);
|
||||
|
||||
const wordList allNames(cloudObjects.sortedNames());
|
||||
|
||||
// Detect missing fields
|
||||
forAll(acceptFields, i)
|
||||
{
|
||||
++nOk;
|
||||
if
|
||||
(
|
||||
acceptFields[i].isLiteral()
|
||||
&& !allNames.found(acceptFields[i])
|
||||
)
|
||||
{
|
||||
missed.append(i);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
for (const word& fldName : allNames)
|
||||
{
|
||||
Info << "\n*** Warning: user specified field '" << userFields[i]
|
||||
<< "' unavailable" << endl;
|
||||
const auto iter = cloudObjects.cfind(fldName);
|
||||
if (!pred(fldName) || !iter.found())
|
||||
{
|
||||
continue; // reject
|
||||
}
|
||||
|
||||
const IOobject& io = *(iter.val());
|
||||
|
||||
if
|
||||
(
|
||||
//OR: fieldTypes::basic.found(io.headerClassName())
|
||||
io.headerClassName() == IOField<label>::typeName
|
||||
|| io.headerClassName() == IOField<scalar>::typeName
|
||||
|| io.headerClassName() == IOField<vector>::typeName
|
||||
|| io.headerClassName() == IOField<sphericalTensor>::typeName
|
||||
|| io.headerClassName() == IOField<symmTensor>::typeName
|
||||
|| io.headerClassName() == IOField<tensor>::typeName
|
||||
)
|
||||
{
|
||||
// Transfer from cloudObjects -> filteredObjects
|
||||
filteredObjects.add(cloudObjects.remove(fldName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nOk;
|
||||
if (missed.size())
|
||||
{
|
||||
WarningInFunction
|
||||
<< nl
|
||||
<< "Cannot find field file matching "
|
||||
<< UIndirectList<wordRe>(acceptFields, missed) << endl;
|
||||
}
|
||||
|
||||
return filteredObjects;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
void writeVTK(OFstream& os, const label& value)
|
||||
void readFieldsAndWriteVTK
|
||||
(
|
||||
OFstream& os,
|
||||
const List<labelList>& particleMap,
|
||||
const IOobjectList& filteredObjects
|
||||
)
|
||||
{
|
||||
os << value;
|
||||
processFields<label>(os, particleMap, filteredObjects);
|
||||
processFields<scalar>(os, particleMap, filteredObjects);
|
||||
processFields<vector>(os, particleMap, filteredObjects);
|
||||
processFields<sphericalTensor>(os, particleMap, filteredObjects);
|
||||
processFields<symmTensor>(os, particleMap, filteredObjects);
|
||||
processFields<tensor>(os, particleMap, filteredObjects);
|
||||
}
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
template<>
|
||||
void writeVTK(OFstream& os, const scalar& value)
|
||||
{
|
||||
os << value;
|
||||
}
|
||||
|
||||
}
|
||||
using namespace Foam;
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -153,37 +193,31 @@ int main(int argc, char *argv[])
|
||||
const fileName vtkTimePath(vtkPath/runTime.timeName());
|
||||
mkDir(vtkTimePath);
|
||||
|
||||
Info<< " Reading particle positions" << endl;
|
||||
|
||||
PtrList<passiveParticle> particles(0);
|
||||
pointField particlePosition;
|
||||
labelList particleToTrack;
|
||||
label nTracks = 0;
|
||||
|
||||
// Transfer particles to (more convenient) list
|
||||
{
|
||||
passiveParticleCloud ppc(mesh, cloudName);
|
||||
Info<< "\n Read " << returnReduce(ppc.size(), sumOp<label>())
|
||||
Info<< " Reading particle positions" << endl;
|
||||
|
||||
passiveParticleCloud myCloud(mesh, cloudName);
|
||||
Info<< "\n Read " << returnReduce(myCloud.size(), sumOp<label>())
|
||||
<< " particles" << endl;
|
||||
|
||||
particles.setSize(ppc.size());
|
||||
const label nParticles = myCloud.size();
|
||||
|
||||
label i = 0;
|
||||
forAllIters(ppc, iter)
|
||||
particlePosition.resize(nParticles);
|
||||
particleToTrack.resize(nParticles);
|
||||
|
||||
LabelPairMap<label> trackTable;
|
||||
|
||||
label np = 0;
|
||||
for (const passiveParticle& p : myCloud)
|
||||
{
|
||||
particles.set(i++, ppc.remove(&iter()));
|
||||
}
|
||||
|
||||
// myCloud should now be empty
|
||||
}
|
||||
|
||||
List<label> particleToTrack(particles.size());
|
||||
label nTracks = 0;
|
||||
|
||||
{
|
||||
labelPairLookup trackTable;
|
||||
|
||||
forAll(particles, i)
|
||||
{
|
||||
const label origProc = particles[i].origProc();
|
||||
const label origId = particles[i].origId();
|
||||
const label origId = p.origId();
|
||||
const label origProc = p.origProc();
|
||||
particlePosition[np] = p.position();
|
||||
|
||||
const labelPair key(origProc, origId);
|
||||
|
||||
@ -191,17 +225,19 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (iter.found())
|
||||
{
|
||||
particleToTrack[i] = *iter;
|
||||
particleToTrack[np] = *iter;
|
||||
}
|
||||
else
|
||||
{
|
||||
particleToTrack[i] = nTracks;
|
||||
trackTable.insert(key, nTracks);
|
||||
++nTracks;
|
||||
particleToTrack[np] = trackTable.size();
|
||||
trackTable.insert(key, trackTable.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++np;
|
||||
}
|
||||
|
||||
nTracks = trackTable.size();
|
||||
}
|
||||
|
||||
if (nTracks == 0)
|
||||
{
|
||||
@ -230,7 +266,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// Store the particle age per track
|
||||
IOobjectList cloudObjs
|
||||
IOobjectList cloudObjects
|
||||
(
|
||||
mesh,
|
||||
runTime.timeName(),
|
||||
@ -239,25 +275,30 @@ int main(int argc, char *argv[])
|
||||
|
||||
// TODO: gather age across all procs
|
||||
{
|
||||
tmp<scalarField> tage =
|
||||
readParticleField<scalar>("age", cloudObjs);
|
||||
tmp<IOField<scalar>> tage =
|
||||
readParticleField<scalar>("age", cloudObjects);
|
||||
|
||||
const scalarField& age = tage();
|
||||
const auto& age = tage();
|
||||
|
||||
labelList trackSamples(nTracks, Zero);
|
||||
|
||||
forAll(particleToTrack, i)
|
||||
{
|
||||
const label trackI = particleToTrack[i];
|
||||
const label sampleI = trackSamples[trackI];
|
||||
agePerTrack[trackI][sampleI] = age[i];
|
||||
particleMap[trackI][sampleI] = i;
|
||||
trackSamples[trackI]++;
|
||||
const label tracki = particleToTrack[i];
|
||||
const label samplei = trackSamples[tracki];
|
||||
agePerTrack[tracki][samplei] = age[i];
|
||||
particleMap[tracki][samplei] = i;
|
||||
++trackSamples[tracki];
|
||||
}
|
||||
tage.clear();
|
||||
}
|
||||
|
||||
|
||||
const IOobjectList filteredObjects
|
||||
(
|
||||
preFilterFields(cloudObjects, acceptFields, excludeFields)
|
||||
);
|
||||
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
OFstream os(vtkTimePath/"particleTracks.vtk");
|
||||
@ -295,7 +336,7 @@ int main(int argc, char *argv[])
|
||||
forAll(ids, j)
|
||||
{
|
||||
const label localId = particleIds[j];
|
||||
const vector pos(particles[localId].position());
|
||||
const point& pos = particlePosition[localId];
|
||||
os << pos.x() << ' ' << pos.y() << ' ' << pos.z()
|
||||
<< nl;
|
||||
}
|
||||
@ -330,22 +371,14 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
|
||||
const label nFields = validateFields(userFields, cloudObjs);
|
||||
const label nFields = filteredObjects.size();
|
||||
|
||||
os << "POINT_DATA " << nPoints << nl
|
||||
<< "FIELD attributes " << nFields << nl;
|
||||
|
||||
Info<< "\n Processing fields" << nl << endl;
|
||||
|
||||
processFields<label>(os, particleMap, userFields, cloudObjs);
|
||||
processFields<scalar>(os, particleMap, userFields, cloudObjs);
|
||||
processFields<vector>(os, particleMap, userFields, cloudObjs);
|
||||
processFields<sphericalTensor>
|
||||
(os, particleMap, userFields, cloudObjs);
|
||||
processFields<symmTensor>
|
||||
(os, particleMap, userFields, cloudObjs);
|
||||
processFields<tensor>(os, particleMap, userFields, cloudObjs);
|
||||
|
||||
readFieldsAndWriteVTK(os, particleMap, filteredObjects);
|
||||
}
|
||||
}
|
||||
Info<< endl;
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -31,113 +31,71 @@ License
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
bool Foam::fieldOk(const IOobjectList& cloudObjs, const word& name)
|
||||
{
|
||||
return cloudObjs.cfindObject<IOField<Type>>(name) != nullptr;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>> Foam::readParticleField
|
||||
Foam::tmp<Foam::IOField<Type>> Foam::readParticleField
|
||||
(
|
||||
const word& name,
|
||||
const IOobjectList cloudObjs
|
||||
const word& fieldName,
|
||||
const IOobjectList& cloudObjects
|
||||
)
|
||||
{
|
||||
const IOobject* obj = cloudObjs.cfindObject<IOField<Type>>(name);
|
||||
if (obj != nullptr)
|
||||
const IOobject* io = cloudObjects.cfindObject<IOField<Type>>(fieldName);
|
||||
if (io)
|
||||
{
|
||||
IOField<Type> newField(*obj);
|
||||
return tmp<Field<Type>>::New(std::move(newField));
|
||||
return tmp<IOField<Type>>::New(*io);
|
||||
}
|
||||
|
||||
FatalErrorInFunction
|
||||
<< "Error: cloud field name " << name
|
||||
<< " not found or the wrong type"
|
||||
<< "Cloud field name " << fieldName
|
||||
<< " not found or the incorrect type"
|
||||
<< abort(FatalError);
|
||||
|
||||
return Field<Type>::null();
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::readFields
|
||||
(
|
||||
PtrList<List<Type>>& values,
|
||||
const List<word>& fieldNames,
|
||||
const IOobjectList& cloudObjs
|
||||
)
|
||||
{
|
||||
forAll(fieldNames, fieldi)
|
||||
{
|
||||
const word& fieldName = fieldNames[fieldi];
|
||||
|
||||
const IOobject* obj = cloudObjs.cfindObject<IOField<Type>>(fieldName);
|
||||
if (obj != nullptr)
|
||||
{
|
||||
Info<< " reading field " << fieldName << endl;
|
||||
IOField<Type> newField(*obj);
|
||||
values.set(fieldi, new List<Type>(std::move(newField)));
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Unable to read field " << fieldName
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::writeVTK(OFstream& os, const Type& value)
|
||||
{
|
||||
os << value.component(0);
|
||||
for (label i=1; i<pTraits<Type>::nComponents; i++)
|
||||
os << component(value, 0);
|
||||
for (label d=1; d < pTraits<Type>::nComponents; ++d)
|
||||
{
|
||||
os << ' ' << value.component(i);
|
||||
os << ' ' << component(value, d);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::writeVTKFields
|
||||
void Foam::writeVTKField
|
||||
(
|
||||
OFstream& os,
|
||||
const PtrList<List<Type>>& values,
|
||||
const List<List<label>>& addr,
|
||||
const List<word>& fieldNames
|
||||
const IOField<Type>& field,
|
||||
const List<labelList>& addr
|
||||
)
|
||||
{
|
||||
label step = max(floor(8/pTraits<Type>::nComponents), 1);
|
||||
const label step = max(1, floor(8/pTraits<Type>::nComponents));
|
||||
|
||||
forAll(values, fieldi)
|
||||
Info<< " writing field " << field.name() << endl;
|
||||
os << nl << field.name() << ' '
|
||||
<< int(pTraits<Type>::nComponents) << ' '
|
||||
<< field.size() << " float" << nl;
|
||||
|
||||
///label offset = 0;
|
||||
for (const labelList& ids : addr)
|
||||
{
|
||||
Info<< " writing field " << fieldNames[fieldi] << endl;
|
||||
os << nl << fieldNames[fieldi] << ' '
|
||||
<< int(pTraits<Type>::nComponents) << ' '
|
||||
<< values[fieldi].size() << " float" << nl;
|
||||
label offset = 0;
|
||||
forAll(addr, tracki)
|
||||
List<Type> data(UIndirectList<Type>(field, ids));
|
||||
label nData = data.size() - 1;
|
||||
forAll(data, i)
|
||||
{
|
||||
const List<label> ids(addr[tracki]);
|
||||
|
||||
List<Type> data(UIndirectList<Type>(values[fieldi], ids));
|
||||
label nData = data.size() - 1;
|
||||
forAll(data, i)
|
||||
writeVTK<Type>(os, data[i]);
|
||||
if (((i + 1) % step == 0) || (i == nData))
|
||||
{
|
||||
writeVTK<Type>(os, data[i]);
|
||||
if (((i + 1) % step == 0) || (i == nData))
|
||||
{
|
||||
os << nl;
|
||||
}
|
||||
else
|
||||
{
|
||||
os << ' ';
|
||||
}
|
||||
os << nl;
|
||||
}
|
||||
else
|
||||
{
|
||||
os << ' ';
|
||||
}
|
||||
offset += ids.size();
|
||||
}
|
||||
/// offset += ids.size();
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,36 +104,28 @@ template<class Type>
|
||||
void Foam::processFields
|
||||
(
|
||||
OFstream& os,
|
||||
const List<List<label>>& addr,
|
||||
const List<word>& userFieldNames,
|
||||
const IOobjectList& cloudObjs
|
||||
const List<labelList>& addr,
|
||||
const IOobjectList& cloudObjects
|
||||
)
|
||||
{
|
||||
IOobjectList objects(cloudObjs.lookupClass(IOField<Type>::typeName));
|
||||
|
||||
if (objects.size())
|
||||
for (const word& fldName : cloudObjects.sortedNames<IOField<Type>>())
|
||||
{
|
||||
DynamicList<word> fieldNames(objects.size());
|
||||
forAll(userFieldNames, i)
|
||||
const IOobject* io = cloudObjects.cfindObject<IOField<Type>>(fldName);
|
||||
|
||||
if (!io)
|
||||
{
|
||||
const IOobject* obj = objects.findObject(userFieldNames[i]);
|
||||
if (obj != nullptr)
|
||||
{
|
||||
fieldNames.append(obj->name());
|
||||
}
|
||||
FatalErrorInFunction
|
||||
<< "Could not read field:" << fldName
|
||||
<< " type:" << IOField<Type>::typeName
|
||||
<< abort(FatalError);
|
||||
}
|
||||
fieldNames.shrink();
|
||||
else
|
||||
{
|
||||
Info<< " reading field " << fldName << endl;
|
||||
IOField<Type> field(*io);
|
||||
|
||||
PtrList<List<Type>> values(fieldNames.size());
|
||||
readFields<Type>(values, fieldNames, cloudObjs);
|
||||
|
||||
writeVTKFields<Type>
|
||||
(
|
||||
os,
|
||||
values,
|
||||
addr,
|
||||
fieldNames
|
||||
);
|
||||
writeVTKField<Type>(os, field, addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -25,13 +26,12 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef steadyParticleTracksTemplates_H
|
||||
#define steadyParticleTracksTemplates_H
|
||||
#ifndef Foam_steadyParticleTracksTemplates_H
|
||||
#define Foam_steadyParticleTracksTemplates_H
|
||||
|
||||
#include "OFstream.H"
|
||||
#include "IOobjectList.H"
|
||||
#include "PtrList.H"
|
||||
#include "Field.H"
|
||||
#include "IOField.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -41,42 +41,29 @@ namespace Foam
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
bool fieldOk(const IOobjectList& cloudObjs, const word& name);
|
||||
|
||||
template<class Type>
|
||||
tmp<Field<Type>> readParticleField
|
||||
tmp<IOField<Type>> readParticleField
|
||||
(
|
||||
const word& name,
|
||||
const IOobjectList cloudObjs
|
||||
);
|
||||
|
||||
template<class Type>
|
||||
void readFields
|
||||
(
|
||||
PtrList<List<Type>>& values,
|
||||
const List<word>& fields,
|
||||
const IOobjectList& cloudObjs
|
||||
const word& fieldName,
|
||||
const IOobjectList& cloudObjects
|
||||
);
|
||||
|
||||
template<class Type>
|
||||
void writeVTK(OFstream& os, const Type& value);
|
||||
|
||||
template<class Type>
|
||||
void writeVTKFields
|
||||
void writeVTKField
|
||||
(
|
||||
OFstream& os,
|
||||
const PtrList<List<Type>>& values,
|
||||
const List<List<label>>& addr,
|
||||
const List<word>& fieldNames
|
||||
const IOField<Type>& field,
|
||||
const List<labelList>& addr
|
||||
);
|
||||
|
||||
template<class Type>
|
||||
void processFields
|
||||
(
|
||||
OFstream& os,
|
||||
const List<List<label>>& addr,
|
||||
const List<word>& userFieldNames,
|
||||
const IOobjectList& cloudObjs
|
||||
const List<labelList>& addr,
|
||||
const IOobjectList& cloudObjects
|
||||
);
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -482,6 +482,7 @@ DebugSwitches
|
||||
constantAbsorptionEmission 0;
|
||||
constantAlphaContactAngle 0;
|
||||
constantScatter 0;
|
||||
coordSetWriter 0;
|
||||
coordinateSystem 0;
|
||||
corrected 0;
|
||||
coupled 0;
|
||||
@ -983,7 +984,6 @@ DebugSwitches
|
||||
wedge 0;
|
||||
weighted 0;
|
||||
word 0;
|
||||
writer 0;
|
||||
xmgr 0;
|
||||
zeroGradient 0;
|
||||
zoneToCell 0;
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2020 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -28,6 +28,7 @@ License
|
||||
|
||||
#include "histogram.H"
|
||||
#include "volFields.H"
|
||||
#include "ListOps.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
@ -42,41 +43,6 @@ namespace functionObjects
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::functionObjects::histogram::writeGraph
|
||||
(
|
||||
const coordSet& coords,
|
||||
const word& fieldName,
|
||||
const scalarField& normalizedValues,
|
||||
const scalarField& absoluteValues
|
||||
) const
|
||||
{
|
||||
fileName outputPath = baseTimeDir();
|
||||
mkDir(outputPath);
|
||||
OFstream graphFile
|
||||
(
|
||||
outputPath
|
||||
/formatterPtr_().getFileName
|
||||
(
|
||||
coords,
|
||||
wordList(1, fieldName)
|
||||
)
|
||||
);
|
||||
|
||||
Log << " Writing histogram of " << fieldName
|
||||
<< " to " << graphFile.name() << endl;
|
||||
|
||||
wordList fieldNames(2);
|
||||
fieldNames[0] = fieldName;
|
||||
fieldNames[1] = fieldName + "Count";
|
||||
List<const scalarField*> yPtrs(2);
|
||||
yPtrs[0] = &normalizedValues;
|
||||
yPtrs[1] = &absoluteValues;
|
||||
formatterPtr_().write(coords, fieldNames, yPtrs, graphFile);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::functionObjects::histogram::histogram
|
||||
@ -86,10 +52,11 @@ Foam::functionObjects::histogram::histogram
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
fvMeshFunctionObject(name, runTime, dict),
|
||||
writeFile(obr_, name),
|
||||
functionObjects::fvMeshFunctionObject(name, runTime, dict),
|
||||
functionObjects::writeFile(obr_, name),
|
||||
max_(-GREAT),
|
||||
min_(GREAT)
|
||||
min_(GREAT),
|
||||
setWriterPtr_(nullptr)
|
||||
{
|
||||
read(dict);
|
||||
}
|
||||
@ -116,8 +83,13 @@ bool Foam::functionObjects::histogram::read(const dictionary& dict)
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
const word format(dict.get<word>("setFormat"));
|
||||
formatterPtr_ = writer<scalar>::New(format);
|
||||
const word writeType(dict.get<word>("setFormat"));
|
||||
|
||||
setWriterPtr_ = coordSetWriter::New
|
||||
(
|
||||
writeType,
|
||||
dict.subOrEmptyDict("formatOptions").optionalSubDict(writeType)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -133,38 +105,30 @@ bool Foam::functionObjects::histogram::write()
|
||||
{
|
||||
Log << type() << " " << name() << " write:" << nl;
|
||||
|
||||
autoPtr<volScalarField> fieldPtr;
|
||||
if (obr_.foundObject<volScalarField>(fieldName_))
|
||||
tmp<volScalarField> tfield;
|
||||
tfield.cref(obr_.cfindObject<volScalarField>(fieldName_));
|
||||
|
||||
if (tfield)
|
||||
{
|
||||
Log << " Looking up field " << fieldName_ << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log << " Reading field " << fieldName_ << endl;
|
||||
fieldPtr.reset
|
||||
tfield = tmp<volScalarField>::New
|
||||
(
|
||||
new volScalarField
|
||||
IOobject
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fieldName_,
|
||||
mesh_.time().timeName(),
|
||||
mesh_,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
mesh_
|
||||
)
|
||||
fieldName_,
|
||||
mesh_.time().timeName(),
|
||||
mesh_,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
mesh_
|
||||
);
|
||||
}
|
||||
|
||||
const volScalarField& field =
|
||||
(
|
||||
fieldPtr
|
||||
? fieldPtr()
|
||||
: obr_.lookupObject<volScalarField>(fieldName_)
|
||||
);
|
||||
|
||||
const auto& field = tfield();
|
||||
|
||||
scalar histMax = max_;
|
||||
scalar histMin = min_;
|
||||
@ -188,14 +152,16 @@ bool Foam::functionObjects::histogram::write()
|
||||
}
|
||||
|
||||
// Calculate the mid-points of bins for the graph axis
|
||||
pointField xBin(nBins_);
|
||||
const scalar delta = (histMax- histMin)/nBins_;
|
||||
pointField xBin(nBins_, Zero);
|
||||
const scalar delta = (histMax - histMin)/nBins_;
|
||||
|
||||
scalar x = histMin + 0.5*delta;
|
||||
forAll(xBin, i)
|
||||
{
|
||||
xBin[i] = point(x, 0, 0);
|
||||
x += delta;
|
||||
scalar x = histMin + 0.5*delta;
|
||||
for (point& p : xBin)
|
||||
{
|
||||
p.x() = x;
|
||||
x += delta;
|
||||
}
|
||||
}
|
||||
|
||||
scalarField dataNormalized(nBins_, Zero);
|
||||
@ -223,23 +189,27 @@ bool Foam::functionObjects::histogram::write()
|
||||
{
|
||||
dataNormalized /= sumData;
|
||||
|
||||
const coordSet coords
|
||||
const coordSet coords(fieldName_, "x", xBin, mag(xBin));
|
||||
|
||||
auto& writer = *setWriterPtr_;
|
||||
|
||||
writer.open
|
||||
(
|
||||
fieldName_,
|
||||
"x",
|
||||
xBin,
|
||||
mag(xBin)
|
||||
coords,
|
||||
(
|
||||
writeFile::baseTimeDir()
|
||||
/ (coords.name() + coordSetWriter::suffix(fieldName_))
|
||||
)
|
||||
);
|
||||
|
||||
Log << " Writing histogram of " << fieldName_
|
||||
<< " to " << writer.path() << endl;
|
||||
|
||||
// Convert count field from labelField to scalarField
|
||||
scalarField count(dataCount.size());
|
||||
forAll(count, i)
|
||||
{
|
||||
count[i] = 1.0*dataCount[i];
|
||||
}
|
||||
writer.nFields(2);
|
||||
writer.write(fieldName_, dataNormalized);
|
||||
writer.write(fieldName_ + "Count", dataCount);
|
||||
|
||||
writeGraph(coords, fieldName_, dataNormalized, count);
|
||||
writer.close(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2016 OpenFOAM Foundation
|
||||
Copyright (C) 2017-2020 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -100,12 +100,12 @@ SourceFiles
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef functionObjects_histogram_H
|
||||
#define functionObjects_histogram_H
|
||||
#ifndef Foam_functionObjects_histogram_H
|
||||
#define Foam_functionObjects_histogram_H
|
||||
|
||||
#include "fvMeshFunctionObject.H"
|
||||
#include "writeFile.H"
|
||||
#include "writer.H"
|
||||
#include "coordSetWriter.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -120,8 +120,8 @@ namespace functionObjects
|
||||
|
||||
class histogram
|
||||
:
|
||||
public fvMeshFunctionObject,
|
||||
public writeFile
|
||||
public functionObjects::fvMeshFunctionObject,
|
||||
public functionObjects::writeFile
|
||||
{
|
||||
// Private Data
|
||||
|
||||
@ -138,18 +138,7 @@ class histogram
|
||||
scalar min_;
|
||||
|
||||
//- Output formatter to write
|
||||
autoPtr<writer<scalar>> formatterPtr_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
void writeGraph
|
||||
(
|
||||
const coordSet& coords,
|
||||
const word& valueName,
|
||||
const scalarField& normalizedValues,
|
||||
const scalarField& absoluteValues
|
||||
) const;
|
||||
mutable autoPtr<coordSetWriter> setWriterPtr_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2016-2020 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -78,8 +78,13 @@ bool Foam::functionObjects::particleDistribution::read(const dictionary& dict)
|
||||
dict.readEntry("cloud", cloudName_);
|
||||
dict.readIfPresent("tagField", tagFieldName_);
|
||||
dict.readEntry("nameVsBinWidth", nameVsBinWidth_);
|
||||
const word format(dict.get<word>("setFormat"));
|
||||
writerPtr_ = writer<scalar>::New(format);
|
||||
|
||||
const word setFormat(dict.get<word>("setFormat"));
|
||||
writerPtr_ = coordSetWriter::New
|
||||
(
|
||||
setFormat,
|
||||
dict.subOrEmptyDict("formatOptions").optionalSubDict(setFormat)
|
||||
);
|
||||
|
||||
Info<< type() << " " << name() << " output:" << nl
|
||||
<< " Processing cloud : " << cloudName_ << nl
|
||||
@ -104,12 +109,10 @@ bool Foam::functionObjects::particleDistribution::write()
|
||||
|
||||
if (!mesh_.foundObject<cloud>(cloudName_))
|
||||
{
|
||||
wordList cloudNames(mesh_.names<cloud>());
|
||||
|
||||
WarningInFunction
|
||||
<< "Unable to find cloud " << cloudName_
|
||||
<< " in the mesh database. Available clouds include:"
|
||||
<< cloudNames << endl;
|
||||
<< flatOutput(mesh_.sortedNames<cloud>()) << endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -153,16 +156,17 @@ bool Foam::functionObjects::particleDistribution::write()
|
||||
}
|
||||
|
||||
|
||||
bool ok = false;
|
||||
forAll(nameVsBinWidth_, i)
|
||||
{
|
||||
ok = false;
|
||||
ok = ok || processField<scalar>(cloudObr, i, tagAddr);
|
||||
ok = ok || processField<vector>(cloudObr, i, tagAddr);
|
||||
ok = ok || processField<tensor>(cloudObr, i, tagAddr);
|
||||
ok = ok || processField<sphericalTensor>(cloudObr, i, tagAddr);
|
||||
ok = ok || processField<symmTensor>(cloudObr, i, tagAddr);
|
||||
ok = ok || processField<tensor>(cloudObr, i, tagAddr);
|
||||
const bool ok
|
||||
(
|
||||
processField<scalar>(cloudObr, i, tagAddr)
|
||||
|| processField<vector>(cloudObr, i, tagAddr)
|
||||
|| processField<tensor>(cloudObr, i, tagAddr)
|
||||
|| processField<sphericalTensor>(cloudObr, i, tagAddr)
|
||||
|| processField<symmTensor>(cloudObr, i, tagAddr)
|
||||
|| processField<tensor>(cloudObr, i, tagAddr)
|
||||
);
|
||||
|
||||
if (log && !ok)
|
||||
{
|
||||
@ -189,10 +193,10 @@ void Foam::functionObjects::particleDistribution::generateDistribution
|
||||
return;
|
||||
}
|
||||
|
||||
word fName(fieldName);
|
||||
word fldName(fieldName);
|
||||
if (tag != -1)
|
||||
{
|
||||
fName = fName + '_' + Foam::name(tag);
|
||||
fldName += '_' + Foam::name(tag);
|
||||
}
|
||||
|
||||
distributionModels::general distribution
|
||||
@ -202,31 +206,20 @@ void Foam::functionObjects::particleDistribution::generateDistribution
|
||||
rndGen_
|
||||
);
|
||||
|
||||
const Field<scalar> distX(distribution.x());
|
||||
const Field<scalar> distY(distribution.y());
|
||||
Field<scalar> distX(distribution.x());
|
||||
Field<scalar> distY(distribution.y());
|
||||
|
||||
pointField xBin(distX.size(), Zero);
|
||||
xBin.replace(0, distX);
|
||||
const coordSet coords
|
||||
(
|
||||
fName,
|
||||
"x",
|
||||
xBin,
|
||||
distX
|
||||
);
|
||||
xBin.replace(vector::X, distX);
|
||||
|
||||
const wordList fieldNames(1, fName);
|
||||
const coordSet coords(fldName, "x", std::move(xBin), std::move(distX));
|
||||
|
||||
fileName outputPath(baseTimeDir());
|
||||
mkDir(outputPath);
|
||||
OFstream graphFile(outputPath/writerPtr_->getFileName(coords, fieldNames));
|
||||
writerPtr_->open(coords, baseTimeDir() / fldName);
|
||||
fileName outFile = writerPtr_->write(fldName, distY);
|
||||
writerPtr_->close(true);
|
||||
|
||||
Log << " Writing distribution of " << fieldName
|
||||
<< " to " << graphFile.name() << endl;
|
||||
|
||||
List<const scalarField*> yPtrs(1);
|
||||
yPtrs[0] = &distY;
|
||||
writerPtr_->write(coords, fieldNames, yPtrs, graphFile);
|
||||
Log << " Wrote distribution of " << fieldName
|
||||
<< " to " << time_.relativePath(outFile) << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2016-2020 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -103,7 +103,7 @@ SourceFiles
|
||||
#include "scalarField.H"
|
||||
#include "Random.H"
|
||||
#include "Tuple2.H"
|
||||
#include "writer.H"
|
||||
#include "coordSetWriter.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -118,7 +118,7 @@ namespace functionObjects
|
||||
|
||||
class particleDistribution
|
||||
:
|
||||
public fvMeshFunctionObject,
|
||||
public functionObjects::fvMeshFunctionObject,
|
||||
public writeFile
|
||||
{
|
||||
protected:
|
||||
@ -138,7 +138,7 @@ protected:
|
||||
List<Tuple2<word, scalar>> nameVsBinWidth_;
|
||||
|
||||
//- Writer
|
||||
autoPtr<writer<scalar>> writerPtr_;
|
||||
mutable autoPtr<coordSetWriter> writerPtr_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2013-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2020 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -27,6 +27,8 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "regionSizeDistribution.H"
|
||||
#include "regionSplit.H"
|
||||
#include "volFields.H"
|
||||
#include "fvcVolumeIntegrate.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
@ -47,31 +49,47 @@ namespace Foam
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::functionObjects::regionSizeDistribution::writeGraph
|
||||
(
|
||||
const coordSet& coords,
|
||||
const word& valueName,
|
||||
const scalarField& values
|
||||
) const
|
||||
namespace Foam
|
||||
{
|
||||
const wordList valNames(1, valueName);
|
||||
|
||||
fileName outputPath = baseTimeDir();
|
||||
mkDir(outputPath);
|
||||
template<class Type>
|
||||
static Map<Type> regionSum(const regionSplit& regions, const Field<Type>& fld)
|
||||
{
|
||||
// Per region the sum of fld
|
||||
Map<Type> regionToSum(regions.nRegions()/Pstream::nProcs());
|
||||
|
||||
OFstream str(outputPath/formatterPtr_().getFileName(coords, valNames));
|
||||
forAll(fld, celli)
|
||||
{
|
||||
const label regioni = regions[celli];
|
||||
regionToSum(regioni, Type(Zero)) += fld[celli];
|
||||
}
|
||||
|
||||
Log << " Writing distribution of " << valueName << " to " << str.name()
|
||||
<< endl;
|
||||
Pstream::mapCombineGather(regionToSum, plusEqOp<Type>());
|
||||
Pstream::mapCombineScatter(regionToSum);
|
||||
|
||||
List<const scalarField*> valPtrs(1);
|
||||
valPtrs[0] = &values;
|
||||
formatterPtr_().write(coords, valNames, valPtrs, str);
|
||||
return regionToSum;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
static List<Type> extractData(const labelUList& keys, const Map<Type>& regionData)
|
||||
{
|
||||
List<Type> sortedData(keys.size());
|
||||
|
||||
forAll(keys, i)
|
||||
{
|
||||
sortedData[i] = regionData[keys[i]];
|
||||
}
|
||||
return sortedData;
|
||||
}
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::functionObjects::regionSizeDistribution::writeAlphaFields
|
||||
(
|
||||
const regionSplit& regions,
|
||||
@ -222,7 +240,7 @@ Foam::functionObjects::regionSizeDistribution::divide
|
||||
}
|
||||
else
|
||||
{
|
||||
result[i] = 0.0;
|
||||
result[i] = 0;
|
||||
}
|
||||
}
|
||||
return tresult;
|
||||
@ -232,8 +250,9 @@ Foam::functionObjects::regionSizeDistribution::divide
|
||||
void Foam::functionObjects::regionSizeDistribution::writeGraphs
|
||||
(
|
||||
const word& fieldName, // name of field
|
||||
const labelList& indices, // index of bin for each region
|
||||
const scalarField& sortedField, // per region field data
|
||||
|
||||
const labelList& indices, // index of bin for each region
|
||||
const scalarField& binCount, // per bin number of regions
|
||||
const coordSet& coords // graph data for bins
|
||||
) const
|
||||
@ -260,12 +279,44 @@ void Foam::functionObjects::regionSizeDistribution::writeGraphs
|
||||
sqrt(divide(binSqrSum, binCount) - Foam::sqr(binAvg))
|
||||
);
|
||||
|
||||
// Write average
|
||||
writeGraph(coords, fieldName + "_sum", binSum);
|
||||
// Write average
|
||||
writeGraph(coords, fieldName + "_avg", binAvg);
|
||||
// Write deviation
|
||||
writeGraph(coords, fieldName + "_dev", binDev);
|
||||
|
||||
auto& writer = formatterPtr_();
|
||||
|
||||
word outputName;
|
||||
if (writer.buffering())
|
||||
{
|
||||
outputName =
|
||||
(
|
||||
coords.name()
|
||||
+ coordSetWriter::suffix
|
||||
(
|
||||
wordList
|
||||
({
|
||||
fieldName + "_sum",
|
||||
fieldName + "_avg",
|
||||
fieldName + "_dev"
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputName = coords.name();
|
||||
}
|
||||
|
||||
writer.open
|
||||
(
|
||||
coords,
|
||||
(baseTimeDir() / outputName)
|
||||
);
|
||||
|
||||
Log << " Writing distribution of "
|
||||
<< fieldName << " to " << writer.path() << endl;
|
||||
|
||||
writer.write(fieldName + "_sum", binSum);
|
||||
writer.write(fieldName + "_avg", binAvg);
|
||||
writer.write(fieldName + "_dev", binDev);
|
||||
writer.close(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,18 +341,15 @@ void Foam::functionObjects::regionSizeDistribution::writeGraphs
|
||||
scalarField sortedField
|
||||
(
|
||||
sortedNormalisation
|
||||
* extractData
|
||||
(
|
||||
sortedRegions,
|
||||
regionField
|
||||
)
|
||||
* extractData(sortedRegions, regionField)
|
||||
);
|
||||
|
||||
writeGraphs
|
||||
(
|
||||
fieldName, // name of field
|
||||
indices, // index of bin for each region
|
||||
sortedField, // per region field data
|
||||
|
||||
indices, // index of bin for each region
|
||||
binCount, // per bin number of regions
|
||||
coords // graph data for bins
|
||||
);
|
||||
@ -343,8 +391,12 @@ bool Foam::functionObjects::regionSizeDistribution::read(const dictionary& dict)
|
||||
dict.readEntry("patches", patchNames_);
|
||||
dict.readEntry("fields", fields_);
|
||||
|
||||
const word format(dict.get<word>("setFormat"));
|
||||
formatterPtr_ = writer<scalar>::New(format);
|
||||
const word setFormat(dict.get<word>("setFormat"));
|
||||
formatterPtr_ = coordSetWriter::New
|
||||
(
|
||||
setFormat,
|
||||
dict.subOrEmptyDict("formatOptions").optionalSubDict(setFormat)
|
||||
);
|
||||
|
||||
if (dict.found(coordinateSystem::typeName_()))
|
||||
{
|
||||
@ -385,15 +437,16 @@ bool Foam::functionObjects::regionSizeDistribution::write()
|
||||
{
|
||||
Log << type() << " " << name() << " write:" << nl;
|
||||
|
||||
autoPtr<volScalarField> alphaPtr;
|
||||
if (obr_.foundObject<volScalarField>(alphaName_))
|
||||
tmp<volScalarField> talpha;
|
||||
talpha.cref(obr_.cfindObject<volScalarField>(alphaName_));
|
||||
if (talpha)
|
||||
{
|
||||
Log << " Looking up field " << alphaName_ << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< " Reading field " << alphaName_ << endl;
|
||||
alphaPtr.reset
|
||||
talpha.reset
|
||||
(
|
||||
new volScalarField
|
||||
(
|
||||
@ -409,14 +462,7 @@ bool Foam::functionObjects::regionSizeDistribution::write()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
const volScalarField& alpha =
|
||||
(
|
||||
alphaPtr
|
||||
? *alphaPtr
|
||||
: obr_.lookupObject<volScalarField>(alphaName_)
|
||||
);
|
||||
const auto& alpha = talpha();
|
||||
|
||||
Log << " Volume of alpha = "
|
||||
<< fvc::domainIntegrate(alpha).value()
|
||||
@ -460,10 +506,9 @@ bool Foam::functionObjects::regionSizeDistribution::write()
|
||||
if (fvp.coupled())
|
||||
{
|
||||
tmp<scalarField> townFld(fvp.patchInternalField());
|
||||
const scalarField& ownFld = townFld();
|
||||
|
||||
tmp<scalarField> tnbrFld(fvp.patchNeighbourField());
|
||||
const scalarField& nbrFld = tnbrFld();
|
||||
const auto& ownFld = townFld();
|
||||
const auto& nbrFld = tnbrFld();
|
||||
|
||||
label start = fvp.patch().patch().start();
|
||||
|
||||
@ -663,13 +708,15 @@ bool Foam::functionObjects::regionSizeDistribution::write()
|
||||
if (allRegionVolume.size())
|
||||
{
|
||||
// Construct mids of bins for plotting
|
||||
pointField xBin(nBins_);
|
||||
pointField xBin(nBins_, Zero);
|
||||
|
||||
scalar x = 0.5*delta;
|
||||
forAll(xBin, i)
|
||||
{
|
||||
xBin[i] = point(x, 0, 0);
|
||||
x += delta;
|
||||
scalar x = 0.5*delta;
|
||||
for (point& p : xBin)
|
||||
{
|
||||
p.x() = x;
|
||||
x += delta;
|
||||
}
|
||||
}
|
||||
|
||||
const coordSet coords("diameter", "x", xBin, mag(xBin));
|
||||
@ -682,11 +729,7 @@ bool Foam::functionObjects::regionSizeDistribution::write()
|
||||
|
||||
scalarField sortedVols
|
||||
(
|
||||
extractData
|
||||
(
|
||||
sortedRegions,
|
||||
allRegionAlphaVolume
|
||||
)
|
||||
extractData(sortedRegions, allRegionAlphaVolume)
|
||||
);
|
||||
|
||||
vectorField centroids(sortedVols.size(), Zero);
|
||||
@ -712,11 +755,7 @@ bool Foam::functionObjects::regionSizeDistribution::write()
|
||||
// 2. centroid
|
||||
vectorField sortedMoment
|
||||
(
|
||||
extractData
|
||||
(
|
||||
sortedRegions,
|
||||
allRegionAlphaDistance
|
||||
)
|
||||
extractData(sortedRegions, allRegionAlphaDistance)
|
||||
);
|
||||
|
||||
centroids = sortedMoment/sortedVols + origin_;
|
||||
@ -756,17 +795,30 @@ bool Foam::functionObjects::regionSizeDistribution::write()
|
||||
if (Pstream::master())
|
||||
{
|
||||
// Construct mids of bins for plotting
|
||||
pointField xBin(nDownstreamBins_);
|
||||
pointField xBin(nDownstreamBins_, Zero);
|
||||
|
||||
scalar x = 0.5*deltaX;
|
||||
forAll(xBin, i)
|
||||
{
|
||||
xBin[i] = point(x, 0, 0);
|
||||
x += deltaX;
|
||||
scalar x = 0.5*deltaX;
|
||||
for (point& p : xBin)
|
||||
{
|
||||
p.x() = x;
|
||||
x += deltaX;
|
||||
}
|
||||
}
|
||||
|
||||
const coordSet coords("distance", "x", xBin, mag(xBin));
|
||||
writeGraph(coords, "isoPlanes", binDownCount);
|
||||
|
||||
auto& writer = formatterPtr_();
|
||||
writer.nFields(1);
|
||||
|
||||
writer.open
|
||||
(
|
||||
coords,
|
||||
writeFile::baseTimeDir() / (coords.name() + "_isoPlanes")
|
||||
);
|
||||
|
||||
writer.write("isoPlanes", binDownCount);
|
||||
writer.close(true);
|
||||
}
|
||||
|
||||
// Write to log
|
||||
@ -819,7 +871,17 @@ bool Foam::functionObjects::regionSizeDistribution::write()
|
||||
// Write counts
|
||||
if (Pstream::master())
|
||||
{
|
||||
writeGraph(coords, "count", binCount);
|
||||
auto& writer = formatterPtr_();
|
||||
writer.nFields(1);
|
||||
|
||||
writer.open
|
||||
(
|
||||
coords,
|
||||
writeFile::baseTimeDir() / (coords.name() + "_count")
|
||||
);
|
||||
|
||||
writer.write("count", binCount);
|
||||
writer.close(true);
|
||||
}
|
||||
|
||||
// Write to log
|
||||
@ -849,28 +911,28 @@ bool Foam::functionObjects::regionSizeDistribution::write()
|
||||
writeGraphs
|
||||
(
|
||||
"volume", // name of field
|
||||
indices, // per region the bin index
|
||||
sortedVols, // per region field data
|
||||
|
||||
indices, // per region the bin index
|
||||
binCount, // per bin number of regions
|
||||
coords // graph data for bins
|
||||
);
|
||||
|
||||
// Collect some more field
|
||||
// Collect some more fields
|
||||
{
|
||||
wordList scalarNames(obr_.names(volScalarField::typeName));
|
||||
|
||||
const labelList selected(fields_.matching(scalarNames));
|
||||
|
||||
for (const label fieldi : selected)
|
||||
for
|
||||
(
|
||||
const word& fldName
|
||||
: obr_.sortedNames<volScalarField>(fields_)
|
||||
)
|
||||
{
|
||||
const word& fldName = scalarNames[fieldi];
|
||||
|
||||
Log << " Scalar field " << fldName << endl;
|
||||
|
||||
const scalarField& fld = obr_.lookupObject
|
||||
<
|
||||
volScalarField
|
||||
>(fldName).primitiveField();
|
||||
tmp<Field<scalar>> tfld
|
||||
(
|
||||
obr_.lookupObject<volScalarField>(fldName).primitiveField()
|
||||
);
|
||||
const auto& fld = tfld();
|
||||
|
||||
writeGraphs
|
||||
(
|
||||
@ -887,21 +949,20 @@ bool Foam::functionObjects::regionSizeDistribution::write()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
wordList vectorNames(obr_.names(volVectorField::typeName));
|
||||
|
||||
const labelList selected(fields_.matching(vectorNames));
|
||||
|
||||
for (const label fieldi : selected)
|
||||
for
|
||||
(
|
||||
const word& fldName
|
||||
: obr_.sortedNames<volVectorField>(fields_)
|
||||
)
|
||||
{
|
||||
const word& fldName = vectorNames[fieldi];
|
||||
|
||||
Log << " Vector field " << fldName << endl;
|
||||
|
||||
vectorField fld = obr_.lookupObject
|
||||
<
|
||||
volVectorField
|
||||
>(fldName).primitiveField();
|
||||
tmp<Field<vector>> tfld
|
||||
(
|
||||
obr_.lookupObject<volVectorField>(fldName).primitiveField()
|
||||
);
|
||||
|
||||
if (csysPtr_)
|
||||
{
|
||||
@ -910,18 +971,18 @@ bool Foam::functionObjects::regionSizeDistribution::write()
|
||||
<< csysPtr_->name()
|
||||
<< endl;
|
||||
|
||||
fld = csysPtr_->localVector(fld);
|
||||
tfld = csysPtr_->localVector(tfld());
|
||||
}
|
||||
|
||||
const auto& fld = tfld();
|
||||
|
||||
// Components
|
||||
|
||||
for (direction cmp = 0; cmp < vector::nComponents; cmp++)
|
||||
for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt)
|
||||
{
|
||||
writeGraphs
|
||||
(
|
||||
fldName + vector::componentNames[cmp],
|
||||
alphaVol*fld.component(cmp),// per cell field data
|
||||
fldName + vector::componentNames[cmpt],
|
||||
alphaVol*fld.component(cmpt),// per cell field data
|
||||
|
||||
regions, // per cell the region(=droplet)
|
||||
sortedRegions, // valid regions in sorted order
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2013-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2020 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -169,17 +169,16 @@ SourceFiles
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef functionObjects_regionSizeDistribution_H
|
||||
#define functionObjects_regionSizeDistribution_H
|
||||
#ifndef Foam_functionObjects_regionSizeDistribution_H
|
||||
#define Foam_functionObjects_regionSizeDistribution_H
|
||||
|
||||
#include "fvMeshFunctionObject.H"
|
||||
#include "writeFile.H"
|
||||
#include "writer.H"
|
||||
#include "coordSetWriter.H"
|
||||
#include "Map.H"
|
||||
#include "volFieldsFwd.H"
|
||||
#include "wordRes.H"
|
||||
#include "coordinateSystem.H"
|
||||
#include "Switch.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -197,7 +196,7 @@ namespace functionObjects
|
||||
|
||||
class regionSizeDistribution
|
||||
:
|
||||
public fvMeshFunctionObject,
|
||||
public functionObjects::fvMeshFunctionObject,
|
||||
public writeFile
|
||||
{
|
||||
// Private Data
|
||||
@ -224,7 +223,7 @@ class regionSizeDistribution
|
||||
wordRes fields_;
|
||||
|
||||
//- Output formatter to write
|
||||
autoPtr<writer<scalar>> formatterPtr_;
|
||||
mutable autoPtr<coordSetWriter> formatterPtr_;
|
||||
|
||||
//- Optional coordinate system
|
||||
autoPtr<coordinateSystem> csysPtr_;
|
||||
@ -253,20 +252,6 @@ class regionSizeDistribution
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
template<class Type>
|
||||
Map<Type> regionSum(const regionSplit&, const Field<Type>&) const;
|
||||
|
||||
//- Get data in order
|
||||
template<class Type>
|
||||
List<Type> extractData(const labelUList& keys, const Map<Type>&) const;
|
||||
|
||||
void writeGraph
|
||||
(
|
||||
const coordSet& coords,
|
||||
const word& valueName,
|
||||
const scalarField& values
|
||||
) const;
|
||||
|
||||
//- Write volfields with the parts of alpha which are not
|
||||
//- droplets (liquidCore, backGround)
|
||||
void writeAlphaFields
|
||||
@ -287,8 +272,9 @@ class regionSizeDistribution
|
||||
void writeGraphs
|
||||
(
|
||||
const word& fieldName, // name of field
|
||||
const labelList& indices, // index of bin for each region
|
||||
const scalarField& sortedField, // per region field data
|
||||
|
||||
const labelList& indices, // index of bin for each region
|
||||
const scalarField& binCount, // per bin number of regions
|
||||
const coordSet& coords // graph data for bins
|
||||
) const;
|
||||
@ -301,6 +287,7 @@ class regionSizeDistribution
|
||||
const regionSplit& regions, // per cell the region(=droplet)
|
||||
const labelList& sortedRegions, // valid regions in sorted order
|
||||
const scalarField& sortedNormalisation,
|
||||
|
||||
const labelList& indices, // index of bin for each region
|
||||
const scalarField& binCount, // per bin number of regions
|
||||
const coordSet& coords // graph data for bins
|
||||
@ -355,12 +342,6 @@ public:
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "regionSizeDistributionTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2015 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2021 OpenCFD Ltd.
|
||||
Copyright (C) 2015-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -29,6 +29,7 @@ License
|
||||
#include "streamLineBase.H"
|
||||
#include "fvMesh.H"
|
||||
#include "ReadFields.H"
|
||||
#include "OFstream.H"
|
||||
#include "sampledSet.H"
|
||||
#include "globalIndex.H"
|
||||
#include "mapDistribute.H"
|
||||
@ -626,8 +627,7 @@ bool Foam::functionObjects::streamLineBase::writeToFile()
|
||||
|
||||
|
||||
// Note: filenames scattered below since used in global call
|
||||
fileName scalarVtkFile;
|
||||
fileName vectorVtkFile;
|
||||
HashTable<fileName> outputFileNames;
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
@ -706,117 +706,112 @@ bool Foam::functionObjects::streamLineBase::writeToFile()
|
||||
}
|
||||
}
|
||||
|
||||
// Convert scalar values
|
||||
|
||||
if (!allScalars_.empty() && !tracks.empty())
|
||||
const bool canWrite =
|
||||
(
|
||||
!tracks.empty()
|
||||
&& trackWriterPtr_
|
||||
&& trackWriterPtr_->enabled()
|
||||
&& (!allScalars_.empty() || !allVectors_.empty())
|
||||
);
|
||||
|
||||
if (canWrite)
|
||||
{
|
||||
List<List<scalarField>> scalarValues(allScalars_.size());
|
||||
auto& writer = trackWriterPtr_();
|
||||
|
||||
forAll(allScalars_, scalari)
|
||||
writer.nFields(allScalars_.size() + allVectors_.size());
|
||||
|
||||
writer.open
|
||||
(
|
||||
tracks,
|
||||
(vtkPath / tracks[0].name())
|
||||
);
|
||||
|
||||
|
||||
// Temporary measure
|
||||
if (!allScalars_.empty())
|
||||
{
|
||||
DynamicList<scalarList>& allTrackVals = allScalars_[scalari];
|
||||
scalarValues[scalari].setSize(nTracks);
|
||||
List<List<scalarField>> scalarValues(allScalars_.size());
|
||||
|
||||
forAll(allTrackVals, tracki)
|
||||
forAll(allScalars_, scalari)
|
||||
{
|
||||
scalarList& vals = allTrackVals[tracki];
|
||||
if (vals.size())
|
||||
DynamicList<scalarList>& allTrackVals = allScalars_[scalari];
|
||||
scalarValues[scalari].resize(nTracks);
|
||||
|
||||
forAll(allTrackVals, tracki)
|
||||
{
|
||||
const label newTracki = oldToNewTrack[tracki];
|
||||
scalarValues[scalari][newTracki].transfer(vals);
|
||||
scalarList& vals = allTrackVals[tracki];
|
||||
if (vals.size())
|
||||
{
|
||||
const label newTracki = oldToNewTrack[tracki];
|
||||
scalarValues[scalari][newTracki].transfer(vals);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
forAll(scalarNames_, i)
|
||||
{
|
||||
fileName outFile =
|
||||
writer.write(scalarNames_[i], scalarValues[i]);
|
||||
|
||||
outputFileNames.insert
|
||||
(
|
||||
scalarNames_[i],
|
||||
time_.relativePath(outFile, true)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
scalarVtkFile = fileName
|
||||
(
|
||||
vtkPath
|
||||
/ scalarFormatterPtr_().getFileName
|
||||
(
|
||||
tracks[0],
|
||||
scalarNames_
|
||||
)
|
||||
);
|
||||
|
||||
Log << " Writing data to " << scalarVtkFile.path() << endl;
|
||||
|
||||
scalarFormatterPtr_().write
|
||||
(
|
||||
true, // writeTracks
|
||||
List<scalarField>(), // times
|
||||
tracks,
|
||||
scalarNames_,
|
||||
scalarValues,
|
||||
OFstream(scalarVtkFile)()
|
||||
);
|
||||
}
|
||||
|
||||
// Convert vector values
|
||||
|
||||
if (!allVectors_.empty() && !tracks.empty())
|
||||
{
|
||||
List<List<vectorField>> vectorValues(allVectors_.size());
|
||||
|
||||
forAll(allVectors_, vectori)
|
||||
if (!allVectors_.empty())
|
||||
{
|
||||
DynamicList<vectorList>& allTrackVals = allVectors_[vectori];
|
||||
vectorValues[vectori].setSize(nTracks);
|
||||
List<List<vectorField>> vectorValues(allVectors_.size());
|
||||
|
||||
forAll(allTrackVals, tracki)
|
||||
forAll(allVectors_, vectori)
|
||||
{
|
||||
vectorList& vals = allTrackVals[tracki];
|
||||
if (vals.size())
|
||||
DynamicList<vectorList>& allTrackVals = allVectors_[vectori];
|
||||
vectorValues[vectori].setSize(nTracks);
|
||||
|
||||
forAll(allTrackVals, tracki)
|
||||
{
|
||||
const label newTracki = oldToNewTrack[tracki];
|
||||
vectorValues[vectori][newTracki].transfer(vals);
|
||||
vectorList& vals = allTrackVals[tracki];
|
||||
if (vals.size())
|
||||
{
|
||||
const label newTracki = oldToNewTrack[tracki];
|
||||
vectorValues[vectori][newTracki].transfer(vals);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
forAll(vectorNames_, i)
|
||||
{
|
||||
fileName outFile =
|
||||
writer.write(vectorNames_[i], vectorValues[i]);
|
||||
|
||||
outputFileNames.insert
|
||||
(
|
||||
scalarNames_[i],
|
||||
time_.relativePath(outFile, true)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
vectorVtkFile = fileName
|
||||
(
|
||||
vtkPath
|
||||
/ vectorFormatterPtr_().getFileName(tracks[0], vectorNames_)
|
||||
);
|
||||
|
||||
//Info<< " Writing vector data to " << vectorVtkFile << endl;
|
||||
|
||||
vectorFormatterPtr_().write
|
||||
(
|
||||
true, // writeTracks
|
||||
List<scalarField>(), // times
|
||||
tracks,
|
||||
vectorNames_,
|
||||
vectorValues,
|
||||
OFstream(vectorVtkFile)()
|
||||
);
|
||||
writer.close(true);
|
||||
}
|
||||
|
||||
// Log << " Writing data to " << scalarVtkFile.path() << endl;
|
||||
}
|
||||
|
||||
|
||||
// File names are generated on the master but setProperty needs to
|
||||
// be across all procs
|
||||
Pstream::scatter(scalarVtkFile);
|
||||
for (const word& fieldName : scalarNames_)
|
||||
{
|
||||
dictionary propsDict;
|
||||
propsDict.add
|
||||
(
|
||||
"file",
|
||||
time_.relativePath(scalarVtkFile, true)
|
||||
);
|
||||
setProperty(fieldName, propsDict);
|
||||
}
|
||||
// File names generated on the master but setProperty needed everywher
|
||||
Pstream::scatter(outputFileNames);
|
||||
|
||||
Pstream::scatter(vectorVtkFile);
|
||||
for (const word& fieldName : vectorNames_)
|
||||
forAllConstIters(outputFileNames, iter)
|
||||
{
|
||||
const word& fieldName = iter.key();
|
||||
const fileName& outputName = iter.val();
|
||||
|
||||
dictionary propsDict;
|
||||
propsDict.add
|
||||
(
|
||||
"file",
|
||||
time_.relativePath(vectorVtkFile, true)
|
||||
);
|
||||
propsDict.add("file", outputName);
|
||||
setProperty(fieldName, propsDict);
|
||||
}
|
||||
|
||||
@ -844,7 +839,7 @@ Foam::functionObjects::streamLineBase::streamLineBase
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
fvMeshFunctionObject(name, runTime, dict),
|
||||
functionObjects::fvMeshFunctionObject(name, runTime, dict),
|
||||
dict_(dict),
|
||||
fields_()
|
||||
{}
|
||||
@ -858,7 +853,7 @@ Foam::functionObjects::streamLineBase::streamLineBase
|
||||
const wordList& fieldNames
|
||||
)
|
||||
:
|
||||
fvMeshFunctionObject(name, runTime, dict),
|
||||
functionObjects::fvMeshFunctionObject(name, runTime, dict),
|
||||
dict_(dict),
|
||||
fields_(fieldNames)
|
||||
{}
|
||||
@ -959,8 +954,13 @@ bool Foam::functionObjects::streamLineBase::read(const dictionary& dict)
|
||||
sampledSetPtr_.clear();
|
||||
sampledSetAxis_.clear();
|
||||
|
||||
scalarFormatterPtr_ = writer<scalar>::New(dict.get<word>("setFormat"));
|
||||
vectorFormatterPtr_ = writer<vector>::New(dict.get<word>("setFormat"));
|
||||
const word setFormat(dict.get<word>("setFormat"));
|
||||
|
||||
trackWriterPtr_ = coordSetWriter::New
|
||||
(
|
||||
setFormat,
|
||||
dict.subOrEmptyDict("formatOptions").optionalSubDict(setFormat)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2015 OpenFOAM Foundation
|
||||
Copyright (C) 2016 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -36,14 +36,14 @@ SourceFiles
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef streamLineBase_H
|
||||
#define streamLineBase_H
|
||||
#ifndef Foam_functionObjects_streamLineBase_H
|
||||
#define Foam_functionObjects_streamLineBase_H
|
||||
|
||||
#include "fvMeshFunctionObject.H"
|
||||
#include "DynamicList.H"
|
||||
#include "scalarList.H"
|
||||
#include "vectorList.H"
|
||||
#include "writer.H"
|
||||
#include "coordSetWriter.H"
|
||||
#include "indirectPrimitivePatch.H"
|
||||
#include "interpolation.H"
|
||||
#include "Enum.H"
|
||||
@ -53,6 +53,7 @@ SourceFiles
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward Declarations
|
||||
class meshSearch;
|
||||
class sampledSet;
|
||||
|
||||
@ -65,7 +66,7 @@ namespace functionObjects
|
||||
|
||||
class streamLineBase
|
||||
:
|
||||
public fvMeshFunctionObject
|
||||
public functionObjects::fvMeshFunctionObject
|
||||
{
|
||||
public:
|
||||
|
||||
@ -128,16 +129,13 @@ protected:
|
||||
wordList vectorNames_;
|
||||
|
||||
|
||||
// Demand driven
|
||||
// Demand driven
|
||||
|
||||
//- File writer for scalar data
|
||||
autoPtr<writer<scalar>> scalarFormatterPtr_;
|
||||
|
||||
//- File writer for vector data
|
||||
autoPtr<writer<vector>> vectorFormatterPtr_;
|
||||
//- File writer for tracks data
|
||||
mutable autoPtr<coordSetWriter> trackWriterPtr_;
|
||||
|
||||
|
||||
// Generated data
|
||||
// Generated Data
|
||||
|
||||
//- All tracks. Per track the points it passed through
|
||||
DynamicList<List<point>> allTracks_;
|
||||
|
||||
@ -441,7 +441,7 @@ void Foam::meshRefinement::nearestFace
|
||||
(
|
||||
const labelUList& startFaces,
|
||||
const bitSet& isBlockedFace,
|
||||
|
||||
|
||||
autoPtr<mapDistribute>& mapPtr,
|
||||
labelList& faceToStart,
|
||||
const label nIter
|
||||
@ -2808,23 +2808,19 @@ Foam::fileName Foam::meshRefinement::writeLeakPath
|
||||
const polyMesh& mesh,
|
||||
const pointField& locationsInMesh,
|
||||
const pointField& locationsOutsideMesh,
|
||||
const writer<scalar>& leakPathFormatter,
|
||||
const boolList& blockedFace
|
||||
const boolList& blockedFace,
|
||||
coordSetWriter& writer
|
||||
)
|
||||
{
|
||||
const polyBoundaryMesh& pbm = mesh.boundaryMesh();
|
||||
|
||||
fileName outputDir;
|
||||
if (Pstream::master())
|
||||
{
|
||||
outputDir =
|
||||
mesh.time().globalPath()
|
||||
/ functionObject::outputPrefix
|
||||
/ mesh.pointsInstance();
|
||||
outputDir.clean();
|
||||
mkDir(outputDir);
|
||||
}
|
||||
|
||||
fileName outputDir
|
||||
(
|
||||
mesh.time().globalPath()
|
||||
/ functionObject::outputPrefix
|
||||
/ mesh.pointsInstance()
|
||||
);
|
||||
outputDir.clean(); // Remove unneeded ".."
|
||||
|
||||
// Write the leak path
|
||||
|
||||
@ -2877,7 +2873,7 @@ Foam::fileName Foam::meshRefinement::writeLeakPath
|
||||
label& n = nElemsPerSegment[segmenti];
|
||||
|
||||
points[n] = leakPath[elemi];
|
||||
dist[n] = leakPath.curveDist()[elemi];
|
||||
dist[n] = leakPath.distance()[elemi];
|
||||
n++;
|
||||
}
|
||||
}
|
||||
@ -2887,13 +2883,11 @@ Foam::fileName Foam::meshRefinement::writeLeakPath
|
||||
{
|
||||
// Collect data from all processors
|
||||
List<pointList> gatheredPts(Pstream::nProcs());
|
||||
gatheredPts[Pstream::myProcNo()] =
|
||||
std::move(segmentPoints[segmenti]);
|
||||
gatheredPts[Pstream::myProcNo()] = std::move(segmentPoints[segmenti]);
|
||||
Pstream::gatherList(gatheredPts);
|
||||
|
||||
List<scalarList> gatheredDist(Pstream::nProcs());
|
||||
gatheredDist[Pstream::myProcNo()] =
|
||||
std::move(segmentDist[segmenti]);
|
||||
gatheredDist[Pstream::myProcNo()] = std::move(segmentDist[segmenti]);
|
||||
Pstream::gatherList(gatheredDist);
|
||||
|
||||
// Combine processor lists into one big list.
|
||||
@ -2912,7 +2906,7 @@ Foam::fileName Foam::meshRefinement::writeLeakPath
|
||||
)
|
||||
);
|
||||
|
||||
// Sort according to curveDist
|
||||
// Sort according to distance
|
||||
labelList indexSet(Foam::sortedOrder(allDist));
|
||||
|
||||
allLeakPaths.set
|
||||
@ -2932,42 +2926,28 @@ Foam::fileName Foam::meshRefinement::writeLeakPath
|
||||
fileName fName;
|
||||
if (Pstream::master())
|
||||
{
|
||||
List<List<scalarField>> allLeakData(1);
|
||||
List<scalarField>& varData = allLeakData[0];
|
||||
varData.setSize(allLeakPaths.size());
|
||||
List<scalarField> allLeakData(allLeakPaths.size());
|
||||
forAll(allLeakPaths, segmenti)
|
||||
{
|
||||
varData[segmenti] = allLeakPaths[segmenti].curveDist();
|
||||
allLeakData[segmenti] = allLeakPaths[segmenti].distance();
|
||||
}
|
||||
|
||||
const wordList valueSetNames(1, "leakPath");
|
||||
writer.nFields(1);
|
||||
|
||||
fName =
|
||||
outputDir
|
||||
/leakPathFormatter.getFileName
|
||||
(
|
||||
allLeakPaths[0],
|
||||
valueSetNames
|
||||
);
|
||||
writer.open
|
||||
(
|
||||
allLeakPaths,
|
||||
(outputDir / allLeakPaths[0].name())
|
||||
);
|
||||
|
||||
// Note scope to force writing to finish before
|
||||
// FatalError exit
|
||||
OFstream ofs(fName);
|
||||
if (ofs.opened())
|
||||
{
|
||||
leakPathFormatter.write
|
||||
(
|
||||
true, // write tracks
|
||||
List<scalarField>(), // times
|
||||
allLeakPaths,
|
||||
valueSetNames,
|
||||
allLeakData,
|
||||
ofs
|
||||
);
|
||||
}
|
||||
fName = writer.write("leakPath", allLeakData);
|
||||
|
||||
// Force writing to finish before FatalError exit
|
||||
writer.close(true);
|
||||
}
|
||||
|
||||
Pstream::scatter(fName);
|
||||
// Probably do not need to broadcast name (only written on master anyhow)
|
||||
UPstream::broadcast(fName);
|
||||
|
||||
return fName;
|
||||
}
|
||||
@ -2982,11 +2962,12 @@ Foam::label Foam::meshRefinement::findRegions
|
||||
const vector& perturbVec,
|
||||
const pointField& locationsInMesh,
|
||||
const pointField& locationsOutsideMesh,
|
||||
const bool exitIfLeakPath,
|
||||
const refPtr<writer<scalar>>& leakPathFormatter,
|
||||
const label nRegions,
|
||||
labelList& cellRegion,
|
||||
const boolList& blockedFace
|
||||
const boolList& blockedFace,
|
||||
// Leak-path
|
||||
const bool exitIfLeakPath,
|
||||
const refPtr<coordSetWriter>& leakPathFormatter
|
||||
)
|
||||
{
|
||||
bitSet insideCell(mesh.nCells());
|
||||
@ -3022,7 +3003,10 @@ Foam::label Foam::meshRefinement::findRegions
|
||||
// mesh do not conflict with those inside
|
||||
forAll(locationsOutsideMesh, i)
|
||||
{
|
||||
// Find the region containing the point
|
||||
// Find the region containing the point,
|
||||
// and the corresponding inside region index
|
||||
|
||||
label indexi;
|
||||
label regioni = findRegion
|
||||
(
|
||||
mesh,
|
||||
@ -3031,46 +3015,39 @@ Foam::label Foam::meshRefinement::findRegions
|
||||
locationsOutsideMesh[i]
|
||||
);
|
||||
|
||||
if (regioni != -1)
|
||||
if (regioni == -1 && (indexi = insideRegions.find(regioni)) != -1)
|
||||
{
|
||||
// Do a quick check for locationsOutsideMesh overlapping with
|
||||
// inside ones.
|
||||
label index = insideRegions.find(regioni);
|
||||
if (index != -1)
|
||||
if (leakPathFormatter)
|
||||
{
|
||||
if (leakPathFormatter.valid())
|
||||
{
|
||||
const fileName fName
|
||||
const fileName fName
|
||||
(
|
||||
writeLeakPath
|
||||
(
|
||||
writeLeakPath
|
||||
(
|
||||
mesh,
|
||||
locationsInMesh,
|
||||
locationsOutsideMesh,
|
||||
leakPathFormatter,
|
||||
blockedFace
|
||||
)
|
||||
);
|
||||
Info<< "Dumped leak path to " << fName << endl;
|
||||
}
|
||||
mesh,
|
||||
locationsInMesh,
|
||||
locationsOutsideMesh,
|
||||
blockedFace,
|
||||
leakPathFormatter.constCast()
|
||||
)
|
||||
);
|
||||
Info<< "Dumped leak path to " << fName << endl;
|
||||
}
|
||||
|
||||
if (exitIfLeakPath)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Location in mesh " << locationsInMesh[index]
|
||||
<< " is inside same mesh region " << regioni
|
||||
<< " as one of the locations outside mesh "
|
||||
<< locationsOutsideMesh
|
||||
<< exit(FatalError);
|
||||
}
|
||||
else
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Location in mesh " << locationsInMesh[index]
|
||||
<< " is inside same mesh region " << regioni
|
||||
<< " as one of the locations outside mesh "
|
||||
<< locationsOutsideMesh << endl;
|
||||
}
|
||||
auto& err =
|
||||
(
|
||||
exitIfLeakPath
|
||||
? FatalErrorInFunction
|
||||
: WarningInFunction
|
||||
);
|
||||
|
||||
err << "Location in mesh " << locationsInMesh[indexi]
|
||||
<< " is inside same mesh region " << regioni
|
||||
<< " as one of the locations outside mesh "
|
||||
<< locationsOutsideMesh << endl;
|
||||
|
||||
if (exitIfLeakPath)
|
||||
{
|
||||
FatalError << exit(FatalError);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3103,7 +3080,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::splitMeshRegions
|
||||
const pointField& locationsInMesh,
|
||||
const pointField& locationsOutsideMesh,
|
||||
const bool exitIfLeakPath,
|
||||
const refPtr<writer<scalar>>& leakPathFormatter
|
||||
const refPtr<coordSetWriter>& leakPathFormatter
|
||||
)
|
||||
{
|
||||
// Force calculation of face decomposition (used in findCell)
|
||||
@ -3120,14 +3097,15 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::splitMeshRegions
|
||||
label nRemove = findRegions
|
||||
(
|
||||
mesh_,
|
||||
mergeDistance_ * vector::one, // perturbVec
|
||||
vector::uniform(mergeDistance_), // perturbVec
|
||||
locationsInMesh,
|
||||
locationsOutsideMesh,
|
||||
exitIfLeakPath,
|
||||
leakPathFormatter,
|
||||
cellRegion.nRegions(),
|
||||
cellRegion,
|
||||
blockedFace
|
||||
blockedFace,
|
||||
// Leak-path
|
||||
exitIfLeakPath,
|
||||
leakPathFormatter
|
||||
);
|
||||
|
||||
// Subset
|
||||
|
||||
@ -60,7 +60,7 @@ SourceFiles
|
||||
#include "surfaceZonesInfo.H"
|
||||
#include "volumeType.H"
|
||||
#include "DynamicField.H"
|
||||
#include "writer.H"
|
||||
#include "coordSetWriter.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -587,7 +587,7 @@ private:
|
||||
const pointField& locationsInMesh,
|
||||
const wordList& regionsInMesh,
|
||||
const pointField& locationsOutsideMesh,
|
||||
const refPtr<writer<scalar>>& leakPathFormatter,
|
||||
const refPtr<coordSetWriter>& leakPathFormatter,
|
||||
|
||||
const labelList& neiLevel,
|
||||
const pointField& neiCc,
|
||||
@ -622,8 +622,8 @@ private:
|
||||
const polyMesh& mesh,
|
||||
const pointField& locationsInMesh,
|
||||
const pointField& locationsOutsideMesh,
|
||||
const writer<scalar>& leakPathFormatter,
|
||||
const boolList& blockedFace
|
||||
const boolList& blockedFace,
|
||||
coordSetWriter& leakPathWriter
|
||||
);
|
||||
|
||||
|
||||
@ -846,7 +846,7 @@ private:
|
||||
const pointField& locationsInMesh,
|
||||
const wordList& zonesInMesh,
|
||||
const pointField& locationsOutsideMesh,
|
||||
const refPtr<writer<scalar>>& leakPathFormatter,
|
||||
const refPtr<coordSetWriter>& leakPathFormatter,
|
||||
|
||||
labelList& cellToZone,
|
||||
labelList& unnamedRegion1,
|
||||
@ -1303,7 +1303,7 @@ public:
|
||||
const pointField& locationsInMesh,
|
||||
const wordList& regionsInMesh,
|
||||
const pointField& locationsOutsideMesh,
|
||||
const refPtr<writer<scalar>>& leakPathFormatter
|
||||
const refPtr<coordSetWriter>& leakPathFormatter
|
||||
);
|
||||
|
||||
//- Merge free-standing baffles
|
||||
@ -1334,7 +1334,7 @@ public:
|
||||
const pointField& locationsInMesh,
|
||||
const wordList& regionsInMesh,
|
||||
const pointField& locationsOutsideMesh,
|
||||
const writer<scalar>& leakPathFormatter
|
||||
const refPtr<coordSetWriter>& leakPathFormatter
|
||||
);
|
||||
|
||||
//- Remove cells from limitRegions if level -1
|
||||
@ -1436,7 +1436,7 @@ public:
|
||||
const pointField& locationsInMesh,
|
||||
const wordList& regionsInMesh,
|
||||
const pointField& locationsOutsideMesh,
|
||||
const refPtr<writer<scalar>>& leakPathFormatter,
|
||||
const refPtr<coordSetWriter>& leakPathFormatter,
|
||||
wordPairHashTable& zonesToFaceZone
|
||||
);
|
||||
|
||||
@ -1543,11 +1543,12 @@ public:
|
||||
const vector& perturbVec,
|
||||
const pointField& locationsInMesh,
|
||||
const pointField& locationsOutsideMesh,
|
||||
const bool exitIfLeakPath,
|
||||
const refPtr<writer<scalar>>& leakPathFormatter,
|
||||
const label nRegions,
|
||||
labelList& cellRegion,
|
||||
const boolList& blockedFace
|
||||
const boolList& blockedFace,
|
||||
// Leak-path
|
||||
const bool exitIfLeakPath,
|
||||
const refPtr<coordSetWriter>& leakPathFormatter
|
||||
);
|
||||
|
||||
//- Split mesh. Keep part containing point. Return empty map if
|
||||
@ -1558,8 +1559,9 @@ public:
|
||||
const labelList& globalToSlavePatch,
|
||||
const pointField& locationsInMesh,
|
||||
const pointField& locationsOutsideMesh,
|
||||
// Leak-path
|
||||
const bool exitIfLeakPath,
|
||||
const refPtr<writer<scalar>>& leakPathFormatter
|
||||
const refPtr<coordSetWriter>& leakPathFormatter
|
||||
);
|
||||
|
||||
//- Split faces into two
|
||||
|
||||
@ -292,7 +292,7 @@ void Foam::meshRefinement::getBafflePatches
|
||||
const pointField& locationsInMesh,
|
||||
const wordList& zonesInMesh,
|
||||
const pointField& locationsOutsideMesh,
|
||||
const refPtr<writer<scalar>>& leakPathFormatter,
|
||||
const refPtr<coordSetWriter>& leakPathFormatter,
|
||||
const labelList& neiLevel,
|
||||
const pointField& neiCc,
|
||||
|
||||
@ -1688,7 +1688,7 @@ void Foam::meshRefinement::findCellZoneInsideWalk
|
||||
(
|
||||
mesh_,
|
||||
cellRegion,
|
||||
mergeDistance_ * vector::one,
|
||||
vector::uniform(mergeDistance_),
|
||||
insidePoint
|
||||
);
|
||||
|
||||
@ -1959,7 +1959,7 @@ void Foam::meshRefinement::findCellZoneTopo
|
||||
(
|
||||
mesh_,
|
||||
cellRegion,
|
||||
mergeDistance_ * vector::one,
|
||||
vector::uniform(mergeDistance_),
|
||||
keepPoint
|
||||
);
|
||||
|
||||
@ -2843,7 +2843,7 @@ void Foam::meshRefinement::zonify
|
||||
const pointField& locationsInMesh,
|
||||
const wordList& zonesInMesh,
|
||||
const pointField& locationsOutsideMesh,
|
||||
const refPtr<writer<scalar>>& leakPathFormatter,
|
||||
const refPtr<coordSetWriter>& leakPathFormatter,
|
||||
|
||||
labelList& cellToZone,
|
||||
labelList& unnamedRegion1,
|
||||
@ -2961,7 +2961,7 @@ void Foam::meshRefinement::zonify
|
||||
<< endl;
|
||||
|
||||
// Dump leak path
|
||||
if (leakPathFormatter.valid())
|
||||
if (leakPathFormatter)
|
||||
{
|
||||
boolList blockedFace(mesh_.nFaces(), false);
|
||||
UIndirectList<bool>(blockedFace, unnamedFaces) = true;
|
||||
@ -2972,8 +2972,8 @@ void Foam::meshRefinement::zonify
|
||||
mesh_,
|
||||
locationsInMesh,
|
||||
locationsOutsideMesh,
|
||||
leakPathFormatter(),
|
||||
blockedFace
|
||||
blockedFace,
|
||||
leakPathFormatter.constCast()
|
||||
)
|
||||
);
|
||||
Info<< "Dumped leak path to " << fName << endl;
|
||||
@ -3065,7 +3065,7 @@ void Foam::meshRefinement::zonify
|
||||
<< endl;
|
||||
|
||||
// Dump leak path
|
||||
if (leakPathFormatter.valid())
|
||||
if (leakPathFormatter)
|
||||
{
|
||||
boolList blockedFace(mesh_.nFaces(), false);
|
||||
UIndirectList<bool>(blockedFace, unnamedFaces) = true;
|
||||
@ -3077,8 +3077,8 @@ void Foam::meshRefinement::zonify
|
||||
mesh_,
|
||||
locationsInMesh,
|
||||
locationsOutsideMesh,
|
||||
leakPathFormatter(),
|
||||
blockedFace
|
||||
blockedFace,
|
||||
leakPathFormatter.constCast()
|
||||
)
|
||||
);
|
||||
Info<< "Dumped leak path to " << fName << endl;
|
||||
@ -4509,7 +4509,7 @@ void Foam::meshRefinement::baffleAndSplitMesh
|
||||
const pointField& locationsInMesh,
|
||||
const wordList& zonesInMesh,
|
||||
const pointField& locationsOutsideMesh,
|
||||
const refPtr<writer<scalar>>& leakPathFormatter
|
||||
const refPtr<coordSetWriter>& leakPathFormatter
|
||||
)
|
||||
{
|
||||
// Introduce baffles
|
||||
@ -4536,7 +4536,7 @@ void Foam::meshRefinement::baffleAndSplitMesh
|
||||
locationsInMesh,
|
||||
zonesInMesh,
|
||||
locationsOutsideMesh,
|
||||
refPtr<writer<scalar>>(nullptr),
|
||||
refPtr<coordSetWriter>(nullptr),
|
||||
|
||||
neiLevel,
|
||||
neiCc,
|
||||
@ -4610,7 +4610,7 @@ void Foam::meshRefinement::baffleAndSplitMesh
|
||||
locationsInMesh,
|
||||
zonesInMesh,
|
||||
locationsOutsideMesh,
|
||||
refPtr<writer<scalar>>(nullptr),
|
||||
refPtr<coordSetWriter>(nullptr),
|
||||
|
||||
neiLevel,
|
||||
neiCc,
|
||||
@ -4760,7 +4760,7 @@ void Foam::meshRefinement::mergeFreeStandingBaffles
|
||||
locationsInMesh,
|
||||
locationsOutsideMesh,
|
||||
true, // Exit if any connection between inside and outside
|
||||
refPtr<writer<scalar>>(nullptr) //leakPathFormatter
|
||||
refPtr<coordSetWriter>(nullptr) // leakPathFormatter
|
||||
);
|
||||
|
||||
|
||||
@ -4785,7 +4785,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::splitMesh
|
||||
const pointField& locationsInMesh,
|
||||
const wordList& zonesInMesh,
|
||||
const pointField& locationsOutsideMesh,
|
||||
const writer<scalar>& leakPathFormatter
|
||||
const refPtr<coordSetWriter>& leakPathFormatter
|
||||
)
|
||||
{
|
||||
// Determine patches to put intersections into
|
||||
@ -4834,14 +4834,15 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::splitMesh
|
||||
findRegions
|
||||
(
|
||||
mesh_,
|
||||
mergeDistance_ * vector::one, // perturbVec
|
||||
vector::uniform(mergeDistance_), // perturbVec
|
||||
locationsInMesh,
|
||||
locationsOutsideMesh,
|
||||
false, // do not exit if outside location found
|
||||
leakPathFormatter,
|
||||
cellRegion.nRegions(),
|
||||
cellRegion,
|
||||
blockedFace
|
||||
blockedFace,
|
||||
// Leak-path
|
||||
false, // do not exit if outside location found
|
||||
leakPathFormatter
|
||||
);
|
||||
|
||||
return splitMesh
|
||||
@ -5272,7 +5273,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::removeLimitShells
|
||||
locationsInMesh,
|
||||
zonesInMesh,
|
||||
locationsOutsideMesh,
|
||||
refPtr<writer<scalar>>(nullptr),
|
||||
refPtr<coordSetWriter>(nullptr),
|
||||
|
||||
neiLevel,
|
||||
neiCc,
|
||||
@ -5574,7 +5575,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
|
||||
const pointField& locationsInMesh,
|
||||
const wordList& zonesInMesh,
|
||||
const pointField& locationsOutsideMesh,
|
||||
const refPtr<writer<scalar>>& leakPathFormatter,
|
||||
const refPtr<coordSetWriter>& leakPathFormatter,
|
||||
wordPairHashTable& zonesToFaceZone
|
||||
)
|
||||
{
|
||||
|
||||
@ -67,7 +67,7 @@ Foam::snappyRefineDriver::snappyRefineDriver
|
||||
fvMeshDistribute& distributor,
|
||||
const labelUList& globalToMasterPatch,
|
||||
const labelUList& globalToSlavePatch,
|
||||
const writer<scalar>& setFormatter,
|
||||
coordSetWriter& setFormatter,
|
||||
const bool dryRun
|
||||
)
|
||||
:
|
||||
|
||||
@ -41,7 +41,7 @@ SourceFiles
|
||||
#include "labelList.H"
|
||||
#include "scalarField.H"
|
||||
#include "Tuple2.H"
|
||||
#include "writer.H"
|
||||
#include "coordSetWriter.H"
|
||||
#include "DynamicList.H"
|
||||
#include "labelVector.H"
|
||||
#include "meshRefinement.H"
|
||||
@ -83,7 +83,7 @@ class snappyRefineDriver
|
||||
const labelList globalToSlavePatch_;
|
||||
|
||||
//- How to write lines. Used e.g. when writing leak-paths
|
||||
const writer<scalar>& setFormatter_;
|
||||
coordSetWriter& setFormatter_;
|
||||
|
||||
//- Are we operating in test mode?
|
||||
const bool dryRun_;
|
||||
@ -275,7 +275,7 @@ public:
|
||||
fvMeshDistribute& distributor,
|
||||
const labelUList& globalToMasterPatch,
|
||||
const labelUList& globalToSlavePatch,
|
||||
const writer<scalar>& setFormatter,
|
||||
coordSetWriter& setFormatter,
|
||||
const bool dryRun = false
|
||||
);
|
||||
|
||||
|
||||
@ -136,16 +136,19 @@ coordSet/coordSet.C
|
||||
|
||||
setWriters = coordSet/writers
|
||||
|
||||
$(setWriters)/common/writers.C
|
||||
$(setWriters)/csv/csvSetWriterRunTime.C
|
||||
$(setWriters)/ensight/ensightSetWriterRunTime.C
|
||||
$(setWriters)/gltf/gltfSetWriterRunTime.C
|
||||
$(setWriters)/gnuplot/gnuplotSetWriterRunTime.C
|
||||
$(setWriters)/nastran/nastranSetWriterRunTime.C
|
||||
$(setWriters)/raw/rawSetWriterRunTime.C
|
||||
$(setWriters)/common/coordSetWriter.C
|
||||
$(setWriters)/common/coordSetWriterBuffers.C
|
||||
$(setWriters)/common/coordSetWriterNew.C
|
||||
$(setWriters)/csv/csvCoordSetWriter.C
|
||||
$(setWriters)/ensight/ensightCoordSetWriter.C
|
||||
$(setWriters)/gltf/gltfCoordSetWriter.C
|
||||
$(setWriters)/gnuplot/gnuplotCoordSetWriter.C
|
||||
$(setWriters)/nastran/nastranCoordSetWriter.C
|
||||
$(setWriters)/null/nullCoordSetWriter.C
|
||||
$(setWriters)/raw/rawCoordSetWriter.C
|
||||
$(setWriters)/vtk/foamVtkCoordSetWriter.C
|
||||
$(setWriters)/vtk/vtkSetWriterRunTime.C
|
||||
$(setWriters)/xmgrace/xmgraceSetWriterRunTime.C
|
||||
$(setWriters)/vtk/vtkCoordSetWriter.C
|
||||
$(setWriters)/xmgrace/xmgraceCoordSetWriter.C
|
||||
|
||||
graph/curve.C
|
||||
graph/graph.C
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2017-2018 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -27,6 +27,7 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "coordSet.H"
|
||||
#include "globalIndex.H"
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * * //
|
||||
|
||||
@ -36,11 +37,13 @@ const Foam::Enum
|
||||
>
|
||||
Foam::coordSet::coordFormatNames
|
||||
({
|
||||
{ coordFormat::XYZ, "xyz" },
|
||||
{ coordFormat::X, "x" },
|
||||
{ coordFormat::Y, "y" },
|
||||
{ coordFormat::Z, "z" },
|
||||
{ coordFormat::RADIUS, "radius" },
|
||||
{ coordFormat::DISTANCE, "distance" },
|
||||
{ coordFormat::XYZ, "xyz" },
|
||||
/// { coordFormat::DEFAULT, "default" },
|
||||
});
|
||||
|
||||
|
||||
@ -48,12 +51,12 @@ Foam::coordSet::coordFormatNames
|
||||
|
||||
void Foam::coordSet::checkDimensions() const
|
||||
{
|
||||
if (size() != curveDist_.size())
|
||||
if (points().size() != distance().size())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Size of points and curve distance must be the same" << nl
|
||||
<< " points size : " << size()
|
||||
<< " curve size : " << curveDist_.size()
|
||||
<< "Size not equal :" << nl
|
||||
<< " points:" << points().size()
|
||||
<< " distance:" << distance().size()
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
@ -61,6 +64,15 @@ void Foam::coordSet::checkDimensions() const
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
// Foam::coordSet::coordSet()
|
||||
// :
|
||||
// pointField(),
|
||||
// name_(),
|
||||
// distance_(),
|
||||
// axis_(coordFormat::DEFAULT)
|
||||
// {}
|
||||
|
||||
|
||||
Foam::coordSet::coordSet
|
||||
(
|
||||
const word& name,
|
||||
@ -69,8 +81,8 @@ Foam::coordSet::coordSet
|
||||
:
|
||||
pointField(),
|
||||
name_(name),
|
||||
axis_(axisType),
|
||||
curveDist_()
|
||||
distance_(),
|
||||
axis_(axisType)
|
||||
{}
|
||||
|
||||
|
||||
@ -80,10 +92,7 @@ Foam::coordSet::coordSet
|
||||
const word& axis
|
||||
)
|
||||
:
|
||||
pointField(),
|
||||
name_(name),
|
||||
axis_(coordFormatNames[axis]),
|
||||
curveDist_()
|
||||
coordSet(name, coordFormatNames.get(axis))
|
||||
{}
|
||||
|
||||
|
||||
@ -92,13 +101,13 @@ Foam::coordSet::coordSet
|
||||
const word& name,
|
||||
const word& axis,
|
||||
const List<point>& points,
|
||||
const scalarList& curveDist
|
||||
const scalarList& dist
|
||||
)
|
||||
:
|
||||
pointField(points),
|
||||
name_(name),
|
||||
axis_(coordFormatNames[axis]),
|
||||
curveDist_(curveDist)
|
||||
distance_(dist),
|
||||
axis_(coordFormatNames[axis])
|
||||
{
|
||||
checkDimensions();
|
||||
}
|
||||
@ -109,13 +118,13 @@ Foam::coordSet::coordSet
|
||||
const word& name,
|
||||
const word& axis,
|
||||
List<point>&& points,
|
||||
scalarList&& curveDist
|
||||
scalarList&& dist
|
||||
)
|
||||
:
|
||||
pointField(std::move(points)),
|
||||
name_(name),
|
||||
axis_(coordFormatNames[axis]),
|
||||
curveDist_(std::move(curveDist))
|
||||
distance_(std::move(dist)),
|
||||
axis_(coordFormatNames.get(axis))
|
||||
{
|
||||
checkDimensions();
|
||||
}
|
||||
@ -123,7 +132,7 @@ Foam::coordSet::coordSet
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::coordSet::hasVectorAxis() const
|
||||
bool Foam::coordSet::hasVectorAxis() const noexcept
|
||||
{
|
||||
return axis_ == coordFormat::XYZ;
|
||||
}
|
||||
@ -131,72 +140,105 @@ bool Foam::coordSet::hasVectorAxis() const
|
||||
|
||||
Foam::scalar Foam::coordSet::scalarCoord(const label index) const
|
||||
{
|
||||
const point& p = operator[](index);
|
||||
|
||||
switch (axis_)
|
||||
{
|
||||
case coordFormat::X:
|
||||
{
|
||||
return p.x();
|
||||
return points()[index].x();
|
||||
}
|
||||
case coordFormat::Y:
|
||||
{
|
||||
return p.y();
|
||||
return points()[index].y();
|
||||
}
|
||||
case coordFormat::Z:
|
||||
{
|
||||
return p.z();
|
||||
return points()[index].z();
|
||||
}
|
||||
case coordFormat::RADIUS:
|
||||
{
|
||||
return mag(points()[index]);
|
||||
}
|
||||
case coordFormat::DISTANCE:
|
||||
{
|
||||
// Note: If this has been constructed from the 'name' and 'axis'
|
||||
// constructor the curveDist list will not have been set
|
||||
// Note: the distance will unset it constructed from
|
||||
// 'name' and 'axis' only
|
||||
|
||||
if (curveDist_.empty())
|
||||
if (distance().empty())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Axis type '" << coordFormatNames[axis_]
|
||||
<< "' requested but curve distance has not been set"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
return curveDist_[index];
|
||||
return distance()[index];
|
||||
}
|
||||
default:
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Illegal axis specification '" << coordFormatNames[axis_]
|
||||
<< "' for sampling line " << name_
|
||||
<< "' for sampling " << name_
|
||||
<< exit(FatalError);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Foam::point Foam::coordSet::vectorCoord(const label index) const
|
||||
const Foam::point& Foam::coordSet::vectorCoord(const label index) const
|
||||
{
|
||||
const point& p = operator[](index);
|
||||
|
||||
return p;
|
||||
return points()[index];
|
||||
}
|
||||
|
||||
|
||||
Foam::Ostream& Foam::coordSet::write(Ostream& os) const
|
||||
{
|
||||
os << "name:" << name_ << " axis:" << coordFormatNames[axis_]
|
||||
os << "name:" << name_ << " axis:" << coordFormatNames[axis_] << nl
|
||||
<< nl
|
||||
<< nl << "\t(coord)"
|
||||
<< endl;
|
||||
<< "\t(coord)" << nl;
|
||||
|
||||
for (const point& pt : *this)
|
||||
for (const point& p : *this)
|
||||
{
|
||||
os << '\t' << pt << endl;
|
||||
os << '\t' << p << nl;
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
Foam::autoPtr<Foam::coordSet> Foam::coordSet::gatherSort
|
||||
(
|
||||
labelList& sortOrder
|
||||
) const
|
||||
{
|
||||
// Combine sampleSet from processors. Sort by distance.
|
||||
// Return ordering in indexSet.
|
||||
// Note: only master results are valid
|
||||
|
||||
List<point> allPoints(globalIndex::gatherOp(points()));
|
||||
List<scalar> allDistance(globalIndex::gatherOp(distance()));
|
||||
|
||||
if (Pstream::master() && allDistance.empty())
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Gathered empty coordSet: " << name() << endl;
|
||||
}
|
||||
|
||||
// Sort according to distance
|
||||
Foam::sortedOrder(allDistance, sortOrder); // uses stable sort
|
||||
|
||||
// Repopulate gathered points/distances in the correct order
|
||||
allPoints = List<point>(allPoints, sortOrder);
|
||||
allDistance = List<scalar>(allDistance, sortOrder);
|
||||
|
||||
return autoPtr<coordSet>::New
|
||||
(
|
||||
name(),
|
||||
axis(),
|
||||
std::move(allPoints),
|
||||
std::move(allDistance)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2012 OpenFOAM Foundation
|
||||
Copyright (C) 2017-2018 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -35,11 +35,11 @@ SourceFiles
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef coordSet_H
|
||||
#define coordSet_H
|
||||
#ifndef Foam_coordSet_H
|
||||
#define Foam_coordSet_H
|
||||
|
||||
#include "pointField.H"
|
||||
#include "word.H"
|
||||
#include "scalarList.H"
|
||||
#include "Enum.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
@ -57,49 +57,55 @@ class coordSet
|
||||
{
|
||||
public:
|
||||
|
||||
// Public data types
|
||||
// Public Data Types
|
||||
|
||||
//- Enumeration defining the output format for coordinates
|
||||
enum class coordFormat
|
||||
{
|
||||
XYZ,
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
DISTANCE
|
||||
X, //!< Use 'x' component of points for (scalar) axis
|
||||
Y, //!< Use 'y' component of points for (scalar) axis
|
||||
Z, //!< Use 'z' component of points for (scalar) axis
|
||||
RADIUS, //!< Use mag of points for (scalar) axis
|
||||
DISTANCE, //!< Use additional distance field for (scalar) axis
|
||||
XYZ, //!< Use x,y,z point values
|
||||
/// DEFAULT
|
||||
};
|
||||
|
||||
//- String representation of coordFormat enum
|
||||
static const Enum<coordFormat> coordFormatNames;
|
||||
|
||||
private:
|
||||
|
||||
//- Check for consistent dimensions of points and curve distance
|
||||
void checkDimensions() const;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- Name
|
||||
const word name_;
|
||||
word name_;
|
||||
|
||||
//- Axis write type
|
||||
const coordFormat axis_;
|
||||
//- Cumulative distance for "distance" write specifier.
|
||||
scalarList distance_;
|
||||
|
||||
//- Cumulative distance "distance" write specifier.
|
||||
scalarList curveDist_;
|
||||
//- Axis type
|
||||
coordFormat axis_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Check for consistent dimensions of points and curve distance
|
||||
void checkDimensions() const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
// Note: curveDist will be empty
|
||||
/// //- Default construct
|
||||
/// coordSet();
|
||||
|
||||
//- Default construct with name and axis type
|
||||
coordSet(const word& name, const coordFormat axisType);
|
||||
|
||||
//- Construct from components
|
||||
// Note: curveDist will be empty
|
||||
//- Default construct with name and axis type
|
||||
coordSet(const word& name, const word& axis);
|
||||
|
||||
//- Copy construct from components
|
||||
@ -108,7 +114,7 @@ public:
|
||||
const word& name,
|
||||
const word& axis,
|
||||
const List<point>& points,
|
||||
const scalarList& curveDist
|
||||
const scalarList& dist
|
||||
);
|
||||
|
||||
//- Move construct from components
|
||||
@ -117,66 +123,116 @@ public:
|
||||
const word& name,
|
||||
const word& axis,
|
||||
List<point>&& points,
|
||||
scalarList&& curveDist
|
||||
scalarList&& dist
|
||||
);
|
||||
|
||||
|
||||
// Member functions
|
||||
// Member Functions
|
||||
|
||||
const word& name() const
|
||||
// Access
|
||||
|
||||
//- The coord-set name
|
||||
const word& name() const noexcept
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
word axis() const
|
||||
//- The sort axis name
|
||||
const word& axis() const
|
||||
{
|
||||
return coordFormatNames[axis_];
|
||||
}
|
||||
|
||||
//- Set the points
|
||||
//- Return the points
|
||||
const pointField& points() const noexcept
|
||||
{
|
||||
return static_cast<const pointField&>(*this);
|
||||
}
|
||||
|
||||
//- Return the cumulative distance
|
||||
const scalarList& distance() const noexcept
|
||||
{
|
||||
return distance_;
|
||||
}
|
||||
|
||||
//- Return the number of points
|
||||
label nPoints() const noexcept
|
||||
{
|
||||
return pointField::size();
|
||||
}
|
||||
|
||||
|
||||
// Edit
|
||||
|
||||
//- Rename the coordinate set
|
||||
void rename(const word& newName)
|
||||
{
|
||||
name_ = newName;
|
||||
}
|
||||
|
||||
//- Copy assign new points
|
||||
void setPoints(const List<point>& newPoints)
|
||||
{
|
||||
static_cast<pointField&>(*this) = newPoints;
|
||||
}
|
||||
|
||||
//- Set the points
|
||||
//- Move assign new points
|
||||
void setPoints(List<point>&& newPoints)
|
||||
{
|
||||
static_cast<pointField&>(*this) = std::move(newPoints);
|
||||
}
|
||||
|
||||
//- Return the cumulative distance
|
||||
const scalarList& curveDist() const
|
||||
//- Copy assign the cumulative distance
|
||||
void setDistance(const scalarList& dist, const bool check=true)
|
||||
{
|
||||
return curveDist_;
|
||||
distance_ = dist;
|
||||
if (check) checkDimensions();
|
||||
}
|
||||
|
||||
//- Set the cumulative distance
|
||||
void setCurveDist(const scalarList& curveDist)
|
||||
//- Move assign the cumulative distance
|
||||
void setDistance(scalarList&& dist, const bool check=true)
|
||||
{
|
||||
curveDist_ = curveDist;
|
||||
checkDimensions();
|
||||
distance_ = std::move(dist);
|
||||
if (check) checkDimensions();
|
||||
}
|
||||
|
||||
//- Set the cumulative distance
|
||||
void setCurveDist(scalarList&& curveDist)
|
||||
{
|
||||
curveDist_ = std::move(curveDist);
|
||||
checkDimensions();
|
||||
}
|
||||
|
||||
//- Is axis specification a vector
|
||||
bool hasVectorAxis() const;
|
||||
// Output-related
|
||||
|
||||
//- True if axis specification is a vector
|
||||
bool hasVectorAxis() const noexcept;
|
||||
|
||||
//- Get coordinate of point according to axis specification.
|
||||
// If axis="distance" is the curveDist[index]
|
||||
// If axis="distance" is the distance[index]
|
||||
scalar scalarCoord(const label index) const;
|
||||
|
||||
//- Get point according to axis="xyz" specification
|
||||
vector vectorCoord(const label index) const;
|
||||
const vector& vectorCoord(const label index) const;
|
||||
|
||||
//- Write to stream
|
||||
Ostream& write(Ostream& os) const;
|
||||
|
||||
|
||||
// Other
|
||||
|
||||
//- Gather and sort.
|
||||
// \return (on master) gathered set and overall sort order
|
||||
autoPtr<coordSet> gatherSort(labelList& sortOrder) const;
|
||||
|
||||
|
||||
// Housekeeping
|
||||
|
||||
//- Return the cumulative distance
|
||||
const scalarList& curveDist() const noexcept
|
||||
{
|
||||
return distance_;
|
||||
}
|
||||
|
||||
//- Copy assign the cumulative distance
|
||||
void setCurveDist(const scalarList& dist)
|
||||
{
|
||||
setDistance(dist);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
455
src/meshTools/coordSet/writers/common/coordSetWriter.C
Normal file
455
src/meshTools/coordSet/writers/common/coordSetWriter.C
Normal file
@ -0,0 +1,455 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "coordSet.H"
|
||||
#include "coordSetWriter.H"
|
||||
#include "Time.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(coordSetWriter, 0);
|
||||
defineRunTimeSelectionTable(coordSetWriter, word);
|
||||
defineRunTimeSelectionTable(coordSetWriter, wordDict);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
Foam::word Foam::coordSetWriter::suffix
|
||||
(
|
||||
const word& fldName,
|
||||
const word& fileExt
|
||||
)
|
||||
{
|
||||
word result;
|
||||
|
||||
if (!fldName.empty())
|
||||
{
|
||||
result += '_' + fldName;
|
||||
}
|
||||
|
||||
return result.ext(fileExt);
|
||||
}
|
||||
|
||||
|
||||
Foam::word Foam::coordSetWriter::suffix
|
||||
(
|
||||
const wordList& fieldNames,
|
||||
const word& fileExt
|
||||
)
|
||||
{
|
||||
word result;
|
||||
|
||||
for (const word& fldName : fieldNames)
|
||||
{
|
||||
if (!fldName.empty())
|
||||
{
|
||||
result += '_' + fldName;
|
||||
}
|
||||
}
|
||||
|
||||
return result.ext(fileExt);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::coordSetWriter::coordSetWriter()
|
||||
:
|
||||
coords_(),
|
||||
trackTimes_(),
|
||||
upToDate_(false),
|
||||
wroteGeom_(false),
|
||||
/// parallel_(true),
|
||||
buffering_(false),
|
||||
useTracks_(false),
|
||||
useTimeDir_(false),
|
||||
verbose_(false),
|
||||
nFields_(0),
|
||||
currTime_(),
|
||||
outputPath_()
|
||||
{}
|
||||
|
||||
|
||||
Foam::coordSetWriter::coordSetWriter(const dictionary& options)
|
||||
:
|
||||
coordSetWriter()
|
||||
{
|
||||
options.readIfPresent("verbose", verbose_);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::coordSetWriter::~coordSetWriter()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Controls * * * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::coordSetWriter::setTime(const instant& inst)
|
||||
{
|
||||
currTime_ = inst;
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriter::setTime(scalar timeValue)
|
||||
{
|
||||
currTime_ = instant(timeValue);
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriter::setTime(scalar timeValue, const word& timeName)
|
||||
{
|
||||
currTime_.value() = timeValue;
|
||||
currTime_.name() = timeName;
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriter::unsetTime()
|
||||
{
|
||||
currTime_.value() = 0;
|
||||
currTime_.name().clear();
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriter::beginTime(const Time& t)
|
||||
{
|
||||
setTime(t.value(), t.timeName());
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriter::beginTime(const instant& inst)
|
||||
{
|
||||
setTime(inst);
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriter::endTime()
|
||||
{
|
||||
// Flush bufferred data
|
||||
if (nDataColumns())
|
||||
{
|
||||
writeBuffered();
|
||||
}
|
||||
clearBuffers();
|
||||
|
||||
unsetTime();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::coordSetWriter::open(const fileName& outputPath)
|
||||
{
|
||||
outputPath_ = outputPath;
|
||||
wroteGeom_ = false;
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriter::open
|
||||
(
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath
|
||||
)
|
||||
{
|
||||
close();
|
||||
setCoordinates(coords);
|
||||
open(outputPath);
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriter::open
|
||||
(
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath
|
||||
)
|
||||
{
|
||||
close();
|
||||
setTracks(tracks);
|
||||
open(outputPath);
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriter::close(bool force)
|
||||
{
|
||||
if (nDataColumns())
|
||||
{
|
||||
if (verbose_) Info<< "Flush buffered data:" << nl;
|
||||
writeBuffered();
|
||||
}
|
||||
clearBuffers();
|
||||
|
||||
outputPath_.clear();
|
||||
wroteGeom_ = false;
|
||||
|
||||
if (force)
|
||||
{
|
||||
coords_.clear();
|
||||
trackTimes_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriter::clear()
|
||||
{
|
||||
close();
|
||||
expire();
|
||||
coords_.clear();
|
||||
trackTimes_.clear();
|
||||
clearBuffers(); // Reset any buffering
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriter::setCoordinates(const coordSet* coords)
|
||||
{
|
||||
expire();
|
||||
clearBuffers(); // Reset any buffering
|
||||
|
||||
if (coords)
|
||||
{
|
||||
coords_.resize(1);
|
||||
coords_.set(0, coords);
|
||||
}
|
||||
else
|
||||
{
|
||||
coords_.clear();
|
||||
}
|
||||
trackTimes_.clear();
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriter::setCoordinates(const coordSet& coords)
|
||||
{
|
||||
setCoordinates(&coords);
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriter::setTracks(const UPtrList<coordSet>& tracks)
|
||||
{
|
||||
expire();
|
||||
clearBuffers(); // Reset any buffering
|
||||
|
||||
// Shallow copy (pointers)
|
||||
|
||||
coords_.resize(tracks.size());
|
||||
forAll(coords_, tracki)
|
||||
{
|
||||
coords_.set(tracki, tracks.get(tracki));
|
||||
}
|
||||
trackTimes_.clear();
|
||||
useTracks_ = true;
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriter::setTrackTimes(const UList<scalarField>& times)
|
||||
{
|
||||
if (times.size() == coords_.size())
|
||||
{
|
||||
trackTimes_ = times;
|
||||
}
|
||||
else
|
||||
{
|
||||
trackTimes_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::coordSetWriter::numPoints() const
|
||||
{
|
||||
label nTotal = 0;
|
||||
|
||||
forAll(coords_, tracki)
|
||||
{
|
||||
const auto* ptr = coords_.get(tracki);
|
||||
if (ptr) nTotal += ptr->size();
|
||||
}
|
||||
|
||||
return nTotal;
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::coordSetWriter::numTracks() const
|
||||
{
|
||||
return coords_.size();
|
||||
}
|
||||
|
||||
|
||||
bool Foam::coordSetWriter::needsUpdate() const
|
||||
{
|
||||
return !upToDate_;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::coordSetWriter::wroteData() const
|
||||
{
|
||||
return wroteGeom_;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::coordSetWriter::expire()
|
||||
{
|
||||
const bool changed = upToDate_;
|
||||
|
||||
upToDate_ = false;
|
||||
wroteGeom_ = false;
|
||||
coords_.clear();
|
||||
trackTimes_.clear();
|
||||
|
||||
// Field count (nFields_) is a different type of accounting
|
||||
// and is unaffected by geometry changes
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::coordSetWriter::hasCoords() const
|
||||
{
|
||||
return !coords_.empty();
|
||||
}
|
||||
|
||||
|
||||
bool Foam::coordSetWriter::empty() const
|
||||
{
|
||||
return coords_.empty();
|
||||
}
|
||||
|
||||
Foam::fileName Foam::coordSetWriter::getExpectedPath
|
||||
(
|
||||
const word& fileExt
|
||||
) const
|
||||
{
|
||||
fileName file;
|
||||
|
||||
if (!outputPath_.empty())
|
||||
{
|
||||
if (useTimeDir() && !timeName().empty())
|
||||
{
|
||||
// Splice in time-directory
|
||||
file = outputPath_.path() / timeName() / outputPath_.name();
|
||||
}
|
||||
else
|
||||
{
|
||||
file = outputPath_;
|
||||
}
|
||||
|
||||
file.ext(fileExt); // Append extension - can also be empty
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
Foam::fileName Foam::coordSetWriter::getFieldPrefixedPath
|
||||
(
|
||||
const word& fieldName,
|
||||
const word& fileExt
|
||||
) const
|
||||
{
|
||||
if (outputPath_.empty() || fieldName.empty())
|
||||
{
|
||||
return getExpectedPath(fileExt);
|
||||
}
|
||||
|
||||
// Field: rootdir/<TIME>/<field>_NAME.ext
|
||||
|
||||
fileName file;
|
||||
if (useTimeDir() && !timeName().empty())
|
||||
{
|
||||
// Splice in time-directory
|
||||
file = outputPath_.path() / timeName();
|
||||
}
|
||||
else
|
||||
{
|
||||
file = outputPath_.path();
|
||||
}
|
||||
|
||||
// Append <field>_NAME.EXT
|
||||
file /= (fieldName + '_' + outputPath_.name());
|
||||
file.ext(fileExt); // Append extension - can also be empty
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriter::checkOpen() const
|
||||
{
|
||||
if (!is_open())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< type() << " : Attempted to write without a path" << nl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::coordSetWriter::merge() const
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
// Possible future requirement...
|
||||
//
|
||||
// if (parallel_ && Pstream::parRun() && !upToDate_)
|
||||
// {
|
||||
// changed = merged_.merge(coords_, mergeDim_);
|
||||
// }
|
||||
upToDate_ = true;
|
||||
|
||||
if (changed)
|
||||
{
|
||||
wroteGeom_ = false;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::Ostream& Foam::operator<<
|
||||
(
|
||||
Ostream& os,
|
||||
const InfoProxy<coordSetWriter>& ip
|
||||
)
|
||||
{
|
||||
const coordSetWriter& w = ip.t_;
|
||||
|
||||
os << "coordSetWriter:"
|
||||
<< " upToDate: " << w.upToDate_
|
||||
<< " nFields: " << w.nFields_
|
||||
<< " time: " << w.currTime_
|
||||
<< " path: " << w.outputPath_ << endl;
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
597
src/meshTools/coordSet/writers/common/coordSetWriter.H
Normal file
597
src/meshTools/coordSet/writers/common/coordSetWriter.H
Normal file
@ -0,0 +1,597 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 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/>.
|
||||
|
||||
Class
|
||||
Foam::coordSetWriter
|
||||
|
||||
Description
|
||||
Base class for writing coordSet(s) and tracks with fields.
|
||||
|
||||
Example:
|
||||
\verbatim
|
||||
coordSet coords(...);
|
||||
|
||||
// Construct writer of xmgr type
|
||||
autoPtr<coordSetWriter> writer(coordSetWriter::New("vtk"));
|
||||
|
||||
writer.open(coords, path/name);
|
||||
|
||||
writer.write("density", rho);
|
||||
writer.write("velocity", U);
|
||||
|
||||
\endverbatim
|
||||
|
||||
SourceFiles
|
||||
coordSetWriterI.H
|
||||
coordSetWriter.C
|
||||
coordSetWriterBuffers.C
|
||||
coordSetWriterNew.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_coordSetWriter_H
|
||||
#define Foam_coordSetWriter_H
|
||||
|
||||
#include "coordSet.H"
|
||||
#include "typeInfo.H"
|
||||
#include "vector.H"
|
||||
#include "tensor.H"
|
||||
#include "fileName.H"
|
||||
#include "wordList.H"
|
||||
#include "Field.H"
|
||||
#include "DynamicList.H"
|
||||
#include "PtrDynList.H"
|
||||
#include "UPtrList.H"
|
||||
#include "instant.H"
|
||||
#include "InfoProxy.H"
|
||||
#include "runTimeSelectionTables.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward Declarations
|
||||
class coordSetWriter;
|
||||
class Time;
|
||||
|
||||
Ostream& operator<<(Ostream& os, const InfoProxy<coordSetWriter>&);
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class coordSetWriter Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class coordSetWriter
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- Reference to coordinate set(s)
|
||||
UPtrList<const coordSet> coords_;
|
||||
|
||||
//- Track times (eg, streamlines), one per coords_ entry
|
||||
List<scalarField> trackTimes_;
|
||||
|
||||
//- The content is up-to-date?
|
||||
mutable bool upToDate_;
|
||||
|
||||
//- Track if geometry has been written since the last open
|
||||
mutable bool wroteGeom_;
|
||||
|
||||
/// //- Writing in parallel (via master)
|
||||
/// bool parallel_;
|
||||
|
||||
//- Writer with buffering output
|
||||
mutable bool buffering_;
|
||||
|
||||
//- Prefer tracks to points during single set writing
|
||||
bool useTracks_;
|
||||
|
||||
//- Insert additional time sub-directory in the output path
|
||||
bool useTimeDir_;
|
||||
|
||||
//- Additional output verbosity
|
||||
bool verbose_;
|
||||
|
||||
//- The number of fields
|
||||
label nFields_;
|
||||
|
||||
//- The current time value/name
|
||||
instant currTime_;
|
||||
|
||||
//- The full output directory and file (coords) name
|
||||
fileName outputPath_;
|
||||
|
||||
|
||||
// Buffering
|
||||
|
||||
#undef defineBufferMethod
|
||||
#define defineBufferMethod(Type) \
|
||||
\
|
||||
/* Names of Type fields */ \
|
||||
DynamicList<word> Type##Names_; \
|
||||
\
|
||||
/* Values of Type fields */ \
|
||||
PtrDynList<Field<Type>> Type##Fields_; \
|
||||
\
|
||||
/* Add named Type field to buffering */ \
|
||||
void appendField(const word& fieldName, const Field<Type>& vals) \
|
||||
{ \
|
||||
Type##Names_.append(fieldName); \
|
||||
Type##Fields_.append(vals.clone()); \
|
||||
}
|
||||
|
||||
defineBufferMethod(label);
|
||||
defineBufferMethod(scalar);
|
||||
defineBufferMethod(vector);
|
||||
defineBufferMethod(sphericalTensor);
|
||||
defineBufferMethod(symmTensor);
|
||||
defineBufferMethod(tensor);
|
||||
|
||||
#undef defineBufferMethod
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
// Buffering
|
||||
|
||||
//- Write line contents (eg, buffered)
|
||||
static void writeLine(Ostream&, const UList<word>&, const char* sep);
|
||||
|
||||
//- Write line contents (eg, buffered)
|
||||
static void writeLine(Ostream&, const UList<scalar>&, const char* sep);
|
||||
|
||||
//- Clear out buffering
|
||||
void clearBuffers();
|
||||
|
||||
//- The number of buffer data columns, after splitting into components
|
||||
label nDataColumns() const;
|
||||
|
||||
//- Write buffered data
|
||||
virtual bool writeBuffered();
|
||||
|
||||
//- Write buffered data
|
||||
void writeBufferContents
|
||||
(
|
||||
Ostream& os,
|
||||
const coordSet& coords,
|
||||
const char* sep
|
||||
) const;
|
||||
|
||||
//- Get buffered data line (components)
|
||||
void getBufferLine
|
||||
(
|
||||
DynamicList<scalar>& buf,
|
||||
const coordSet& coords,
|
||||
const label pointi
|
||||
) const;
|
||||
|
||||
|
||||
// File Operations
|
||||
|
||||
//- Get expected (characteristic) output file name - information only
|
||||
fileName getExpectedPath(const word& fileExt = word::null) const;
|
||||
|
||||
//- Get field-prefixed output file name.
|
||||
// Eg, dir/U_name.raw
|
||||
fileName getFieldPrefixedPath
|
||||
(
|
||||
const word& fieldName,
|
||||
const word& fileExt = word::null
|
||||
) const;
|
||||
|
||||
//- Verify that the outputPath_ has been set or FatalError
|
||||
void checkOpen() const;
|
||||
|
||||
//- Perform any merging if not already upToDate (parallel)
|
||||
//- or simply mark as being up-to-date
|
||||
virtual bool merge() const;
|
||||
|
||||
|
||||
// Helpers
|
||||
|
||||
//- Repackage field into a UPtrList
|
||||
template<class Type>
|
||||
static UPtrList<const Field<Type>>
|
||||
repackageFields
|
||||
(
|
||||
const Field<Type>& field
|
||||
);
|
||||
|
||||
//- Repackage multiple fields into a UPtrList
|
||||
template<class Type>
|
||||
static UPtrList<const Field<Type>>
|
||||
repackageFields
|
||||
(
|
||||
const UList<Field<Type>>& fieldValues
|
||||
);
|
||||
|
||||
//- Write coordinates and values
|
||||
template<class Type>
|
||||
static void writeTable
|
||||
(
|
||||
Ostream& os,
|
||||
const coordSet& coords,
|
||||
const UList<Type>& values,
|
||||
const char* sep
|
||||
);
|
||||
|
||||
|
||||
// Normal write templates
|
||||
|
||||
//- Dummy templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName, //!< Name of field
|
||||
const Field<Type>& values //!< Local field values to write
|
||||
)
|
||||
{
|
||||
/// if (!wroteGeom_)
|
||||
/// {
|
||||
/// return this->write();
|
||||
/// }
|
||||
return fileName::null;
|
||||
}
|
||||
|
||||
//- Dummy templated write operation. Multiple tracks
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const List<Field<Type>>& fieldValues
|
||||
)
|
||||
{
|
||||
return fileName::null;
|
||||
}
|
||||
|
||||
|
||||
//- No copy construct
|
||||
coordSetWriter(const coordSetWriter&) = delete;
|
||||
|
||||
//- No copy assignment
|
||||
void operator=(const coordSetWriter&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("coordSetWriter");
|
||||
|
||||
// Declare run-time constructor selection table
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
coordSetWriter,
|
||||
word,
|
||||
(),
|
||||
()
|
||||
);
|
||||
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
coordSetWriter,
|
||||
wordDict,
|
||||
(
|
||||
const dictionary& writeOptions
|
||||
),
|
||||
(writeOptions)
|
||||
);
|
||||
|
||||
|
||||
// Selectors
|
||||
|
||||
//- True if New is likely to succeed for this writeType
|
||||
static bool supportedType(const word& writeType);
|
||||
|
||||
//- Return a reference to the selected writer
|
||||
static autoPtr<coordSetWriter> New(const word& writeFormat);
|
||||
|
||||
//- Return a reference to the selected writer
|
||||
// Select with extra write option
|
||||
static autoPtr<coordSetWriter> New
|
||||
(
|
||||
const word& writeFormat,
|
||||
const dictionary& writeOptions
|
||||
);
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
coordSetWriter();
|
||||
|
||||
//- Default construct with specified options
|
||||
explicit coordSetWriter(const dictionary& options);
|
||||
|
||||
|
||||
//- Destructor. Calls close()
|
||||
virtual ~coordSetWriter();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Helpers
|
||||
|
||||
//- Name suffix based on fieldName (underscore separator)
|
||||
static word suffix
|
||||
(
|
||||
const word& fldName,
|
||||
const word& fileExt = word::null
|
||||
);
|
||||
|
||||
//- Name suffix based on fieldNames (underscore separator)
|
||||
static word suffix
|
||||
(
|
||||
const wordList& fieldNames,
|
||||
const word& fileExt = word::null
|
||||
);
|
||||
|
||||
|
||||
// Capability
|
||||
|
||||
//- True if the format uses internal buffering (eg, column output)
|
||||
virtual bool buffering() const;
|
||||
|
||||
//- Turn internal buffering on/off (only if supported by the writer)
|
||||
virtual bool buffering(const bool on);
|
||||
|
||||
//- The writer is enabled. If the writer is not enabled, it may be
|
||||
//- possible for the caller to skip various preparatory operations.
|
||||
// This method is primarily useful for the null writer
|
||||
virtual bool enabled() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Bookkeeping
|
||||
|
||||
//- Does the writer need an update (eg, lagging behind other changes)
|
||||
virtual bool needsUpdate() const;
|
||||
|
||||
//- Geometry or fields written since the last open?
|
||||
virtual bool wroteData() const;
|
||||
|
||||
//- Mark that content changed and the writer will need an update,
|
||||
//- and set nFields = 0.
|
||||
// May also free up unneeded data.
|
||||
// Return false if it was previously already expired.
|
||||
virtual bool expire();
|
||||
|
||||
//- Close any open output, remove coordSet associations and
|
||||
//- expire the writer.
|
||||
virtual void clear();
|
||||
|
||||
|
||||
// Content Association
|
||||
|
||||
//- Set coordinates, can also be nullptr
|
||||
virtual void setCoordinates(const coordSet* coords);
|
||||
|
||||
//- Set coordinates
|
||||
virtual void setCoordinates(const coordSet& coords);
|
||||
|
||||
//- Set track coordinates
|
||||
virtual void setTracks(const UPtrList<coordSet>& tracks);
|
||||
|
||||
//- Set track times
|
||||
virtual void setTrackTimes(const UList<scalarField>& times);
|
||||
|
||||
|
||||
// Queries, Access
|
||||
|
||||
//- The number of associated points (local processor)
|
||||
label numPoints() const;
|
||||
|
||||
//- The number of coordinate tracks
|
||||
label numTracks() const;
|
||||
|
||||
//- Writer is associated with content
|
||||
bool hasCoords() const;
|
||||
|
||||
//- Writer is not associated with content
|
||||
bool empty() const;
|
||||
|
||||
//- Test if outputPath has been set
|
||||
inline bool is_open() const noexcept;
|
||||
|
||||
//- The number of expected output fields.
|
||||
// Currently only used by the legacy VTK format.
|
||||
inline label nFields() const noexcept;
|
||||
|
||||
//- Set the number of expected output fields
|
||||
// Currently only used by the legacy VTK format.
|
||||
// \return old value
|
||||
inline label nFields(const label n) noexcept;
|
||||
|
||||
//- Prefer tracks to points during single set writing
|
||||
inline bool useTracks() const noexcept;
|
||||
|
||||
//- Enable/disable tracks preference
|
||||
// \return old value
|
||||
inline bool useTracks(const bool on) noexcept;
|
||||
|
||||
//- Should a time directory be spliced into the output path?
|
||||
inline bool useTimeDir() const noexcept;
|
||||
|
||||
//- Enable/disable use of spliced output path
|
||||
// \return old value
|
||||
inline bool useTimeDir(const bool on) noexcept;
|
||||
|
||||
//- Get output verbosity
|
||||
inline bool verbose() const noexcept;
|
||||
|
||||
//- Enable/disable verbose output
|
||||
// \return old value
|
||||
inline bool verbose(bool on) noexcept;
|
||||
|
||||
|
||||
// Time
|
||||
|
||||
//- True if there is a known time
|
||||
inline bool hasTime() const;
|
||||
|
||||
//- The current time value/name
|
||||
inline const word& timeName() const;
|
||||
|
||||
//- The current time value/name
|
||||
inline scalar timeValue() const;
|
||||
|
||||
|
||||
//- Set the current time
|
||||
void setTime(const instant& inst);
|
||||
|
||||
//- Set current time from timeValue, auto generating the name
|
||||
void setTime(scalar timeValue);
|
||||
|
||||
//- Set current time from timeValue and timeName
|
||||
void setTime(scalar timeValue, const word& timeName);
|
||||
|
||||
//- Clear the current time
|
||||
void unsetTime();
|
||||
|
||||
|
||||
//- Begin a time-step
|
||||
virtual void beginTime(const Time& t);
|
||||
|
||||
//- Begin a time-step
|
||||
virtual void beginTime(const instant& inst);
|
||||
|
||||
//- End a time-step
|
||||
virtual void endTime();
|
||||
|
||||
|
||||
// Output
|
||||
|
||||
//- Expected (characteristic) output file name - information only.
|
||||
//- Return empty when is_open() is false.
|
||||
virtual fileName path() const = 0;
|
||||
|
||||
//- Write separate geometry to file.
|
||||
/// TBD: virtual fileName write() = 0;
|
||||
|
||||
//- Open for output on specified path, using existing content
|
||||
virtual void open(const fileName& outputPath);
|
||||
|
||||
//- Open from components
|
||||
virtual void open
|
||||
(
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath
|
||||
);
|
||||
|
||||
//- Open from components
|
||||
virtual void open
|
||||
(
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath
|
||||
);
|
||||
|
||||
//- Finish output, performing any necessary cleanup
|
||||
// Optional force disassociation with any coordSet(s)
|
||||
virtual void close(bool force = false);
|
||||
|
||||
|
||||
// Other
|
||||
|
||||
//- Return info proxy.
|
||||
virtual InfoProxy<coordSetWriter> info() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
//- Output info proxy
|
||||
friend Ostream& operator<<
|
||||
(
|
||||
Ostream& os,
|
||||
const InfoProxy<coordSetWriter>& ip
|
||||
);
|
||||
|
||||
|
||||
// Write methods
|
||||
|
||||
#undef declareCoordSetWriterWriteMethod
|
||||
#define declareCoordSetWriterWriteMethod(Type) \
|
||||
\
|
||||
/*! \brief Write field of Type (point data) */ \
|
||||
virtual fileName write \
|
||||
( \
|
||||
const word& fieldName, /*!< Name of field */ \
|
||||
const Field<Type>& field /*!< Field values */ \
|
||||
) = 0; \
|
||||
\
|
||||
/*! \brief Write track fields of Type (point data) */ \
|
||||
virtual fileName write \
|
||||
( \
|
||||
const word& fieldName, /*!< Name of field */ \
|
||||
const List<Field<Type>>& fieldValues /*!< Per-track values */ \
|
||||
) = 0;
|
||||
|
||||
declareCoordSetWriterWriteMethod(label);
|
||||
declareCoordSetWriterWriteMethod(scalar);
|
||||
declareCoordSetWriterWriteMethod(vector);
|
||||
declareCoordSetWriterWriteMethod(sphericalTensor);
|
||||
declareCoordSetWriterWriteMethod(symmTensor);
|
||||
declareCoordSetWriterWriteMethod(tensor);
|
||||
|
||||
|
||||
#undef declareCoordSetWriterWriteMethod
|
||||
#define declareCoordSetWriterWriteMethod(Type) \
|
||||
\
|
||||
/*! \brief Write field of Type (point data) */ \
|
||||
virtual fileName write \
|
||||
( \
|
||||
const word& fieldName, /*!< Name of field */ \
|
||||
const Field<Type>& values /*!< Field values */ \
|
||||
); /* override */ \
|
||||
\
|
||||
/*! \brief Write track fields of Type (point data) */ \
|
||||
virtual fileName write \
|
||||
( \
|
||||
const word& fieldName, /*!< Name of field */ \
|
||||
const List<Field<Type>>& fieldValues /*!< Per-track values */ \
|
||||
); /* override */
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "coordSetWriterI.H"
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "coordSetWriterTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
197
src/meshTools/coordSet/writers/common/coordSetWriterBuffers.C
Normal file
197
src/meshTools/coordSet/writers/common/coordSetWriterBuffers.C
Normal file
@ -0,0 +1,197 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "coordSetWriter.H"
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::coordSetWriter::writeLine
|
||||
(
|
||||
Ostream& os,
|
||||
const UList<word>& values,
|
||||
const char* sep
|
||||
)
|
||||
{
|
||||
if (!values.empty())
|
||||
{
|
||||
forAll(values, coli)
|
||||
{
|
||||
if (coli && sep) os << sep;
|
||||
os << values[coli];
|
||||
}
|
||||
os << nl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriter::writeLine
|
||||
(
|
||||
Ostream& os,
|
||||
const UList<scalar>& values,
|
||||
const char* sep
|
||||
)
|
||||
{
|
||||
if (!values.empty())
|
||||
{
|
||||
forAll(values, coli)
|
||||
{
|
||||
if (coli && sep) os << sep;
|
||||
os << values[coli];
|
||||
}
|
||||
os << nl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriter::clearBuffers()
|
||||
{
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(Type) \
|
||||
{ \
|
||||
Type##Names_.clear(); \
|
||||
Type##Fields_.clear(); \
|
||||
}
|
||||
|
||||
doLocalCode(label);
|
||||
doLocalCode(scalar);
|
||||
doLocalCode(vector);
|
||||
doLocalCode(sphericalTensor);
|
||||
doLocalCode(symmTensor);
|
||||
doLocalCode(tensor);
|
||||
#undef doLocalCode
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::coordSetWriter::nDataColumns() const
|
||||
{
|
||||
label ncol = 0;
|
||||
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(Type) \
|
||||
ncol += (Type##Fields_.size() * pTraits<Type>::nComponents);
|
||||
|
||||
doLocalCode(label);
|
||||
doLocalCode(scalar);
|
||||
doLocalCode(vector);
|
||||
doLocalCode(sphericalTensor);
|
||||
doLocalCode(symmTensor);
|
||||
doLocalCode(tensor);
|
||||
#undef doLocalCode
|
||||
|
||||
return ncol;
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriter::getBufferLine
|
||||
(
|
||||
DynamicList<scalar>& buf,
|
||||
const coordSet& coords,
|
||||
const label pointi
|
||||
) const
|
||||
{
|
||||
buf.clear();
|
||||
|
||||
if (coords.hasVectorAxis())
|
||||
{
|
||||
const vector& p = coords.vectorCoord(pointi);
|
||||
buf.append(p.x());
|
||||
buf.append(p.y());
|
||||
buf.append(p.z());
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.append(coords.scalarCoord(pointi));
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(Type) \
|
||||
\
|
||||
for (const auto& fld : Type##Fields_) \
|
||||
{ \
|
||||
const auto& val = fld[pointi]; \
|
||||
for (direction d=0; d < pTraits<Type>::nComponents; ++d) \
|
||||
{ \
|
||||
buf.append(component(val, d)); \
|
||||
} \
|
||||
}
|
||||
|
||||
doLocalCode(label);
|
||||
doLocalCode(scalar);
|
||||
doLocalCode(vector);
|
||||
doLocalCode(sphericalTensor);
|
||||
doLocalCode(symmTensor);
|
||||
doLocalCode(tensor);
|
||||
#undef doLocalCode
|
||||
}
|
||||
while (false);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::coordSetWriter::writeBuffered()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriter::writeBufferContents
|
||||
(
|
||||
Ostream& os,
|
||||
const coordSet& coords,
|
||||
const char* sep
|
||||
) const
|
||||
{
|
||||
const label npts = coords.size();
|
||||
const label ncomp = nDataColumns();
|
||||
|
||||
DynamicList<scalar> compCols(3 + ncomp);
|
||||
|
||||
for (label pointi = 0; pointi < npts; ++pointi)
|
||||
{
|
||||
getBufferLine(compCols, coords, pointi);
|
||||
writeLine(os, compCols, sep);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Controls * * * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::coordSetWriter::buffering() const
|
||||
{
|
||||
return buffering_;
|
||||
}
|
||||
|
||||
|
||||
// disabled
|
||||
bool Foam::coordSetWriter::buffering(const bool)
|
||||
{
|
||||
return buffering_;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
110
src/meshTools/coordSet/writers/common/coordSetWriterI.H
Normal file
110
src/meshTools/coordSet/writers/common/coordSetWriterI.H
Normal file
@ -0,0 +1,110 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
inline bool Foam::coordSetWriter::is_open() const noexcept
|
||||
{
|
||||
return !outputPath_.empty();
|
||||
}
|
||||
|
||||
|
||||
inline Foam::label Foam::coordSetWriter::nFields() const noexcept
|
||||
{
|
||||
return nFields_;
|
||||
}
|
||||
|
||||
|
||||
inline Foam::label Foam::coordSetWriter::nFields(const label n) noexcept
|
||||
{
|
||||
label old(nFields_);
|
||||
nFields_ = n;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::coordSetWriter::useTracks() const noexcept
|
||||
{
|
||||
return useTracks_;
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::coordSetWriter::useTracks(const bool on) noexcept
|
||||
{
|
||||
bool old(useTracks_);
|
||||
useTracks_ = on;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::coordSetWriter::useTimeDir() const noexcept
|
||||
{
|
||||
return useTimeDir_;
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::coordSetWriter::useTimeDir(const bool on) noexcept
|
||||
{
|
||||
bool old(useTimeDir_);
|
||||
useTimeDir_ = on;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::coordSetWriter::verbose() const noexcept
|
||||
{
|
||||
return verbose_;
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::coordSetWriter::verbose(bool on) noexcept
|
||||
{
|
||||
bool old(verbose_);
|
||||
verbose_ = on;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::coordSetWriter::hasTime() const
|
||||
{
|
||||
return currTime_.name().size();
|
||||
}
|
||||
|
||||
|
||||
inline const Foam::word& Foam::coordSetWriter::timeName() const
|
||||
{
|
||||
return currTime_.name();
|
||||
}
|
||||
|
||||
|
||||
inline Foam::scalar Foam::coordSetWriter::timeValue() const
|
||||
{
|
||||
return currTime_.name().empty() ? 0 : currTime_.value();
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,81 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 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/>.
|
||||
|
||||
InClass
|
||||
Foam::coordSetWriterMethods
|
||||
|
||||
Description
|
||||
Convenience macros for instantiating coordSetWriter methods.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_coordSetWriterMethods_H
|
||||
#define Foam_coordSetWriterMethods_H
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Instantiate templated method for standard types
|
||||
#define defineCoordSetWriterWriteField(ThisClass, ValueType) \
|
||||
\
|
||||
Foam::fileName ThisClass::write \
|
||||
( \
|
||||
const word& fieldName, \
|
||||
const Field<ValueType>& values \
|
||||
) \
|
||||
{ \
|
||||
return writeTemplate(fieldName, values); \
|
||||
} \
|
||||
\
|
||||
Foam::fileName ThisClass::write \
|
||||
( \
|
||||
const word& fieldName, \
|
||||
const List<Field<ValueType>>& fieldValues \
|
||||
) \
|
||||
{ \
|
||||
return writeTemplate(fieldName, fieldValues); \
|
||||
}
|
||||
|
||||
|
||||
#define defineCoordSetWriterWriteFields(ThisClass) \
|
||||
defineCoordSetWriterWriteField(ThisClass, label); \
|
||||
defineCoordSetWriterWriteField(ThisClass, scalar); \
|
||||
defineCoordSetWriterWriteField(ThisClass, vector); \
|
||||
defineCoordSetWriterWriteField(ThisClass, sphericalTensor); \
|
||||
defineCoordSetWriterWriteField(ThisClass, symmTensor); \
|
||||
defineCoordSetWriterWriteField(ThisClass, tensor)
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
98
src/meshTools/coordSet/writers/common/coordSetWriterNew.C
Normal file
98
src/meshTools/coordSet/writers/common/coordSetWriterNew.C
Normal file
@ -0,0 +1,98 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "coordSet.H"
|
||||
#include "coordSetWriter.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::coordSetWriter::supportedType(const word& writeType)
|
||||
{
|
||||
return
|
||||
(
|
||||
wordConstructorTablePtr_->found(writeType)
|
||||
|| wordDictConstructorTablePtr_->found(writeType)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Foam::autoPtr<Foam::coordSetWriter> Foam::coordSetWriter::New
|
||||
(
|
||||
const word& writeType
|
||||
)
|
||||
{
|
||||
auto* ctorPtr = wordConstructorTable(writeType);
|
||||
|
||||
if (!ctorPtr)
|
||||
{
|
||||
FatalErrorInLookup
|
||||
(
|
||||
"setWriter",
|
||||
writeType,
|
||||
*wordConstructorTablePtr_
|
||||
) << exit(FatalError);
|
||||
}
|
||||
|
||||
return autoPtr<coordSetWriter>(ctorPtr());
|
||||
}
|
||||
|
||||
|
||||
Foam::autoPtr<Foam::coordSetWriter> Foam::coordSetWriter::New
|
||||
(
|
||||
const word& writeType,
|
||||
const dictionary& writeOpts
|
||||
)
|
||||
{
|
||||
// Constructors with dictionary options
|
||||
{
|
||||
auto* ctorPtr = wordDictConstructorTable(writeType);
|
||||
|
||||
if (ctorPtr)
|
||||
{
|
||||
return autoPtr<coordSetWriter>(ctorPtr(writeOpts));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Constructors without dictionary options
|
||||
auto* ctorPtr = wordConstructorTable(writeType);
|
||||
|
||||
if (!ctorPtr)
|
||||
{
|
||||
FatalErrorInLookup
|
||||
(
|
||||
"setWriter",
|
||||
writeType,
|
||||
*wordConstructorTablePtr_
|
||||
) << exit(FatalError);
|
||||
}
|
||||
|
||||
return autoPtr<coordSetWriter>(ctorPtr());
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -5,8 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2012-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2019 OpenCFD Ltd.
|
||||
Copyright (C) 2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -26,49 +25,63 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "regionSizeDistribution.H"
|
||||
#include "regionSplit.H"
|
||||
#include "volFields.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::Map<Type> Foam::functionObjects::regionSizeDistribution::regionSum
|
||||
(
|
||||
const regionSplit& regions,
|
||||
const Field<Type>& fld
|
||||
) const
|
||||
Foam::UPtrList<const Foam::Field<Type>>
|
||||
Foam::coordSetWriter::repackageFields(const Field<Type>& field)
|
||||
{
|
||||
// Per region the sum of fld
|
||||
Map<Type> regionToSum(regions.nRegions()/Pstream::nProcs());
|
||||
UPtrList<const Field<Type>> fieldPtrs(1);
|
||||
fieldPtrs.set(0, &field);
|
||||
|
||||
forAll(fld, celli)
|
||||
{
|
||||
const label regioni = regions[celli];
|
||||
regionToSum(regioni, Type(Zero)) += fld[celli];
|
||||
}
|
||||
|
||||
Pstream::mapCombineGather(regionToSum, plusEqOp<Type>());
|
||||
Pstream::mapCombineScatter(regionToSum);
|
||||
|
||||
return regionToSum;
|
||||
return fieldPtrs;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::List<Type> Foam::functionObjects::regionSizeDistribution::extractData
|
||||
(
|
||||
const labelUList& keys,
|
||||
const Map<Type>& regionData
|
||||
) const
|
||||
Foam::UPtrList<const Foam::Field<Type>>
|
||||
Foam::coordSetWriter::repackageFields(const UList<Field<Type>>& fieldValues)
|
||||
{
|
||||
List<Type> sortedData(keys.size());
|
||||
|
||||
forAll(keys, i)
|
||||
UPtrList<const Field<Type>> fieldPtrs(fieldValues.size());
|
||||
forAll(fieldValues, i)
|
||||
{
|
||||
sortedData[i] = regionData[keys[i]];
|
||||
fieldPtrs.set(i, &(fieldValues[i]));
|
||||
}
|
||||
|
||||
return fieldPtrs;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::coordSetWriter::writeTable
|
||||
(
|
||||
Ostream& os,
|
||||
const coordSet& coords,
|
||||
const UList<Type>& values,
|
||||
const char* sep
|
||||
)
|
||||
{
|
||||
forAll(coords, pointi)
|
||||
{
|
||||
// Output coordinate (point or scalar) with separator
|
||||
if (coords.hasVectorAxis())
|
||||
{
|
||||
const vector& p = coords.vectorCoord(pointi);
|
||||
os << p.x() << sep << p.y() << sep << p.z();
|
||||
}
|
||||
else
|
||||
{
|
||||
os << coords.scalarCoord(pointi);
|
||||
}
|
||||
|
||||
// Output component values with separator
|
||||
const auto& val = values[pointi];
|
||||
for (direction d=0; d < pTraits<Type>::nComponents; ++d)
|
||||
{
|
||||
os << sep << component(val, d);
|
||||
}
|
||||
os << nl;
|
||||
}
|
||||
return sortedData;
|
||||
}
|
||||
|
||||
|
||||
@ -1,280 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2019-2021 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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "writer.H"
|
||||
#include "coordSet.H"
|
||||
#include "OFstream.H"
|
||||
#include "OSspecific.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::autoPtr<Foam::writer<Type>> Foam::writer<Type>::New
|
||||
(
|
||||
const word& writeType
|
||||
)
|
||||
{
|
||||
auto* ctorPtr = wordConstructorTable(writeType);
|
||||
|
||||
if (!ctorPtr)
|
||||
{
|
||||
FatalErrorInLookup
|
||||
(
|
||||
"writer",
|
||||
writeType,
|
||||
*wordConstructorTablePtr_
|
||||
) << exit(FatalError);
|
||||
}
|
||||
|
||||
return autoPtr<writer<Type>>(ctorPtr());
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::autoPtr<Foam::writer<Type>> Foam::writer<Type>::New
|
||||
(
|
||||
const word& writeType,
|
||||
const dictionary& formatOptions
|
||||
)
|
||||
{
|
||||
auto* ctorPtr = dictConstructorTable(writeType);
|
||||
|
||||
if (!ctorPtr)
|
||||
{
|
||||
FatalErrorInLookup
|
||||
(
|
||||
"writer",
|
||||
writeType,
|
||||
*dictConstructorTablePtr_
|
||||
) << exit(FatalError);
|
||||
}
|
||||
|
||||
return autoPtr<writer<Type>>(ctorPtr(formatOptions));
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::writer<Type>::getBaseName
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSets
|
||||
) const
|
||||
{
|
||||
fileName fName(points.name());
|
||||
|
||||
forAll(valueSets, i)
|
||||
{
|
||||
fName += '_' + valueSets[i];
|
||||
}
|
||||
|
||||
return fName;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::writer<Type>::writeCoord
|
||||
(
|
||||
const coordSet& points,
|
||||
const label pointi,
|
||||
Ostream& os
|
||||
) const
|
||||
{
|
||||
if (points.hasVectorAxis())
|
||||
{
|
||||
write(points.vectorCoord(pointi), os);
|
||||
}
|
||||
else
|
||||
{
|
||||
write(points.scalarCoord(pointi), os);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::writer<Type>::writeTable
|
||||
(
|
||||
const coordSet& points,
|
||||
const List<Type>& values,
|
||||
Ostream& os
|
||||
) const
|
||||
{
|
||||
forAll(points, pointi)
|
||||
{
|
||||
writeCoord(points, pointi, os);
|
||||
writeSeparator(os);
|
||||
write(values[pointi], os);
|
||||
os << nl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::writer<Type>::writeTable
|
||||
(
|
||||
const coordSet& points,
|
||||
const List<const List<Type>*>& valuesPtrList,
|
||||
Ostream& os
|
||||
) const
|
||||
{
|
||||
forAll(points, pointi)
|
||||
{
|
||||
writeCoord(points, pointi, os);
|
||||
|
||||
forAll(valuesPtrList, i)
|
||||
{
|
||||
writeSeparator(os);
|
||||
|
||||
const List<Type>& values = *valuesPtrList[i];
|
||||
write(values[pointi], os);
|
||||
}
|
||||
os << nl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::writer<Type>::writer()
|
||||
{}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::writer<Type>::writer(const dictionary& dict)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
void Foam::writer<Type>::write
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSetNames,
|
||||
const List<Field<Type>>& valueSets,
|
||||
Ostream& os
|
||||
) const
|
||||
{
|
||||
List<const Field<Type>*> valueSetPtrs(valueSets.size());
|
||||
forAll(valueSetPtrs, i)
|
||||
{
|
||||
valueSetPtrs[i] = &valueSets[i];
|
||||
}
|
||||
write(points, valueSetNames, valueSetPtrs, os);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::Ostream& Foam::writer<Type>::write
|
||||
(
|
||||
const scalar value,
|
||||
Ostream& os
|
||||
) const
|
||||
{
|
||||
return os << value;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
template<class VSType>
|
||||
Foam::Ostream& Foam::writer<Type>::writeVS
|
||||
(
|
||||
const VSType& value,
|
||||
Ostream& os
|
||||
) const
|
||||
{
|
||||
for (direction d=0; d<VSType::nComponents; d++)
|
||||
{
|
||||
if (d > 0)
|
||||
{
|
||||
writeSeparator(os);
|
||||
}
|
||||
|
||||
os << value.component(d);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::writer<Type>::writeSeparator
|
||||
(
|
||||
Ostream& os
|
||||
) const
|
||||
{
|
||||
os << token::SPACE << token::TAB;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::Ostream& Foam::writer<Type>::write
|
||||
(
|
||||
const vector& value,
|
||||
Ostream& os
|
||||
) const
|
||||
{
|
||||
return writeVS(value, os);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::Ostream& Foam::writer<Type>::write
|
||||
(
|
||||
const sphericalTensor& value,
|
||||
Ostream& os
|
||||
) const
|
||||
{
|
||||
return writeVS(value, os);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::Ostream& Foam::writer<Type>::write
|
||||
(
|
||||
const symmTensor& value,
|
||||
Ostream& os
|
||||
) const
|
||||
{
|
||||
return writeVS(value, os);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::Ostream& Foam::writer<Type>::write
|
||||
(
|
||||
const tensor& value,
|
||||
Ostream& os
|
||||
) const
|
||||
{
|
||||
return writeVS(value, os);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,244 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2021 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/>.
|
||||
|
||||
Class
|
||||
Foam::writer
|
||||
|
||||
Description
|
||||
Base class for graphics format writing. Entry points are
|
||||
- write(..). \n
|
||||
Write to an Ostream a table of points with corresponding values.
|
||||
- write(scalar/vector/sphericalTensor/symmTensor/tensor). \n
|
||||
Write single scalar/vector/sphericalTensor/symmTensor/tensor.
|
||||
Default is to write space separated components.
|
||||
|
||||
Example:
|
||||
\verbatim
|
||||
// Construct writer of xmgr type
|
||||
autoPtr<writer<scalar>> scalarFormatter(writer<scalar>::New("xmgr"));
|
||||
|
||||
// Output list of points and corresponding values
|
||||
scalarFormatter().write
|
||||
(
|
||||
coordSet(...)
|
||||
"U.component(0)", // name of values
|
||||
vals // values
|
||||
);
|
||||
\endverbatim
|
||||
|
||||
SourceFiles
|
||||
writer.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef writer_H
|
||||
#define writer_H
|
||||
|
||||
#include "fileName.H"
|
||||
#include "wordList.H"
|
||||
#include "vector.H"
|
||||
#include "tensor.H"
|
||||
#include "typeInfo.H"
|
||||
#include "runTimeSelectionTables.H"
|
||||
#include "autoPtr.H"
|
||||
#include "Field.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward Declarations
|
||||
class coordSet;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class writer Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Type>
|
||||
class writer
|
||||
{
|
||||
protected:
|
||||
|
||||
//- Generates filename from coordSet and sampled fields
|
||||
fileName getBaseName(const coordSet&, const wordList&) const;
|
||||
|
||||
void writeCoord(const coordSet&, const label sampleI, Ostream&) const;
|
||||
|
||||
//- Writes single-column ascii write. Column 1 is coordSet coordinate,
|
||||
// columns 2 is the value. Uses write() function
|
||||
// to write coordinate in correct format.
|
||||
void writeTable(const coordSet&, const List<Type>&, Ostream&) const;
|
||||
|
||||
//- Writes multi-column ascii write. Column 1 is coordSet coordinate,
|
||||
// columns 2..n are the values. Uses write() function
|
||||
// to write coordinate in correct format.
|
||||
void writeTable
|
||||
(
|
||||
const coordSet&,
|
||||
const List<const List<Type>*>&,
|
||||
Ostream& os
|
||||
) const;
|
||||
|
||||
//- Writes a separator. Used by write functions.
|
||||
virtual void writeSeparator(Ostream& os) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("writer");
|
||||
|
||||
// Declare run-time constructor selection table
|
||||
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
writer,
|
||||
word,
|
||||
(),
|
||||
()
|
||||
);
|
||||
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
writer,
|
||||
dict,
|
||||
(
|
||||
const dictionary& formatOptions
|
||||
),
|
||||
(formatOptions)
|
||||
);
|
||||
|
||||
|
||||
// Selectors
|
||||
|
||||
//- Return a reference to the selected writer
|
||||
static autoPtr<writer> New(const word& writeFormat);
|
||||
|
||||
//- Return a reference to the selected writer
|
||||
static autoPtr<writer> New
|
||||
(
|
||||
const word& writeFormat,
|
||||
const dictionary& formatOptions
|
||||
);
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
writer();
|
||||
|
||||
//- Construct with dictionary
|
||||
explicit writer(const dictionary& dict);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~writer() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Generate file name with correct extension
|
||||
virtual fileName getFileName
|
||||
(
|
||||
const coordSet&,
|
||||
const wordList&
|
||||
) const = 0;
|
||||
|
||||
//- General entry point for writing.
|
||||
// The data is organized in a set of point with one or more values
|
||||
// per point
|
||||
virtual void write
|
||||
(
|
||||
const coordSet&,
|
||||
const wordList&,
|
||||
const List<const Field<Type>*>&,
|
||||
Ostream&
|
||||
) const = 0;
|
||||
|
||||
//- General entry point for writing.
|
||||
// The data is organized in a set of point with one or more values
|
||||
// per point
|
||||
virtual void write
|
||||
(
|
||||
const coordSet&,
|
||||
const wordList&,
|
||||
const List<Field<Type>>&,
|
||||
Ostream&
|
||||
) const;
|
||||
|
||||
//- General entry point for writing of multiple coordSets.
|
||||
// Each coordSet (track) has same data variables.
|
||||
// The data is per variable, per track, per point of track.
|
||||
// If writeTracks adds connecting lines (wherever applicable)
|
||||
virtual void write
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream&
|
||||
) const = 0;
|
||||
|
||||
//- Write scalar as ascii
|
||||
virtual Ostream& write(const scalar, Ostream&) const;
|
||||
|
||||
template<class VSType>
|
||||
Ostream& writeVS(const VSType&, Ostream&) const;
|
||||
|
||||
//- Write vector. Tab separated ascii
|
||||
virtual Ostream& write(const vector&, Ostream&) const;
|
||||
|
||||
//- Write sphericalTensor. Tab separated ascii
|
||||
virtual Ostream& write(const sphericalTensor&, Ostream&) const;
|
||||
|
||||
//- Write symmTensor. Tab separated ascii
|
||||
virtual Ostream& write(const symmTensor&, Ostream&) const;
|
||||
|
||||
//- Write tensor. Tab separated ascii
|
||||
virtual Ostream& write(const tensor&, Ostream&) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "writer.C"
|
||||
#endif
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,53 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2021 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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "writers.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
#define defineSetWriterType(dataType) \
|
||||
defineNamedTemplateTypeNameAndDebug(writer<dataType >, 0); \
|
||||
defineTemplatedRunTimeSelectionTable(writer, word, dataType); \
|
||||
defineTemplatedRunTimeSelectionTable(writer, dict, dataType);
|
||||
|
||||
defineSetWriterType(scalar);
|
||||
defineSetWriterType(vector);
|
||||
defineSetWriterType(sphericalTensor);
|
||||
defineSetWriterType(symmTensor);
|
||||
defineSetWriterType(tensor);
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,85 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
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/>.
|
||||
|
||||
InClass
|
||||
Foam::writer
|
||||
|
||||
SourceFiles
|
||||
writers.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef writers_H
|
||||
#define writers_H
|
||||
|
||||
#include "writer.H"
|
||||
#include "fieldTypes.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
// Only used internally
|
||||
#define makeTypeSetWritersTypeName(typeWriter, dataType) \
|
||||
\
|
||||
defineNamedTemplateTypeNameAndDebug(typeWriter<dataType>, 0)
|
||||
|
||||
// Sometimes used externally
|
||||
#define makeSetWritersTypeName(typeWriter) \
|
||||
\
|
||||
makeTypeSetWritersTypeName(typeWriter, scalar); \
|
||||
makeTypeSetWritersTypeName(typeWriter, vector); \
|
||||
makeTypeSetWritersTypeName(typeWriter, sphericalTensor); \
|
||||
makeTypeSetWritersTypeName(typeWriter, symmTensor); \
|
||||
makeTypeSetWritersTypeName(typeWriter, tensor)
|
||||
|
||||
// Define type info for single dataType template instantiation (eg, vector)
|
||||
#define makeSetWriterType(typeWriter, dataType) \
|
||||
\
|
||||
defineNamedTemplateTypeNameAndDebug(typeWriter<dataType>, 0); \
|
||||
addTemplatedToRunTimeSelectionTable \
|
||||
( \
|
||||
writer, typeWriter, dataType, word \
|
||||
); \
|
||||
addTemplatedToRunTimeSelectionTable \
|
||||
( \
|
||||
writer, typeWriter, dataType, dict \
|
||||
);
|
||||
|
||||
|
||||
// Define type info for scalar, vector etc. instantiations
|
||||
#define makeSetWriters(typeWriter) \
|
||||
\
|
||||
makeSetWriterType(typeWriter, scalar); \
|
||||
makeSetWriterType(typeWriter, vector); \
|
||||
makeSetWriterType(typeWriter, sphericalTensor); \
|
||||
makeSetWriterType(typeWriter, symmTensor); \
|
||||
makeSetWriterType(typeWriter, tensor)
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -5,8 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2021 OpenCFD Ltd.
|
||||
Copyright (C) 2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -26,183 +25,242 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "csvSetWriter.H"
|
||||
#include "csvCoordSetWriter.H"
|
||||
#include "coordSet.H"
|
||||
#include "fileName.H"
|
||||
#include "OFstream.H"
|
||||
#include "OSspecific.H"
|
||||
#include "coordSetWriterMethods.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace coordSetWriters
|
||||
{
|
||||
defineTypeName(csvWriter);
|
||||
addToRunTimeSelectionTable(coordSetWriter, csvWriter, word);
|
||||
addToRunTimeSelectionTable(coordSetWriter, csvWriter, wordDict);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Implementation
|
||||
#include "csvCoordSetWriterImpl.C"
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::csvSetWriter<Type>::csvSetWriter()
|
||||
Foam::coordSetWriters::csvWriter::csvWriter()
|
||||
:
|
||||
writer<Type>()
|
||||
{}
|
||||
coordSetWriter(),
|
||||
streamOpt_(),
|
||||
precision_(IOstream::defaultPrecision())
|
||||
{
|
||||
buffering_ = true;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::csvSetWriter<Type>::csvSetWriter(const dictionary& dict)
|
||||
Foam::coordSetWriters::csvWriter::csvWriter(const dictionary& options)
|
||||
:
|
||||
writer<Type>(dict)
|
||||
{}
|
||||
coordSetWriter(options),
|
||||
streamOpt_
|
||||
(
|
||||
IOstream::ASCII,
|
||||
IOstream::compressionEnum("compression", options)
|
||||
),
|
||||
precision_
|
||||
(
|
||||
options.getOrDefault("precision", IOstream::defaultPrecision())
|
||||
)
|
||||
{
|
||||
buffering_ = options.getOrDefault("buffer", true);
|
||||
}
|
||||
|
||||
|
||||
Foam::coordSetWriters::csvWriter::csvWriter
|
||||
(
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
csvWriter(options)
|
||||
{
|
||||
open(coords, outputPath);
|
||||
}
|
||||
|
||||
|
||||
Foam::coordSetWriters::csvWriter::csvWriter
|
||||
(
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
csvWriter(options)
|
||||
{
|
||||
open(tracks, outputPath);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::coordSetWriters::csvWriter::~csvWriter()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::csvSetWriter<Type>::getFileName
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSetNames
|
||||
) const
|
||||
bool Foam::coordSetWriters::csvWriter::buffering(const bool on)
|
||||
{
|
||||
return this->getBaseName(points, valueSetNames) + ".csv";
|
||||
const bool old(buffering_);
|
||||
buffering_ = on;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::csvSetWriter<Type>::write
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSetNames,
|
||||
const List<const Field<Type>*>& valueSets,
|
||||
Ostream& os
|
||||
) const
|
||||
Foam::fileName Foam::coordSetWriters::csvWriter::path() const
|
||||
{
|
||||
writeHeader(points,valueSetNames,os);
|
||||
// Assume !useTracks_, otherwise too fragile
|
||||
|
||||
// Collect sets into columns
|
||||
List<const List<Type>*> columns(valueSets.size());
|
||||
// 1) rootdir/<TIME>/setName.csv
|
||||
// 2) rootdir/setName.csv
|
||||
|
||||
forAll(valueSets, i)
|
||||
{
|
||||
columns[i] = valueSets[i];
|
||||
}
|
||||
|
||||
this->writeTable(points, columns, os);
|
||||
return getExpectedPath("csv");
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::csvSetWriter<Type>::write
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream& os
|
||||
) const
|
||||
bool Foam::coordSetWriters::csvWriter::writeBuffered()
|
||||
{
|
||||
writeHeader(tracks[0],valueSetNames,os);
|
||||
|
||||
if (valueSets.size() != valueSetNames.size())
|
||||
if (coords_.empty())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Number of variables:" << valueSetNames.size() << endl
|
||||
<< "Number of valueSets:" << valueSets.size()
|
||||
<< exit(FatalError);
|
||||
clearBuffers();
|
||||
return false;
|
||||
}
|
||||
const auto& coords = coords_[0];
|
||||
|
||||
List<const List<Type>*> columns(valueSets.size());
|
||||
|
||||
forAll(tracks, trackI)
|
||||
DynamicList<word> headCols(3 + nDataColumns());
|
||||
|
||||
do
|
||||
{
|
||||
// Collect sets into columns
|
||||
forAll(valueSets, i)
|
||||
if (coords.hasVectorAxis())
|
||||
{
|
||||
columns[i] = &valueSets[i][trackI];
|
||||
// x, y, z
|
||||
headCols.append("x");
|
||||
headCols.append("y");
|
||||
headCols.append("z");
|
||||
}
|
||||
else
|
||||
{
|
||||
headCols.append(coords.axis());
|
||||
}
|
||||
|
||||
this->writeTable(tracks[trackI], columns, os);
|
||||
os << nl << nl;
|
||||
}
|
||||
}
|
||||
// label, scalar
|
||||
headCols.append(labelNames_);
|
||||
headCols.append(scalarNames_);
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::csvSetWriter<Type>::writeSeparator(Ostream& os) const
|
||||
{
|
||||
os << token::COMMA;
|
||||
}
|
||||
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
// otherwise compiler complains about specialization
|
||||
template<>
|
||||
void csvSetWriter<scalar>::writeHeader
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSetNames,
|
||||
Ostream& os
|
||||
) const
|
||||
{
|
||||
writeCoordHeader(points, os);
|
||||
|
||||
forAll(valueSetNames, i)
|
||||
{
|
||||
if (i)
|
||||
{
|
||||
writeSeparator(os);
|
||||
// vector space
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(Type) \
|
||||
\
|
||||
for (const word& fldName : Type##Names_) \
|
||||
{ \
|
||||
for (direction d=0; d < pTraits<Type>::nComponents; ++d) \
|
||||
{ \
|
||||
headCols.append(fldName + '_' + Foam::name(d)); \
|
||||
} \
|
||||
}
|
||||
os << valueSetNames[i];
|
||||
}
|
||||
|
||||
os << nl;
|
||||
doLocalCode(vector);
|
||||
doLocalCode(sphericalTensor);
|
||||
doLocalCode(symmTensor);
|
||||
doLocalCode(tensor);
|
||||
#undef doLocalCode
|
||||
}
|
||||
while (false);
|
||||
|
||||
|
||||
// Field:
|
||||
// 1) rootdir/<TIME>/setName.csv
|
||||
// 2) rootdir/setName.csv
|
||||
|
||||
fileName outputFile = path();
|
||||
|
||||
if (!isDir(outputFile.path()))
|
||||
{
|
||||
mkDir(outputFile.path());
|
||||
}
|
||||
|
||||
OFstream os(outputFile, streamOpt_);
|
||||
os.precision(precision_);
|
||||
|
||||
writeLine(os, headCols, ",");
|
||||
|
||||
writeBufferContents(os, coords, ",");
|
||||
|
||||
clearBuffers();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Implementation * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::coordSetWriters::csvWriter::writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const Field<Type>& values
|
||||
)
|
||||
{
|
||||
checkOpen();
|
||||
if (coords_.empty())
|
||||
{
|
||||
return fileName::null;
|
||||
}
|
||||
|
||||
if (useTracks_ || !buffering_)
|
||||
{
|
||||
UPtrList<const Field<Type>> fieldPtrs(repackageFields(values));
|
||||
return writeTemplate(fieldName, fieldPtrs);
|
||||
}
|
||||
|
||||
// Buffering version
|
||||
appendField(fieldName, values);
|
||||
return path();
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::csvSetWriter<Type>::writeHeader
|
||||
Foam::fileName Foam::coordSetWriters::csvWriter::writeTemplate
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSetNames,
|
||||
Ostream& os
|
||||
) const
|
||||
const word& fieldName,
|
||||
const List<Field<Type>>& fieldValues
|
||||
)
|
||||
{
|
||||
writeCoordHeader(points, os);
|
||||
|
||||
forAll(valueSetNames, i)
|
||||
checkOpen();
|
||||
if (coords_.empty())
|
||||
{
|
||||
for (label j=0; j<Type::nComponents; j++)
|
||||
{
|
||||
if (i || j)
|
||||
{
|
||||
writeSeparator(os);
|
||||
}
|
||||
os << valueSetNames[i] << "_" << j;
|
||||
}
|
||||
return fileName::null;
|
||||
}
|
||||
useTracks_ = true; // Extra safety
|
||||
|
||||
os << nl;
|
||||
UPtrList<const Field<Type>> fieldPtrs(repackageFields(fieldValues));
|
||||
return writeTemplate(fieldName, fieldPtrs);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::csvSetWriter<Type>::writeCoordHeader
|
||||
(
|
||||
const coordSet& points,
|
||||
Ostream& os
|
||||
) const
|
||||
{
|
||||
const word axisName(points.axis());
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
if (points.hasVectorAxis())
|
||||
{
|
||||
for (auto iter = axisName.cbegin(); iter != axisName.cend(); ++iter)
|
||||
{
|
||||
os << *iter;
|
||||
writeSeparator(os);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
os << axisName;
|
||||
writeSeparator(os);
|
||||
}
|
||||
}
|
||||
// Field writing methods
|
||||
defineCoordSetWriterWriteFields(Foam::coordSetWriters::csvWriter);
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
179
src/meshTools/coordSet/writers/csv/csvCoordSetWriter.H
Normal file
179
src/meshTools/coordSet/writers/csv/csvCoordSetWriter.H
Normal file
@ -0,0 +1,179 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2021-2022 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/>.
|
||||
|
||||
Class
|
||||
Foam::coordSetWriters::csvWriter
|
||||
|
||||
Description
|
||||
Write coordSet(s) in csv format
|
||||
|
||||
The formatOptions for csv:
|
||||
\table
|
||||
Property | Description | Required | Default
|
||||
buffer | Use buffered output | no | true
|
||||
compression | Use file compression | no | false
|
||||
precision | Write precision in ascii | no | same as IOstream
|
||||
\endtable
|
||||
|
||||
When called with a single coordSet, will buffer the output of
|
||||
all fields and output together in the order of label/scalar/vector/...
|
||||
each of which is sorted alphabetically according to the field name.
|
||||
|
||||
When called as a track writer (eg, with multiple coordSets),
|
||||
will emit one file per field.
|
||||
|
||||
SourceFiles
|
||||
csvCoorSetWriter.C
|
||||
csvCoorSetWriterImpl.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_coordSetWriters_csvWriter_H
|
||||
#define Foam_coordSetWriters_csvWriter_H
|
||||
|
||||
#include "coordSetWriter.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace coordSetWriters
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class csvWriter Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class csvWriter
|
||||
:
|
||||
public coordSetWriter
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- Output stream option
|
||||
IOstreamOption streamOpt_;
|
||||
|
||||
//- ASCII write precision
|
||||
unsigned precision_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const UPtrList<const Field<Type>>& fieldPtrs
|
||||
);
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName, //!< Name of field
|
||||
const Field<Type>& vals //!< Local field values to write
|
||||
);
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const List<Field<Type>>& fieldValues
|
||||
);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Write buffered data
|
||||
virtual bool writeBuffered();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information (no debug)
|
||||
TypeNameNoDebug("csv");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
csvWriter();
|
||||
|
||||
//- Default construct with specified options
|
||||
explicit csvWriter(const dictionary& options);
|
||||
|
||||
//- Construct from components
|
||||
csvWriter
|
||||
(
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
//- Construct from components
|
||||
csvWriter
|
||||
(
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
|
||||
//- Destructor. Calls close()
|
||||
virtual ~csvWriter();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Enable/disable internal buffering
|
||||
virtual bool buffering(const bool on); // override
|
||||
|
||||
//- Characteristic output file name - information only
|
||||
// \warning incorrect for unbuffered or track output!
|
||||
virtual fileName path() const; // override
|
||||
|
||||
declareCoordSetWriterWriteMethod(label);
|
||||
declareCoordSetWriterWriteMethod(scalar);
|
||||
declareCoordSetWriterWriteMethod(vector);
|
||||
declareCoordSetWriterWriteMethod(sphericalTensor);
|
||||
declareCoordSetWriterWriteMethod(symmTensor);
|
||||
declareCoordSetWriterWriteMethod(tensor);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace coordSetWriters
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
144
src/meshTools/coordSet/writers/csv/csvCoordSetWriterImpl.C
Normal file
144
src/meshTools/coordSet/writers/csv/csvCoordSetWriterImpl.C
Normal file
@ -0,0 +1,144 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "IOmanip.H"
|
||||
#include "OFstream.H"
|
||||
#include "OSspecific.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
// Output coordinate header
|
||||
static void writeCoordHeader
|
||||
(
|
||||
Ostream& os,
|
||||
const coordSet& coords,
|
||||
const label count /* (future?) */
|
||||
)
|
||||
{
|
||||
if (coords.hasVectorAxis())
|
||||
{
|
||||
os << "x,y,z";
|
||||
}
|
||||
else
|
||||
{
|
||||
// axis name
|
||||
// const word axisName(coords.axis());
|
||||
os << word(coords.axis());
|
||||
}
|
||||
}
|
||||
|
||||
// Write field name, use named components for VectorSpace
|
||||
template<class Type>
|
||||
static inline void writeHeader(Ostream& os, const word& fieldName)
|
||||
{
|
||||
/// os << ' '; // Extra space
|
||||
|
||||
const auto nCmpts(pTraits<Type>::nComponents);
|
||||
|
||||
if (pTraits<Type>::rank || nCmpts > 1)
|
||||
{
|
||||
for (direction d = 0; d < nCmpts; ++d)
|
||||
{
|
||||
os << ',' << fieldName
|
||||
<< '_' << pTraits<Type>::componentNames[d];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
os << ',' << fieldName;
|
||||
}
|
||||
}
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::coordSetWriters::csvWriter::writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const UPtrList<const Field<Type>>& fieldPtrs
|
||||
)
|
||||
{
|
||||
if (coords_.size() != fieldPtrs.size())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Attempted to write field: " << fieldName
|
||||
<< " (" << fieldPtrs.size() << " entries) for "
|
||||
<< coords_.size() << " sets" << nl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
label nPoints = 0;
|
||||
for (const auto& pts : coords_)
|
||||
{
|
||||
nPoints += pts.size();
|
||||
}
|
||||
|
||||
|
||||
// Field: rootdir/<TIME>/<field>_setName.csv
|
||||
|
||||
fileName outputFile = getFieldPrefixedPath(fieldName, "csv");
|
||||
|
||||
if (verbose_)
|
||||
{
|
||||
Info<< "Writing field " << fieldName;
|
||||
Info<< " to " << outputFile << endl;
|
||||
}
|
||||
|
||||
// Master only
|
||||
{
|
||||
if (!isDir(outputFile.path()))
|
||||
{
|
||||
mkDir(outputFile.path());
|
||||
}
|
||||
|
||||
OFstream os(outputFile, streamOpt_);
|
||||
os.precision(precision_);
|
||||
|
||||
// Header
|
||||
{
|
||||
writeCoordHeader(os, coords_[0], nPoints);
|
||||
writeHeader<Type>(os, fieldName);
|
||||
os << nl;
|
||||
}
|
||||
|
||||
forAll(coords_, tracki)
|
||||
{
|
||||
writeTable(os, coords_[tracki], fieldPtrs[tracki], ",");
|
||||
}
|
||||
}
|
||||
|
||||
wroteGeom_ = true;
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,131 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2021 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/>.
|
||||
|
||||
Class
|
||||
Foam::csvSetWriter
|
||||
|
||||
Description
|
||||
Write set in csv format
|
||||
|
||||
SourceFiles
|
||||
csvCoordSetWriter.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_coordSetWriters_csvWriter_H
|
||||
#define Foam_coordSetWriters_csvWriter_H
|
||||
|
||||
#include "writer.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class csvSetWriter Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Type>
|
||||
class csvSetWriter
|
||||
:
|
||||
public writer<Type>
|
||||
{
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
void writeCoordHeader(const coordSet&, Ostream&) const;
|
||||
|
||||
void writeHeader(const coordSet&, const wordList&, Ostream&) const;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
virtual void writeSeparator(Ostream&) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("csv");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
csvSetWriter();
|
||||
|
||||
//- Construct with dictionary
|
||||
explicit csvSetWriter(const dictionary& dict);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~csvSetWriter() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
virtual fileName getFileName
|
||||
(
|
||||
const coordSet&,
|
||||
const wordList&
|
||||
) const;
|
||||
|
||||
virtual void write
|
||||
(
|
||||
const coordSet&,
|
||||
const wordList&,
|
||||
const List<const Field<Type>*>&,
|
||||
Ostream&
|
||||
) const;
|
||||
|
||||
virtual void write
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream&
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "csvCoordSetWriter.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,39 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2012 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
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 "csvSetWriter.H"
|
||||
#include "writers.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
makeSetWriters(csvSetWriter);
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2021 OpenCFD Ltd.
|
||||
Copyright (C) 2021-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -26,277 +26,321 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "ensightSetWriter.H"
|
||||
#include "ensightCoordSetWriter.H"
|
||||
#include "coordSet.H"
|
||||
#include "IOmanip.H"
|
||||
#include "ensightCase.H"
|
||||
#include "ensightGeoFile.H"
|
||||
#include "ensightOutput.H"
|
||||
#include "ensightPTraits.H"
|
||||
#include "coordSetWriterMethods.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace coordSetWriters
|
||||
{
|
||||
defineTypeName(ensightWriter);
|
||||
addToRunTimeSelectionTable(coordSetWriter, ensightWriter, word);
|
||||
addToRunTimeSelectionTable(coordSetWriter, ensightWriter, wordDict);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
template<class Type>
|
||||
static void writeTrackField
|
||||
(
|
||||
ensightFile& os,
|
||||
const UPtrList<const Field<Type>>& fieldPtrs
|
||||
)
|
||||
{
|
||||
// Write field (serial only)
|
||||
os.writeKeyword(ensightPTraits<Type>::typeName);
|
||||
forAll(fieldPtrs, tracki)
|
||||
{
|
||||
// Write as point data
|
||||
|
||||
os.beginPart(tracki); // Part index (0-based)
|
||||
ensightOutput::Detail::writeFieldComponents
|
||||
(
|
||||
os,
|
||||
ensightFile::coordinates,
|
||||
fieldPtrs[tracki],
|
||||
false /* serial only! */
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::coordSetWriters::ensightWriter::writeGeometry
|
||||
(
|
||||
ensightGeoFile& os,
|
||||
elemOutputType elemOutput
|
||||
) const
|
||||
{
|
||||
// Writing tracks as x/y/z coordinates, optionally with points
|
||||
// or points/lines as elements.
|
||||
//
|
||||
// The requirements are so basic that they do not warrant an
|
||||
// ensightPart treatment at all.
|
||||
|
||||
forAll(coords_, tracki)
|
||||
{
|
||||
const auto& coords = coords_[tracki];
|
||||
const label nPoints = coords.size();
|
||||
|
||||
word partName("track" + Foam::name(tracki));
|
||||
if (coords_.size() == 1 && elemOutputType::WRITE_LINES != elemOutput)
|
||||
{
|
||||
partName = "sampled";
|
||||
}
|
||||
|
||||
ensightOutput::Detail::writeCoordinates
|
||||
(
|
||||
os,
|
||||
tracki, // Part index (0-based)
|
||||
partName,
|
||||
nPoints,
|
||||
static_cast<const pointField&>(coords),
|
||||
false /* serial only! */
|
||||
);
|
||||
|
||||
if (elemOutputType::WRITE_POINTS == elemOutput)
|
||||
{
|
||||
if (nPoints)
|
||||
{
|
||||
os.writeKeyword("point");
|
||||
os.write(nPoints);
|
||||
os.newline();
|
||||
for (label pointi = 0; pointi < nPoints; ++pointi)
|
||||
{
|
||||
os.write(pointi+1); // From 0-based to 1-based index
|
||||
os.newline();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (elemOutputType::WRITE_LINES == elemOutput)
|
||||
{
|
||||
const label nLines = (nPoints-1);
|
||||
if (nPoints == 1)
|
||||
{
|
||||
os.writeKeyword("point");
|
||||
os.write(nPoints);
|
||||
os.newline();
|
||||
for (label pointi = 0; pointi < nPoints; ++pointi)
|
||||
{
|
||||
os.write(pointi+1); // From 0-based to 1-based index
|
||||
os.newline();
|
||||
}
|
||||
}
|
||||
else if (nLines > 0)
|
||||
{
|
||||
os.writeKeyword("bar2");
|
||||
os.write(nLines);
|
||||
os.newline();
|
||||
for (label pointi = 0; pointi < nLines; ++pointi)
|
||||
{
|
||||
os.write(pointi+1); // From 0-based to 1-based index
|
||||
os.write(pointi+2);
|
||||
os.newline();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::ensightSetWriter<Type>::ensightSetWriter()
|
||||
Foam::coordSetWriters::ensightWriter::ensightWriter()
|
||||
:
|
||||
writer<Type>()
|
||||
coordSetWriter(),
|
||||
writeFormat_(IOstream::ASCII),
|
||||
collateTimes_(true),
|
||||
caching_("fieldsDict") // Historic name
|
||||
{}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::ensightSetWriter<Type>::ensightSetWriter(const dictionary& dict)
|
||||
Foam::coordSetWriters::ensightWriter::ensightWriter(const dictionary& options)
|
||||
:
|
||||
writer<Type>(dict)
|
||||
coordSetWriter(options),
|
||||
writeFormat_
|
||||
(
|
||||
IOstreamOption::formatEnum("format", options, IOstream::ASCII)
|
||||
),
|
||||
collateTimes_(options.getOrDefault("collateTimes", true)),
|
||||
caching_("fieldsDict") // Historic name
|
||||
{}
|
||||
|
||||
|
||||
Foam::coordSetWriters::ensightWriter::ensightWriter
|
||||
(
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
ensightWriter(options)
|
||||
{
|
||||
open(coords, outputPath);
|
||||
}
|
||||
|
||||
|
||||
Foam::coordSetWriters::ensightWriter::ensightWriter
|
||||
(
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
ensightWriter(options)
|
||||
{
|
||||
open(tracks, outputPath);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::coordSetWriters::ensightWriter::~ensightWriter()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::ensightSetWriter<Type>::getFileName
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSetNames
|
||||
) const
|
||||
Foam::fileName Foam::coordSetWriters::ensightWriter::path() const
|
||||
{
|
||||
return
|
||||
this->getBaseName(points, valueSetNames)
|
||||
//+ '_'
|
||||
//+ ensightPTraits<Type>::typeName
|
||||
+ ".case";
|
||||
// Assume collateTimes == true, otherwise too fragile
|
||||
|
||||
// Collated
|
||||
// ========
|
||||
// CaseFile: rootdir/NAME/NAME.case
|
||||
// Geometry: rootdir/NAME/data/<index>/geometry
|
||||
// Field: rootdir/NAME/data/<index>/field
|
||||
|
||||
if (!outputPath_.empty())
|
||||
{
|
||||
return outputPath_ / (ensight::FileName(outputPath_.name()) + ".case");
|
||||
}
|
||||
|
||||
return fileName();
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::ensightSetWriter<Type>::write
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSetNames,
|
||||
const List<const Field<Type>*>& valueSets,
|
||||
Ostream& os
|
||||
) const
|
||||
void Foam::coordSetWriters::ensightWriter::close(const bool force)
|
||||
{
|
||||
const fileName base(os.name().lessExt());
|
||||
const fileName meshFile(base + ".mesh");
|
||||
caching_.clear();
|
||||
coordSetWriter::close(force);
|
||||
}
|
||||
|
||||
// Write .case file
|
||||
os << "FORMAT" << nl
|
||||
<< "type: ensight gold" << nl
|
||||
<< nl
|
||||
<< "GEOMETRY" << nl
|
||||
<< "model: 1 " << meshFile.name().c_str() << nl
|
||||
<< nl
|
||||
<< "VARIABLE"
|
||||
<< nl;
|
||||
|
||||
for (const word& valueName : valueSetNames)
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
// Field writing implementations
|
||||
|
||||
#include "ensightCoordSetWriterCollated.C"
|
||||
#include "ensightCoordSetWriterUncollated.C"
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::coordSetWriters::ensightWriter::writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const Field<Type>& values
|
||||
)
|
||||
{
|
||||
checkOpen();
|
||||
if (coords_.empty())
|
||||
{
|
||||
fileName dataFile(base + ".***." + valueName);
|
||||
|
||||
os.setf(ios_base::left);
|
||||
os << ensightPTraits<Type>::typeName
|
||||
<< " per node: 1 "
|
||||
<< setw(15) << valueName
|
||||
<< " " << dataFile.name().c_str()
|
||||
<< nl;
|
||||
return fileName::null;
|
||||
}
|
||||
os << nl
|
||||
<< "TIME" << nl
|
||||
<< "time set: 1" << nl
|
||||
<< "number of steps: 1" << nl
|
||||
<< "filename start number: 0" << nl
|
||||
<< "filename increment: 1" << nl
|
||||
<< "time values:" << nl
|
||||
<< "0.00000e+00" << nl;
|
||||
|
||||
// Write .mesh file
|
||||
if (coords_.size() != 1)
|
||||
{
|
||||
string desc("Written by OpenFOAM");
|
||||
OFstream os(meshFile);
|
||||
os.setf(ios_base::scientific, ios_base::floatfield);
|
||||
os.precision(5);
|
||||
|
||||
os << "Ensight Geometry File" << nl
|
||||
<< desc.c_str() << nl
|
||||
<< "node id assign" << nl
|
||||
<< "element id assign" << nl
|
||||
<< "part" << nl
|
||||
<< setw(10) << 1 << nl
|
||||
<< "internalMesh" << nl
|
||||
<< "coordinates" << nl
|
||||
<< setw(10) << points.size() << nl;
|
||||
|
||||
for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt)
|
||||
{
|
||||
for (const point& p : points)
|
||||
{
|
||||
const float comp = narrowFloat(p[cmpt]);
|
||||
os << setw(12) << comp << nl;
|
||||
}
|
||||
}
|
||||
os << "point" << nl
|
||||
<< setw(10) << points.size() << nl;
|
||||
forAll(points, pointi)
|
||||
{
|
||||
os << setw(10) << pointi+1 << nl;
|
||||
}
|
||||
FatalErrorInFunction
|
||||
<< "Attempted to write field: " << fieldName
|
||||
<< " (" << 1 << " entries) for "
|
||||
<< coords_.size() << " sets" << nl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
// Write data files
|
||||
forAll(valueSetNames, seti)
|
||||
UPtrList<const Field<Type>> fieldPtrs(repackageFields(values));
|
||||
|
||||
elemOutputType elemOutput =
|
||||
(
|
||||
useTracks_
|
||||
? elemOutputType::WRITE_LINES
|
||||
: elemOutputType::NO_ELEMENTS
|
||||
);
|
||||
|
||||
if (collateTimes_)
|
||||
{
|
||||
const word& valueName = valueSetNames[seti];
|
||||
const Field<Type>& fld = *(valueSets[seti]);
|
||||
|
||||
fileName dataFile(base + ".000." + valueName);
|
||||
OFstream os(dataFile);
|
||||
os.setf(ios_base::scientific, ios_base::floatfield);
|
||||
os.precision(5);
|
||||
|
||||
os << ensightPTraits<Type>::typeName << nl
|
||||
<< "part" << nl
|
||||
<< setw(10) << 1 << nl
|
||||
<< "coordinates" << nl;
|
||||
|
||||
for (direction d=0; d < pTraits<Type>::nComponents; ++d)
|
||||
{
|
||||
const direction cmpt = ensightPTraits<Type>::componentOrder[d];
|
||||
|
||||
for (const Type& val : fld)
|
||||
{
|
||||
const float comp = narrowFloat(component(val, cmpt));
|
||||
os << setw(12) << comp << nl;
|
||||
}
|
||||
}
|
||||
return writeCollated(fieldName, fieldPtrs, elemOutput);
|
||||
}
|
||||
else
|
||||
{
|
||||
return writeUncollated(fieldName, fieldPtrs, elemOutput);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::ensightSetWriter<Type>::write
|
||||
Foam::fileName Foam::coordSetWriters::ensightWriter::writeTemplate
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream& os
|
||||
) const
|
||||
const word& fieldName,
|
||||
const List<Field<Type>>& fieldValues
|
||||
)
|
||||
{
|
||||
const fileName base(os.name().lessExt());
|
||||
const fileName meshFile(base + ".mesh");
|
||||
|
||||
// Write .case file
|
||||
os << "FORMAT" << nl
|
||||
<< "type: ensight gold" << nl
|
||||
<< nl
|
||||
<< "GEOMETRY" << nl
|
||||
<< "model: 1 " << meshFile.name().c_str() << nl
|
||||
<< nl
|
||||
<< "VARIABLE"
|
||||
<< nl;
|
||||
|
||||
for (const word& valueName : valueSetNames)
|
||||
checkOpen();
|
||||
if (coords_.empty())
|
||||
{
|
||||
fileName dataFile(base + ".***." + valueName);
|
||||
|
||||
os.setf(ios_base::left);
|
||||
os << ensightPTraits<Type>::typeName
|
||||
<< " per node: 1 "
|
||||
<< setw(15) << valueName
|
||||
<< " " << dataFile.name().c_str()
|
||||
<< nl;
|
||||
return fileName::null;
|
||||
}
|
||||
os << nl
|
||||
<< "TIME" << nl
|
||||
<< "time set: 1" << nl
|
||||
<< "number of steps: 1" << nl
|
||||
<< "filename start number: 0" << nl
|
||||
<< "filename increment: 1" << nl
|
||||
<< "time values:" << nl
|
||||
<< "0.00000e+00" << nl;
|
||||
|
||||
// Write .mesh file
|
||||
if (coords_.size() != fieldValues.size())
|
||||
{
|
||||
string desc("Written by OpenFOAM");
|
||||
OFstream os(meshFile);
|
||||
os.setf(ios_base::scientific, ios_base::floatfield);
|
||||
os.precision(5);
|
||||
os << "Ensight Geometry File" << nl
|
||||
<< desc.c_str() << nl
|
||||
<< "node id assign" << nl
|
||||
<< "element id assign" << nl;
|
||||
|
||||
forAll(tracks, tracki)
|
||||
{
|
||||
const coordSet& points = tracks[tracki];
|
||||
|
||||
os << "part" << nl
|
||||
<< setw(10) << tracki+1 << nl
|
||||
<< "internalMesh" << nl
|
||||
<< "coordinates" << nl
|
||||
<< setw(10) << points.size() << nl;
|
||||
|
||||
for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt)
|
||||
{
|
||||
for (const point& p : points)
|
||||
{
|
||||
const float comp = narrowFloat(p[cmpt]);
|
||||
os << setw(12) << comp << nl;
|
||||
}
|
||||
}
|
||||
|
||||
if (writeTracks)
|
||||
{
|
||||
os << "bar2" << nl
|
||||
<< setw(10) << points.size()-1 << nl;
|
||||
for (label i = 0; i < points.size()-1; i++)
|
||||
{
|
||||
os << setw(10) << i+1
|
||||
<< setw(10) << i+2
|
||||
<< nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
FatalErrorInFunction
|
||||
<< "Attempted to write field: " << fieldName
|
||||
<< " (" << fieldValues.size() << " entries) for "
|
||||
<< coords_.size() << " sets" << nl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
UPtrList<const Field<Type>> fieldPtrs(repackageFields(fieldValues));
|
||||
|
||||
// Write data files
|
||||
forAll(valueSetNames, seti)
|
||||
if (collateTimes_)
|
||||
{
|
||||
const word& valueName = valueSetNames[seti];
|
||||
const List<Field<Type>>& fieldVals = valueSets[seti];
|
||||
|
||||
fileName dataFile(base + ".000." + valueName);
|
||||
OFstream os(dataFile);
|
||||
os.setf(ios_base::scientific, ios_base::floatfield);
|
||||
os.precision(5);
|
||||
{
|
||||
os << ensightPTraits<Type>::typeName << nl;
|
||||
|
||||
forAll(fieldVals, tracki)
|
||||
{
|
||||
const Field<Type>& fld = fieldVals[tracki];
|
||||
|
||||
os << "part" << nl
|
||||
<< setw(10) << tracki+1 << nl
|
||||
<< "coordinates" << nl;
|
||||
|
||||
for (direction d=0; d < pTraits<Type>::nComponents; ++d)
|
||||
{
|
||||
const direction cmpt =
|
||||
ensightPTraits<Type>::componentOrder[d];
|
||||
|
||||
for (const Type& val : fld)
|
||||
{
|
||||
const float comp = narrowFloat(component(val, cmpt));
|
||||
os << setw(12) << comp << nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return writeCollated
|
||||
(
|
||||
fieldName,
|
||||
fieldPtrs,
|
||||
elemOutputType::WRITE_LINES
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
return writeUncollated
|
||||
(
|
||||
fieldName,
|
||||
fieldPtrs,
|
||||
elemOutputType::WRITE_LINES
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Field writing methods
|
||||
defineCoordSetWriterWriteFields(Foam::coordSetWriters::ensightWriter);
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
220
src/meshTools/coordSet/writers/ensight/ensightCoordSetWriter.H
Normal file
220
src/meshTools/coordSet/writers/ensight/ensightCoordSetWriter.H
Normal file
@ -0,0 +1,220 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2021-2022 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/>.
|
||||
|
||||
Class
|
||||
Foam::coordSetWriters::ensightCoordSetWriter
|
||||
|
||||
Description
|
||||
A coordSetWriter for Ensight format.
|
||||
|
||||
\verbatim
|
||||
formatOptions
|
||||
{
|
||||
ensight
|
||||
{
|
||||
format ascii;
|
||||
collateTimes true;
|
||||
}
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
Format options:
|
||||
\table
|
||||
Property | Description | Required | Default
|
||||
format | ascii/binary | no | ascii
|
||||
collateTimes | use common geometry for times | no | true
|
||||
\endtable
|
||||
|
||||
SourceFiles
|
||||
ensightCoordSetWriter.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_coordSetWriters_ensightWriter_H
|
||||
#define Foam_coordSetWriters_ensightWriter_H
|
||||
|
||||
#include "coordSetWriter.H"
|
||||
#include "ensightWriterCaching.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward Declarations
|
||||
class ensightGeoFile;
|
||||
|
||||
namespace coordSetWriters
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class ensightWriter Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class ensightWriter
|
||||
:
|
||||
public coordSetWriter
|
||||
{
|
||||
// Data Types
|
||||
|
||||
//- Types of element output
|
||||
enum elemOutputType
|
||||
{
|
||||
NO_ELEMENTS = 0,
|
||||
WRITE_POINTS = 1,
|
||||
WRITE_LINES = 2
|
||||
};
|
||||
|
||||
|
||||
// Private Data
|
||||
|
||||
//- Output format option (default: IOstream::ASCII)
|
||||
IOstreamOption::streamFormat writeFormat_;
|
||||
|
||||
//- Collate times (default: true)
|
||||
bool collateTimes_;
|
||||
|
||||
//- Cached information for times, geometry, fields (collated)
|
||||
ensightOutput::writerCaching caching_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Write geometry
|
||||
void writeGeometry
|
||||
(
|
||||
ensightGeoFile& os,
|
||||
elemOutputType elemOutput
|
||||
) const;
|
||||
|
||||
//- Write geometry
|
||||
fileName writeCollated(const bool writeTracks);
|
||||
|
||||
//- Write geometry
|
||||
fileName writeUncollated(const bool writeTracks);
|
||||
|
||||
//- Templated write operation - one file per timestep
|
||||
template<class Type>
|
||||
fileName writeCollated
|
||||
(
|
||||
const word& fieldName,
|
||||
const UPtrList<const Field<Type>>& fieldPtrs,
|
||||
elemOutputType elemOutput
|
||||
);
|
||||
|
||||
//- Templated write operation - all time steps in single file
|
||||
template<class Type>
|
||||
fileName writeUncollated
|
||||
(
|
||||
const word& fieldName,
|
||||
const UPtrList<const Field<Type>>& fieldPtrs,
|
||||
elemOutputType elemOutput
|
||||
);
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const Field<Type>& values
|
||||
);
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const List<Field<Type>>& fieldValues
|
||||
);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information (no debug)
|
||||
TypeNameNoDebug("ensight");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
ensightWriter();
|
||||
|
||||
//- Default construct with specified options
|
||||
explicit ensightWriter(const dictionary& options);
|
||||
|
||||
//- Construct from components
|
||||
ensightWriter
|
||||
(
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
//- Construct from components
|
||||
ensightWriter
|
||||
(
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
|
||||
//- Destructor. Calls close()
|
||||
virtual ~ensightWriter();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Finish output, clears output times.
|
||||
// Later reuse will rebuild times from fieldsDict file cache.
|
||||
virtual void close(bool force = false); // override
|
||||
|
||||
|
||||
// Write
|
||||
|
||||
//- Expected (characteristic) output file name - information only
|
||||
// \warning incorrect for uncollated output!
|
||||
virtual fileName path() const; // override
|
||||
|
||||
declareCoordSetWriterWriteMethod(label);
|
||||
declareCoordSetWriterWriteMethod(scalar);
|
||||
declareCoordSetWriterWriteMethod(vector);
|
||||
declareCoordSetWriterWriteMethod(sphericalTensor);
|
||||
declareCoordSetWriterWriteMethod(symmTensor);
|
||||
declareCoordSetWriterWriteMethod(tensor);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace coordSetWriters
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,280 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::fileName Foam::coordSetWriters::ensightWriter::writeCollated
|
||||
(
|
||||
const bool writeTracks
|
||||
)
|
||||
{
|
||||
// Collated?
|
||||
// ========
|
||||
// CaseFile: rootdir/NAME/NAME.case
|
||||
// Geometry: rootdir/NAME/NAME.mesh
|
||||
|
||||
wroteGeom_ = true;
|
||||
return fileName::null;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::coordSetWriters::ensightWriter::writeCollated
|
||||
(
|
||||
const word& fieldName,
|
||||
const UPtrList<const Field<Type>>& fieldPtrs,
|
||||
elemOutputType elemOutput
|
||||
)
|
||||
{
|
||||
// Geometry changed since last output? Capture now
|
||||
const bool geomChanged = (!upToDate_);
|
||||
|
||||
checkOpen();
|
||||
|
||||
const ensight::FileName baseName(outputPath_.name());
|
||||
const ensight::VarName varName(fieldName);
|
||||
|
||||
|
||||
// Collated
|
||||
// ========
|
||||
// CaseFile: rootdir/NAME/NAME.case
|
||||
// Geometry: rootdir/NAME/data/<index>/geometry
|
||||
// Field: rootdir/NAME/data/<index>/field
|
||||
|
||||
// Use geometry name as sub-directory for results. Eg,
|
||||
// - NAME1/NAME1.case
|
||||
// - NAME1/data/00000000/geometry
|
||||
// - NAME1/data/00000000/VAR1
|
||||
// - NAME1/data/00000000/VAR2
|
||||
|
||||
// Names "data" and "geometry" as per ensightCase:
|
||||
const char* fmt = "%08d";
|
||||
const char* mask = "data/********/";
|
||||
|
||||
// Ignore the useTimeDir setting - manage ourselves
|
||||
const fileName baseDir = outputPath_;
|
||||
|
||||
const word timeDir = timeName();
|
||||
const scalar timeValue = currTime_.value();
|
||||
|
||||
const fileName outputFile = baseDir / baseName + ".case";
|
||||
|
||||
if (verbose_)
|
||||
{
|
||||
Info<< "Writing case file to " << outputFile << endl;
|
||||
}
|
||||
|
||||
// Update geometry
|
||||
merge();
|
||||
|
||||
{
|
||||
if (!isDir(outputFile.path()))
|
||||
{
|
||||
mkDir(outputFile.path());
|
||||
}
|
||||
|
||||
const bool stateChanged =
|
||||
caching_.update
|
||||
(
|
||||
baseDir,
|
||||
timeValue,
|
||||
geomChanged,
|
||||
fieldName,
|
||||
ensightPTraits<Type>::typeName,
|
||||
varName
|
||||
);
|
||||
|
||||
|
||||
// The most current time and geometry indices
|
||||
const label timeIndex = caching_.latestTimeIndex();
|
||||
const label geomIndex = caching_.latestGeomIndex();
|
||||
|
||||
|
||||
// This will be used for the name of a static geometry,
|
||||
// or just the masking part for moving geometries.
|
||||
const fileName geometryName
|
||||
(
|
||||
"data"/word::printf(fmt, geomIndex)/ensightCase::geometryName
|
||||
);
|
||||
|
||||
|
||||
// Do case file
|
||||
if (stateChanged)
|
||||
{
|
||||
OFstream osCase(outputFile, IOstream::ASCII);
|
||||
|
||||
// Format options
|
||||
osCase.setf(ios_base::left);
|
||||
osCase.setf(ios_base::scientific, ios_base::floatfield);
|
||||
osCase.precision(5);
|
||||
|
||||
if (verbose_)
|
||||
{
|
||||
Info<< "Writing case file to " << osCase.name() << endl;
|
||||
}
|
||||
|
||||
|
||||
// The geometry can be any of the following:
|
||||
// 0: constant/static
|
||||
// 1: moving, with the same frequency as the data
|
||||
// 2: moving, with different frequency as the data
|
||||
|
||||
const label tsGeom = caching_.geometryTimeset();
|
||||
|
||||
osCase
|
||||
<< "FORMAT" << nl
|
||||
<< "type: ensight gold" << nl
|
||||
<< nl
|
||||
<< "GEOMETRY" << nl;
|
||||
|
||||
if (tsGeom)
|
||||
{
|
||||
// moving
|
||||
osCase
|
||||
<< "model: " << tsGeom << " " // time-set (1|2)
|
||||
<< mask << geometryName.name() << nl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// steady
|
||||
osCase
|
||||
<< "model: "
|
||||
<< geometryName.c_str() << nl;
|
||||
}
|
||||
|
||||
osCase
|
||||
<< nl
|
||||
<< "VARIABLE" << nl;
|
||||
|
||||
|
||||
for (const entry& dEntry : caching_.fieldsDict())
|
||||
{
|
||||
const dictionary& subDict = dEntry.dict();
|
||||
|
||||
const word varType(subDict.get<word>("type"));
|
||||
const word varName
|
||||
(
|
||||
subDict.getOrDefault<word>
|
||||
(
|
||||
"name",
|
||||
dEntry.keyword() // fieldName as fallback
|
||||
)
|
||||
);
|
||||
|
||||
osCase
|
||||
<< varType
|
||||
<<
|
||||
(
|
||||
true // this->isPointData()
|
||||
? " per node: 1 " // time-set 1
|
||||
: " per element: 1 " // time-set 1
|
||||
)
|
||||
<< setw(15) << varName << ' '
|
||||
<< mask << varName << nl;
|
||||
}
|
||||
|
||||
osCase
|
||||
<< nl
|
||||
<< "TIME" << nl;
|
||||
|
||||
ensightCase::printTimeset(osCase, 1, caching_.times());
|
||||
if (tsGeom == 2)
|
||||
{
|
||||
ensightCase::printTimeset
|
||||
(
|
||||
osCase,
|
||||
tsGeom,
|
||||
caching_.times(),
|
||||
caching_.geometries()
|
||||
);
|
||||
}
|
||||
|
||||
osCase << "# end" << nl;
|
||||
}
|
||||
|
||||
|
||||
// Location for data (and possibly the geometry as well)
|
||||
fileName dataDir = baseDir/"data"/word::printf(fmt, timeIndex);
|
||||
|
||||
// As per mkdir -p "data/00000000"
|
||||
mkDir(dataDir);
|
||||
|
||||
|
||||
const fileName geomFile(baseDir/geometryName);
|
||||
|
||||
if (!exists(geomFile))
|
||||
{
|
||||
if (verbose_)
|
||||
{
|
||||
Info<< "Writing geometry to " << geomFile.name() << endl;
|
||||
}
|
||||
|
||||
// Two-argument form for path-name to avoid validating base-dir
|
||||
ensightGeoFile osGeom
|
||||
(
|
||||
geomFile.path(),
|
||||
geomFile.name(),
|
||||
writeFormat_
|
||||
);
|
||||
|
||||
writeGeometry(osGeom, elemOutput);
|
||||
}
|
||||
|
||||
|
||||
// Write field
|
||||
ensightFile osField
|
||||
(
|
||||
dataDir,
|
||||
varName,
|
||||
writeFormat_
|
||||
);
|
||||
|
||||
if (verbose_)
|
||||
{
|
||||
Info<< "Writing field file to " << osField.name() << endl;
|
||||
}
|
||||
|
||||
|
||||
// Write field (serial only)
|
||||
writeTrackField<Type>(osField, fieldPtrs);
|
||||
|
||||
|
||||
// Timestamp in the directory for future reference
|
||||
{
|
||||
OFstream timeStamp(dataDir/"time");
|
||||
timeStamp
|
||||
<< "# timestep time" << nl
|
||||
<< dataDir.name() << ' ' << timeValue << nl;
|
||||
}
|
||||
}
|
||||
|
||||
wroteGeom_ = true;
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,158 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::fileName Foam::coordSetWriters::ensightWriter::writeUncollated
|
||||
(
|
||||
const bool writeTracks
|
||||
)
|
||||
{
|
||||
return fileName::null;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::coordSetWriters::ensightWriter::writeUncollated
|
||||
(
|
||||
const word& fieldName,
|
||||
const UPtrList<const Field<Type>>& fieldPtrs,
|
||||
elemOutputType elemOutput
|
||||
)
|
||||
{
|
||||
checkOpen();
|
||||
|
||||
const ensight::FileName baseName(outputPath_.name());
|
||||
const ensight::VarName varName(fieldName);
|
||||
|
||||
|
||||
// Uncollated
|
||||
// ==========
|
||||
// CaseFile: rootdir/time/<field>/NAME.case
|
||||
// Geometry: rootdir/time/<field>/NAME.<index>.mesh
|
||||
// Field: rootdir/time/<field>/NAME.<index>.<field>
|
||||
|
||||
// Variable name as sub-directory for results. Eg,
|
||||
// - VAR1/NAME1.case
|
||||
// - VAR1/NAME1.00000000.mesh
|
||||
// - VAR1/NAME1.00000001.VAR1
|
||||
// and
|
||||
// - VAR2/NAME1.case
|
||||
// - VAR2/NAME1.00000000.mesh
|
||||
// - VAR2/NAME1.00000001.VAR2
|
||||
|
||||
|
||||
fileName outputDir;
|
||||
if (useTimeDir() && !timeName().empty())
|
||||
{
|
||||
// Splice in time-directory
|
||||
outputDir = outputPath_.path() / timeName();
|
||||
}
|
||||
else
|
||||
{
|
||||
outputDir = outputPath_.path();
|
||||
}
|
||||
|
||||
const fileName baseDir = outputDir / varName;
|
||||
const word timeDir = timeName();
|
||||
const scalar timeValue = currTime_.value();
|
||||
|
||||
const fileName outputFile = baseDir / baseName + ".case";
|
||||
|
||||
if (verbose_)
|
||||
{
|
||||
Info<< "Writing case file to " << outputFile << endl;
|
||||
}
|
||||
|
||||
merge();
|
||||
|
||||
|
||||
{
|
||||
if (!isDir(outputFile.path()))
|
||||
{
|
||||
mkDir(outputFile.path());
|
||||
}
|
||||
|
||||
OFstream osCase(outputFile, IOstream::ASCII);
|
||||
|
||||
// Format options
|
||||
osCase.setf(ios_base::left);
|
||||
osCase.setf(ios_base::scientific, ios_base::floatfield);
|
||||
osCase.precision(5);
|
||||
|
||||
// Two-argument form for path-name to avoid validating base-dir
|
||||
ensightGeoFile osGeom
|
||||
(
|
||||
baseDir,
|
||||
baseName + ".00000000.mesh",
|
||||
writeFormat_
|
||||
);
|
||||
ensightFile osField
|
||||
(
|
||||
baseDir,
|
||||
baseName + ".00000000." + varName,
|
||||
writeFormat_
|
||||
);
|
||||
|
||||
osCase
|
||||
<< "FORMAT" << nl
|
||||
<< "type: ensight gold" << nl
|
||||
<< nl
|
||||
<< "GEOMETRY" << nl
|
||||
<< "model: 1 " << osGeom.name().name() << nl
|
||||
<< nl
|
||||
<< "VARIABLE" << nl
|
||||
<< ensightPTraits<Type>::typeName
|
||||
<<
|
||||
(
|
||||
true // this->isPointData()
|
||||
? " per node: 1 " // time-set 1
|
||||
: " per element: 1 " // time-set 1
|
||||
)
|
||||
<< setw(15) << varName << ' '
|
||||
<< baseName.c_str() << ".********." << varName << nl;
|
||||
|
||||
osCase
|
||||
<< nl
|
||||
<< "TIME" << nl;
|
||||
|
||||
ensightCase::printTimeset(osCase, 1, timeValue);
|
||||
osCase << "# end" << nl;
|
||||
|
||||
|
||||
writeGeometry(osGeom, elemOutput);
|
||||
|
||||
// Write field (serial only)
|
||||
writeTrackField<Type>(osField, fieldPtrs);
|
||||
}
|
||||
|
||||
wroteGeom_ = true;
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,118 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2021 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/>.
|
||||
|
||||
Class
|
||||
Foam::ensightSetWriter
|
||||
|
||||
Description
|
||||
|
||||
SourceFiles
|
||||
ensightCoordSetWriter.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_coordSetWriters_ensightWriter_H
|
||||
#define Foam_coordSetWriters_ensightWriter_H
|
||||
|
||||
#include "writer.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class ensightSetWriter Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Type>
|
||||
class ensightSetWriter
|
||||
:
|
||||
public writer<Type>
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("ensight");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
ensightSetWriter();
|
||||
|
||||
//- Construct with dictionary
|
||||
explicit ensightSetWriter(const dictionary& dict);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~ensightSetWriter() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
virtual fileName getFileName
|
||||
(
|
||||
const coordSet&,
|
||||
const wordList&
|
||||
) const;
|
||||
|
||||
virtual void write
|
||||
(
|
||||
const coordSet&,
|
||||
const wordList&,
|
||||
const List<const Field<Type>*>&,
|
||||
Ostream&
|
||||
) const;
|
||||
|
||||
virtual void write
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream&
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "ensightCoordSetWriter.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,39 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2012 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
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 "ensightSetWriter.H"
|
||||
#include "writers.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
makeSetWriters(ensightSetWriter);
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -25,19 +25,30 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "gltfSetWriter.H"
|
||||
#include "gltfCoordSetWriter.H"
|
||||
#include "coordSet.H"
|
||||
#include "fileName.H"
|
||||
#include "OFstream.H"
|
||||
#include "floatVector.H"
|
||||
#include "OSspecific.H"
|
||||
#include "foamGltfScene.H"
|
||||
#include "foamGltfSceneWriter.H"
|
||||
#include "coordSetWriterMethods.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
const Foam::Enum<typename Foam::gltfSetWriter<Type>::fieldOption>
|
||||
Foam::gltfSetWriter<Type>::fieldOptionNames_
|
||||
namespace Foam
|
||||
{
|
||||
namespace coordSetWriters
|
||||
{
|
||||
defineTypeName(gltfWriter);
|
||||
addToRunTimeSelectionTable(coordSetWriter, gltfWriter, word);
|
||||
addToRunTimeSelectionTable(coordSetWriter, gltfWriter, wordDict);
|
||||
}
|
||||
}
|
||||
|
||||
const Foam::Enum<Foam::coordSetWriters::gltfWriter::fieldOption>
|
||||
Foam::coordSetWriters::gltfWriter::fieldOptionNames_
|
||||
({
|
||||
// No naming for NONE
|
||||
{ fieldOption::UNIFORM, "uniform" },
|
||||
@ -45,10 +56,90 @@ Foam::gltfSetWriter<Type>::fieldOptionNames_
|
||||
});
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
template<class Type>
|
||||
Foam::word Foam::gltfSetWriter<Type>::getColourMap
|
||||
static tmp<vectorField> getBoundedColours
|
||||
(
|
||||
const colourTable& colours,
|
||||
const Field<Type>& field,
|
||||
const scalar boundMin,
|
||||
const scalar boundMax
|
||||
)
|
||||
{
|
||||
const label boundDelta = (boundMax - boundMin + ROOTVSMALL);
|
||||
|
||||
auto tresult = tmp<vectorField>::New(field.size());
|
||||
auto& result = tresult.ref();
|
||||
|
||||
forAll(field, i)
|
||||
{
|
||||
const Type& val = field[i];
|
||||
|
||||
const scalar f =
|
||||
(
|
||||
pTraits<Type>::nComponents == 1
|
||||
? scalar(component(val, 0))
|
||||
: scalar(mag(val))
|
||||
);
|
||||
|
||||
// 0-1 clipped by value()
|
||||
result[i] = colours.value((f - boundMin)/boundDelta);
|
||||
}
|
||||
|
||||
return tresult;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
static vector getAnimationColour
|
||||
(
|
||||
const dictionary& dict,
|
||||
const colourTable& colours,
|
||||
const Field<Type>& field
|
||||
)
|
||||
{
|
||||
scalar refValue(0);
|
||||
scalarMinMax valLimits;
|
||||
|
||||
if (pTraits<Type>::nComponents == 1)
|
||||
{
|
||||
MinMax<Type> scanned(minMax(field));
|
||||
|
||||
refValue = scalar(component(field[0], 0));
|
||||
valLimits.min() = scalar(component(scanned.min(), 0));
|
||||
valLimits.max() = scalar(component(scanned.max(), 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use mag() for multiple components
|
||||
refValue = mag(field[0]);
|
||||
valLimits = minMaxMag(field);
|
||||
}
|
||||
|
||||
dict.readIfPresent("min", valLimits.min());
|
||||
dict.readIfPresent("max", valLimits.max());
|
||||
|
||||
const scalar fraction =
|
||||
(
|
||||
(refValue - valLimits.min())
|
||||
/ (valLimits.max() - valLimits.min() + ROOTVSMALL)
|
||||
);
|
||||
|
||||
// 0-1 clipped by value()
|
||||
return colours.value(fraction);
|
||||
}
|
||||
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::word Foam::coordSetWriters::gltfWriter::getColourMap
|
||||
(
|
||||
const dictionary& dict
|
||||
) const
|
||||
@ -60,8 +151,7 @@ Foam::word Foam::gltfSetWriter<Type>::getColourMap
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
const Foam::colourTable& Foam::gltfSetWriter<Type>::getColourTable
|
||||
const Foam::colourTable& Foam::coordSetWriters::gltfWriter::getColourTable
|
||||
(
|
||||
const dictionary& dict
|
||||
) const
|
||||
@ -70,8 +160,7 @@ const Foam::colourTable& Foam::gltfSetWriter<Type>::getColourTable
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::scalarMinMax Foam::gltfSetWriter<Type>::getFieldLimits
|
||||
Foam::scalarMinMax Foam::coordSetWriters::gltfWriter::getFieldLimits
|
||||
(
|
||||
const word& fieldName
|
||||
) const
|
||||
@ -87,8 +176,8 @@ Foam::scalarMinMax Foam::gltfSetWriter<Type>::getFieldLimits
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::scalarField> Foam::gltfSetWriter<Type>::getAlphaField
|
||||
Foam::tmp<Foam::scalarField>
|
||||
Foam::coordSetWriters::gltfWriter::getAlphaField
|
||||
(
|
||||
const dictionary& dict
|
||||
) const
|
||||
@ -141,27 +230,10 @@ Foam::tmp<Foam::scalarField> Foam::gltfSetWriter<Type>::getAlphaField
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::vector Foam::gltfSetWriter<Type>::getTrackAnimationColour
|
||||
(
|
||||
const colourTable& colours,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
const label tracki
|
||||
) const
|
||||
void Foam::coordSetWriters::gltfWriter::setupAnimationColour()
|
||||
{
|
||||
if (!colour_)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Attempting to get colour when colour option is off"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
const dictionary& dict = animationDict_;
|
||||
|
||||
// Fallback value
|
||||
vector colourValue(Zero);
|
||||
|
||||
const entry* eptr = dict.findEntry("colour", keyType::LITERAL);
|
||||
|
||||
if (!eptr || !eptr->isStream())
|
||||
@ -175,8 +247,11 @@ Foam::vector Foam::gltfSetWriter<Type>::getTrackAnimationColour
|
||||
// Value specified
|
||||
|
||||
ITstream& is = eptr->stream();
|
||||
is >> colourValue;
|
||||
is >> animateColourValue_;
|
||||
dict.checkITstream(is, "colour");
|
||||
|
||||
// Has uniform value
|
||||
animateColourOption_ = fieldOption::UNIFORM;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -188,85 +263,59 @@ Foam::vector Foam::gltfSetWriter<Type>::getTrackAnimationColour
|
||||
{
|
||||
case fieldOption::NONE:
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot select 'none' for colour entry!" << nl
|
||||
<< "... possible programming error"
|
||||
<< exit(FatalError);
|
||||
break;
|
||||
}
|
||||
case fieldOption::UNIFORM:
|
||||
{
|
||||
dict.readEntry("colourValue", colourValue);
|
||||
dict.readEntry("colourValue", animateColourValue_);
|
||||
|
||||
// Has uniform value
|
||||
animateColourOption_ = fieldOption::UNIFORM;
|
||||
break;
|
||||
}
|
||||
case fieldOption::FIELD:
|
||||
{
|
||||
const word fieldName = dict.get<word>("colourField");
|
||||
const label fieldi = valueSetNames.find(fieldName);
|
||||
if (fieldi == -1)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Unable to find field " << fieldName
|
||||
<< ". Valid field names are:" << valueSetNames
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
const Field<Type>& colourFld = valueSets[fieldi][tracki];
|
||||
|
||||
|
||||
scalar refValue(0);
|
||||
scalarMinMax valLimits;
|
||||
|
||||
if (pTraits<Type>::nComponents == 1)
|
||||
{
|
||||
MinMax<Type> scanned(minMax(colourFld));
|
||||
|
||||
refValue = scalar(component(colourFld[0], 0));
|
||||
valLimits.min() = scalar(component(scanned.min(), 0));
|
||||
valLimits.max() = scalar(component(scanned.max(), 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use mag() for multiple components
|
||||
refValue = mag(colourFld[0]);
|
||||
valLimits = minMaxMag(colourFld);
|
||||
}
|
||||
|
||||
dict.readIfPresent("min", valLimits.min());
|
||||
dict.readIfPresent("max", valLimits.max());
|
||||
|
||||
const scalar fraction =
|
||||
(
|
||||
(refValue - valLimits.min())
|
||||
/ (valLimits.max() - valLimits.min() + ROOTVSMALL)
|
||||
);
|
||||
|
||||
return colours.value(fraction); // 0-1 clipped by value()
|
||||
// Needs named field...
|
||||
animateColourName_ = dict.get<word>("colourField");
|
||||
animateColourOption_ = fieldOption::FIELD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return colourValue;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::gltfSetWriter<Type>::gltfSetWriter()
|
||||
Foam::coordSetWriters::gltfWriter::gltfWriter()
|
||||
:
|
||||
writer<Type>(),
|
||||
coordSetWriter(),
|
||||
writer_(nullptr),
|
||||
animate_(false),
|
||||
colour_(false),
|
||||
animateColourOption_(fieldOption::NONE),
|
||||
animateColourName_(),
|
||||
animateColourValue_(Zero),
|
||||
fieldInfoDict_(),
|
||||
animationDict_()
|
||||
{}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::gltfSetWriter<Type>::gltfSetWriter(const dictionary& dict)
|
||||
Foam::coordSetWriters::gltfWriter::gltfWriter(const dictionary& options)
|
||||
:
|
||||
writer<Type>(dict),
|
||||
animate_(dict.getOrDefault("animate", false)),
|
||||
colour_(dict.getOrDefault("colour", false)),
|
||||
fieldInfoDict_(dict.subOrEmptyDict("fieldInfo")),
|
||||
animationDict_(dict.subOrEmptyDict("animationInfo"))
|
||||
coordSetWriter(options),
|
||||
writer_(nullptr),
|
||||
animate_(options.getOrDefault("animate", false)),
|
||||
colour_(options.getOrDefault("colour", false)),
|
||||
animateColourOption_(fieldOption::NONE),
|
||||
animateColourName_(),
|
||||
animateColourValue_(Zero),
|
||||
fieldInfoDict_(options.subOrEmptyDict("fieldInfo")),
|
||||
animationDict_(options.subOrEmptyDict("animationInfo"))
|
||||
{
|
||||
// fieldInfo
|
||||
// {
|
||||
@ -281,50 +330,139 @@ Foam::gltfSetWriter<Type>::gltfSetWriter(const dictionary& dict)
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::gltfSetWriter<Type>::getFileName
|
||||
Foam::coordSetWriters::gltfWriter::gltfWriter
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSetNames
|
||||
) const
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
gltfWriter(options)
|
||||
{
|
||||
return this->getBaseName(points, valueSetNames) + ".gltf";
|
||||
open(coords, outputPath);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::gltfSetWriter<Type>::write
|
||||
Foam::coordSetWriters::gltfWriter::gltfWriter
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSetNames,
|
||||
const List<const Field<Type>*>& valueSets,
|
||||
Ostream& os
|
||||
) const
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
gltfWriter(options)
|
||||
{
|
||||
if (valueSets.size() != valueSetNames.size())
|
||||
open(tracks, outputPath);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::coordSetWriters::gltfWriter::~gltfWriter()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::fileName Foam::coordSetWriters::gltfWriter::path() const
|
||||
{
|
||||
// 1) rootdir/<TIME>/setName.gltf
|
||||
// 2) rootdir/setName.gltf
|
||||
|
||||
return getExpectedPath("gltf");
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriters::gltfWriter::close(bool force)
|
||||
{
|
||||
writer_.reset(nullptr);
|
||||
coordSetWriter::close(force);
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriters::gltfWriter::beginTime(const Time& t)
|
||||
{
|
||||
writer_.reset(nullptr);
|
||||
coordSetWriter::beginTime(t);
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriters::gltfWriter::beginTime(const instant& inst)
|
||||
{
|
||||
writer_.reset(nullptr);
|
||||
coordSetWriter::beginTime(inst);
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriters::gltfWriter::endTime()
|
||||
{
|
||||
writer_.reset(nullptr);
|
||||
coordSetWriter::endTime();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Implementation * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::coordSetWriters::gltfWriter::writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const UPtrList<const Field<Type>>& fieldPtrs
|
||||
)
|
||||
{
|
||||
if (coords_.size() != fieldPtrs.size())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Number of variables:" << valueSetNames.size() << endl
|
||||
<< "Number of valueSets:" << valueSets.size()
|
||||
<< "Attempted to write field: " << fieldName
|
||||
<< " (" << fieldPtrs.size() << " entries) for "
|
||||
<< coords_.size() << " sets" << nl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
glTF::scene scene;
|
||||
const label meshi = scene.addMesh(points, "points");
|
||||
forAll(valueSetNames, i)
|
||||
const auto& tracks = coords_;
|
||||
|
||||
// const auto& times = trackTimes_;
|
||||
|
||||
if (!writer_)
|
||||
{
|
||||
scene.addFieldToMesh(*valueSets[i], valueSetNames[i], meshi);
|
||||
// Field:
|
||||
// 1) rootdir/<TIME>/setName.gltf
|
||||
// 2) rootdir/setName.gltf
|
||||
|
||||
fileName outputFile = path();
|
||||
|
||||
writer_.reset(new glTF::sceneWriter(outputFile));
|
||||
|
||||
auto& scene = writer_->getScene();
|
||||
|
||||
meshes_.resize(tracks.size());
|
||||
|
||||
forAll(tracks, tracki)
|
||||
{
|
||||
word meshName("track:" + Foam::name(tracki));
|
||||
if (tracks.size() == 1)
|
||||
{
|
||||
meshName = "points";
|
||||
}
|
||||
|
||||
meshes_[tracki] = scene.addMesh(tracks[tracki], meshName);
|
||||
}
|
||||
}
|
||||
|
||||
if (colour_)
|
||||
{
|
||||
forAll(valueSets, fieldi)
|
||||
{
|
||||
const auto& field = *valueSets[fieldi];
|
||||
const word& fieldName = valueSetNames[fieldi];
|
||||
|
||||
auto& scene = writer_->getScene();
|
||||
|
||||
forAll(tracks, tracki)
|
||||
{
|
||||
const label meshi = meshes_[tracki];
|
||||
const auto& field = fieldPtrs[tracki];
|
||||
|
||||
scene.addFieldToMesh(field, fieldName, meshi);
|
||||
|
||||
if (colour_)
|
||||
{
|
||||
const dictionary dict = fieldInfoDict_.subOrEmptyDict(fieldName);
|
||||
const auto& colours = getColourTable(dict);
|
||||
|
||||
@ -333,11 +471,7 @@ void Foam::gltfSetWriter<Type>::write
|
||||
|
||||
const scalarMinMax valLimits = getFieldLimits(fieldName);
|
||||
|
||||
// Generated field colours
|
||||
vectorField fieldColour(field.size());
|
||||
|
||||
scalarMinMax fldLimits;
|
||||
|
||||
if (pTraits<Type>::nComponents == 1)
|
||||
{
|
||||
MinMax<Type> scanned(minMax(field));
|
||||
@ -351,24 +485,17 @@ void Foam::gltfSetWriter<Type>::write
|
||||
fldLimits = minMaxMag(field);
|
||||
}
|
||||
|
||||
const scalar minf = max(fldLimits.min(), valLimits.min());
|
||||
const scalar maxf = min(fldLimits.max(), valLimits.max());
|
||||
const scalar deltaf = (maxf - minf + SMALL);
|
||||
|
||||
forAll(field, i)
|
||||
{
|
||||
const Type& val = field[i];
|
||||
|
||||
const scalar f =
|
||||
// Generated field colours
|
||||
vectorField fieldColour
|
||||
(
|
||||
getBoundedColours
|
||||
(
|
||||
pTraits<Type>::nComponents == 1
|
||||
? scalar(component(val, 0))
|
||||
: scalar(mag(val))
|
||||
);
|
||||
|
||||
// 0-1 clipped by value()
|
||||
fieldColour[i] = colours.value((f - minf)/deltaf);
|
||||
}
|
||||
colours,
|
||||
field,
|
||||
max(fldLimits.min(), valLimits.min()), // boundMin
|
||||
min(fldLimits.max(), valLimits.max()) // boundMax
|
||||
)
|
||||
);
|
||||
|
||||
scene.addColourToMesh
|
||||
(
|
||||
@ -380,226 +507,260 @@ void Foam::gltfSetWriter<Type>::write
|
||||
}
|
||||
}
|
||||
|
||||
scene.write(os);
|
||||
return writer_().path();
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::gltfSetWriter<Type>::write
|
||||
Foam::fileName Foam::coordSetWriters::gltfWriter::writeTemplate_animate
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream& os
|
||||
) const
|
||||
const word& fieldName,
|
||||
const UPtrList<const Field<Type>>& fieldPtrs
|
||||
)
|
||||
{
|
||||
if (valueSets.size() != valueSetNames.size())
|
||||
if (coords_.size() != fieldPtrs.size())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Number of variables:" << valueSetNames.size() << endl
|
||||
<< "Number of valueSets:" << valueSets.size()
|
||||
<< "Attempted to write field: " << fieldName
|
||||
<< " (" << fieldPtrs.size() << " entries) for "
|
||||
<< coords_.size() << " sets" << nl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
if (animate_)
|
||||
{
|
||||
writeAnimateTracks
|
||||
(
|
||||
writeTracks,
|
||||
times,
|
||||
tracks,
|
||||
valueSetNames,
|
||||
valueSets,
|
||||
os
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
writeStaticTracks
|
||||
(
|
||||
writeTracks,
|
||||
times,
|
||||
tracks,
|
||||
valueSetNames,
|
||||
valueSets,
|
||||
os
|
||||
);
|
||||
}
|
||||
}
|
||||
const auto& tracks = this->coords_;
|
||||
const auto& times = this->trackTimes_;
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::gltfSetWriter<Type>::writeStaticTracks
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream& os
|
||||
) const
|
||||
{
|
||||
glTF::scene scene;
|
||||
forAll(tracks, tracki)
|
||||
if (!writer_)
|
||||
{
|
||||
const vectorField& track = tracks[tracki];
|
||||
const label meshi = scene.addMesh(track, "track:" + Foam::name(tracki));
|
||||
forAll(valueSetNames, fieldi)
|
||||
// Field:
|
||||
// 1) rootdir/<TIME>/setName.gltf
|
||||
// 2) rootdir/setName.gltf
|
||||
|
||||
fileName outputFile = path();
|
||||
|
||||
writer_.reset(new glTF::sceneWriter(outputFile));
|
||||
|
||||
auto& scene = writer_->getScene();
|
||||
|
||||
meshes_.resize(tracks.size());
|
||||
|
||||
const label animationi = scene.createAnimation("animation");
|
||||
|
||||
forAll(tracks, tracki)
|
||||
{
|
||||
const word& fieldName = valueSetNames[fieldi];
|
||||
const auto& field = valueSets[fieldi][tracki];
|
||||
scene.addFieldToMesh(field, fieldName, meshi);
|
||||
}
|
||||
const auto& track = tracks[tracki];
|
||||
|
||||
if (colour_)
|
||||
{
|
||||
forAll(valueSets, fieldi)
|
||||
if (track.empty())
|
||||
{
|
||||
const auto& field = valueSets[fieldi][tracki];
|
||||
const word& fieldName = valueSetNames[fieldi];
|
||||
|
||||
const dictionary dict =
|
||||
fieldInfoDict_.subOrEmptyDict(fieldName);
|
||||
const auto& colours = getColourTable(dict);
|
||||
|
||||
const auto talpha = getAlphaField(dict);
|
||||
const scalarField& alpha = talpha();
|
||||
|
||||
const scalarMinMax valLimits = getFieldLimits(fieldName);
|
||||
|
||||
|
||||
// Generated field colours
|
||||
vectorField fieldColour(field.size());
|
||||
|
||||
scalarMinMax fldLimits;
|
||||
|
||||
if (pTraits<Type>::nComponents == 1)
|
||||
{
|
||||
MinMax<Type> scanned(minMax(field));
|
||||
|
||||
fldLimits.min() = scalar(component(scanned.min(), 0));
|
||||
fldLimits.max() = scalar(component(scanned.max(), 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use mag() for multiple components
|
||||
fldLimits = minMaxMag(field);
|
||||
}
|
||||
|
||||
const scalar minf = max(fldLimits.min(), valLimits.min());
|
||||
const scalar maxf = min(fldLimits.max(), valLimits.max());
|
||||
const scalar deltaf = (maxf - minf + SMALL);
|
||||
|
||||
forAll(field, i)
|
||||
{
|
||||
const Type& val = field[i];
|
||||
|
||||
const scalar f =
|
||||
(
|
||||
pTraits<Type>::nComponents == 1
|
||||
? scalar(component(val, 0))
|
||||
: scalar(mag(val))
|
||||
);
|
||||
|
||||
// 0-1 clipped by value()
|
||||
fieldColour[i] = colours.value((f - minf)/deltaf);
|
||||
}
|
||||
|
||||
scene.addColourToMesh
|
||||
(
|
||||
fieldColour,
|
||||
"Colour:" + fieldName,
|
||||
meshi,
|
||||
alpha
|
||||
);
|
||||
meshes_[tracki] = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Seed starting position
|
||||
|
||||
meshes_[tracki] =
|
||||
scene.addMesh
|
||||
(
|
||||
vectorField(1, track[0]),
|
||||
"track:" + Foam::name(tracki)
|
||||
);
|
||||
|
||||
const label meshi = meshes_[tracki];
|
||||
|
||||
// Time frames
|
||||
const label timeId =
|
||||
scene.addField(times[tracki], "time:" + Foam::name(tracki));
|
||||
|
||||
// Translations
|
||||
const vectorField translation(track - track[0]);
|
||||
const label translationId =
|
||||
scene.addField(translation, "translation");
|
||||
|
||||
scene.addToAnimation(animationi, timeId, translationId, meshi);
|
||||
}
|
||||
}
|
||||
|
||||
scene.write(os);
|
||||
}
|
||||
|
||||
auto& scene = writer_->getScene();
|
||||
|
||||
template<class Type>
|
||||
void Foam::gltfSetWriter<Type>::writeAnimateTracks
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream& os
|
||||
) const
|
||||
{
|
||||
const auto& colours = getColourTable(animationDict_);
|
||||
|
||||
glTF::scene scene;
|
||||
const label animationi = scene.createAnimation("animation");
|
||||
// Seed starting field values
|
||||
|
||||
forAll(tracks, tracki)
|
||||
{
|
||||
const auto& track = tracks[tracki];
|
||||
const label meshi = meshes_[tracki];
|
||||
const Field<Type>& field = fieldPtrs[tracki];
|
||||
|
||||
if (track.empty())
|
||||
if (track.empty() || meshi < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Seed starting positions and field values
|
||||
const label meshi =
|
||||
scene.addMesh
|
||||
(
|
||||
vectorField(1, track[0]),
|
||||
"track:" + Foam::name(tracki)
|
||||
);
|
||||
// Seed starting field values
|
||||
scene.addFieldToMesh(Field<Type>(1, field[0]), fieldName, meshi);
|
||||
}
|
||||
|
||||
forAll(valueSetNames, fieldi)
|
||||
|
||||
// Note: colours cannot be animated... setting a fixed value.
|
||||
// However, we need to wait until the field is actually seen
|
||||
|
||||
if (colour_)
|
||||
{
|
||||
if (animateColourOption_ == fieldOption::NONE)
|
||||
{
|
||||
const Field<Type>& field = valueSets[fieldi][tracki];
|
||||
const word& fieldName = valueSetNames[fieldi];
|
||||
scene.addFieldToMesh(Field<Type>(1, field[0]), fieldName, meshi);
|
||||
// First time - scan for information
|
||||
setupAnimationColour();
|
||||
}
|
||||
|
||||
// Time frames
|
||||
const label timeId =
|
||||
scene.addField(times[tracki], "time:" + Foam::name(tracki));
|
||||
|
||||
// Translations
|
||||
const vectorField translation(track - track[0]);
|
||||
const label translationId = scene.addField(translation, "translation");
|
||||
|
||||
scene.addToAnimation(animationi, timeId, translationId, meshi);
|
||||
|
||||
// Note: colours cannot be animated... setting a fixed value
|
||||
if (colour_)
|
||||
switch (animateColourOption_)
|
||||
{
|
||||
const vector colour =
|
||||
getTrackAnimationColour
|
||||
case fieldOption::NONE:
|
||||
{
|
||||
// Should not occur
|
||||
break;
|
||||
}
|
||||
case fieldOption::UNIFORM:
|
||||
{
|
||||
// Colour value is known
|
||||
|
||||
vectorField fieldColour(1, animateColourValue_);
|
||||
scalarField alphaChannel(1, 1.0);
|
||||
|
||||
const auto talpha = getAlphaField(animationDict_);
|
||||
|
||||
if (talpha && talpha().size())
|
||||
{
|
||||
alphaChannel[0] = talpha()[0];
|
||||
}
|
||||
|
||||
forAll(tracks, tracki)
|
||||
{
|
||||
const auto& track = tracks[tracki];
|
||||
const label meshi = meshes_[tracki];
|
||||
|
||||
if (track.empty() || meshi < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
scene.addColourToMesh
|
||||
(
|
||||
fieldColour,
|
||||
"Colour:fixed", // ... or "Colour:constant"
|
||||
meshi,
|
||||
alphaChannel
|
||||
);
|
||||
}
|
||||
|
||||
// Mark as done
|
||||
animateColourName_.clear();
|
||||
animateColourOption_ = fieldOption::FIELD;
|
||||
break;
|
||||
}
|
||||
case fieldOption::FIELD:
|
||||
{
|
||||
if
|
||||
(
|
||||
colours,
|
||||
valueSetNames,
|
||||
valueSets,
|
||||
tracki
|
||||
);
|
||||
!animateColourName_.empty()
|
||||
&& animateColourName_ == fieldName
|
||||
)
|
||||
{
|
||||
// This is the desired colour field. Process now
|
||||
|
||||
const auto talpha = getAlphaField(animationDict_);
|
||||
const auto& colours = getColourTable(animationDict_);
|
||||
|
||||
const scalarField& alpha = talpha();
|
||||
vectorField fieldColour(1, Zero);
|
||||
scalarField alphaChannel(1, 1.0);
|
||||
|
||||
scene.addColourToMesh
|
||||
(
|
||||
vectorField(1, colour),
|
||||
"Colour:fixed", // ... or "Colour:constant"
|
||||
meshi,
|
||||
scalarField(1, alpha[0])
|
||||
);
|
||||
const auto talpha = getAlphaField(animationDict_);
|
||||
|
||||
if (talpha && talpha().size())
|
||||
{
|
||||
alphaChannel[0] = talpha()[0];
|
||||
}
|
||||
|
||||
forAll(tracks, tracki)
|
||||
{
|
||||
const auto& track = tracks[tracki];
|
||||
const label meshi = meshes_[tracki];
|
||||
const Field<Type>& field = fieldPtrs[tracki];
|
||||
|
||||
if (track.empty() || meshi < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
fieldColour[0] =
|
||||
getAnimationColour(animationDict_, colours, field);
|
||||
|
||||
scene.addColourToMesh
|
||||
(
|
||||
fieldColour,
|
||||
"Colour:fixed", // ... or "Colour:constant"
|
||||
meshi,
|
||||
alphaChannel
|
||||
);
|
||||
}
|
||||
|
||||
// Mark colouring as done. Avoid retriggering
|
||||
animateColourName_.clear();
|
||||
animateColourOption_ = fieldOption::FIELD;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scene.write(os);
|
||||
return writer_().path();
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::coordSetWriters::gltfWriter::writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const Field<Type>& values
|
||||
)
|
||||
{
|
||||
checkOpen();
|
||||
if (coords_.empty())
|
||||
{
|
||||
return fileName::null;
|
||||
}
|
||||
|
||||
UPtrList<const Field<Type>> fieldPtrs(repackageFields(values));
|
||||
return writeTemplate(fieldName, fieldPtrs);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::coordSetWriters::gltfWriter::writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const List<Field<Type>>& fieldValues
|
||||
)
|
||||
{
|
||||
checkOpen();
|
||||
if (coords_.empty())
|
||||
{
|
||||
return fileName::null;
|
||||
}
|
||||
|
||||
UPtrList<const Field<Type>> fieldPtrs(repackageFields(fieldValues));
|
||||
|
||||
if (animate_ && trackTimes_.size() >= coords_.size())
|
||||
{
|
||||
return writeTemplate_animate(fieldName, fieldPtrs);
|
||||
}
|
||||
|
||||
return writeTemplate(fieldName, fieldPtrs);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Field writing methods
|
||||
defineCoordSetWriterWriteFields(Foam::coordSetWriters::gltfWriter);
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -24,10 +24,11 @@ License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::gltfSetWriter
|
||||
Foam::coordSetWriters::gltfWriter
|
||||
|
||||
Description
|
||||
Writes point data in glTF v2 format
|
||||
A coordSet(s) writer in glTF v2 format, which is particularly
|
||||
useful for writing track data.
|
||||
|
||||
Two files are generated:
|
||||
- filename.bin : a binary file containing all scene entities
|
||||
@ -121,23 +122,25 @@ SourceFiles
|
||||
#ifndef Foam_coordSetWriters_gltfWriter_H
|
||||
#define Foam_coordSetWriters_gltfWriter_H
|
||||
|
||||
#include "writer.H"
|
||||
#include "coordSetWriter.H"
|
||||
#include "colourTable.H"
|
||||
#include "foamGltfFwd.H"
|
||||
#include "MinMax.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace coordSetWriters
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class gltfSetWriter Declaration
|
||||
Class gltfWriter Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Type>
|
||||
class gltfSetWriter
|
||||
class gltfWriter
|
||||
:
|
||||
public writer<Type>
|
||||
public coordSetWriter
|
||||
{
|
||||
public:
|
||||
|
||||
@ -160,18 +163,33 @@ private:
|
||||
|
||||
// Private Data
|
||||
|
||||
//- Backend output
|
||||
autoPtr<glTF::sceneWriter> writer_;
|
||||
|
||||
//- Flag to animate - for particle tracks only
|
||||
bool animate_;
|
||||
|
||||
//- Flag to add field colours
|
||||
bool colour_;
|
||||
|
||||
//- Animation colour option
|
||||
fieldOption animateColourOption_;
|
||||
|
||||
//- Animation colour field name
|
||||
word animateColourName_;
|
||||
|
||||
//- Animation colour value
|
||||
vector animateColourValue_;
|
||||
|
||||
//- Local field information
|
||||
const dictionary fieldInfoDict_;
|
||||
|
||||
//- Animation information
|
||||
const dictionary animationDict_;
|
||||
|
||||
//- The mesh indices in glTF scene
|
||||
labelList meshes_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
@ -184,103 +202,117 @@ private:
|
||||
//- Return the named min/max field limits (from sub-dictionary)
|
||||
scalarMinMax getFieldLimits(const word& fieldName) const;
|
||||
|
||||
//- Setup animation colour or field to search for
|
||||
void setupAnimationColour();
|
||||
|
||||
//- Return the alpha field for mesh values
|
||||
tmp<scalarField> getAlphaField(const dictionary& dict) const;
|
||||
|
||||
//- Return the animation colour when animating tracks
|
||||
vector getTrackAnimationColour
|
||||
|
||||
//- Templated write operation (static tracks)
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const colourTable& colours,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
const label tracki
|
||||
) const;
|
||||
const word& fieldName,
|
||||
const UPtrList<const Field<Type>>& fieldPtrs
|
||||
);
|
||||
|
||||
//- Write animated tracks
|
||||
template<class Type>
|
||||
fileName writeTemplate_animate
|
||||
(
|
||||
const word& fieldName,
|
||||
const UPtrList<const Field<Type>>& fieldPtrs
|
||||
);
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName, //!< Name of field
|
||||
const Field<Type>& vals //!< Local field values to write
|
||||
);
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const List<Field<Type>>& fieldValues
|
||||
);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("gltf");
|
||||
//- Runtime type information (no debug)
|
||||
TypeNameNoDebug("gltf");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
gltfSetWriter();
|
||||
gltfWriter();
|
||||
|
||||
//- Construct from dictionary
|
||||
explicit gltfSetWriter(const dictionary& dict);
|
||||
//- Default construct with specified options
|
||||
explicit gltfWriter(const dictionary& options);
|
||||
|
||||
//- Construct from components
|
||||
gltfWriter
|
||||
(
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
//- Construct from components
|
||||
gltfWriter
|
||||
(
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~gltfSetWriter() = default;
|
||||
//- Destructor. Calls close()
|
||||
virtual ~gltfWriter();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Return the file name
|
||||
virtual fileName getFileName
|
||||
(
|
||||
const coordSet&,
|
||||
const wordList&
|
||||
) const;
|
||||
//- Expected (characteristic) output file name - information only
|
||||
virtual fileName path() const; // override
|
||||
|
||||
//- Write
|
||||
virtual void write
|
||||
(
|
||||
const coordSet&,
|
||||
const wordList&,
|
||||
const List<const Field<Type>*>&,
|
||||
Ostream&
|
||||
) const;
|
||||
//- Close and reset, clears backend.
|
||||
virtual void close(bool force = false); // override
|
||||
|
||||
//- Write tracks (main entry point)
|
||||
virtual void write
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>&,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>&,
|
||||
Ostream&
|
||||
) const;
|
||||
//- Begin time step. Clears existing backend.
|
||||
virtual void beginTime(const Time& t); // override
|
||||
|
||||
//- Write animated tracks
|
||||
virtual void writeAnimateTracks
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream&
|
||||
) const;
|
||||
//- Begin time step. Clears existing backend.
|
||||
virtual void beginTime(const instant& inst); // override
|
||||
|
||||
//- Write static tracks
|
||||
virtual void writeStaticTracks
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream&
|
||||
) const;
|
||||
//- End time step. Clears existing backend.
|
||||
virtual void endTime(); // override
|
||||
|
||||
|
||||
// Write
|
||||
|
||||
declareCoordSetWriterWriteMethod(label);
|
||||
declareCoordSetWriterWriteMethod(scalar);
|
||||
declareCoordSetWriterWriteMethod(vector);
|
||||
declareCoordSetWriterWriteMethod(sphericalTensor);
|
||||
declareCoordSetWriterWriteMethod(symmTensor);
|
||||
declareCoordSetWriterWriteMethod(tensor);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace coordSetWriters
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "gltfCoordSetWriter.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,39 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2021 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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "gltfSetWriter.H"
|
||||
#include "writers.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
makeSetWriters(gltfSetWriter);
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2017-2021 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -26,135 +26,239 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "gnuplotSetWriter.H"
|
||||
#include "gnuplotCoordSetWriter.H"
|
||||
#include "coordSet.H"
|
||||
#include "fileName.H"
|
||||
#include "OFstream.H"
|
||||
#include "OSspecific.H"
|
||||
#include "coordSetWriterMethods.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace coordSetWriters
|
||||
{
|
||||
defineTypeName(gnuplotWriter);
|
||||
addToRunTimeSelectionTable(coordSetWriter, gnuplotWriter, word);
|
||||
addToRunTimeSelectionTable(coordSetWriter, gnuplotWriter, wordDict);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Implementation
|
||||
#include "gnuplotCoordSetWriterImpl.C"
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::gnuplotSetWriter<Type>::gnuplotSetWriter()
|
||||
Foam::coordSetWriters::gnuplotWriter::gnuplotWriter()
|
||||
:
|
||||
writer<Type>()
|
||||
{}
|
||||
coordSetWriter(),
|
||||
streamOpt_(),
|
||||
precision_(IOstream::defaultPrecision())
|
||||
{
|
||||
buffering_ = true;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::gnuplotSetWriter<Type>::gnuplotSetWriter(const dictionary& dict)
|
||||
Foam::coordSetWriters::gnuplotWriter::gnuplotWriter(const dictionary& options)
|
||||
:
|
||||
writer<Type>(dict)
|
||||
{}
|
||||
coordSetWriter(options),
|
||||
streamOpt_
|
||||
(
|
||||
IOstream::ASCII,
|
||||
IOstream::compressionEnum("compression", options)
|
||||
),
|
||||
precision_
|
||||
(
|
||||
options.getOrDefault("precision", IOstream::defaultPrecision())
|
||||
)
|
||||
{
|
||||
buffering_ = options.getOrDefault("buffer", true);
|
||||
}
|
||||
|
||||
|
||||
Foam::coordSetWriters::gnuplotWriter::gnuplotWriter
|
||||
(
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
gnuplotWriter(options)
|
||||
{
|
||||
open(coords, outputPath);
|
||||
}
|
||||
|
||||
|
||||
Foam::coordSetWriters::gnuplotWriter::gnuplotWriter
|
||||
(
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
gnuplotWriter(options)
|
||||
{
|
||||
open(tracks, outputPath);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::coordSetWriters::gnuplotWriter::~gnuplotWriter()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::gnuplotSetWriter<Type>::getFileName
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSetNames
|
||||
) const
|
||||
bool Foam::coordSetWriters::gnuplotWriter::buffering(const bool on)
|
||||
{
|
||||
return this->getBaseName(points, valueSetNames) + ".gplt";
|
||||
const bool old(buffering_);
|
||||
buffering_ = on;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
Foam::fileName Foam::coordSetWriters::gnuplotWriter::path() const
|
||||
{
|
||||
// 1) rootdir/<TIME>/setName.{gplt}
|
||||
// 2) rootdir/setName.{gplt}
|
||||
|
||||
return getExpectedPath("gplt");
|
||||
}
|
||||
|
||||
|
||||
bool Foam::coordSetWriters::gnuplotWriter::writeBuffered()
|
||||
{
|
||||
if (coords_.empty())
|
||||
{
|
||||
clearBuffers();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Field:
|
||||
// 1) rootdir/<TIME>/setName.gplt
|
||||
// 2) rootdir/setName.gplt
|
||||
|
||||
fileName outputFile = path();
|
||||
|
||||
if (!isDir(outputFile.path()))
|
||||
{
|
||||
mkDir(outputFile.path());
|
||||
}
|
||||
|
||||
OFstream os(outputFile, streamOpt_);
|
||||
os.precision(precision_);
|
||||
|
||||
os << "set term pngcairo" << nl
|
||||
<< "set output \"" << outputFile.nameLessExt() << ".png\"" << nl;
|
||||
|
||||
label nplots = 0;
|
||||
do
|
||||
{
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(Type) \
|
||||
for (const word& fldName : Type##Names_) \
|
||||
{ \
|
||||
os << (nplots++ ? ", \\" : "plot \\") << nl; \
|
||||
os << " '-' title \"" << fldName << "\" with lines"; \
|
||||
}
|
||||
|
||||
doLocalCode(label);
|
||||
doLocalCode(scalar);
|
||||
doLocalCode(vector);
|
||||
doLocalCode(sphericalTensor);
|
||||
doLocalCode(symmTensor);
|
||||
doLocalCode(tensor);
|
||||
#undef doLocalCode
|
||||
}
|
||||
while (false);
|
||||
|
||||
os << nl << nl;
|
||||
|
||||
if (nplots)
|
||||
{
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(Type) \
|
||||
for (const Field<Type>& fld : Type##Fields_) \
|
||||
{ \
|
||||
writeTable(os, coords_[0], fld, " \t"); \
|
||||
os << "end_data" << nl << nl; \
|
||||
}
|
||||
|
||||
doLocalCode(label);
|
||||
doLocalCode(scalar);
|
||||
doLocalCode(vector);
|
||||
doLocalCode(sphericalTensor);
|
||||
doLocalCode(symmTensor);
|
||||
doLocalCode(tensor);
|
||||
#undef doLocalCode
|
||||
}
|
||||
|
||||
os << "# end plot" << nl;
|
||||
|
||||
clearBuffers();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::gnuplotSetWriter<Type>::write
|
||||
Foam::fileName Foam::coordSetWriters::gnuplotWriter::writeTemplate
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSetNames,
|
||||
const List<const Field<Type>*>& valueSets,
|
||||
Ostream& os
|
||||
) const
|
||||
const word& fieldName,
|
||||
const Field<Type>& values
|
||||
)
|
||||
{
|
||||
os << "set term postscript color" << nl
|
||||
<< "set output \"" << points.name() << ".ps\"" << nl;
|
||||
|
||||
// Set secondary Y axis if using two columns. Falls back to same
|
||||
// values if both on same scale. However, ignore if more columns.
|
||||
if (valueSetNames.size() == 2)
|
||||
checkOpen();
|
||||
if (coords_.empty())
|
||||
{
|
||||
os << "set ylabel \"" << valueSetNames[0] << "\"" << nl
|
||||
<< "set y2label \"" << valueSetNames[1] << "\"" << nl
|
||||
<< "set ytics nomirror" << nl << "set y2tics" << nl;
|
||||
return fileName::null;
|
||||
}
|
||||
|
||||
os << "plot";
|
||||
|
||||
forAll(valueSets, i)
|
||||
if (useTracks_ || !buffering_)
|
||||
{
|
||||
if (i)
|
||||
{
|
||||
os << ',';
|
||||
}
|
||||
|
||||
os << " \"-\" title \"" << valueSetNames[i] << "\" with lines";
|
||||
|
||||
if (valueSetNames.size() == 2)
|
||||
{
|
||||
os << " axes x1y" << (i+1) ;
|
||||
}
|
||||
UPtrList<const Field<Type>> fieldPtrs(repackageFields(values));
|
||||
return writeTemplate(fieldName, fieldPtrs);
|
||||
}
|
||||
os << nl;
|
||||
|
||||
forAll(valueSets, i)
|
||||
{
|
||||
this->writeTable(points, *valueSets[i], os);
|
||||
os << "e" << nl;
|
||||
}
|
||||
|
||||
// Buffering version
|
||||
appendField(fieldName, values);
|
||||
|
||||
return path();
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::gnuplotSetWriter<Type>::write
|
||||
Foam::fileName Foam::coordSetWriters::gnuplotWriter::writeTemplate
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream& os
|
||||
) const
|
||||
const word& fieldName,
|
||||
const List<Field<Type>>& fieldValues
|
||||
)
|
||||
{
|
||||
if (valueSets.size() != valueSetNames.size())
|
||||
checkOpen();
|
||||
if (coords_.empty())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Number of variables:" << valueSetNames.size() << endl
|
||||
<< "Number of valueSets:" << valueSets.size()
|
||||
<< exit(FatalError);
|
||||
return fileName::null;
|
||||
}
|
||||
if (tracks.size() > 0)
|
||||
{
|
||||
os << "set term postscript color" << nl
|
||||
<< "set output \"" << tracks[0].name() << ".ps\"" << nl;
|
||||
|
||||
forAll(tracks, trackI)
|
||||
{
|
||||
os << "plot";
|
||||
|
||||
forAll(valueSets, i)
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
os << ',';
|
||||
}
|
||||
|
||||
os << " \"-\" title \"" << valueSetNames[i] << "\" with lines";
|
||||
}
|
||||
os << nl;
|
||||
|
||||
forAll(valueSets, i)
|
||||
{
|
||||
this->writeTable(tracks[trackI], valueSets[i][trackI], os);
|
||||
os << "e" << nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
UPtrList<const Field<Type>> fieldPtrs(repackageFields(fieldValues));
|
||||
return writeTemplate(fieldName, fieldPtrs);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Field writing methods
|
||||
defineCoordSetWriterWriteFields(Foam::coordSetWriters::gnuplotWriter);
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
179
src/meshTools/coordSet/writers/gnuplot/gnuplotCoordSetWriter.H
Normal file
179
src/meshTools/coordSet/writers/gnuplot/gnuplotCoordSetWriter.H
Normal file
@ -0,0 +1,179 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2021-2022 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/>.
|
||||
|
||||
Class
|
||||
Foam::coordSetWriters::gnuplotWriter
|
||||
|
||||
Description
|
||||
A coordSet(s) writer in gnuplot format.
|
||||
|
||||
The formatOptions for gnuplot:
|
||||
\table
|
||||
Property | Description | Required | Default
|
||||
buffer | Use buffered output | no | true
|
||||
compression | Use file compression | no | false
|
||||
precision | Write precision in ascii | no | same as IOstream
|
||||
\endtable
|
||||
|
||||
When called with a single coordSet, will buffer the output of
|
||||
all fields and output together in the order of label/scalar/vector/...
|
||||
each of which is sorted alphabetically according to the field name.
|
||||
|
||||
When called as a track writer (eg, with multiple coordSets),
|
||||
will emit one file per field.
|
||||
|
||||
SourceFiles
|
||||
gnuplotCoordSetWriter.C
|
||||
gnuplotCoordSetWriterImpl.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_coordSetWriters_gnuplotWriter_H
|
||||
#define Foam_coordSetWriters_gnuplotWriter_H
|
||||
|
||||
#include "coordSetWriter.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace coordSetWriters
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class gnuplotWriter Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class gnuplotWriter
|
||||
:
|
||||
public coordSetWriter
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- Output stream option
|
||||
IOstreamOption streamOpt_;
|
||||
|
||||
//- ASCII write precision
|
||||
unsigned precision_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const UPtrList<const Field<Type>>& fieldPtrs
|
||||
);
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName, //!< Name of field
|
||||
const Field<Type>& vals //!< Local field values to write
|
||||
);
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const List<Field<Type>>& fieldValues
|
||||
);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Write buffered data
|
||||
virtual bool writeBuffered();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information (no debug)
|
||||
TypeNameNoDebug("gnuplot");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
gnuplotWriter();
|
||||
|
||||
//- Default construct with specified options
|
||||
explicit gnuplotWriter(const dictionary& options);
|
||||
|
||||
//- Construct from components
|
||||
gnuplotWriter
|
||||
(
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
//- Construct from components
|
||||
gnuplotWriter
|
||||
(
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
|
||||
//- Destructor. Calls close()
|
||||
virtual ~gnuplotWriter();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Enable/disable internal buffering
|
||||
virtual bool buffering(const bool on); // override
|
||||
|
||||
//- Characteristic output file name - information only
|
||||
virtual fileName path() const; // override
|
||||
|
||||
declareCoordSetWriterWriteMethod(label);
|
||||
declareCoordSetWriterWriteMethod(scalar);
|
||||
declareCoordSetWriterWriteMethod(vector);
|
||||
declareCoordSetWriterWriteMethod(sphericalTensor);
|
||||
declareCoordSetWriterWriteMethod(symmTensor);
|
||||
declareCoordSetWriterWriteMethod(tensor);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // Endnamespace coordSetWriters
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,96 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "IOmanip.H"
|
||||
#include "OFstream.H"
|
||||
#include "OSspecific.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::coordSetWriters::gnuplotWriter::writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const UPtrList<const Field<Type>>& fieldPtrs
|
||||
)
|
||||
{
|
||||
if (coords_.size() != fieldPtrs.size())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Attempted to write field: " << fieldName
|
||||
<< " (" << fieldPtrs.size() << " entries) for "
|
||||
<< coords_.size() << " sets" << nl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
///const label nPoints = numPoints();
|
||||
|
||||
|
||||
// Field: rootdir/<TIME>/<field>_setName.gplt
|
||||
|
||||
fileName outputFile = getFieldPrefixedPath(fieldName, "gplt");
|
||||
|
||||
if (verbose_)
|
||||
{
|
||||
Info<< "Writing field " << fieldName;
|
||||
Info<< " to " << outputFile << endl;
|
||||
}
|
||||
|
||||
// Master only
|
||||
{
|
||||
if (!isDir(outputFile.path()))
|
||||
{
|
||||
mkDir(outputFile.path());
|
||||
}
|
||||
|
||||
OFstream os(outputFile, streamOpt_);
|
||||
os.precision(precision_);
|
||||
|
||||
os << "set term pngcairo" << nl
|
||||
<< "set output \"" << outputFile.nameLessExt() << ".png\"" << nl;
|
||||
|
||||
// Header
|
||||
{
|
||||
os << "plot \\" << nl;
|
||||
os << " '-' title \"" << fieldName << "\" with lines";
|
||||
os << nl << nl;
|
||||
}
|
||||
|
||||
forAll(coords_, tracki)
|
||||
{
|
||||
writeTable(os, coords_[tracki], fieldPtrs[tracki], " \t");
|
||||
}
|
||||
os << "end_data" << nl << nl;
|
||||
os << "# end plot" << nl;
|
||||
}
|
||||
|
||||
wroteGeom_ = true;
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,117 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2021 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/>.
|
||||
|
||||
Class
|
||||
Foam::gnuplotSetWriter
|
||||
|
||||
Description
|
||||
|
||||
SourceFiles
|
||||
gnuplotCoordSetWriter.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_coordSetWriters_gnuplotWriter_H
|
||||
#define Foam_coordSetWriters_gnuplotWriter_H
|
||||
|
||||
#include "writer.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class gnuplotSetWriter Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Type>
|
||||
class gnuplotSetWriter
|
||||
:
|
||||
public writer<Type>
|
||||
{
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("gnuplot");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
gnuplotSetWriter();
|
||||
|
||||
//- Construct with dictionary
|
||||
explicit gnuplotSetWriter(const dictionary& dict);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~gnuplotSetWriter() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
virtual fileName getFileName
|
||||
(
|
||||
const coordSet&,
|
||||
const wordList&
|
||||
) const;
|
||||
|
||||
virtual void write
|
||||
(
|
||||
const coordSet&,
|
||||
const wordList&,
|
||||
const List<const Field<Type>*>&,
|
||||
Ostream&
|
||||
) const;
|
||||
|
||||
virtual void write
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream&
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "gnuplotCoordSetWriter.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,39 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2012 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
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 "gnuplotSetWriter.H"
|
||||
#include "writers.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
makeSetWriters(gnuplotSetWriter);
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2018-2021 OpenCFD Ltd.
|
||||
Copyright (C) 2018-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -25,175 +25,198 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "nastranSetWriter.H"
|
||||
#include "nastranCoordSetWriter.H"
|
||||
#include "coordSet.H"
|
||||
#include "IOmanip.H"
|
||||
#include "OFstream.H"
|
||||
#include "OSspecific.H"
|
||||
#include "coordSetWriterMethods.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace coordSetWriters
|
||||
{
|
||||
defineTypeName(nastranWriter);
|
||||
addToRunTimeSelectionTable(coordSetWriter, nastranWriter, word);
|
||||
addToRunTimeSelectionTable(coordSetWriter, nastranWriter, wordDict);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
template<class Type>
|
||||
static inline void putValue(Ostream& os, const Type& value, const int width)
|
||||
{
|
||||
if (width) os << setw(width);
|
||||
os << value;
|
||||
}
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::Ostream& Foam::coordSetWriters::nastranWriter::writeKeyword
|
||||
(
|
||||
Ostream& os,
|
||||
const word& keyword
|
||||
) const
|
||||
{
|
||||
return fileFormats::NASCore::writeKeyword(os, keyword, writeFormat_);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::nastranSetWriter<Type>::nastranSetWriter()
|
||||
Foam::coordSetWriters::nastranWriter::nastranWriter()
|
||||
:
|
||||
writer<Type>()
|
||||
{}
|
||||
coordSetWriter(),
|
||||
writeFormat_(fieldFormat::FREE),
|
||||
separator_()
|
||||
{
|
||||
if (writeFormat_ == fieldFormat::FREE)
|
||||
{
|
||||
separator_ = ",";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::nastranSetWriter<Type>::nastranSetWriter(const dictionary& dict)
|
||||
Foam::coordSetWriters::nastranWriter::nastranWriter(const dictionary& options)
|
||||
:
|
||||
writer<Type>(dict)
|
||||
{}
|
||||
coordSetWriter(options),
|
||||
writeFormat_
|
||||
(
|
||||
fileFormats::NASCore::fieldFormatNames.getOrDefault
|
||||
(
|
||||
"format",
|
||||
options,
|
||||
fieldFormat::FREE
|
||||
)
|
||||
),
|
||||
separator_()
|
||||
{
|
||||
if (writeFormat_ == fieldFormat::FREE)
|
||||
{
|
||||
separator_ = ",";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::coordSetWriters::nastranWriter::nastranWriter
|
||||
(
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
nastranWriter(options)
|
||||
{
|
||||
open(coords, outputPath);
|
||||
}
|
||||
|
||||
|
||||
Foam::coordSetWriters::nastranWriter::nastranWriter
|
||||
(
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
nastranWriter(options)
|
||||
{
|
||||
open(tracks, outputPath);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::coordSetWriters::nastranWriter::~nastranWriter()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::nastranSetWriter<Type>::getFileName
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSetNames
|
||||
) const
|
||||
Foam::fileName Foam::coordSetWriters::nastranWriter::path() const
|
||||
{
|
||||
return this->getBaseName(points, valueSetNames) + ".nas";
|
||||
// 1) rootdir/<TIME>/setName.{nas}
|
||||
// 2) rootdir/setName.{nas}
|
||||
|
||||
return getExpectedPath("nas");
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::nastranSetWriter<Type>::write
|
||||
void Foam::coordSetWriters::nastranWriter::writeGeometry
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSetNames,
|
||||
const List<const Field<Type>*>& valueSets,
|
||||
Ostream& os
|
||||
Ostream& os,
|
||||
label nTracks
|
||||
) const
|
||||
{
|
||||
os << "TITLE=OpenFOAM "
|
||||
<< this->getBaseName(points, valueSetNames).c_str()
|
||||
<< nl
|
||||
<< "$" << nl
|
||||
<< "BEGIN BULK" << nl;
|
||||
|
||||
forAll(points, pointi)
|
||||
{
|
||||
fileFormats::NASCore::writeCoord
|
||||
(
|
||||
os, points[pointi], pointi, fieldFormat::FREE
|
||||
);
|
||||
}
|
||||
|
||||
if (false)
|
||||
{
|
||||
// Single track with multiple segments
|
||||
const label nEdges = points.size()-1;
|
||||
for (label edgei = 0; edgei < nEdges; ++edgei)
|
||||
{
|
||||
fileFormats::NASCore::writeKeyword
|
||||
(
|
||||
os,
|
||||
"PLOTEL",
|
||||
fieldFormat::FREE
|
||||
);
|
||||
|
||||
// fieldFormat::SHORT
|
||||
//os.setf(std::ios_base::right);
|
||||
//os << setw(8) << edgei+1
|
||||
// << setw(8) << edgei+1
|
||||
// << setw(8) << edgei+2
|
||||
// << nl;
|
||||
//os.unsetf(std::ios_base::right);
|
||||
|
||||
// fieldFormat::FREE
|
||||
os << ',' << edgei+1
|
||||
<< ',' << edgei+1
|
||||
<< ',' << edgei+2
|
||||
<< nl;
|
||||
}
|
||||
}
|
||||
|
||||
os << "ENDDATA" << nl;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::nastranSetWriter<Type>::write
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream& os
|
||||
) const
|
||||
{
|
||||
if (valueSets.size() != valueSetNames.size())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Number of variables:" << valueSetNames.size() << endl
|
||||
<< "Number of valueSets:" << valueSets.size()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
if (tracks.empty())
|
||||
if (coords_.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
os << "TITLE=OpenFOAM "
|
||||
<< this->getBaseName(tracks[0], valueSetNames).c_str()
|
||||
<< nl
|
||||
<< "$" << nl
|
||||
<< "BEGIN BULK" << nl;
|
||||
// Field width (SHORT, LONG formats)
|
||||
const int width =
|
||||
(
|
||||
writeFormat_ == fieldFormat::SHORT ? 8
|
||||
: writeFormat_ == fieldFormat::LONG ? 16
|
||||
: 0
|
||||
);
|
||||
|
||||
// label nTracks = tracks.size();
|
||||
// label nPoints = 0;
|
||||
// forAll(tracks, i)
|
||||
// {
|
||||
// nPoints += tracks[i].size();
|
||||
// }
|
||||
// Separator char (FREE format)
|
||||
const char sep = (writeFormat_ == fieldFormat::FREE ? ',' : '\0');
|
||||
|
||||
// Write points
|
||||
os << '$' << nl
|
||||
<< "$ Points" << nl
|
||||
<< '$' << nl;
|
||||
|
||||
label globalPointi = 0;
|
||||
for (const coordSet& points : tracks)
|
||||
for (const coordSet& coords : coords_)
|
||||
{
|
||||
for (const point& p : points)
|
||||
for (const point& p : coords)
|
||||
{
|
||||
fileFormats::NASCore::writeCoord
|
||||
(
|
||||
os, p, globalPointi, fieldFormat::FREE
|
||||
os, p, globalPointi, writeFormat_
|
||||
);
|
||||
++globalPointi;
|
||||
}
|
||||
}
|
||||
|
||||
if (writeTracks)
|
||||
if (nTracks)
|
||||
{
|
||||
// Write ids of track points to file
|
||||
globalPointi = 0;
|
||||
label globalEdgei = 0;
|
||||
label globalPointi = 0;
|
||||
for (const coordSet& points : tracks)
|
||||
|
||||
for (label tracki = 0; tracki < nTracks; ++tracki)
|
||||
{
|
||||
const label nEdges = points.size()-1;
|
||||
const label nEdges = (coords_[tracki].size() - 1);
|
||||
|
||||
for (label edgei = 0; edgei < nEdges; ++edgei)
|
||||
{
|
||||
fileFormats::NASCore::writeKeyword
|
||||
(
|
||||
os,
|
||||
"PLOTEL",
|
||||
fieldFormat::FREE
|
||||
);
|
||||
writeKeyword(os, "PLOTEL");
|
||||
if (sep) os << sep;
|
||||
|
||||
// fieldFormat::SHORT
|
||||
//os.setf(std::ios_base::right);
|
||||
//os << setw(8) << globalEdgei+1
|
||||
// << setw(8) << globalPointi+1
|
||||
// << setw(8) << globalPointi+2
|
||||
// << nl;
|
||||
//os.unsetf(std::ios_base::right);
|
||||
putValue(os, globalEdgei+1, width); // Edge id
|
||||
if (sep) os << sep;
|
||||
|
||||
// fieldFormat::FREE
|
||||
os << ',' << globalEdgei+1
|
||||
<< ',' << globalPointi+1
|
||||
<< ',' << globalPointi+2
|
||||
<< nl;
|
||||
putValue(os, globalPointi+1, width);
|
||||
if (sep) os << sep;
|
||||
|
||||
putValue(os, globalPointi+2, width);
|
||||
os << nl;
|
||||
|
||||
++globalEdgei;
|
||||
++globalPointi;
|
||||
@ -201,8 +224,100 @@ void Foam::nastranSetWriter<Type>::write
|
||||
}
|
||||
}
|
||||
|
||||
os << "ENDDATA" << nl;
|
||||
wroteGeom_ = true;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::coordSetWriters::nastranWriter::writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const Field<Type>& values
|
||||
)
|
||||
{
|
||||
checkOpen();
|
||||
if (coords_.empty())
|
||||
{
|
||||
return fileName::null;
|
||||
}
|
||||
|
||||
fileName outputFile = path();
|
||||
|
||||
if (!wroteGeom_)
|
||||
{
|
||||
if (verbose_)
|
||||
{
|
||||
Info<< "Writing nastran geometry to " << outputFile << endl;
|
||||
}
|
||||
|
||||
if (!isDir(outputFile.path()))
|
||||
{
|
||||
mkDir(outputFile.path());
|
||||
}
|
||||
|
||||
OFstream os(outputFile);
|
||||
fileFormats::NASCore::setPrecision(os, writeFormat_);
|
||||
|
||||
os << "TITLE=OpenFOAM " << outputFile.nameLessExt()
|
||||
<< " geometry" << nl
|
||||
<< "BEGIN BULK" << nl;
|
||||
|
||||
writeGeometry(os, (useTracks_ ? coords_.size() : 0));
|
||||
|
||||
os << "ENDDATA" << nl;
|
||||
}
|
||||
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::coordSetWriters::nastranWriter::writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const List<Field<Type>>& fieldValues
|
||||
)
|
||||
{
|
||||
checkOpen();
|
||||
if (coords_.empty())
|
||||
{
|
||||
return fileName::null;
|
||||
}
|
||||
|
||||
fileName outputFile = path();
|
||||
|
||||
if (!wroteGeom_)
|
||||
{
|
||||
if (verbose_)
|
||||
{
|
||||
Info<< "Writing nastran geometry to " << outputFile << endl;
|
||||
}
|
||||
|
||||
if (!isDir(outputFile.path()))
|
||||
{
|
||||
mkDir(outputFile.path());
|
||||
}
|
||||
|
||||
OFstream os(outputFile);
|
||||
fileFormats::NASCore::setPrecision(os, writeFormat_);
|
||||
|
||||
os << "TITLE=OpenFOAM " << outputFile.nameLessExt()
|
||||
<< " geometry" << nl
|
||||
<< "BEGIN BULK" << nl;
|
||||
|
||||
writeGeometry(os, coords_.size());
|
||||
|
||||
os << "ENDDATA" << nl;
|
||||
}
|
||||
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Field writing methods
|
||||
defineCoordSetWriterWriteFields(Foam::coordSetWriters::nastranWriter);
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
178
src/meshTools/coordSet/writers/nastran/nastranCoordSetWriter.H
Normal file
178
src/meshTools/coordSet/writers/nastran/nastranCoordSetWriter.H
Normal file
@ -0,0 +1,178 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2018-2022 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/>.
|
||||
|
||||
Class
|
||||
Foam::coordSetWriters::nastranWriter
|
||||
|
||||
Description
|
||||
Write coordSet(s) as Nastran plot lines. Does not do field data.
|
||||
|
||||
The formatOptions for nastran:
|
||||
\table
|
||||
Property | Description | Required | Default
|
||||
format | short / long / free | no | free
|
||||
\endtable
|
||||
|
||||
\section Output file locations
|
||||
|
||||
The \c rootdir normally corresponds to something like
|
||||
\c postProcessing/\<name\>
|
||||
|
||||
\subsection Geometry
|
||||
\verbatim
|
||||
rootdir
|
||||
`-- <time>
|
||||
|-- setName0.{nas}
|
||||
`-- setName1.{nas}
|
||||
\endverbatim
|
||||
|
||||
SourceFiles
|
||||
nastranCoordSetWriter.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_coordSetWriters_nastranWriter_H
|
||||
#define Foam_coordSetWriters_nastranWriter_H
|
||||
|
||||
#include "coordSetWriter.H"
|
||||
#include "NASCore.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace coordSetWriters
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class nastranWriter Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class nastranWriter
|
||||
:
|
||||
public coordSetWriter
|
||||
{
|
||||
public:
|
||||
|
||||
//- File field formats
|
||||
using fieldFormat = Foam::fileFormats::NASCore::fieldFormat;
|
||||
|
||||
//- Output load format
|
||||
using loadFormat = Foam::fileFormats::NASCore::loadFormat;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
//- Field format (width and separator)
|
||||
fieldFormat writeFormat_;
|
||||
|
||||
//- Separator used for free format
|
||||
word separator_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Write the formatted keyword to the output stream
|
||||
Ostream& writeKeyword(Ostream& os, const word& keyword) const;
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName, //!< Name of field
|
||||
const Field<Type>& values //!< Local field values to write
|
||||
);
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const List<Field<Type>>& fieldValues
|
||||
);
|
||||
|
||||
//- Write geometry to file.
|
||||
void writeGeometry(Ostream& os, label nTracks) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information (no debug)
|
||||
TypeNameNoDebug("nastran");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
nastranWriter();
|
||||
|
||||
//- Default construct with specified options
|
||||
explicit nastranWriter(const dictionary& options);
|
||||
|
||||
//- Construct from components
|
||||
nastranWriter
|
||||
(
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
//- Construct from components
|
||||
nastranWriter
|
||||
(
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
|
||||
//- Destructor. Calls close()
|
||||
virtual ~nastranWriter();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Characteristic output file name - information only
|
||||
virtual fileName path() const; // override
|
||||
|
||||
declareCoordSetWriterWriteMethod(label);
|
||||
declareCoordSetWriterWriteMethod(scalar);
|
||||
declareCoordSetWriterWriteMethod(vector);
|
||||
declareCoordSetWriterWriteMethod(sphericalTensor);
|
||||
declareCoordSetWriterWriteMethod(symmTensor);
|
||||
declareCoordSetWriterWriteMethod(tensor);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace coordSetWriters
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,134 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2018-2021 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/>.
|
||||
|
||||
Class
|
||||
Foam::nastranSetWriter
|
||||
|
||||
Description
|
||||
Line format in Nastran (currently hardcoded to 'free' format)
|
||||
|
||||
Does not do field data.
|
||||
|
||||
SourceFiles
|
||||
nastranCoordSetWriter.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_coordSetWriters_nastranWriter_H
|
||||
#define Foam_coordSetWriters_nastranWriter_H
|
||||
|
||||
#include "writer.H"
|
||||
#include "NASCore.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class nastranSetWriter Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Type>
|
||||
class nastranSetWriter
|
||||
:
|
||||
public writer<Type>
|
||||
{
|
||||
// Private Member Functions
|
||||
|
||||
//- Write the formatted keyword to the output stream
|
||||
Ostream& writeKeyword
|
||||
(
|
||||
Ostream& os,
|
||||
const word& keyword
|
||||
) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- File field formats
|
||||
using fieldFormat = Foam::fileFormats::NASCore::fieldFormat;
|
||||
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("nastran");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
nastranSetWriter();
|
||||
|
||||
//- Construct with dictionary
|
||||
explicit nastranSetWriter(const dictionary& dict);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~nastranSetWriter() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
virtual fileName getFileName
|
||||
(
|
||||
const coordSet&,
|
||||
const wordList&
|
||||
) const;
|
||||
|
||||
virtual void write
|
||||
(
|
||||
const coordSet&,
|
||||
const wordList&,
|
||||
const List<const Field<Type>*>&,
|
||||
Ostream&
|
||||
) const;
|
||||
|
||||
virtual void write
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream&
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "nastranCoordSetWriter.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,39 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2018 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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "nastranSetWriter.H"
|
||||
#include "writers.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
makeSetWriters(nastranSetWriter);
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
157
src/meshTools/coordSet/writers/null/nullCoordSetWriter.C
Normal file
157
src/meshTools/coordSet/writers/null/nullCoordSetWriter.C
Normal file
@ -0,0 +1,157 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "nullCoordSetWriter.H"
|
||||
#include "coordSetWriterMethods.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace coordSetWriters
|
||||
{
|
||||
defineTypeName(nullWriter);
|
||||
addToRunTimeSelectionTable(coordSetWriter, nullWriter, word);
|
||||
addToRunTimeSelectionTable(coordSetWriter, nullWriter, wordDict);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::coordSetWriters::nullWriter::nullWriter()
|
||||
:
|
||||
coordSetWriter()
|
||||
{}
|
||||
|
||||
|
||||
Foam::coordSetWriters::nullWriter::nullWriter(const dictionary& options)
|
||||
:
|
||||
nullWriter()
|
||||
{}
|
||||
|
||||
|
||||
Foam::coordSetWriters::nullWriter::nullWriter
|
||||
(
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
nullWriter()
|
||||
{}
|
||||
|
||||
|
||||
Foam::coordSetWriters::nullWriter::nullWriter
|
||||
(
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
nullWriter()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::coordSetWriters::nullWriter::~nullWriter()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::coordSetWriters::nullWriter::enabled() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::coordSetWriters::nullWriter::buffering() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::coordSetWriters::nullWriter::needsUpdate() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::coordSetWriters::nullWriter::wroteData() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriters::nullWriter::setCoordinates
|
||||
(
|
||||
const coordSet* coords
|
||||
)
|
||||
{}
|
||||
|
||||
|
||||
void Foam::coordSetWriters::nullWriter::setCoordinates
|
||||
(
|
||||
const coordSet& coords
|
||||
)
|
||||
{}
|
||||
|
||||
|
||||
void Foam::coordSetWriters::nullWriter::setTracks
|
||||
(
|
||||
const UPtrList<coordSet>& tracks
|
||||
)
|
||||
{}
|
||||
|
||||
|
||||
Foam::fileName Foam::coordSetWriters::nullWriter::path() const
|
||||
{
|
||||
return fileName();
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriters::nullWriter::open(const fileName& outputPath)
|
||||
{}
|
||||
|
||||
|
||||
// Foam::fileName Foam::coordSetWriters::nullWriter::write()
|
||||
// {
|
||||
// wroteGeom_ = true;
|
||||
// return fileName::null;
|
||||
// }
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Field writing methods
|
||||
defineCoordSetWriterWriteFields(Foam::coordSetWriters::nullWriter);
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
177
src/meshTools/coordSet/writers/null/nullCoordSetWriter.H
Normal file
177
src/meshTools/coordSet/writers/null/nullCoordSetWriter.H
Normal file
@ -0,0 +1,177 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 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/>.
|
||||
|
||||
Class
|
||||
Foam::coordSetWriters::nullWriter
|
||||
|
||||
Description
|
||||
A coordSet(s) writer with suppressed output.
|
||||
|
||||
SourceFiles
|
||||
nullCoordSetWriter.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_coordSetWriters_nullWriter_H
|
||||
#define Foam_coordSetWriters_nullWriter_H
|
||||
|
||||
#include "coordSetWriter.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace coordSetWriters
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class nullWriter Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class nullWriter
|
||||
:
|
||||
public coordSetWriter
|
||||
{
|
||||
// Private Member Functions
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName, //!< Name of field
|
||||
const Field<Type>& values //!< Local field values to write
|
||||
)
|
||||
{
|
||||
return fileName();
|
||||
}
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const List<Field<Type>>& fieldValues
|
||||
)
|
||||
{
|
||||
return fileName();
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information (no debug)
|
||||
TypeNameNoDebug("none");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
nullWriter();
|
||||
|
||||
//- Construct with some output options
|
||||
explicit nullWriter(const dictionary& options);
|
||||
|
||||
//- Construct from components
|
||||
nullWriter
|
||||
(
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
//- Construct from components
|
||||
nullWriter
|
||||
(
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~nullWriter();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Capability
|
||||
|
||||
//- False: The null writer is never enabled, which lets the caller
|
||||
//- skip various (possibly expensive) preparatory operations.
|
||||
virtual bool enabled() const;
|
||||
|
||||
//- False: no internal buffering possible
|
||||
virtual bool buffering() const; // override
|
||||
|
||||
//- False: never needs an update.
|
||||
virtual bool needsUpdate() const;
|
||||
|
||||
//- True: like a /dev/null device.
|
||||
virtual bool wroteData() const;
|
||||
|
||||
|
||||
// Content Association
|
||||
|
||||
//- Set coordinates (no-op).
|
||||
virtual void setCoordinates(const coordSet*); // override
|
||||
|
||||
//- Set coordinates (no-op).
|
||||
virtual void setCoordinates(const coordSet&); // override
|
||||
|
||||
//- Set tracks (no-op).
|
||||
virtual void setTracks(const UPtrList<coordSet>&); // override
|
||||
|
||||
|
||||
// Output
|
||||
|
||||
//- Characteristic output file name - information only.
|
||||
//- Always an empty fileName
|
||||
virtual fileName path() const; // override
|
||||
|
||||
//- Open for output on specified path, using existing content (no-op)
|
||||
virtual void open(const fileName& outputPath); // override
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
declareCoordSetWriterWriteMethod(label);
|
||||
declareCoordSetWriterWriteMethod(scalar);
|
||||
declareCoordSetWriterWriteMethod(vector);
|
||||
declareCoordSetWriterWriteMethod(sphericalTensor);
|
||||
declareCoordSetWriterWriteMethod(symmTensor);
|
||||
declareCoordSetWriterWriteMethod(tensor);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace coordSetWriters
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2021 OpenCFD Ltd.
|
||||
Copyright (C) 2021-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -26,94 +26,199 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "rawSetWriter.H"
|
||||
#include "rawCoordSetWriter.H"
|
||||
#include "coordSet.H"
|
||||
#include "fileName.H"
|
||||
#include "OFstream.H"
|
||||
#include "OSspecific.H"
|
||||
#include "stringOps.H"
|
||||
#include "coordSetWriterMethods.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace coordSetWriters
|
||||
{
|
||||
defineTypeName(rawWriter);
|
||||
addToRunTimeSelectionTable(coordSetWriter, rawWriter, word);
|
||||
addToRunTimeSelectionTable(coordSetWriter, rawWriter, wordDict);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Implementation
|
||||
#include "rawCoordSetWriterImpl.C"
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::rawSetWriter<Type>::rawSetWriter()
|
||||
Foam::coordSetWriters::rawWriter::rawWriter()
|
||||
:
|
||||
writer<Type>()
|
||||
{}
|
||||
coordSetWriter(),
|
||||
streamOpt_(),
|
||||
precision_(IOstream::defaultPrecision())
|
||||
{
|
||||
buffering_ = true;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::rawSetWriter<Type>::rawSetWriter(const dictionary& dict)
|
||||
Foam::coordSetWriters::rawWriter::rawWriter(const dictionary& options)
|
||||
:
|
||||
writer<Type>(dict)
|
||||
{}
|
||||
coordSetWriter(options),
|
||||
streamOpt_
|
||||
(
|
||||
IOstream::ASCII,
|
||||
IOstream::compressionEnum("compression", options)
|
||||
),
|
||||
precision_
|
||||
(
|
||||
options.getOrDefault("precision", IOstream::defaultPrecision())
|
||||
)
|
||||
{
|
||||
buffering_ = options.getOrDefault("buffer", true);
|
||||
}
|
||||
|
||||
|
||||
Foam::coordSetWriters::rawWriter::rawWriter
|
||||
(
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
rawWriter(options)
|
||||
{
|
||||
open(coords, outputPath);
|
||||
}
|
||||
|
||||
|
||||
Foam::coordSetWriters::rawWriter::rawWriter
|
||||
(
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
rawWriter(options)
|
||||
{
|
||||
open(tracks, outputPath);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::coordSetWriters::rawWriter::~rawWriter()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Controls * * * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::coordSetWriters::rawWriter::buffering(const bool on)
|
||||
{
|
||||
const bool old(buffering_);
|
||||
buffering_ = on;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::rawSetWriter<Type>::getFileName
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSetNames
|
||||
) const
|
||||
Foam::fileName Foam::coordSetWriters::rawWriter::path() const
|
||||
{
|
||||
return this->getBaseName(points, valueSetNames) + ".xy";
|
||||
// Assume !useTracks_, otherwise too fragile
|
||||
|
||||
// 1) rootdir/<TIME>/setName.raw
|
||||
// 2) rootdir/setName.raw
|
||||
|
||||
return getExpectedPath("xy"); // Traditionally 'xy', not 'raw'
|
||||
}
|
||||
|
||||
|
||||
bool Foam::coordSetWriters::rawWriter::writeBuffered()
|
||||
{
|
||||
if (coords_.empty())
|
||||
{
|
||||
clearBuffers();
|
||||
return false;
|
||||
}
|
||||
const auto& coords = coords_[0];
|
||||
|
||||
// Field:
|
||||
// 1) rootdir/<TIME>/setName.raw
|
||||
// 2) rootdir/setName.raw
|
||||
|
||||
fileName outputFile = path();
|
||||
|
||||
if (!isDir(outputFile.path()))
|
||||
{
|
||||
mkDir(outputFile.path());
|
||||
}
|
||||
|
||||
OFstream os(outputFile, streamOpt_);
|
||||
os.precision(precision_);
|
||||
|
||||
writeBufferContents(os, coords, " \t");
|
||||
|
||||
clearBuffers();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::rawSetWriter<Type>::write
|
||||
Foam::fileName Foam::coordSetWriters::rawWriter::writeTemplate
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSetNames,
|
||||
const List<const Field<Type>*>& valueSets,
|
||||
Ostream& os
|
||||
) const
|
||||
const word& fieldName,
|
||||
const Field<Type>& values
|
||||
)
|
||||
{
|
||||
// Collect sets into columns
|
||||
List<const List<Type>*> columns(valueSets.size());
|
||||
|
||||
forAll(valueSets, i)
|
||||
checkOpen();
|
||||
if (coords_.empty())
|
||||
{
|
||||
columns[i] = valueSets[i];
|
||||
return fileName::null;
|
||||
}
|
||||
|
||||
this->writeTable(points, columns, os);
|
||||
if (useTracks_ || !buffering_)
|
||||
{
|
||||
UPtrList<const Field<Type>> fieldPtrs(repackageFields(values));
|
||||
return writeTemplate(fieldName, fieldPtrs);
|
||||
}
|
||||
|
||||
// Buffering version
|
||||
appendField(fieldName, values);
|
||||
return path();
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::rawSetWriter<Type>::write
|
||||
Foam::fileName Foam::coordSetWriters::rawWriter::writeTemplate
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream& os
|
||||
) const
|
||||
const word& fieldName,
|
||||
const List<Field<Type>>& fieldValues
|
||||
)
|
||||
{
|
||||
if (valueSets.size() != valueSetNames.size())
|
||||
checkOpen();
|
||||
if (coords_.empty())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Number of variables:" << valueSetNames.size() << endl
|
||||
<< "Number of valueSets:" << valueSets.size()
|
||||
<< exit(FatalError);
|
||||
return fileName::null;
|
||||
}
|
||||
useTracks_ = true; // Extra safety
|
||||
|
||||
List<const List<Type>*> columns(valueSets.size());
|
||||
|
||||
forAll(tracks, trackI)
|
||||
{
|
||||
// Collect sets into columns
|
||||
forAll(valueSets, i)
|
||||
{
|
||||
columns[i] = &valueSets[i][trackI];
|
||||
}
|
||||
|
||||
this->writeTable(tracks[trackI], columns, os);
|
||||
os << nl << nl;
|
||||
}
|
||||
UPtrList<const Field<Type>> fieldPtrs(repackageFields(fieldValues));
|
||||
return writeTemplate(fieldName, fieldPtrs);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Field writing methods
|
||||
defineCoordSetWriterWriteFields(Foam::coordSetWriters::rawWriter);
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
178
src/meshTools/coordSet/writers/raw/rawCoordSetWriter.H
Normal file
178
src/meshTools/coordSet/writers/raw/rawCoordSetWriter.H
Normal file
@ -0,0 +1,178 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 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/>.
|
||||
|
||||
Class
|
||||
Foam::coordSetWriters::rawWriter
|
||||
|
||||
Description
|
||||
A coordSet(s) in raw format.
|
||||
|
||||
The formatOptions for raw:
|
||||
\table
|
||||
Property | Description | Required | Default
|
||||
buffer | Use buffered output | no | true
|
||||
compression | Use file compression | no | false
|
||||
precision | Write precision in ascii | no | same as IOstream
|
||||
\endtable
|
||||
|
||||
When called with a single coordSet, will buffer the output of
|
||||
all fields and output together in the order of label/scalar/vector/...
|
||||
each of which is sorted alphabetically according to the field name.
|
||||
|
||||
When called as a track writer (eg, with multiple coordSets),
|
||||
will emit one file per field.
|
||||
|
||||
SourceFiles
|
||||
rawCoordSetWriter.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_coordSetWriters_rawWriter_H
|
||||
#define Foam_coordSetWriters_rawWriter_H
|
||||
|
||||
#include "coordSetWriter.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace coordSetWriters
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class rawWriter Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class rawWriter
|
||||
:
|
||||
public coordSetWriter
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- Output stream option
|
||||
IOstreamOption streamOpt_;
|
||||
|
||||
//- ASCII write precision
|
||||
unsigned precision_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const UPtrList<const Field<Type>>& fieldPtrs
|
||||
);
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName, //!< Name of field
|
||||
const Field<Type>& vals //!< Local field values to write
|
||||
);
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName, //!< Name of field
|
||||
const List<Field<Type>>& fieldValues
|
||||
);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Write buffered data
|
||||
virtual bool writeBuffered();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information (no debug)
|
||||
TypeNameNoDebug("raw");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
rawWriter();
|
||||
|
||||
//- Default construct with specified options
|
||||
explicit rawWriter(const dictionary& options);
|
||||
|
||||
//- Construct from components
|
||||
rawWriter
|
||||
(
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
//- Construct from components
|
||||
rawWriter
|
||||
(
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
|
||||
//- Destructor. Calls close()
|
||||
virtual ~rawWriter();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Enable/disable internal buffering
|
||||
virtual bool buffering(const bool on); // override
|
||||
|
||||
//- Characteristic output file name - information only
|
||||
// \warning incorrect for unbuffered or track output!
|
||||
virtual fileName path() const; // override
|
||||
|
||||
declareCoordSetWriterWriteMethod(label);
|
||||
declareCoordSetWriterWriteMethod(scalar);
|
||||
declareCoordSetWriterWriteMethod(vector);
|
||||
declareCoordSetWriterWriteMethod(sphericalTensor);
|
||||
declareCoordSetWriterWriteMethod(symmTensor);
|
||||
declareCoordSetWriterWriteMethod(tensor);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace coordSetWriters
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
149
src/meshTools/coordSet/writers/raw/rawCoordSetWriterImpl.C
Normal file
149
src/meshTools/coordSet/writers/raw/rawCoordSetWriterImpl.C
Normal file
@ -0,0 +1,149 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "IOmanip.H"
|
||||
#include "OFstream.H"
|
||||
#include "OSspecific.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
// Output coordinate header
|
||||
static void writeCoordHeader
|
||||
(
|
||||
Ostream& os,
|
||||
const coordSet& coords,
|
||||
const label count
|
||||
)
|
||||
{
|
||||
if (coords.hasVectorAxis())
|
||||
{
|
||||
os << "POINT_DATA" << ' ' << count << nl;
|
||||
os << "# x y z";
|
||||
}
|
||||
else
|
||||
{
|
||||
word axisName(coords.axis());
|
||||
word dataName(stringOps::upper(axisName) + "_DATA");
|
||||
|
||||
os << dataName << ' ' << count << nl;
|
||||
os << "# " << axisName;
|
||||
}
|
||||
}
|
||||
|
||||
// Write field name, use named components for VectorSpace
|
||||
template<class Type>
|
||||
static inline void writeHeader(Ostream& os, const word& fieldName)
|
||||
{
|
||||
os << ' '; // Extra space
|
||||
|
||||
const auto nCmpts(pTraits<Type>::nComponents);
|
||||
|
||||
if (pTraits<Type>::rank || nCmpts > 1)
|
||||
{
|
||||
for (direction d = 0; d < nCmpts; ++d)
|
||||
{
|
||||
os << ' ' << fieldName
|
||||
<< '_' << pTraits<Type>::componentNames[d];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
os << ' ' << fieldName;
|
||||
}
|
||||
}
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::coordSetWriters::rawWriter::writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const UPtrList<const Field<Type>>& fieldPtrs
|
||||
)
|
||||
{
|
||||
if (coords_.size() != fieldPtrs.size())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Attempted to write field: " << fieldName
|
||||
<< " (" << fieldPtrs.size() << " entries) for "
|
||||
<< coords_.size() << " sets" << nl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
label nPoints = 0;
|
||||
for (const auto& pts : coords_)
|
||||
{
|
||||
nPoints += pts.size();
|
||||
}
|
||||
|
||||
|
||||
// Field: rootdir/<TIME>/<field>_setName.raw
|
||||
|
||||
fileName outputFile = getFieldPrefixedPath(fieldName, "raw");
|
||||
|
||||
if (verbose_)
|
||||
{
|
||||
Info<< "Writing field " << fieldName;
|
||||
Info<< " to " << outputFile << endl;
|
||||
}
|
||||
|
||||
// Master only
|
||||
{
|
||||
if (!isDir(outputFile.path()))
|
||||
{
|
||||
mkDir(outputFile.path());
|
||||
}
|
||||
|
||||
OFstream os(outputFile, streamOpt_);
|
||||
os.precision(precision_);
|
||||
|
||||
// Header
|
||||
{
|
||||
os << "# " << fieldName << " ";
|
||||
|
||||
writeCoordHeader(os, coords_[0], nPoints);
|
||||
writeHeader<Type>(os, fieldName);
|
||||
os << nl;
|
||||
}
|
||||
|
||||
forAll(coords_, tracki)
|
||||
{
|
||||
writeTable(os, coords_[tracki], fieldPtrs[tracki], " ");
|
||||
}
|
||||
}
|
||||
|
||||
wroteGeom_ = true;
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,117 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2021 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/>.
|
||||
|
||||
Class
|
||||
Foam::rawSetWriter
|
||||
|
||||
Description
|
||||
|
||||
SourceFiles
|
||||
rawCoordSetWriter.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_coordSetWriters_rawWriter_H
|
||||
#define Foam_coordSetWriters_rawWriter_H
|
||||
|
||||
#include "writer.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class rawSetWriter Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Type>
|
||||
class rawSetWriter
|
||||
:
|
||||
public writer<Type>
|
||||
{
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("raw");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
rawSetWriter();
|
||||
|
||||
//- Construct with dictionary
|
||||
explicit rawSetWriter(const dictionary& dict);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~rawSetWriter() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
virtual fileName getFileName
|
||||
(
|
||||
const coordSet&,
|
||||
const wordList&
|
||||
) const;
|
||||
|
||||
virtual void write
|
||||
(
|
||||
const coordSet&,
|
||||
const wordList&,
|
||||
const List<const Field<Type>*>&,
|
||||
Ostream&
|
||||
) const;
|
||||
|
||||
virtual void write
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream&
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "rawCoordSetWriter.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,39 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2012 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
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 "rawSetWriter.H"
|
||||
#include "writers.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
makeSetWriters(rawSetWriter);
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -5,8 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2021 OpenCFD Ltd.
|
||||
Copyright (C) 2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -26,177 +25,310 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "vtkSetWriter.H"
|
||||
#include "vtkCoordSetWriter.H"
|
||||
#include "coordSet.H"
|
||||
#include "fileName.H"
|
||||
#include "OFstream.H"
|
||||
#include "foamVtkCoordSetWriter.H"
|
||||
#include "coordSetWriterMethods.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace coordSetWriters
|
||||
{
|
||||
defineTypeName(vtkWriter);
|
||||
addToRunTimeSelectionTable(coordSetWriter, vtkWriter, word);
|
||||
addToRunTimeSelectionTable(coordSetWriter, vtkWriter, wordDict);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::vtkSetWriter<Type>::vtkSetWriter()
|
||||
Foam::coordSetWriters::vtkWriter::vtkWriter()
|
||||
:
|
||||
writer<Type>()
|
||||
coordSetWriter(),
|
||||
fmtType_(static_cast<unsigned>(vtk::formatType::INLINE_BASE64)),
|
||||
precision_(IOstream::defaultPrecision()),
|
||||
writer_(nullptr)
|
||||
{}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::vtkSetWriter<Type>::vtkSetWriter(const dictionary& dict)
|
||||
Foam::coordSetWriters::vtkWriter::vtkWriter
|
||||
(
|
||||
const vtk::outputOptions& opts
|
||||
)
|
||||
:
|
||||
writer<Type>(dict)
|
||||
coordSetWriter(),
|
||||
fmtType_(static_cast<unsigned>(opts.fmt())),
|
||||
precision_(opts.precision()),
|
||||
writer_(nullptr)
|
||||
{}
|
||||
|
||||
|
||||
Foam::coordSetWriters::vtkWriter::vtkWriter(const dictionary& options)
|
||||
:
|
||||
coordSetWriter(options),
|
||||
fmtType_(static_cast<unsigned>(vtk::formatType::INLINE_BASE64)),
|
||||
precision_
|
||||
(
|
||||
options.getOrDefault("precision", IOstream::defaultPrecision())
|
||||
),
|
||||
writer_(nullptr)
|
||||
{
|
||||
// format: ascii | binary
|
||||
// legacy: true | false
|
||||
|
||||
vtk::outputOptions opts(vtk::formatType::INLINE_BASE64);
|
||||
opts.ascii
|
||||
(
|
||||
IOstream::ASCII
|
||||
== IOstream::formatEnum("format", options, IOstream::BINARY)
|
||||
);
|
||||
|
||||
opts.legacy(options.getOrDefault("legacy", false));
|
||||
|
||||
// Convert back to raw data type
|
||||
fmtType_ = static_cast<unsigned>(opts.fmt());
|
||||
}
|
||||
|
||||
|
||||
Foam::coordSetWriters::vtkWriter::vtkWriter
|
||||
(
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
vtkWriter(options)
|
||||
{
|
||||
open(coords, outputPath);
|
||||
}
|
||||
|
||||
|
||||
Foam::coordSetWriters::vtkWriter::vtkWriter
|
||||
(
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
vtkWriter(options)
|
||||
{
|
||||
open(tracks, outputPath);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::coordSetWriters::vtkWriter::~vtkWriter()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::vtkSetWriter<Type>::getFileName
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSetNames
|
||||
) const
|
||||
Foam::fileName Foam::coordSetWriters::vtkWriter::path() const
|
||||
{
|
||||
return this->getBaseName(points, valueSetNames) + ".vtk";
|
||||
// 1) rootdir/<TIME>/setName.{vtk|vtp}
|
||||
// 2) rootdir/setName.{vtk|vtp}
|
||||
|
||||
// From raw unsigned value to vtk::outputOptions
|
||||
vtk::outputOptions opts(static_cast<vtk::formatType>(fmtType_));
|
||||
|
||||
return getExpectedPath(vtk::polyWriter::ext(opts));
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::vtkSetWriter<Type>::write
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSetNames,
|
||||
const List<const Field<Type>*>& valueSets,
|
||||
Ostream& os
|
||||
) const
|
||||
void Foam::coordSetWriters::vtkWriter::close(bool force)
|
||||
{
|
||||
os << "# vtk DataFile Version 2.0" << nl
|
||||
<< points.name() << nl
|
||||
<< "ASCII" << nl
|
||||
<< "DATASET POLYDATA" << nl
|
||||
<< "POINTS " << points.size() << " double" << nl;
|
||||
writer_.clear();
|
||||
coordSetWriter::close(force);
|
||||
}
|
||||
|
||||
for (const point& pt : points)
|
||||
|
||||
void Foam::coordSetWriters::vtkWriter::beginTime(const Time& t)
|
||||
{
|
||||
writer_.clear();
|
||||
coordSetWriter::beginTime(t);
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriters::vtkWriter::beginTime(const instant& inst)
|
||||
{
|
||||
writer_.clear();
|
||||
coordSetWriter::beginTime(inst);
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriters::vtkWriter::endTime()
|
||||
{
|
||||
writer_.clear();
|
||||
coordSetWriter::endTime();
|
||||
}
|
||||
|
||||
|
||||
Foam::fileName Foam::coordSetWriters::vtkWriter::write()
|
||||
{
|
||||
checkOpen();
|
||||
if (needsUpdate())
|
||||
{
|
||||
os << float(pt.x()) << ' '
|
||||
<< float(pt.y()) << ' '
|
||||
<< float(pt.z()) << nl;
|
||||
writer_.clear();
|
||||
}
|
||||
merge();
|
||||
|
||||
if (coords_.empty())
|
||||
{
|
||||
return fileName::null;
|
||||
}
|
||||
|
||||
os << "POINT_DATA " << points.size() << nl
|
||||
<< " FIELD attributes " << valueSetNames.size() << nl;
|
||||
// From raw unsigned values to vtk::outputOptions
|
||||
vtk::outputOptions opts(static_cast<vtk::formatType>(fmtType_), precision_);
|
||||
|
||||
forAll(valueSetNames, setI)
|
||||
|
||||
// Geometry: rootdir/<TIME>/setName.{vtk|vtp}
|
||||
|
||||
fileName outputFile = getExpectedPath(vtk::polyWriter::ext(opts));
|
||||
|
||||
if (verbose_)
|
||||
{
|
||||
os << valueSetNames[setI] << ' '
|
||||
<< int(pTraits<Type>::nComponents) << ' '
|
||||
<< points.size() << " float" << nl;
|
||||
Info<< "Writing geometry to " << outputFile << endl;
|
||||
}
|
||||
|
||||
const Field<Type>& fld = *valueSets[setI];
|
||||
|
||||
forAll(fld, pointi)
|
||||
if (!writer_ && true) // always (non-parallel)
|
||||
{
|
||||
UPtrList<const pointField> points(coords_.size());
|
||||
forAll(coords_, tracki)
|
||||
{
|
||||
if (pointi)
|
||||
{
|
||||
os << ' ';
|
||||
}
|
||||
writer<Type>::write(fld[pointi], os);
|
||||
points.set(tracki, coords_.get(tracki));
|
||||
}
|
||||
os << nl;
|
||||
|
||||
writer_.reset
|
||||
(
|
||||
new vtk::coordSetWriter
|
||||
(
|
||||
points,
|
||||
opts,
|
||||
outputFile,
|
||||
false // serial!
|
||||
)
|
||||
);
|
||||
|
||||
if (useTracks_ || coords_.size() > 1)
|
||||
{
|
||||
writer_->setElementType(vtk::coordSetWriter::LINE_ELEMENTS);
|
||||
}
|
||||
|
||||
if (this->hasTime())
|
||||
{
|
||||
// Time name in title
|
||||
writer_->setTime(currTime_);
|
||||
writer_->writeTimeValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set name in title
|
||||
writer_->beginFile(outputPath_.nameLessExt());
|
||||
}
|
||||
|
||||
writer_->writeGeometry();
|
||||
}
|
||||
|
||||
wroteGeom_ = true;
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Implementation * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
void Foam::vtkSetWriter<Type>::write
|
||||
Foam::fileName Foam::coordSetWriters::vtkWriter::writeTemplate
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream& os
|
||||
) const
|
||||
const word& fieldName,
|
||||
const UPtrList<const Field<Type>>& fieldPtrs
|
||||
)
|
||||
{
|
||||
if (valueSets.size() != valueSetNames.size())
|
||||
if (coords_.size() != fieldPtrs.size())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Number of variables:" << valueSetNames.size() << endl
|
||||
<< "Number of valueSets:" << valueSets.size()
|
||||
<< "Attempted to write field: " << fieldName
|
||||
<< " (" << fieldPtrs.size() << " entries) for "
|
||||
<< coords_.size() << " sets" << nl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
label nTracks = tracks.size();
|
||||
label nPoints = 0;
|
||||
forAll(tracks, i)
|
||||
// Open file, writing geometry (if required)
|
||||
fileName outputFile = this->write();
|
||||
|
||||
if (!nFields_ && writer_->legacy())
|
||||
{
|
||||
nPoints += tracks[i].size();
|
||||
// Emit error message, but attempt to recover anyhow
|
||||
nFields_ = 1;
|
||||
|
||||
FatalErrorInFunction
|
||||
<< "Using VTK legacy format, but did not define nFields!"
|
||||
<< nl
|
||||
<< "Assuming nFields=1 (may be incorrect) and continuing..."
|
||||
<< nl
|
||||
<< " Field " << fieldName << " to " << outputFile << nl;
|
||||
|
||||
Info<< FatalError;
|
||||
Info<< endl;
|
||||
}
|
||||
|
||||
os << "# vtk DataFile Version 2.0" << nl
|
||||
<< tracks[0].name() << nl
|
||||
<< "ASCII" << nl
|
||||
<< "DATASET POLYDATA" << nl
|
||||
<< "POINTS " << nPoints << " double" << nl;
|
||||
writer_->beginPointData(nFields_);
|
||||
|
||||
for (const coordSet& points : tracks)
|
||||
{
|
||||
for (const point& pt : points)
|
||||
{
|
||||
os << float(pt.x()) << ' '
|
||||
<< float(pt.y()) << ' '
|
||||
<< float(pt.z()) << nl;
|
||||
}
|
||||
}
|
||||
writer_->writePointData(fieldName, fieldPtrs);
|
||||
|
||||
if (writeTracks)
|
||||
{
|
||||
os << "LINES " << nTracks << ' ' << nPoints+nTracks << nl;
|
||||
|
||||
// Write ids of track points to file
|
||||
label globalPtI = 0;
|
||||
forAll(tracks, trackI)
|
||||
{
|
||||
const coordSet& points = tracks[trackI];
|
||||
|
||||
const label len = points.size();
|
||||
|
||||
os << len;
|
||||
for (label i = 0; i < len; ++i)
|
||||
{
|
||||
os << ' ' << globalPtI;
|
||||
++globalPtI;
|
||||
}
|
||||
os << nl;
|
||||
}
|
||||
}
|
||||
|
||||
os << "POINT_DATA " << nPoints << nl
|
||||
<< " FIELD attributes " << valueSetNames.size() << nl;
|
||||
|
||||
forAll(valueSetNames, setI)
|
||||
{
|
||||
os << valueSetNames[setI] << ' '
|
||||
<< int(pTraits<Type>::nComponents) << ' '
|
||||
<< nPoints << " float" << nl;
|
||||
|
||||
const List<Field<Type>>& fieldVals = valueSets[setI];
|
||||
|
||||
for (const Field<Type>& vals : fieldVals)
|
||||
{
|
||||
forAll(vals, j)
|
||||
{
|
||||
if (j)
|
||||
{
|
||||
os << ' ';
|
||||
}
|
||||
writer<Type>::write(vals[j], os);
|
||||
}
|
||||
os << nl;
|
||||
}
|
||||
}
|
||||
wroteGeom_ = true;
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::coordSetWriters::vtkWriter::writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const Field<Type>& values
|
||||
)
|
||||
{
|
||||
checkOpen();
|
||||
if (coords_.empty())
|
||||
{
|
||||
return fileName::null;
|
||||
}
|
||||
|
||||
UPtrList<const Field<Type>> fieldPtrs(repackageFields(values));
|
||||
return writeTemplate(fieldName, fieldPtrs);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::coordSetWriters::vtkWriter::writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const List<Field<Type>>& fieldValues
|
||||
)
|
||||
{
|
||||
checkOpen();
|
||||
if (coords_.empty())
|
||||
{
|
||||
return fileName::null;
|
||||
}
|
||||
useTracks_ = true; // Extra safety
|
||||
|
||||
UPtrList<const Field<Type>> fieldPtrs(repackageFields(fieldValues));
|
||||
return writeTemplate(fieldName, fieldPtrs);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Field writing methods
|
||||
defineCoordSetWriterWriteFields(Foam::coordSetWriters::vtkWriter);
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
185
src/meshTools/coordSet/writers/vtk/vtkCoordSetWriter.H
Normal file
185
src/meshTools/coordSet/writers/vtk/vtkCoordSetWriter.H
Normal file
@ -0,0 +1,185 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2021-2022 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/>.
|
||||
|
||||
Class
|
||||
Foam::coordSetWriters::vtkWriter
|
||||
|
||||
Description
|
||||
|
||||
SourceFiles
|
||||
vtkCoordSetWriter.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_coordSetWriters_vtkWriter_H
|
||||
#define Foam_coordSetWriters_vtkWriter_H
|
||||
|
||||
#include "coordSetWriter.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward Declarations
|
||||
class OFstream;
|
||||
|
||||
namespace vtk
|
||||
{
|
||||
// Forward Declarations
|
||||
class outputOptions;
|
||||
class coordSetWriter;
|
||||
}
|
||||
|
||||
namespace coordSetWriters
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class vtkCoordSetWriter Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class vtkWriter
|
||||
:
|
||||
public coordSetWriter
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- The VTK output format type.
|
||||
// Stored as a raw value to avoid a header dependency on fileFormats
|
||||
unsigned fmtType_;
|
||||
|
||||
//- ASCII write precision
|
||||
unsigned precision_;
|
||||
|
||||
//- Backend writer - master only
|
||||
autoPtr<Foam::vtk::coordSetWriter> writer_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const UPtrList<const Field<Type>>& fieldPtrs
|
||||
);
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName, //!< Name of field
|
||||
const Field<Type>& vals //!< Local field values to write
|
||||
);
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const List<Field<Type>>& fieldValues
|
||||
);
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information (no debug)
|
||||
TypeNameNoDebug("vtk");
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
vtkWriter();
|
||||
|
||||
//- Construct with some output options
|
||||
explicit vtkWriter(const vtk::outputOptions& opts);
|
||||
|
||||
//- Default construct with specified options
|
||||
explicit vtkWriter(const dictionary& options);
|
||||
|
||||
//- Construct from components
|
||||
vtkWriter
|
||||
(
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
//- Construct from components
|
||||
vtkWriter
|
||||
(
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
|
||||
//- Destructor. Calls close()
|
||||
virtual ~vtkWriter();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Expected (characteristic) output file name - information only
|
||||
virtual fileName path() const; // override
|
||||
|
||||
//- Close and reset, clears backend.
|
||||
virtual void close(bool force = false); // override
|
||||
|
||||
//- Begin time step. Clears existing backend.
|
||||
virtual void beginTime(const Time& t); // override
|
||||
|
||||
//- Begin time step. Clears existing backend.
|
||||
virtual void beginTime(const instant& inst); // override
|
||||
|
||||
//- End time step. Clears existing backend.
|
||||
virtual void endTime(); // override
|
||||
|
||||
|
||||
// Write
|
||||
|
||||
//- Write geometry to file.
|
||||
virtual fileName write(); // override
|
||||
|
||||
declareCoordSetWriterWriteMethod(label);
|
||||
declareCoordSetWriterWriteMethod(scalar);
|
||||
declareCoordSetWriterWriteMethod(vector);
|
||||
declareCoordSetWriterWriteMethod(sphericalTensor);
|
||||
declareCoordSetWriterWriteMethod(symmTensor);
|
||||
declareCoordSetWriterWriteMethod(tensor);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace coordSetWriters
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,120 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2021 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/>.
|
||||
|
||||
Class
|
||||
Foam::vtkSetWriter
|
||||
|
||||
Description
|
||||
|
||||
Note
|
||||
The output order of symmTensor is incorrect.
|
||||
|
||||
SourceFiles
|
||||
vtkCoordSetWriter.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_coordSetWriters_vtkWriter_H
|
||||
#define Foam_coordSetWriters_vtkWriter_H
|
||||
|
||||
#include "writer.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class vtkSetWriter Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Type>
|
||||
class vtkSetWriter
|
||||
:
|
||||
public writer<Type>
|
||||
{
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("vtk");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
vtkSetWriter();
|
||||
|
||||
//- Construct with dictionary
|
||||
explicit vtkSetWriter(const dictionary& dict);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~vtkSetWriter() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
virtual fileName getFileName
|
||||
(
|
||||
const coordSet&,
|
||||
const wordList&
|
||||
) const;
|
||||
|
||||
virtual void write
|
||||
(
|
||||
const coordSet&,
|
||||
const wordList&,
|
||||
const List<const Field<Type>*>&,
|
||||
Ostream&
|
||||
) const;
|
||||
|
||||
virtual void write
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream&
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "vtkCoordSetWriter.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,39 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2012 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
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 "vtkSetWriter.H"
|
||||
#include "writers.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
makeSetWriters(vtkSetWriter);
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2021 OpenCFD Ltd.
|
||||
Copyright (C) 2021-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -26,110 +26,244 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "xmgraceSetWriter.H"
|
||||
#include "xmgraceCoordSetWriter.H"
|
||||
#include "coordSet.H"
|
||||
#include "fileName.H"
|
||||
#include "OFstream.H"
|
||||
#include "OSspecific.H"
|
||||
#include "coordSetWriterMethods.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace coordSetWriters
|
||||
{
|
||||
defineTypeName(xmgraceWriter);
|
||||
addToRunTimeSelectionTable(coordSetWriter, xmgraceWriter, word);
|
||||
addToRunTimeSelectionTable(coordSetWriter, xmgraceWriter, wordDict);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Implementation
|
||||
#include "xmgraceCoordSetWriterImpl.C"
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::xmgraceSetWriter<Type>::xmgraceSetWriter()
|
||||
Foam::coordSetWriters::xmgraceWriter::xmgraceWriter()
|
||||
:
|
||||
writer<Type>()
|
||||
{}
|
||||
coordSetWriter(),
|
||||
streamOpt_(),
|
||||
precision_(IOstream::defaultPrecision()),
|
||||
ofile_(nullptr),
|
||||
nWritten_(0)
|
||||
{
|
||||
buffering_ = true;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::xmgraceSetWriter<Type>::xmgraceSetWriter(const dictionary& dict)
|
||||
Foam::coordSetWriters::xmgraceWriter::xmgraceWriter(const dictionary& options)
|
||||
:
|
||||
writer<Type>(dict)
|
||||
{}
|
||||
coordSetWriter(options),
|
||||
streamOpt_
|
||||
(
|
||||
IOstream::ASCII,
|
||||
IOstream::compressionEnum("compression", options)
|
||||
),
|
||||
precision_
|
||||
(
|
||||
options.getOrDefault("precision", IOstream::defaultPrecision())
|
||||
),
|
||||
ofile_(nullptr),
|
||||
nWritten_(0)
|
||||
{
|
||||
buffering_ = options.getOrDefault("buffer", true);
|
||||
}
|
||||
|
||||
|
||||
Foam::coordSetWriters::xmgraceWriter::xmgraceWriter
|
||||
(
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
xmgraceWriter(options)
|
||||
{
|
||||
open(coords, outputPath);
|
||||
}
|
||||
|
||||
|
||||
Foam::coordSetWriters::xmgraceWriter::xmgraceWriter
|
||||
(
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options
|
||||
)
|
||||
:
|
||||
xmgraceWriter(options)
|
||||
{
|
||||
open(tracks, outputPath);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::coordSetWriters::xmgraceWriter::~xmgraceWriter()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::xmgraceSetWriter<Type>::getFileName
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSetNames
|
||||
) const
|
||||
bool Foam::coordSetWriters::xmgraceWriter::buffering(const bool on)
|
||||
{
|
||||
return this->getBaseName(points, valueSetNames) + ".agr";
|
||||
const bool old(buffering_);
|
||||
buffering_ = on;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
Foam::fileName Foam::coordSetWriters::xmgraceWriter::path() const
|
||||
{
|
||||
// Assume !useTracks_, otherwise too fragile
|
||||
|
||||
// 1) rootdir/<TIME>/setName.agr
|
||||
// 2) rootdir/setName.agr
|
||||
|
||||
return getExpectedPath("agr");
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriters::xmgraceWriter::close(bool force)
|
||||
{
|
||||
ofile_.reset(nullptr);
|
||||
nWritten_ = 0;
|
||||
coordSetWriter::close(force);
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriters::xmgraceWriter::beginTime(const Time& t)
|
||||
{
|
||||
ofile_.reset(nullptr);
|
||||
nWritten_ = 0;
|
||||
coordSetWriter::beginTime(t);
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriters::xmgraceWriter::beginTime(const instant& inst)
|
||||
{
|
||||
ofile_.reset(nullptr);
|
||||
nWritten_ = 0;
|
||||
coordSetWriter::beginTime(inst);
|
||||
}
|
||||
|
||||
|
||||
void Foam::coordSetWriters::xmgraceWriter::endTime()
|
||||
{
|
||||
ofile_.reset(nullptr);
|
||||
nWritten_ = 0;
|
||||
coordSetWriter::endTime();
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::xmgraceSetWriter<Type>::write
|
||||
Foam::fileName Foam::coordSetWriters::xmgraceWriter::writeTemplate
|
||||
(
|
||||
const coordSet& points,
|
||||
const wordList& valueSetNames,
|
||||
const List<const Field<Type>*>& valueSets,
|
||||
Ostream& os
|
||||
) const
|
||||
const word& fieldName,
|
||||
const Field<Type>& values
|
||||
)
|
||||
{
|
||||
os << "@g0 on" << nl
|
||||
<< "@with g0" << nl
|
||||
<< "@ title \"" << points.name() << '"' << nl
|
||||
<< "@ xaxis label " << '"' << points.axis() << '"' << nl;
|
||||
|
||||
forAll(valueSets, i)
|
||||
checkOpen();
|
||||
if (coords_.empty())
|
||||
{
|
||||
os << "@ s" << i << " legend " << '"'
|
||||
<< valueSetNames[i] << '"' << nl
|
||||
<< "@target G0.S" << i << nl;
|
||||
|
||||
this->writeTable(points, *valueSets[i], os);
|
||||
|
||||
os << '&' << nl;
|
||||
return fileName::null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::xmgraceSetWriter<Type>::write
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream& os
|
||||
) const
|
||||
{
|
||||
if (valueSets.size() != valueSetNames.size())
|
||||
if (useTracks_ || !buffering_)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Number of variables:" << valueSetNames.size() << endl
|
||||
<< "Number of valueSets:" << valueSets.size()
|
||||
<< exit(FatalError);
|
||||
UPtrList<const Field<Type>> fieldPtrs(repackageFields(values));
|
||||
return writeTemplate(fieldName, fieldPtrs);
|
||||
}
|
||||
if (tracks.size() > 0)
|
||||
|
||||
|
||||
// Regular version
|
||||
|
||||
const auto& coords = coords_[0];
|
||||
|
||||
if (!ofile_)
|
||||
{
|
||||
// Field:
|
||||
// 1) rootdir/<TIME>/setName.agr
|
||||
// 2) rootdir/setName.agr
|
||||
|
||||
const fileName outputFile = path();
|
||||
|
||||
if (!isDir(outputFile.path()))
|
||||
{
|
||||
mkDir(outputFile.path());
|
||||
}
|
||||
|
||||
ofile_.reset(new OFstream(outputFile, streamOpt_));
|
||||
auto& os = ofile_();
|
||||
os.precision(precision_);
|
||||
|
||||
// Preamble
|
||||
os << "@g0 on" << nl
|
||||
<< "@with g0" << nl
|
||||
<< "@ title \"" << tracks[0].name() << '"' << nl
|
||||
<< "@ xaxis label " << '"' << tracks[0].axis() << '"' << nl;
|
||||
<< "@ title \"" << coords.name() << '"' << nl
|
||||
<< "@ xaxis label \"" << coords.axis() << '"' << nl;
|
||||
|
||||
// Data index.
|
||||
label sI = 0;
|
||||
|
||||
forAll(tracks, trackI)
|
||||
{
|
||||
forAll(valueSets, i)
|
||||
{
|
||||
os << "@ s" << sI << " legend " << '"'
|
||||
<< valueSetNames[i] << "_track" << i << '"' << nl
|
||||
<< "@target G0.S" << sI << nl;
|
||||
this->writeTable(tracks[trackI], valueSets[i][trackI], os);
|
||||
os << '&' << nl;
|
||||
|
||||
sI++;
|
||||
}
|
||||
}
|
||||
nWritten_ = 0; // Restarted
|
||||
}
|
||||
auto& os = ofile_();
|
||||
|
||||
// Plot entry
|
||||
{
|
||||
os << "@ s" << nWritten_
|
||||
<< " legend \"" << fieldName << '"' << nl
|
||||
<< "@target G0.S" << nWritten_ << nl;
|
||||
|
||||
writeTable(os, coords, values, " \t");
|
||||
|
||||
os << '&' << nl;
|
||||
os << "# end_data" << nl;
|
||||
++nWritten_;
|
||||
}
|
||||
|
||||
return ofile_().name();
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::coordSetWriters::xmgraceWriter::writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const List<Field<Type>>& fieldValues
|
||||
)
|
||||
{
|
||||
checkOpen();
|
||||
if (coords_.empty())
|
||||
{
|
||||
return fileName::null;
|
||||
}
|
||||
useTracks_ = true; // Extra safety
|
||||
|
||||
UPtrList<const Field<Type>> fieldPtrs(repackageFields(fieldValues));
|
||||
return writeTemplate(fieldName, fieldPtrs);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Field writing methods
|
||||
defineCoordSetWriterWriteFields(Foam::coordSetWriters::xmgraceWriter);
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
204
src/meshTools/coordSet/writers/xmgrace/xmgraceCoordSetWriter.H
Normal file
204
src/meshTools/coordSet/writers/xmgrace/xmgraceCoordSetWriter.H
Normal file
@ -0,0 +1,204 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 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/>.
|
||||
|
||||
Class
|
||||
Foam::coordSetWriters::xmgraceWriter
|
||||
|
||||
Description
|
||||
Write coordSet(s) in xmgrace format
|
||||
|
||||
The formatOptions for xmgrace:
|
||||
\table
|
||||
Property | Description | Required | Default
|
||||
buffer | Use buffered output | no | true
|
||||
compression | Use file compression | no | false
|
||||
precision | Write precision in ascii | no | same as IOstream
|
||||
\endtable
|
||||
|
||||
When called with a single coordSet, will combine all output fields
|
||||
into a single file. Although it is nominally 'buffered', it actually
|
||||
just keeps track of the number of fields written into the file.
|
||||
|
||||
When called as a track writer (eg, with multiple coordSets),
|
||||
will emit one file per field.
|
||||
|
||||
\section Output file locations
|
||||
|
||||
The \c rootdir normally corresponds to something like
|
||||
\c postProcessing/\<name\>
|
||||
|
||||
\subsection Geometry and Fields
|
||||
\verbatim
|
||||
rootdir
|
||||
`-- timeName
|
||||
`-- setName.{agr}
|
||||
\endverbatim
|
||||
|
||||
SourceFiles
|
||||
xmgraceCoordSetWriter.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_coordSetWriters_xmgraceWriter_H
|
||||
#define Foam_coordSetWriters_xmgraceWriter_H
|
||||
|
||||
#include "coordSetWriter.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward Declarations
|
||||
class OFstream;
|
||||
|
||||
namespace coordSetWriters
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class xmgraceWriter Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class xmgraceWriter
|
||||
:
|
||||
public coordSetWriter
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- Output stream option
|
||||
IOstreamOption streamOpt_;
|
||||
|
||||
//- ASCII write precision
|
||||
unsigned precision_;
|
||||
|
||||
//- Backend output file (when buffering)
|
||||
autoPtr<Foam::OFstream> ofile_;
|
||||
|
||||
//- The number of fields written (when buffering)
|
||||
label nWritten_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const UPtrList<const Field<Type>>& fieldPtrs
|
||||
);
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName, //!< Name of field
|
||||
const Field<Type>& vals //!< Local field values to write
|
||||
);
|
||||
|
||||
//- Templated write operation
|
||||
template<class Type>
|
||||
fileName writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const List<Field<Type>>& fieldValues
|
||||
);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information (no debug)
|
||||
TypeNameNoDebug("xmgr");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
xmgraceWriter();
|
||||
|
||||
//- Default construct with specified options
|
||||
explicit xmgraceWriter(const dictionary& options);
|
||||
|
||||
//- Construct from components
|
||||
xmgraceWriter
|
||||
(
|
||||
const coordSet& coords,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
//- Construct from components
|
||||
xmgraceWriter
|
||||
(
|
||||
const UPtrList<coordSet>& tracks,
|
||||
const fileName& outputPath,
|
||||
const dictionary& options = dictionary()
|
||||
);
|
||||
|
||||
|
||||
//- Destructor. Calls close()
|
||||
virtual ~xmgraceWriter();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Enable/disable internal buffering
|
||||
virtual bool buffering(const bool on); // override
|
||||
|
||||
//- Characteristic output file name - information only
|
||||
virtual fileName path() const; // override
|
||||
|
||||
//- Close and reset, clears backend.
|
||||
virtual void close(bool force = false); // override
|
||||
|
||||
//- Begin time step. Clears existing backend.
|
||||
virtual void beginTime(const Time& t); // override
|
||||
|
||||
//- Begin time step. Clears existing backend.
|
||||
virtual void beginTime(const instant& inst); // override
|
||||
|
||||
//- End time step. Clears existing backend.
|
||||
virtual void endTime(); // override
|
||||
|
||||
|
||||
declareCoordSetWriterWriteMethod(label);
|
||||
declareCoordSetWriterWriteMethod(scalar);
|
||||
declareCoordSetWriterWriteMethod(vector);
|
||||
declareCoordSetWriterWriteMethod(sphericalTensor);
|
||||
declareCoordSetWriterWriteMethod(symmTensor);
|
||||
declareCoordSetWriterWriteMethod(tensor);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace coordSetWriters
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,102 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "IOmanip.H"
|
||||
#include "OFstream.H"
|
||||
#include "OSspecific.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::coordSetWriters::xmgraceWriter::writeTemplate
|
||||
(
|
||||
const word& fieldName,
|
||||
const UPtrList<const Field<Type>>& fieldPtrs
|
||||
)
|
||||
{
|
||||
if (coords_.size() != fieldPtrs.size())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Attempted to write field: " << fieldName
|
||||
<< " (" << fieldPtrs.size() << " entries) for "
|
||||
<< coords_.size() << " sets" << nl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
|
||||
// Field: rootdir/<TIME>/<field>_setName.agr
|
||||
|
||||
fileName outputFile = getFieldPrefixedPath(fieldName, "agr");
|
||||
|
||||
if (verbose_)
|
||||
{
|
||||
Info<< "Writing field " << fieldName;
|
||||
Info<< " to " << outputFile << endl;
|
||||
}
|
||||
|
||||
// Master only
|
||||
{
|
||||
if (!isDir(outputFile.path()))
|
||||
{
|
||||
mkDir(outputFile.path());
|
||||
}
|
||||
|
||||
OFstream os(outputFile, streamOpt_);
|
||||
os.precision(precision_);
|
||||
|
||||
// Preamble
|
||||
{
|
||||
const coordSet& coords = coords_[0];
|
||||
|
||||
os << "@g0 on" << nl
|
||||
<< "@with g0" << nl
|
||||
<< "@ title \"" << coords.name() << '"' << nl
|
||||
<< "@ xaxis label \"" << coords.axis() << '"' << nl;
|
||||
}
|
||||
|
||||
const label setNumber = 0;
|
||||
|
||||
// Plot entry
|
||||
os << "@ s" << setNumber
|
||||
<< " legend \"" << fieldName << '"' << nl
|
||||
<< "@target G0.S" << setNumber << nl;
|
||||
|
||||
forAll(coords_, tracki)
|
||||
{
|
||||
writeTable(os, coords_[tracki], fieldPtrs[tracki], " \t");
|
||||
}
|
||||
|
||||
os << '&' << nl;
|
||||
os << "# end_data" << nl;
|
||||
}
|
||||
|
||||
wroteGeom_ = true;
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,117 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2021 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/>.
|
||||
|
||||
Class
|
||||
Foam::xmgraceSetWriter
|
||||
|
||||
Description
|
||||
|
||||
SourceFiles
|
||||
xmgraceCoordSetWriter.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_coordSetWriters_xmgraceWriter_H
|
||||
#define Foam_coordSetWriters_xmgraceWriter_H
|
||||
|
||||
#include "writer.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class xmgraceSetWriter Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Type>
|
||||
class xmgraceSetWriter
|
||||
:
|
||||
public writer<Type>
|
||||
{
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("xmgr");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
xmgraceSetWriter();
|
||||
|
||||
//- Construct with dictionary
|
||||
explicit xmgraceSetWriter(const dictionary& dict);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~xmgraceSetWriter() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
virtual fileName getFileName
|
||||
(
|
||||
const coordSet&,
|
||||
const wordList&
|
||||
) const;
|
||||
|
||||
virtual void write
|
||||
(
|
||||
const coordSet&,
|
||||
const wordList&,
|
||||
const List<const Field<Type>*>&,
|
||||
Ostream&
|
||||
) const;
|
||||
|
||||
virtual void write
|
||||
(
|
||||
const bool writeTracks,
|
||||
const List<scalarField>& times,
|
||||
const PtrList<coordSet>& tracks,
|
||||
const wordList& valueSetNames,
|
||||
const List<List<Field<Type>>>& valueSets,
|
||||
Ostream&
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "xmgraceCoordSetWriter.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,39 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2012 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
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 "xmgraceSetWriter.H"
|
||||
#include "writers.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
makeSetWriters(xmgraceSetWriter);
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2020 OpenCFD Ltd.
|
||||
Copyright (C) 2015-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -32,7 +32,7 @@ License
|
||||
#include "Time.H"
|
||||
#include "DynamicField.H"
|
||||
#include "PatchTools.H"
|
||||
#include "writer.H"
|
||||
#include "coordSetWriter.H"
|
||||
#include "triSurfaceMesh.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
@ -611,7 +611,7 @@ bool Foam::searchableSurfaces::checkSizes
|
||||
bool Foam::searchableSurfaces::checkIntersection
|
||||
(
|
||||
const scalar tolerance,
|
||||
const autoPtr<writer<scalar>>& setWriter,
|
||||
autoPtr<coordSetWriter>& setWriter,
|
||||
const bool report
|
||||
) const
|
||||
{
|
||||
@ -669,7 +669,7 @@ bool Foam::searchableSurfaces::checkIntersection
|
||||
|
||||
label nHits = 0;
|
||||
DynamicField<point> intersections(edges0.size()/100);
|
||||
DynamicField<scalar> intersectionEdge(intersections.capacity());
|
||||
DynamicField<label> intersectionEdge(intersections.capacity());
|
||||
|
||||
forAll(hits, edgeI)
|
||||
{
|
||||
@ -680,7 +680,7 @@ bool Foam::searchableSurfaces::checkIntersection
|
||||
)
|
||||
{
|
||||
intersections.append(hits[edgeI].hitPoint());
|
||||
intersectionEdge.append(1.0*edgeI);
|
||||
intersectionEdge.append(edgeI);
|
||||
nHits++;
|
||||
}
|
||||
}
|
||||
@ -698,7 +698,7 @@ bool Foam::searchableSurfaces::checkIntersection
|
||||
<< " locations."
|
||||
<< endl;
|
||||
|
||||
if (setWriter)
|
||||
if (setWriter && setWriter->enabled())
|
||||
{
|
||||
scalarField dist(mag(intersections));
|
||||
coordSet track
|
||||
@ -708,31 +708,27 @@ bool Foam::searchableSurfaces::checkIntersection
|
||||
std::move(intersections),
|
||||
std::move(dist)
|
||||
);
|
||||
wordList valueSetNames(1, "edgeIndex");
|
||||
List<const scalarField*> valueSets
|
||||
(
|
||||
1,
|
||||
&intersectionEdge
|
||||
);
|
||||
|
||||
fileName fName
|
||||
(
|
||||
setWriter().getFileName(track, valueSetNames)
|
||||
);
|
||||
Info<< " Writing intersection locations to "
|
||||
<< fName << endl;
|
||||
OFstream os
|
||||
(
|
||||
s0.searchableSurface::time().path()
|
||||
/fName
|
||||
);
|
||||
setWriter().write
|
||||
|
||||
auto& writer = *setWriter;
|
||||
writer.nFields(1);
|
||||
|
||||
writer.open
|
||||
(
|
||||
track,
|
||||
valueSetNames,
|
||||
valueSets,
|
||||
os
|
||||
(
|
||||
s0.searchableSurface::time().path()
|
||||
/ (track.name() + "_edgeIndex")
|
||||
)
|
||||
);
|
||||
|
||||
fileName fName =
|
||||
writer.write("edgeIndex", intersectionEdge);
|
||||
|
||||
writer.close(true);
|
||||
|
||||
Info<< " Wrote intersection locations to "
|
||||
<< fName << endl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -841,7 +837,7 @@ Foam::label Foam::searchableSurfaces::checkGeometry
|
||||
(
|
||||
const scalar maxRatio,
|
||||
const scalar tol,
|
||||
const autoPtr<writer<scalar>>& setWriter,
|
||||
autoPtr<coordSetWriter>& setWriter,
|
||||
const scalar minQuality,
|
||||
const bool report
|
||||
) const
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -68,7 +69,7 @@ namespace Foam
|
||||
{
|
||||
|
||||
// Forward Declarations
|
||||
template<class T> class writer;
|
||||
class coordSetWriter;
|
||||
class triSurface;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
@ -254,7 +255,7 @@ public:
|
||||
bool checkIntersection
|
||||
(
|
||||
const scalar tol,
|
||||
const autoPtr<writer<scalar>>&,
|
||||
autoPtr<coordSetWriter>& setWriter,
|
||||
const bool report
|
||||
) const;
|
||||
|
||||
@ -273,7 +274,7 @@ public:
|
||||
(
|
||||
const scalar maxRatio,
|
||||
const scalar tolerance,
|
||||
const autoPtr<writer<scalar>>& setWriter,
|
||||
autoPtr<coordSetWriter>& setWriter,
|
||||
const scalar minQuality,
|
||||
const bool report
|
||||
) const;
|
||||
|
||||
@ -13,7 +13,6 @@ sampledSet/patchSeed/patchSeedSet.C
|
||||
sampledSet/patchEdge/patchEdgeSet.C
|
||||
sampledSet/sampledSet/sampledSet.C
|
||||
sampledSet/sampledSets/sampledSets.C
|
||||
sampledSet/sampledSets/sampledSetsGrouping.C
|
||||
sampledSet/triSurfaceMeshPointSet/triSurfaceMeshPointSet.C
|
||||
sampledSet/uniform/uniformSet.C
|
||||
sampledSet/array/arraySet.C
|
||||
|
||||
@ -57,11 +57,11 @@ void Foam::midPointAndFaceSet::genSamples()
|
||||
while (size() > 0)
|
||||
{
|
||||
// Add first face
|
||||
mpfSamplePoints[mpfSamplei] = operator[](samplei);
|
||||
mpfSamplePoints[mpfSamplei] = points()[samplei];
|
||||
mpfSampleCells[mpfSamplei] = cells_[samplei];
|
||||
mpfSampleFaces[mpfSamplei] = faces_[samplei];
|
||||
mpfSampleSegments[mpfSamplei] = segments_[samplei];
|
||||
mpfSampleCurveDist[mpfSamplei] = curveDist_[samplei];
|
||||
mpfSampleCurveDist[mpfSamplei] = distance_[samplei];
|
||||
++mpfSamplei;
|
||||
|
||||
while
|
||||
@ -70,7 +70,7 @@ void Foam::midPointAndFaceSet::genSamples()
|
||||
&& (segments_[samplei] == segments_[samplei+1])
|
||||
)
|
||||
{
|
||||
point midPoint(0.5*(operator[](samplei) + operator[](samplei+1)));
|
||||
point midPoint(0.5*(points()[samplei] + points()[samplei+1]));
|
||||
label cellm = pointInCell(midPoint, samplei);
|
||||
|
||||
if (cellm != -1)
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2018-2021 OpenCFD Ltd.
|
||||
Copyright (C) 2018-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -30,7 +30,6 @@ License
|
||||
#include "polyMesh.H"
|
||||
#include "primitiveMesh.H"
|
||||
#include "meshSearch.H"
|
||||
#include "writer.H"
|
||||
#include "particle.H"
|
||||
#include "globalIndex.H"
|
||||
|
||||
@ -52,16 +51,16 @@ void Foam::sampledSet::checkDimensions() const
|
||||
(cells_.size() != size())
|
||||
|| (faces_.size() != size())
|
||||
|| (segments_.size() != size())
|
||||
|| (curveDist_.size() != size())
|
||||
|| (distance_.size() != size())
|
||||
)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "sizes not equal : "
|
||||
<< "Sizes not equal : "
|
||||
<< " points:" << size()
|
||||
<< " cells:" << cells_.size()
|
||||
<< " faces:" << faces_.size()
|
||||
<< " segments:" << segments_.size()
|
||||
<< " curveDist:" << curveDist_.size()
|
||||
<< " distance:" << distance_.size()
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
@ -75,14 +74,12 @@ Foam::label Foam::sampledSet::getBoundaryCell(const label facei) const
|
||||
|
||||
Foam::label Foam::sampledSet::getNeighbourCell(const label facei) const
|
||||
{
|
||||
if (facei >= mesh().nInternalFaces())
|
||||
{
|
||||
return mesh().faceOwner()[facei];
|
||||
}
|
||||
else
|
||||
if (facei < mesh().nInternalFaces())
|
||||
{
|
||||
return mesh().faceNeighbour()[facei];
|
||||
}
|
||||
|
||||
return mesh().faceOwner()[facei];
|
||||
}
|
||||
|
||||
|
||||
@ -384,11 +381,11 @@ void Foam::sampledSet::setSamples
|
||||
const labelList& samplingCells,
|
||||
const labelList& samplingFaces,
|
||||
const labelList& samplingSegments,
|
||||
const scalarList& samplingCurveDist
|
||||
const scalarList& samplingDistance
|
||||
)
|
||||
{
|
||||
setPoints(samplingPts);
|
||||
curveDist_ = samplingCurveDist;
|
||||
setDistance(samplingDistance, false); // check=false
|
||||
|
||||
segments_ = samplingSegments;
|
||||
cells_ = samplingCells;
|
||||
@ -404,11 +401,11 @@ void Foam::sampledSet::setSamples
|
||||
labelList&& samplingCells,
|
||||
labelList&& samplingFaces,
|
||||
labelList&& samplingSegments,
|
||||
scalarList&& samplingCurveDist
|
||||
scalarList&& samplingDistance
|
||||
)
|
||||
{
|
||||
setPoints(std::move(samplingPts));
|
||||
curveDist_ = std::move(samplingCurveDist);
|
||||
setDistance(std::move(samplingDistance), false); // check=false
|
||||
|
||||
segments_ = std::move(samplingSegments);
|
||||
cells_ = std::move(samplingCells);
|
||||
@ -418,48 +415,6 @@ void Foam::sampledSet::setSamples
|
||||
}
|
||||
|
||||
|
||||
Foam::autoPtr<Foam::coordSet> Foam::sampledSet::gather
|
||||
(
|
||||
labelList& indexSet,
|
||||
labelList& allSegments
|
||||
) const
|
||||
{
|
||||
// Combine sampleSet from processors. Sort by curveDist. Return
|
||||
// ordering in indexSet.
|
||||
// Note: only master results are valid
|
||||
|
||||
List<point> allPts;
|
||||
globalIndex::gatherOp(*this, allPts);
|
||||
|
||||
globalIndex::gatherOp(segments(), allSegments);
|
||||
|
||||
scalarList allCurveDist;
|
||||
globalIndex::gatherOp(curveDist(), allCurveDist);
|
||||
|
||||
|
||||
if (Pstream::master() && allCurveDist.empty())
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Sample set " << name()
|
||||
<< " has zero points." << endl;
|
||||
}
|
||||
|
||||
// Sort curveDist and use to fill masterSamplePts
|
||||
Foam::sortedOrder(allCurveDist, indexSet); // uses stable sort
|
||||
scalarList sortedDist(allCurveDist, indexSet); // with indices for mapping
|
||||
|
||||
allSegments = UIndirectList<label>(allSegments, indexSet)();
|
||||
|
||||
return autoPtr<coordSet>::New
|
||||
(
|
||||
name(),
|
||||
axis(),
|
||||
List<point>(UIndirectList<point>(allPts, indexSet)),
|
||||
sortedDist
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::sampledSet::sampledSet
|
||||
@ -513,6 +468,25 @@ Foam::sampledSet::sampledSet
|
||||
{}
|
||||
|
||||
|
||||
// Foam::autoPtr<Foam::coordSet> Foam::sampledSet::gather
|
||||
// (
|
||||
// labelList& sortOrder,
|
||||
// labelList& allSegments
|
||||
// ) const
|
||||
// {
|
||||
// autoPtr<coordSet> result(coordSet::gatherSort(sortOrder));
|
||||
//
|
||||
// // Optional
|
||||
// if (notNull(allSegments))
|
||||
// {
|
||||
// globalIndex::gatherOp(segments(), allSegments);
|
||||
// allSegments = UIndirectList<label>(allSegments, sortOrder)();
|
||||
// }
|
||||
//
|
||||
// return result;
|
||||
// }
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::autoPtr<Foam::sampledSet> Foam::sampledSet::New
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2017-2018 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -50,20 +50,20 @@ SourceFiles
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef sampledSet_H
|
||||
#define sampledSet_H
|
||||
#ifndef Foam_sampledSet_H
|
||||
#define Foam_sampledSet_H
|
||||
|
||||
#include "coordSet.H"
|
||||
#include "autoPtr.H"
|
||||
#include "typeInfo.H"
|
||||
#include "runTimeSelectionTables.H"
|
||||
#include "autoPtr.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declarations
|
||||
// Forward Declarations
|
||||
class polyMesh;
|
||||
class meshSearch;
|
||||
|
||||
@ -75,7 +75,7 @@ class sampledSet
|
||||
:
|
||||
public coordSet
|
||||
{
|
||||
// Private data
|
||||
// Private Data
|
||||
|
||||
//- Reference to mesh
|
||||
const polyMesh& mesh_;
|
||||
@ -86,6 +86,8 @@ class sampledSet
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- Segment numbers
|
||||
labelList segments_;
|
||||
|
||||
@ -154,7 +156,7 @@ protected:
|
||||
const labelList& samplingCells,
|
||||
const labelList& samplingFaces,
|
||||
const labelList& samplingSegments,
|
||||
const scalarList& samplingCurveDist
|
||||
const scalarList& samplingDistance
|
||||
);
|
||||
|
||||
//- Set sample data. Move list contents.
|
||||
@ -164,7 +166,7 @@ protected:
|
||||
labelList&& samplingCells,
|
||||
labelList&& samplingFaces,
|
||||
labelList&& samplingSegments,
|
||||
scalarList&& samplingCurveDist
|
||||
scalarList&& samplingDistance
|
||||
);
|
||||
|
||||
public:
|
||||
@ -194,22 +196,58 @@ public:
|
||||
// PtrLists of sampledSet
|
||||
class iNew
|
||||
{
|
||||
//- Reference to the volume mesh
|
||||
const polyMesh& mesh_;
|
||||
const meshSearch& searchEngine_;
|
||||
const meshSearch& search_;
|
||||
|
||||
public:
|
||||
|
||||
iNew(const polyMesh& mesh, const meshSearch& searchEngine)
|
||||
:
|
||||
mesh_(mesh),
|
||||
searchEngine_(searchEngine)
|
||||
search_(searchEngine)
|
||||
{}
|
||||
|
||||
autoPtr<sampledSet> operator()(Istream& is) const
|
||||
{
|
||||
word name(is);
|
||||
dictionary dict(is);
|
||||
return sampledSet::New(name, mesh_, searchEngine_, dict);
|
||||
return sampledSet::New(name, mesh_, search_, dict);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//- PtrList read-construction helper that captures dictionaries used
|
||||
//- during creation.
|
||||
class iNewCapture
|
||||
{
|
||||
//- Reference to the volume mesh
|
||||
const polyMesh& mesh_;
|
||||
const meshSearch& search_;
|
||||
|
||||
//- Captured (recorded) dictionaries
|
||||
DynamicList<dictionary>& capture_;
|
||||
|
||||
public:
|
||||
|
||||
iNewCapture
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const meshSearch& searchEngine,
|
||||
DynamicList<dictionary>& capture
|
||||
)
|
||||
:
|
||||
mesh_(mesh),
|
||||
search_(searchEngine),
|
||||
capture_(capture)
|
||||
{}
|
||||
|
||||
autoPtr<sampledSet> operator()(Istream& is) const
|
||||
{
|
||||
word name(is);
|
||||
capture_.append(dictionary(is));
|
||||
|
||||
return sampledSet::New(name, mesh_, search_, capture_.last());
|
||||
}
|
||||
};
|
||||
|
||||
@ -269,27 +307,27 @@ public:
|
||||
|
||||
// Member Functions
|
||||
|
||||
const polyMesh& mesh() const
|
||||
const polyMesh& mesh() const noexcept
|
||||
{
|
||||
return mesh_;
|
||||
}
|
||||
|
||||
const meshSearch& searchEngine() const
|
||||
const meshSearch& searchEngine() const noexcept
|
||||
{
|
||||
return searchEngine_;
|
||||
}
|
||||
|
||||
const labelList& segments() const
|
||||
const labelList& segments() const noexcept
|
||||
{
|
||||
return segments_;
|
||||
}
|
||||
|
||||
const labelList& cells() const
|
||||
const labelList& cells() const noexcept
|
||||
{
|
||||
return cells_;
|
||||
}
|
||||
|
||||
const labelList& faces() const
|
||||
const labelList& faces() const noexcept
|
||||
{
|
||||
return faces_;
|
||||
}
|
||||
@ -297,13 +335,16 @@ public:
|
||||
//- Output for debugging
|
||||
Ostream& write(Ostream&) const;
|
||||
|
||||
//- Helper: gather onto master and sort.
|
||||
// \return (on master) gathered set and overall sort order
|
||||
autoPtr<coordSet> gather
|
||||
(
|
||||
labelList& indexSet,
|
||||
labelList& allSegments
|
||||
) const;
|
||||
|
||||
// Other
|
||||
|
||||
/// //- Gather and sort.
|
||||
/// \return (on master) gathered set and overall sort order
|
||||
/// autoPtr<coordSet> gather
|
||||
/// (
|
||||
/// labelList& sortOrder,
|
||||
/// labelList& allSegments
|
||||
/// ) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2020 OpenCFD Ltd.
|
||||
Copyright (C) 2011 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -29,9 +29,12 @@ License
|
||||
#include "sampledSets.H"
|
||||
#include "dictionary.H"
|
||||
#include "Time.H"
|
||||
#include "globalIndex.H"
|
||||
#include "volFields.H"
|
||||
#include "volPointInterpolation.H"
|
||||
#include "mapPolyMesh.H"
|
||||
#include "IOobjectList.H"
|
||||
#include "UIndirectList.H"
|
||||
#include "ListOps.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
@ -48,36 +51,287 @@ namespace Foam
|
||||
);
|
||||
}
|
||||
|
||||
bool Foam::sampledSets::verbose_ = false;
|
||||
|
||||
#include "sampledSetsImpl.C"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::sampledSets::combineSampledSets
|
||||
Foam::autoPtr<Foam::coordSetWriter> Foam::sampledSets::newWriter
|
||||
(
|
||||
PtrList<coordSet>& masterSampledSets,
|
||||
labelListList& indexSets
|
||||
word writeType,
|
||||
const dictionary& formatOptions,
|
||||
const dictionary& setDict
|
||||
)
|
||||
{
|
||||
// Combine sampleSets from processors. Sort by curveDist. Return
|
||||
// ordering in indexSets.
|
||||
// Note: only master results are valid
|
||||
// Per-set adjustment
|
||||
setDict.readIfPresent<word>("setFormat", writeType);
|
||||
|
||||
masterSampledSets_.clear();
|
||||
masterSampledSets_.setSize(size());
|
||||
indexSets_.setSize(size());
|
||||
dictionary options = formatOptions.subOrEmptyDict(writeType);
|
||||
|
||||
const PtrList<sampledSet>& sampledSets = *this;
|
||||
options.merge
|
||||
(
|
||||
setDict.subOrEmptyDict("formatOptions").subOrEmptyDict(writeType)
|
||||
);
|
||||
|
||||
forAll(sampledSets, setI)
|
||||
return coordSetWriter::New(writeType, options);
|
||||
}
|
||||
|
||||
|
||||
void Foam::sampledSets::gatherAllSets()
|
||||
{
|
||||
// Any writer references will become invalid
|
||||
for (auto& writer : writers_)
|
||||
{
|
||||
labelList segments;
|
||||
masterSampledSets.set
|
||||
(
|
||||
setI,
|
||||
sampledSets[setI].gather(indexSets[setI], segments)
|
||||
);
|
||||
writer.expire();
|
||||
}
|
||||
|
||||
const PtrList<sampledSet>& localSets = *this;
|
||||
|
||||
gatheredSets_.clear();
|
||||
gatheredSets_.resize(localSets.size());
|
||||
gatheredSorting_.resize_nocopy(localSets.size());
|
||||
globalIndices_.resize_nocopy(localSets.size());
|
||||
|
||||
forAll(localSets, seti)
|
||||
{
|
||||
const coordSet& coords = localSets[seti];
|
||||
|
||||
globalIndices_[seti].reset(coords.size(), globalIndex::gatherOnly{});
|
||||
gatheredSets_.set(seti, coords.gatherSort(gatheredSorting_[seti]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::IOobjectList Foam::sampledSets::preCheckFields()
|
||||
{
|
||||
wordList allFields; // Just needed for warnings
|
||||
HashTable<wordHashSet> selected;
|
||||
|
||||
IOobjectList objects(0);
|
||||
|
||||
if (loadFromFiles_)
|
||||
{
|
||||
// Check files for a particular time
|
||||
objects = IOobjectList(mesh_, mesh_.time().timeName());
|
||||
|
||||
allFields = objects.names();
|
||||
selected = objects.classes(fieldSelection_);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check currently available fields
|
||||
allFields = mesh_.names();
|
||||
selected = mesh_.classes(fieldSelection_);
|
||||
}
|
||||
|
||||
// Probably not needed...
|
||||
// if (Pstream::parRun())
|
||||
// {
|
||||
// Pstream::mapCombineGather(selected, HashSetOps::plusEqOp<word>());
|
||||
// Pstream::mapCombineScatter(selected);
|
||||
// }
|
||||
|
||||
|
||||
DynamicList<label> missed(fieldSelection_.size());
|
||||
|
||||
// Detect missing fields
|
||||
forAll(fieldSelection_, i)
|
||||
{
|
||||
if
|
||||
(
|
||||
fieldSelection_[i].isLiteral()
|
||||
&& !ListOps::found(allFields, fieldSelection_[i])
|
||||
)
|
||||
{
|
||||
missed.append(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (missed.size())
|
||||
{
|
||||
WarningInFunction
|
||||
<< nl
|
||||
<< "Cannot find "
|
||||
<< (loadFromFiles_ ? "field file" : "registered field")
|
||||
<< " matching "
|
||||
<< UIndirectList<wordRe>(fieldSelection_, missed) << endl;
|
||||
}
|
||||
|
||||
|
||||
// The selected field names, ordered by (scalar, vector, ...)
|
||||
// with internal sorting
|
||||
|
||||
selectedFieldNames_.clear();
|
||||
|
||||
do
|
||||
{
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(InputType) \
|
||||
{ \
|
||||
const auto iter = selected.find(InputType::typeName); \
|
||||
if (iter.found()) \
|
||||
{ \
|
||||
selectedFieldNames_.append(iter.val().sortedToc()); \
|
||||
} \
|
||||
}
|
||||
|
||||
doLocalCode(volScalarField);
|
||||
doLocalCode(volVectorField);
|
||||
doLocalCode(volSphericalTensorField);
|
||||
doLocalCode(volSymmTensorField);
|
||||
doLocalCode(volTensorField);
|
||||
#undef doLocalCode
|
||||
}
|
||||
while (false);
|
||||
|
||||
|
||||
// Now propagate field counts (per surface)
|
||||
// - can update writer even when not writing without problem
|
||||
|
||||
const label nFields = selectedFieldNames_.size();
|
||||
|
||||
forAll(writers_, seti)
|
||||
{
|
||||
coordSetWriter& writer = writers_[seti];
|
||||
|
||||
writer.nFields(nFields);
|
||||
}
|
||||
|
||||
return objects;
|
||||
}
|
||||
|
||||
|
||||
void Foam::sampledSets::initDict(const dictionary& dict, const bool initial)
|
||||
{
|
||||
PtrList<sampledSet>::clear();
|
||||
if (initial)
|
||||
{
|
||||
writers_.clear();
|
||||
}
|
||||
|
||||
const entry* eptr = dict.findEntry("sets");
|
||||
|
||||
if (eptr && eptr->isDict())
|
||||
{
|
||||
PtrList<sampledSet> sampSets(eptr->dict().size());
|
||||
if (initial)
|
||||
{
|
||||
writers_.resize(sampSets.size());
|
||||
}
|
||||
|
||||
label seti = 0;
|
||||
|
||||
for (const entry& dEntry : eptr->dict())
|
||||
{
|
||||
if (!dEntry.isDict())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const dictionary& subDict = dEntry.dict();
|
||||
|
||||
autoPtr<sampledSet> sampSet =
|
||||
sampledSet::New
|
||||
(
|
||||
dEntry.keyword(),
|
||||
mesh_,
|
||||
searchEngine_,
|
||||
subDict
|
||||
);
|
||||
|
||||
// if (!sampSet || !sampSet->enabled())
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// Define the set
|
||||
sampSets.set(seti, sampSet);
|
||||
|
||||
// Define writer, but do not attached
|
||||
if (initial)
|
||||
{
|
||||
writers_.set
|
||||
(
|
||||
seti,
|
||||
newWriter(writeFormat_, writeFormatOptions_, subDict)
|
||||
);
|
||||
|
||||
// Use outputDir/TIME/set-name
|
||||
writers_[seti].useTimeDir(true);
|
||||
writers_[seti].verbose(verbose_);
|
||||
}
|
||||
++seti;
|
||||
}
|
||||
|
||||
sampSets.resize(seti);
|
||||
if (initial)
|
||||
{
|
||||
writers_.resize(seti);
|
||||
}
|
||||
static_cast<PtrList<sampledSet>&>(*this).transfer(sampSets);
|
||||
}
|
||||
else if (eptr)
|
||||
{
|
||||
// This is slightly trickier.
|
||||
// We want access to the individual dictionaries used for construction
|
||||
|
||||
DynamicList<dictionary> capture;
|
||||
|
||||
PtrList<sampledSet> input
|
||||
(
|
||||
eptr->stream(),
|
||||
sampledSet::iNewCapture(mesh_, searchEngine_, capture)
|
||||
);
|
||||
|
||||
PtrList<sampledSet> sampSets(input.size());
|
||||
if (initial)
|
||||
{
|
||||
writers_.resize(sampSets.size());
|
||||
}
|
||||
|
||||
label seti = 0;
|
||||
|
||||
forAll(input, inputi)
|
||||
{
|
||||
const dictionary& subDict = capture[inputi];
|
||||
|
||||
autoPtr<sampledSet> sampSet = input.release(inputi);
|
||||
|
||||
// if (!sampSet || !sampSet->enabled())
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// Define the set
|
||||
sampSets.set(seti, sampSet);
|
||||
|
||||
// Define writer, but do not attached
|
||||
if (initial)
|
||||
{
|
||||
writers_.set
|
||||
(
|
||||
seti,
|
||||
newWriter(writeFormat_, writeFormatOptions_, subDict)
|
||||
);
|
||||
|
||||
// Use outputDir/TIME/set-name
|
||||
writers_[seti].useTimeDir(true);
|
||||
writers_[seti].verbose(verbose_);
|
||||
}
|
||||
++seti;
|
||||
}
|
||||
|
||||
sampSets.resize(seti);
|
||||
if (initial)
|
||||
{
|
||||
writers_.resize(seti);
|
||||
}
|
||||
|
||||
static_cast<PtrList<sampledSet>&>(*this).transfer(sampSets);
|
||||
}
|
||||
|
||||
gatherAllSets();
|
||||
|
||||
needsCorrect_ = false;
|
||||
}
|
||||
|
||||
|
||||
@ -90,21 +344,27 @@ Foam::sampledSets::sampledSets
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
functionObjects::regionFunctionObject(name, runTime, dict),
|
||||
functionObjects::fvMeshFunctionObject(name, runTime, dict),
|
||||
PtrList<sampledSet>(),
|
||||
mesh_(refCast<const fvMesh>(obr_)),
|
||||
dict_(dict),
|
||||
loadFromFiles_(false),
|
||||
outputPath_(fileName::null),
|
||||
searchEngine_(mesh_),
|
||||
interpolationScheme_(word::null),
|
||||
writeFormat_(word::null),
|
||||
writeFormatOptions_(dict.subOrEmptyDict("formatOptions"))
|
||||
{
|
||||
outputPath_ =
|
||||
verbose_(false),
|
||||
onExecute_(false),
|
||||
needsCorrect_(false),
|
||||
outputPath_
|
||||
(
|
||||
mesh_.time().globalPath()/functionObject::outputPrefix/name
|
||||
);
|
||||
|
||||
time_.globalPath()/functionObject::outputPrefix/name
|
||||
),
|
||||
searchEngine_(mesh_),
|
||||
samplePointScheme_(),
|
||||
writeFormat_(),
|
||||
writeFormatOptions_(dict.subOrEmptyDict("formatOptions")),
|
||||
writers_(),
|
||||
selectedFieldNames_(),
|
||||
gatheredSets_(),
|
||||
gatheredSorting_(),
|
||||
globalIndices_()
|
||||
{
|
||||
if (mesh_.name() != polyMesh::defaultRegion)
|
||||
{
|
||||
outputPath_ /= mesh_.name();
|
||||
@ -124,26 +384,31 @@ Foam::sampledSets::sampledSets
|
||||
const bool loadFromFiles
|
||||
)
|
||||
:
|
||||
functionObjects::regionFunctionObject(name, obr, dict),
|
||||
functionObjects::fvMeshFunctionObject(name, obr, dict),
|
||||
PtrList<sampledSet>(),
|
||||
mesh_(refCast<const fvMesh>(obr)),
|
||||
dict_(dict),
|
||||
loadFromFiles_(loadFromFiles),
|
||||
outputPath_(fileName::null),
|
||||
searchEngine_(mesh_),
|
||||
interpolationScheme_(word::null),
|
||||
writeFormat_(word::null),
|
||||
writeFormatOptions_(dict.subOrEmptyDict("formatOptions"))
|
||||
{
|
||||
outputPath_ =
|
||||
verbose_(false),
|
||||
onExecute_(false),
|
||||
needsCorrect_(false),
|
||||
outputPath_
|
||||
(
|
||||
mesh_.time().globalPath()/functionObject::outputPrefix/name
|
||||
);
|
||||
|
||||
time_.globalPath()/functionObject::outputPrefix/name
|
||||
),
|
||||
searchEngine_(mesh_),
|
||||
samplePointScheme_(),
|
||||
writeFormat_(),
|
||||
writeFormatOptions_(dict.subOrEmptyDict("formatOptions")),
|
||||
writers_(),
|
||||
selectedFieldNames_(),
|
||||
gatheredSets_(),
|
||||
gatheredSorting_(),
|
||||
globalIndices_()
|
||||
{
|
||||
if (mesh_.name() != polyMesh::defaultRegion)
|
||||
{
|
||||
outputPath_ /= mesh_.name();
|
||||
}
|
||||
|
||||
outputPath_.clean(); // Remove unneeded ".."
|
||||
|
||||
read(dict);
|
||||
@ -152,7 +417,7 @@ Foam::sampledSets::sampledSets
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::sampledSets::verbose(const bool on)
|
||||
bool Foam::sampledSets::verbose(const bool on) noexcept
|
||||
{
|
||||
bool old(verbose_);
|
||||
verbose_ = on;
|
||||
@ -160,122 +425,205 @@ bool Foam::sampledSets::verbose(const bool on)
|
||||
}
|
||||
|
||||
|
||||
bool Foam::sampledSets::read(const dictionary& dict)
|
||||
{
|
||||
if (&dict_ != &dict)
|
||||
{
|
||||
// Update local copy of dictionary
|
||||
dict_ = dict;
|
||||
}
|
||||
|
||||
fvMeshFunctionObject::read(dict);
|
||||
|
||||
PtrList<sampledSet>::clear();
|
||||
writers_.clear();
|
||||
fieldSelection_.clear();
|
||||
selectedFieldNames_.clear();
|
||||
|
||||
gatheredSets_.clear();
|
||||
gatheredSorting_.clear();
|
||||
globalIndices_.clear();
|
||||
|
||||
verbose_ = dict.getOrDefault("verbose", false);
|
||||
onExecute_ = dict.getOrDefault("sampleOnExecute", false);
|
||||
|
||||
samplePointScheme_ =
|
||||
dict.getOrDefault<word>("interpolationScheme", "cellPoint");
|
||||
|
||||
const entry* eptr = dict.findEntry("sets");
|
||||
|
||||
if (eptr)
|
||||
{
|
||||
dict.readEntry("setFormat", writeFormat_);
|
||||
}
|
||||
// const dictionary formatOptions(dict.subOrEmptyDict("formatOptions"));
|
||||
// Writer type and format options
|
||||
// const word writerType =
|
||||
// (eptr ? dict.get<word>("setFormat") : word::null);
|
||||
// writerType_ = (eptr ? dict.get<word>("setFormat") : word::null);
|
||||
|
||||
initDict(dict, true);
|
||||
|
||||
// Have some sets, so sort out which fields are needed and report
|
||||
|
||||
if (this->size())
|
||||
{
|
||||
dict_.readEntry("fields", fieldSelection_);
|
||||
fieldSelection_.uniq();
|
||||
|
||||
// Report
|
||||
forAll(*this, seti)
|
||||
{
|
||||
const sampledSet& s = (*this)[seti];
|
||||
|
||||
if (!seti)
|
||||
{
|
||||
Info<< "Sampled set:" << nl;
|
||||
}
|
||||
|
||||
Info<< " " << s.name() << " -> " << writers_[seti].type()
|
||||
<< nl;
|
||||
}
|
||||
|
||||
Info<< endl;
|
||||
}
|
||||
|
||||
if (debug && Pstream::master())
|
||||
{
|
||||
Pout<< "sample fields:" << flatOutput(fieldSelection_) << nl
|
||||
<< "sample sets:" << nl << '(' << nl;
|
||||
|
||||
for
|
||||
(
|
||||
const sampledSet& s
|
||||
: static_cast<const PtrList<sampledSet>&>(*this)
|
||||
)
|
||||
{
|
||||
Pout<< " " << s << endl;
|
||||
}
|
||||
Pout<< ')' << endl;
|
||||
}
|
||||
|
||||
// FUTURE:
|
||||
// Ensure all sets and merge information are expired
|
||||
// expire(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::sampledSets::performAction(unsigned request)
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
// Nothing to do
|
||||
return true;
|
||||
}
|
||||
else if (needsCorrect_)
|
||||
{
|
||||
searchEngine_.correct();
|
||||
initDict(dict_, false);
|
||||
}
|
||||
|
||||
// FUTURE:
|
||||
// Update sets and store
|
||||
// ...
|
||||
|
||||
// Determine availability of fields.
|
||||
// Count number of fields (only seems to be needed for VTK legacy)
|
||||
|
||||
IOobjectList objects = preCheckFields();
|
||||
|
||||
const label nFields = selectedFieldNames_.size();
|
||||
|
||||
if (!nFields)
|
||||
{
|
||||
// Nothing to do
|
||||
return true;
|
||||
}
|
||||
|
||||
// Update writers
|
||||
|
||||
forAll(*this, seti)
|
||||
{
|
||||
const coordSet& s = gatheredSets_[seti];
|
||||
|
||||
if (request & ACTION_WRITE)
|
||||
{
|
||||
coordSetWriter& writer = writers_[seti];
|
||||
|
||||
if (writer.needsUpdate())
|
||||
{
|
||||
writer.setCoordinates(s);
|
||||
}
|
||||
|
||||
if (writer.buffering())
|
||||
{
|
||||
writer.open
|
||||
(
|
||||
outputPath_
|
||||
/ word(s.name() + coordSetWriter::suffix(selectedFieldNames_))
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.open(outputPath_/s.name());
|
||||
}
|
||||
|
||||
writer.beginTime(mesh_.time());
|
||||
}
|
||||
}
|
||||
|
||||
// Sample fields
|
||||
|
||||
performAction<VolumeField<scalar>>(objects, request);
|
||||
performAction<VolumeField<vector>>(objects, request);
|
||||
performAction<VolumeField<sphericalTensor>>(objects, request);
|
||||
performAction<VolumeField<symmTensor>>(objects, request);
|
||||
performAction<VolumeField<tensor>>(objects, request);
|
||||
|
||||
|
||||
// Finish this time step
|
||||
forAll(writers_, seti)
|
||||
{
|
||||
// Write geometry if no fields were written so that we still
|
||||
// can have something to look at
|
||||
|
||||
if (request & ACTION_WRITE)
|
||||
{
|
||||
/// if (!writers_[seti].wroteData())
|
||||
/// {
|
||||
/// writers_[seti].write();
|
||||
/// }
|
||||
|
||||
writers_[seti].endTime();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::sampledSets::execute()
|
||||
{
|
||||
if (onExecute_)
|
||||
{
|
||||
return performAction(ACTION_ALL & ~ACTION_WRITE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::sampledSets::write()
|
||||
{
|
||||
if (size())
|
||||
{
|
||||
const label nFields = classifyFields();
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "timeName = " << mesh_.time().timeName() << nl
|
||||
<< "scalarFields " << scalarFields_ << nl
|
||||
<< "vectorFields " << vectorFields_ << nl
|
||||
<< "sphTensorFields " << sphericalTensorFields_ << nl
|
||||
<< "symTensorFields " << symmTensorFields_ <<nl
|
||||
<< "tensorFields " << tensorFields_ <<nl;
|
||||
}
|
||||
|
||||
if (nFields)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Creating directory "
|
||||
<< outputPath_/mesh_.time().timeName()
|
||||
<< nl << endl;
|
||||
}
|
||||
|
||||
mkDir(outputPath_/mesh_.time().timeName());
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "No fields to sample" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (nFields)
|
||||
{
|
||||
sampleAndWrite(scalarFields_);
|
||||
sampleAndWrite(vectorFields_);
|
||||
sampleAndWrite(sphericalTensorFields_);
|
||||
sampleAndWrite(symmTensorFields_);
|
||||
sampleAndWrite(tensorFields_);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::sampledSets::read(const dictionary& dict)
|
||||
{
|
||||
dict_ = dict;
|
||||
|
||||
if (dict_.found("sets"))
|
||||
{
|
||||
dict_.readEntry("fields", fieldSelection_);
|
||||
clearFieldGroups();
|
||||
|
||||
dict.readEntry("interpolationScheme", interpolationScheme_);
|
||||
dict.readEntry("setFormat", writeFormat_);
|
||||
|
||||
PtrList<sampledSet> newList
|
||||
(
|
||||
dict_.lookup("sets"),
|
||||
sampledSet::iNew(mesh_, searchEngine_)
|
||||
);
|
||||
transfer(newList);
|
||||
combineSampledSets(masterSampledSets_, indexSets_);
|
||||
|
||||
if (this->size())
|
||||
{
|
||||
Info<< "Reading set description:" << nl;
|
||||
forAll(*this, setI)
|
||||
{
|
||||
Info<< " " << operator[](setI).name() << nl;
|
||||
}
|
||||
Info<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (Pstream::master() && debug)
|
||||
{
|
||||
Pout<< "sample fields:" << fieldSelection_ << nl
|
||||
<< "sample sets:" << nl << "(" << nl;
|
||||
|
||||
forAll(*this, setI)
|
||||
{
|
||||
Pout<< " " << operator[](setI) << endl;
|
||||
}
|
||||
Pout<< ")" << endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
return performAction(ACTION_ALL);
|
||||
}
|
||||
|
||||
|
||||
void Foam::sampledSets::correct()
|
||||
{
|
||||
if (dict_.found("sets"))
|
||||
{
|
||||
searchEngine_.correct();
|
||||
|
||||
PtrList<sampledSet> newList
|
||||
(
|
||||
dict_.lookup("sets"),
|
||||
sampledSet::iNew(mesh_, searchEngine_)
|
||||
);
|
||||
transfer(newList);
|
||||
combineSampledSets(masterSampledSets_, indexSets_);
|
||||
}
|
||||
needsCorrect_ = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2018 OpenCFD Ltd.
|
||||
Copyright (C) 2011 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -29,24 +29,86 @@ Class
|
||||
|
||||
Description
|
||||
Set of sets to sample.
|
||||
Call sampledSets.write() to sample and write files.
|
||||
|
||||
The write() method is used to sample and write files.
|
||||
|
||||
Example of function object specification:
|
||||
|
||||
\verbatim
|
||||
surfaces
|
||||
{
|
||||
type sets;
|
||||
libs (sampling);
|
||||
|
||||
// Write at same frequency as fields
|
||||
writeControl writeTime;
|
||||
writeInterval 1;
|
||||
|
||||
// Fields to be sampled
|
||||
fields (p U);
|
||||
|
||||
// Scheme to obtain values
|
||||
interpolationScheme cellPoint;
|
||||
|
||||
// Output format
|
||||
surfaceFormat vtk;
|
||||
|
||||
formatOptions
|
||||
{
|
||||
vtk
|
||||
{
|
||||
precision 10;
|
||||
}
|
||||
}
|
||||
|
||||
sets
|
||||
{
|
||||
Uref
|
||||
{
|
||||
type cloud;
|
||||
axis xyz;
|
||||
points ((-0.0508 0.0508 0.01));
|
||||
}
|
||||
}
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
Entries:
|
||||
\table
|
||||
Property | Description | Required | Default
|
||||
type | Type-name: sets | yes |
|
||||
sets | Dictionary or list of sample sets | expected |
|
||||
fields | word/regex list of fields to sample | yes |
|
||||
interpolationScheme | scheme to obtain values | no | cellPoint
|
||||
setFormat | output format | yes |
|
||||
sampleOnExecute | Sample (store) on execution as well | no | false
|
||||
formatOptions | dictionary of format options | no |
|
||||
\endtable
|
||||
|
||||
Additional per-set entries:
|
||||
\table
|
||||
Property | Description | Required | Default
|
||||
store | Store surface/fields on registry | no |
|
||||
setFormat | output format | no |
|
||||
formatOptions | dictionary of format options | no |
|
||||
\endtable
|
||||
|
||||
SourceFiles
|
||||
sampledSets.C
|
||||
sampledSetsImpl.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef sampledSets_H
|
||||
#define sampledSets_H
|
||||
#ifndef Foam_sampledSets_H
|
||||
#define Foam_sampledSets_H
|
||||
|
||||
#include "regionFunctionObject.H"
|
||||
#include "fvMeshFunctionObject.H"
|
||||
#include "sampledSet.H"
|
||||
#include "volFieldsFwd.H"
|
||||
#include "meshSearch.H"
|
||||
#include "interpolation.H"
|
||||
#include "coordSet.H"
|
||||
#include "writer.H"
|
||||
#include "wordRes.H"
|
||||
#include "coordSetWriter.H"
|
||||
#include "volFieldsFwd.H"
|
||||
#include "IOobjectList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -55,9 +117,8 @@ namespace Foam
|
||||
|
||||
// Forward Declarations
|
||||
class Time;
|
||||
class objectRegistry;
|
||||
class dictionary;
|
||||
class fvMesh;
|
||||
class globalIndex;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class sampledSets Declaration
|
||||
@ -65,97 +126,37 @@ class fvMesh;
|
||||
|
||||
class sampledSets
|
||||
:
|
||||
public functionObjects::regionFunctionObject,
|
||||
public functionObjects::fvMeshFunctionObject,
|
||||
public PtrList<sampledSet>
|
||||
{
|
||||
// Private Classes
|
||||
|
||||
//- Class used for grouping field types
|
||||
template<class Type>
|
||||
class fieldGroup
|
||||
:
|
||||
public DynamicList<word>
|
||||
{
|
||||
public:
|
||||
|
||||
//- The set formatter
|
||||
autoPtr<writer<Type>> formatter;
|
||||
|
||||
//- Construct null
|
||||
fieldGroup() = default;
|
||||
|
||||
//- Reset format and field list
|
||||
void clear()
|
||||
{
|
||||
DynamicList<word>::clear();
|
||||
formatter.clear();
|
||||
}
|
||||
|
||||
void setFormatter(const word& writeFormat, const dictionary& dict)
|
||||
{
|
||||
formatter = writer<Type>::New(writeFormat, dict);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//- Class used for sampling volFields
|
||||
template<class Type>
|
||||
class volFieldSampler
|
||||
:
|
||||
public List<Field<Type>>
|
||||
{
|
||||
//- Name of this collection of values
|
||||
const word name_;
|
||||
|
||||
public:
|
||||
|
||||
//- Construct interpolating field to the sampleSets
|
||||
volFieldSampler
|
||||
(
|
||||
const word& interpolationScheme,
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field,
|
||||
const PtrList<sampledSet>&
|
||||
);
|
||||
|
||||
//- Construct mapping field to the sampleSets
|
||||
volFieldSampler
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field,
|
||||
const PtrList<sampledSet>&
|
||||
);
|
||||
|
||||
//- Construct from components
|
||||
volFieldSampler
|
||||
(
|
||||
const List<Field<Type>>& values,
|
||||
const word& name
|
||||
);
|
||||
|
||||
//- Return the field name
|
||||
const word& name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Static Data Members
|
||||
|
||||
//- Output verbosity
|
||||
static bool verbose_;
|
||||
|
||||
//- Local control for sampling actions
|
||||
enum sampleActionType : unsigned
|
||||
{
|
||||
ACTION_NONE = 0,
|
||||
ACTION_WRITE = 0x1,
|
||||
ACTION_STORE = 0x2,
|
||||
ACTION_ALL = 0xF
|
||||
};
|
||||
|
||||
// Private Data
|
||||
|
||||
//- Const reference to fvMesh
|
||||
const fvMesh& mesh_;
|
||||
|
||||
//- Keep the dictionary to recreate sets for moving mesh cases
|
||||
dictionary dict_;
|
||||
|
||||
//- Load fields from files (not from objectRegistry)
|
||||
bool loadFromFiles_;
|
||||
|
||||
//- Output verbosity
|
||||
bool verbose_;
|
||||
|
||||
//- Perform sample/store actions on execute as well
|
||||
bool onExecute_;
|
||||
|
||||
//- Correct meshSearch and update sets
|
||||
bool needsCorrect_;
|
||||
|
||||
//- Output path
|
||||
fileName outputPath_;
|
||||
|
||||
@ -168,8 +169,8 @@ class sampledSets
|
||||
//- Names of fields to sample
|
||||
wordRes fieldSelection_;
|
||||
|
||||
//- Interpolation scheme to use
|
||||
word interpolationScheme_;
|
||||
//- Interpolation/sample scheme to obtain values at the points
|
||||
word samplePointScheme_;
|
||||
|
||||
//- Output format to use
|
||||
word writeFormat_;
|
||||
@ -178,61 +179,76 @@ class sampledSets
|
||||
dictionary writeFormatOptions_;
|
||||
|
||||
|
||||
// Categorized scalar/vector/tensor fields
|
||||
// Output control
|
||||
|
||||
fieldGroup<scalar> scalarFields_;
|
||||
fieldGroup<vector> vectorFields_;
|
||||
fieldGroup<sphericalTensor> sphericalTensorFields_;
|
||||
fieldGroup<symmTensor> symmTensorFields_;
|
||||
fieldGroup<tensor> tensorFields_;
|
||||
//- The coordSet writers (one per sampled set)
|
||||
PtrList<coordSetWriter> writers_;
|
||||
|
||||
//- Current list of field names selected for sampling
|
||||
DynamicList<word> selectedFieldNames_;
|
||||
|
||||
|
||||
// Merging structures
|
||||
// Merging
|
||||
|
||||
PtrList<coordSet> masterSampledSets_;
|
||||
labelListList indexSets_;
|
||||
//- Gathered coordSet. (Content only meaningful on master)
|
||||
PtrList<coordSet> gatheredSets_;
|
||||
|
||||
//- Indexed sort order for gathered coordSet.
|
||||
// (Content only meaningful on master)
|
||||
List<labelList> gatheredSorting_;
|
||||
|
||||
//- The globalIndex for gathering. (Content only meaningful on master)
|
||||
List<globalIndex> globalIndices_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Clear old field groups
|
||||
void clearFieldGroups();
|
||||
|
||||
//- Classify field types, returns the number of fields
|
||||
label classifyFields();
|
||||
|
||||
//- Combine points from all processors. Sort by curveDist and produce
|
||||
//- index list. Valid result only on master processor.
|
||||
void combineSampledSets
|
||||
//- A new coordSet writer, with per-set formatOptions
|
||||
static autoPtr<coordSetWriter> newWriter
|
||||
(
|
||||
PtrList<coordSet>& masterSampledSets,
|
||||
labelListList& indexSets
|
||||
word writeType,
|
||||
const dictionary& formatOptions,
|
||||
const dictionary& surfDict
|
||||
);
|
||||
|
||||
//- Combine values from all processors.
|
||||
// Valid result only on master processor.
|
||||
template<class T>
|
||||
void combineSampledValues
|
||||
(
|
||||
const PtrList<volFieldSampler<T>>& sampledFields,
|
||||
const labelListList& indexSets,
|
||||
PtrList<volFieldSampler<T>>& masterFields
|
||||
);
|
||||
//- Perform sampling action with store/write
|
||||
bool performAction(unsigned request);
|
||||
|
||||
//- Write set on master, return fileName
|
||||
//- Count selected/sampled fields
|
||||
// Returns empty IOobjectList if loadFromFiles_ is not active
|
||||
//
|
||||
// Adjusts selectedFieldNames_
|
||||
IOobjectList preCheckFields();
|
||||
|
||||
//- Setup the sets (optional writers)
|
||||
void initDict(const dictionary& dict, const bool initial);
|
||||
|
||||
//- Combine points from all processors.
|
||||
//- Sort by curve distance and produce index list.
|
||||
//- Valid result only on master processor.
|
||||
void gatherAllSets();
|
||||
|
||||
//- Write sampled fieldName on coordSet and on outputDir path
|
||||
template<class Type>
|
||||
fileName writeSampleFile
|
||||
void writeCoordSet
|
||||
(
|
||||
const coordSet& masterSampleSet,
|
||||
const PtrList<volFieldSampler<Type>>& masterFields,
|
||||
const label setI,
|
||||
const fileName& timeDir,
|
||||
const writer<Type>& formatter
|
||||
coordSetWriter& writer,
|
||||
const Field<Type>& values,
|
||||
const word& fieldName
|
||||
);
|
||||
|
||||
template<class Type>
|
||||
void sampleAndWrite(fieldGroup<Type>& fields);
|
||||
//- Get from registry or load from disk
|
||||
template<class GeoField>
|
||||
tmp<GeoField> getOrLoadField(const word& fieldName) const;
|
||||
|
||||
//- Sample and store/write a specific volume field
|
||||
template<class Type>
|
||||
void performAction(const VolumeField<Type>& field, unsigned request);
|
||||
|
||||
//- Sample and write all applicable sampled fields
|
||||
// Only uses IOobjectList when loadFromFiles_ is active
|
||||
template<class GeoField>
|
||||
void performAction(const IOobjectList& objects, unsigned request);
|
||||
|
||||
//- No copy construct
|
||||
sampledSets(const sampledSets&) = delete;
|
||||
@ -253,7 +269,7 @@ public:
|
||||
sampledSets
|
||||
(
|
||||
const word& name,
|
||||
const Time& time,
|
||||
const Time& runTime,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
@ -262,8 +278,8 @@ public:
|
||||
sampledSets
|
||||
(
|
||||
const word& name,
|
||||
const objectRegistry&,
|
||||
const dictionary&,
|
||||
const objectRegistry& obr,
|
||||
const dictionary& dict,
|
||||
const bool loadFromFiles = false
|
||||
);
|
||||
|
||||
@ -276,7 +292,7 @@ public:
|
||||
|
||||
//- Enable/disable verbose output
|
||||
// \return old value
|
||||
bool verbose(const bool on);
|
||||
bool verbose(const bool on) noexcept;
|
||||
|
||||
//- Read the sampledSets
|
||||
virtual bool read(const dictionary&);
|
||||
@ -307,12 +323,6 @@ public:
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "sampledSetsTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -1,129 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2017 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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "sampledSets.H"
|
||||
#include "volFields.H"
|
||||
#include "IOobjectList.H"
|
||||
#include "UIndirectList.H"
|
||||
#include "ListOps.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::sampledSets::clearFieldGroups()
|
||||
{
|
||||
scalarFields_.clear();
|
||||
vectorFields_.clear();
|
||||
sphericalTensorFields_.clear();
|
||||
symmTensorFields_.clear();
|
||||
tensorFields_.clear();
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::sampledSets::classifyFields()
|
||||
{
|
||||
label nFields = 0;
|
||||
clearFieldGroups();
|
||||
|
||||
wordList allFields; // Just needed for warnings
|
||||
HashTable<wordHashSet> available;
|
||||
|
||||
if (loadFromFiles_)
|
||||
{
|
||||
// Check files for a particular time
|
||||
IOobjectList objects(mesh_, mesh_.time().timeName());
|
||||
|
||||
allFields = objects.names();
|
||||
available = objects.classes(fieldSelection_);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check currently available fields
|
||||
allFields = mesh_.names();
|
||||
available = mesh_.classes(fieldSelection_);
|
||||
}
|
||||
|
||||
DynamicList<label> missed(fieldSelection_.size());
|
||||
|
||||
// Detect missing fields
|
||||
forAll(fieldSelection_, i)
|
||||
{
|
||||
if (!ListOps::found(allFields, fieldSelection_[i]))
|
||||
{
|
||||
missed.append(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (missed.size())
|
||||
{
|
||||
WarningInFunction
|
||||
<< nl
|
||||
<< "Cannot find "
|
||||
<< (loadFromFiles_ ? "field file" : "registered field")
|
||||
<< " matching "
|
||||
<< UIndirectList<wordRe>(fieldSelection_, missed) << endl;
|
||||
}
|
||||
|
||||
forAllConstIters(available, iter)
|
||||
{
|
||||
const word& fieldType = iter.key();
|
||||
const wordList fieldNames = iter.val().sortedToc();
|
||||
|
||||
const label count = fieldNames.size(); // pre-filtered, so non-empty
|
||||
|
||||
if (fieldType == volScalarField::typeName)
|
||||
{
|
||||
scalarFields_.append(fieldNames);
|
||||
nFields += count;
|
||||
}
|
||||
else if (fieldType == volVectorField::typeName)
|
||||
{
|
||||
vectorFields_.append(fieldNames);
|
||||
nFields += count;
|
||||
}
|
||||
else if (fieldType == volSphericalTensorField::typeName)
|
||||
{
|
||||
sphericalTensorFields_.append(fieldNames);
|
||||
nFields += count;
|
||||
}
|
||||
else if (fieldType == volSymmTensorField::typeName)
|
||||
{
|
||||
symmTensorFields_.append(fieldNames);
|
||||
nFields += count;
|
||||
}
|
||||
else if (fieldType == volTensorField::typeName)
|
||||
{
|
||||
tensorFields_.append(fieldNames);
|
||||
nFields += count;
|
||||
}
|
||||
}
|
||||
|
||||
return nFields;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
241
src/sampling/sampledSet/sampledSets/sampledSetsImpl.C
Normal file
241
src/sampling/sampledSet/sampledSets/sampledSetsImpl.C
Normal file
@ -0,0 +1,241 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2022 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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "sampledSets.H"
|
||||
#include "globalIndex.H"
|
||||
#include "interpolation.H"
|
||||
#include "volFields.H"
|
||||
#include "volPointInterpolation.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class GeoField>
|
||||
Foam::tmp<GeoField>
|
||||
Foam::sampledSets::getOrLoadField(const word& fieldName) const
|
||||
{
|
||||
tmp<GeoField> tfield;
|
||||
|
||||
if (loadFromFiles_)
|
||||
{
|
||||
tfield.reset
|
||||
(
|
||||
new GeoField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fieldName,
|
||||
mesh_.time().timeName(),
|
||||
mesh_,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
mesh_
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Slightly paranoid here
|
||||
tfield.cref(mesh_.cfindObject<GeoField>(fieldName));
|
||||
}
|
||||
|
||||
return tfield;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::sampledSets::writeCoordSet
|
||||
(
|
||||
coordSetWriter& writer,
|
||||
const Field<Type>& values,
|
||||
const word& fieldName
|
||||
)
|
||||
{
|
||||
fileName outputName;
|
||||
if (Pstream::master())
|
||||
{
|
||||
outputName = writer.write(fieldName, values);
|
||||
}
|
||||
Pstream::scatter(outputName);
|
||||
|
||||
if (outputName.size())
|
||||
{
|
||||
// Case-local file name with "<case>" to make relocatable
|
||||
|
||||
dictionary propsDict;
|
||||
propsDict.add
|
||||
(
|
||||
"file",
|
||||
time_.relativePath(outputName, true)
|
||||
);
|
||||
setProperty(fieldName, propsDict);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::sampledSets::performAction
|
||||
(
|
||||
const VolumeField<Type>& fld,
|
||||
unsigned request
|
||||
)
|
||||
{
|
||||
const word& fieldName = fld.name();
|
||||
|
||||
// The interpolator for this field
|
||||
autoPtr<interpolation<Type>> interpPtr;
|
||||
|
||||
if (!samplePointScheme_.empty() && samplePointScheme_ != "cell")
|
||||
{
|
||||
interpPtr.reset(interpolation<Type>::New(samplePointScheme_, fld));
|
||||
}
|
||||
|
||||
forAll(*this, seti)
|
||||
{
|
||||
const sampledSet& s = (*this)[seti];
|
||||
const globalIndex& globIdx = globalIndices_[seti];
|
||||
const labelList& globOrder = gatheredSorting_[seti];
|
||||
|
||||
const word& setName = s.name();
|
||||
Field<Type> values(s.size());
|
||||
|
||||
if (interpPtr)
|
||||
{
|
||||
forAll(s, samplei)
|
||||
{
|
||||
const point& p = s[samplei];
|
||||
const label celli = s.cells()[samplei];
|
||||
const label facei = s.faces()[samplei];
|
||||
|
||||
if (celli == -1 && facei == -1)
|
||||
{
|
||||
// Special condition for illegal sampling points
|
||||
values[samplei] = pTraits<Type>::max;
|
||||
}
|
||||
else
|
||||
{
|
||||
values[samplei] = interpPtr().interpolate(p, celli, facei);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
forAll(s, samplei)
|
||||
{
|
||||
const label celli = s.cells()[samplei];
|
||||
|
||||
if (celli == -1)
|
||||
{
|
||||
values[samplei] = pTraits<Type>::max;
|
||||
}
|
||||
else
|
||||
{
|
||||
values[samplei] = fld[celli];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Collect data from all processors
|
||||
globIdx.gatherInplace(values);
|
||||
|
||||
// Some values only available on master
|
||||
Type avgValue, minValue, maxValue;
|
||||
label sizeValue;
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
avgValue = average(values);
|
||||
minValue = min(values);
|
||||
maxValue = max(values);
|
||||
sizeValue = values.size();
|
||||
|
||||
// Use sorted order
|
||||
values = UIndirectList<Type>(values, globOrder)();
|
||||
}
|
||||
Pstream::scatter(avgValue);
|
||||
Pstream::scatter(minValue);
|
||||
Pstream::scatter(maxValue);
|
||||
Pstream::scatter(sizeValue);
|
||||
|
||||
// Store results: min/max/average/size with the name of the set
|
||||
// for scoping.
|
||||
// Eg, average(lines,T) ...
|
||||
const word resultArg('(' + setName + ',' + fieldName + ')');
|
||||
|
||||
this->setResult("average" + resultArg, avgValue);
|
||||
this->setResult("min" + resultArg, minValue);
|
||||
this->setResult("max" + resultArg, maxValue);
|
||||
this->setResult("size" + resultArg, sizeValue);
|
||||
|
||||
if (verbose_)
|
||||
{
|
||||
Info<< name() << ' ' << setName << " : " << fieldName << nl
|
||||
<< " avg: " << avgValue << nl
|
||||
<< " min: " << minValue << nl
|
||||
<< " max: " << maxValue << nl << nl;
|
||||
}
|
||||
|
||||
if (request & ACTION_WRITE)
|
||||
{
|
||||
writeCoordSet<Type>(writers_[seti], values, fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class GeoField>
|
||||
void Foam::sampledSets::performAction
|
||||
(
|
||||
const IOobjectList& objects,
|
||||
unsigned request
|
||||
)
|
||||
{
|
||||
wordList fieldNames;
|
||||
if (loadFromFiles_)
|
||||
{
|
||||
fieldNames = objects.sortedNames<GeoField>(fieldSelection_);
|
||||
}
|
||||
else
|
||||
{
|
||||
fieldNames = mesh_.thisDb().sortedNames<GeoField>(fieldSelection_);
|
||||
}
|
||||
|
||||
for (const word& fieldName : fieldNames)
|
||||
{
|
||||
tmp<GeoField> tfield = getOrLoadField<GeoField>(fieldName);
|
||||
|
||||
if (tfield)
|
||||
{
|
||||
performAction<typename GeoField::value_type>(tfield(), request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,376 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2021 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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "sampledSets.H"
|
||||
#include "volFields.H"
|
||||
#include "globalIndex.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::sampledSets::volFieldSampler<Type>::volFieldSampler
|
||||
(
|
||||
const word& interpolationScheme,
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field,
|
||||
const PtrList<sampledSet>& samplers
|
||||
)
|
||||
:
|
||||
List<Field<Type>>(samplers.size()),
|
||||
name_(field.name())
|
||||
{
|
||||
autoPtr<interpolation<Type>> interpolator
|
||||
(
|
||||
interpolation<Type>::New(interpolationScheme, field)
|
||||
);
|
||||
|
||||
forAll(samplers, setI)
|
||||
{
|
||||
Field<Type>& values = this->operator[](setI);
|
||||
const sampledSet& samples = samplers[setI];
|
||||
|
||||
values.setSize(samples.size());
|
||||
forAll(samples, sampleI)
|
||||
{
|
||||
const point& samplePt = samples[sampleI];
|
||||
label celli = samples.cells()[sampleI];
|
||||
label facei = samples.faces()[sampleI];
|
||||
|
||||
if (celli == -1 && facei == -1)
|
||||
{
|
||||
// Special condition for illegal sampling points
|
||||
values[sampleI] = pTraits<Type>::max;
|
||||
}
|
||||
else
|
||||
{
|
||||
values[sampleI] = interpolator().interpolate
|
||||
(
|
||||
samplePt,
|
||||
celli,
|
||||
facei
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::sampledSets::volFieldSampler<Type>::volFieldSampler
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field,
|
||||
const PtrList<sampledSet>& samplers
|
||||
)
|
||||
:
|
||||
List<Field<Type>>(samplers.size()),
|
||||
name_(field.name())
|
||||
{
|
||||
forAll(samplers, setI)
|
||||
{
|
||||
Field<Type>& values = this->operator[](setI);
|
||||
const sampledSet& samples = samplers[setI];
|
||||
|
||||
values.setSize(samples.size());
|
||||
forAll(samples, sampleI)
|
||||
{
|
||||
label celli = samples.cells()[sampleI];
|
||||
|
||||
if (celli ==-1)
|
||||
{
|
||||
values[sampleI] = pTraits<Type>::max;
|
||||
}
|
||||
else
|
||||
{
|
||||
values[sampleI] = field[celli];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::sampledSets::volFieldSampler<Type>::volFieldSampler
|
||||
(
|
||||
const List<Field<Type>>& values,
|
||||
const word& name
|
||||
)
|
||||
:
|
||||
List<Field<Type>>(values),
|
||||
name_(name)
|
||||
{}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::fileName Foam::sampledSets::writeSampleFile
|
||||
(
|
||||
const coordSet& masterSampleSet,
|
||||
const PtrList<volFieldSampler<Type>>& masterFields,
|
||||
const label setI,
|
||||
const fileName& timeDir,
|
||||
const writer<Type>& formatter
|
||||
)
|
||||
{
|
||||
wordList valueSetNames(masterFields.size());
|
||||
List<const Field<Type>*> valueSets(masterFields.size());
|
||||
forAll(masterFields, fieldi)
|
||||
{
|
||||
const word& fieldName = masterFields[fieldi].name();
|
||||
|
||||
valueSetNames[fieldi] = fieldName;
|
||||
|
||||
// Values only available on master
|
||||
Type averageValue, minValue, maxValue;
|
||||
label sizeValue;
|
||||
if (Pstream::master())
|
||||
{
|
||||
valueSets[fieldi] = &masterFields[fieldi][setI];
|
||||
averageValue = average(*valueSets[fieldi]);
|
||||
minValue = min(*valueSets[fieldi]);
|
||||
maxValue = max(*valueSets[fieldi]);
|
||||
sizeValue = valueSets[fieldi]->size();
|
||||
}
|
||||
Pstream::scatter(averageValue);
|
||||
Pstream::scatter(minValue);
|
||||
Pstream::scatter(maxValue);
|
||||
Pstream::scatter(sizeValue);
|
||||
|
||||
// Set results
|
||||
|
||||
setResult("average(" + fieldName + ")", averageValue);
|
||||
setResult("min(" + fieldName + ")", minValue);
|
||||
setResult("max(" + fieldName + ")", maxValue);
|
||||
setResult("size(" + fieldName + ")", sizeValue);
|
||||
}
|
||||
|
||||
fileName fName;
|
||||
if (Pstream::master())
|
||||
{
|
||||
fName = timeDir/formatter.getFileName(masterSampleSet, valueSetNames);
|
||||
|
||||
OFstream ofs(fName);
|
||||
if (ofs.opened())
|
||||
{
|
||||
formatter.write
|
||||
(
|
||||
masterSampleSet,
|
||||
valueSetNames,
|
||||
valueSets,
|
||||
ofs
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
WarningInFunction
|
||||
<< "File " << ofs.name() << " could not be opened. "
|
||||
<< "No data will be written" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
Pstream::scatter(fName);
|
||||
|
||||
return fName;
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void Foam::sampledSets::combineSampledValues
|
||||
(
|
||||
const PtrList<volFieldSampler<T>>& sampledFields,
|
||||
const labelListList& indexSets,
|
||||
PtrList<volFieldSampler<T>>& masterFields
|
||||
)
|
||||
{
|
||||
forAll(sampledFields, fieldi)
|
||||
{
|
||||
List<Field<T>> masterValues(indexSets.size());
|
||||
|
||||
forAll(indexSets, setI)
|
||||
{
|
||||
// Collect data from all processors
|
||||
|
||||
Field<T> allData;
|
||||
globalIndex::gatherOp(sampledFields[fieldi][setI], allData);
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
masterValues[setI] = UIndirectList<T>
|
||||
(
|
||||
allData,
|
||||
indexSets[setI]
|
||||
)();
|
||||
}
|
||||
}
|
||||
|
||||
masterFields.set
|
||||
(
|
||||
fieldi,
|
||||
new volFieldSampler<T>
|
||||
(
|
||||
masterValues,
|
||||
sampledFields[fieldi].name()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::sampledSets::sampleAndWrite(fieldGroup<Type>& fields)
|
||||
{
|
||||
if (fields.size())
|
||||
{
|
||||
const bool interpolate = interpolationScheme_ != "cell";
|
||||
|
||||
// Create or use existing writer
|
||||
if (!fields.formatter)
|
||||
{
|
||||
fields.setFormatter(writeFormat_, writeFormatOptions_);
|
||||
}
|
||||
|
||||
// Storage for interpolated values
|
||||
PtrList<volFieldSampler<Type>> sampledFields(fields.size());
|
||||
|
||||
forAll(fields, fieldi)
|
||||
{
|
||||
if (Pstream::master() && verbose_)
|
||||
{
|
||||
Pout<< "sampledSets::sampleAndWrite: "
|
||||
<< fields[fieldi] << endl;
|
||||
}
|
||||
|
||||
if (loadFromFiles_)
|
||||
{
|
||||
GeometricField<Type, fvPatchField, volMesh> vf
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fields[fieldi],
|
||||
mesh_.time().timeName(),
|
||||
mesh_,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
mesh_
|
||||
);
|
||||
|
||||
if (interpolate)
|
||||
{
|
||||
sampledFields.set
|
||||
(
|
||||
fieldi,
|
||||
new volFieldSampler<Type>
|
||||
(
|
||||
interpolationScheme_,
|
||||
vf,
|
||||
*this
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
sampledFields.set
|
||||
(
|
||||
fieldi,
|
||||
new volFieldSampler<Type>(vf, *this)
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (interpolate)
|
||||
{
|
||||
sampledFields.set
|
||||
(
|
||||
fieldi,
|
||||
new volFieldSampler<Type>
|
||||
(
|
||||
interpolationScheme_,
|
||||
mesh_.lookupObject
|
||||
<GeometricField<Type, fvPatchField, volMesh>>
|
||||
(fields[fieldi]),
|
||||
*this
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
sampledFields.set
|
||||
(
|
||||
fieldi,
|
||||
new volFieldSampler<Type>
|
||||
(
|
||||
mesh_.lookupObject
|
||||
<GeometricField<Type, fvPatchField, volMesh>>
|
||||
(fields[fieldi]),
|
||||
*this
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Combine sampled fields from processors.
|
||||
// Note: only master results are valid
|
||||
|
||||
PtrList<volFieldSampler<Type>> masterFields(sampledFields.size());
|
||||
combineSampledValues(sampledFields, indexSets_, masterFields);
|
||||
|
||||
forAll(masterSampledSets_, setI)
|
||||
{
|
||||
fileName sampleFile = writeSampleFile
|
||||
(
|
||||
masterSampledSets_[setI],
|
||||
masterFields,
|
||||
setI,
|
||||
outputPath_/mesh_.time().timeName(),
|
||||
fields.formatter()
|
||||
);
|
||||
|
||||
if (sampleFile.size())
|
||||
{
|
||||
// Case-local file name with "<case>" to make relocatable
|
||||
|
||||
forAll(masterFields, fieldi)
|
||||
{
|
||||
dictionary propsDict;
|
||||
propsDict.add
|
||||
(
|
||||
"file",
|
||||
time_.relativePath(sampleFile, true)
|
||||
);
|
||||
|
||||
const word& fieldName = masterFields[fieldi].name();
|
||||
setProperty(fieldName, propsDict);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -940,7 +940,7 @@ void Foam::shortestPathSet::genSamples
|
||||
// Get the target point
|
||||
const label outsideCelli = mesh.findCell(outsidePoint);
|
||||
|
||||
// Maintain overall track length. Used to make curveDist continuous.
|
||||
// Maintain overall track length. Used to make curve distance continuous.
|
||||
scalar trackLength = 0;
|
||||
|
||||
List<topoDistanceData<label>> allFaceInfo(mesh.nFaces());
|
||||
|
||||
Reference in New Issue
Block a user