Merge branch 'feature-postpro' into 'develop'

Feature postpro

See merge request Development/OpenFOAM-plus!236
This commit is contained in:
Andrew Heather
2019-02-20 19:43:43 +00:00
182 changed files with 15871 additions and 5831 deletions

View File

@ -8,7 +8,6 @@
#include "wedgePolyPatch.H"
#include "unitConversion.H"
#include "polyMeshTetDecomposition.H"
#include "surfaceWriter.H"
#include "checkTools.H"
#include "functionObject.H"
@ -482,7 +481,7 @@ Foam::label Foam::checkGeometry
(
const polyMesh& mesh,
const bool allGeometry,
const autoPtr<surfaceWriter>& surfWriter,
autoPtr<surfaceWriter>& surfWriter,
const autoPtr<writer<scalar>>& setWriter
)
{
@ -542,7 +541,7 @@ Foam::label Foam::checkGeometry
nonAlignedPoints.write();
if (setWriter.valid())
{
mergeAndWrite(setWriter(), nonAlignedPoints);
mergeAndWrite(*setWriter, nonAlignedPoints);
}
}
}
@ -576,7 +575,7 @@ Foam::label Foam::checkGeometry
cells.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), cells);
mergeAndWrite(*surfWriter, cells);
}
}
}
@ -592,7 +591,7 @@ Foam::label Foam::checkGeometry
aspectCells.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), aspectCells);
mergeAndWrite(*surfWriter, aspectCells);
}
}
}
@ -613,7 +612,7 @@ Foam::label Foam::checkGeometry
faces.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), faces);
mergeAndWrite(*surfWriter, faces);
}
}
}
@ -635,7 +634,7 @@ Foam::label Foam::checkGeometry
cells.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), cells);
mergeAndWrite(*surfWriter, cells);
}
}
}
@ -658,7 +657,7 @@ Foam::label Foam::checkGeometry
faces.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), faces);
mergeAndWrite(*surfWriter, faces);
}
}
}
@ -680,7 +679,7 @@ Foam::label Foam::checkGeometry
faces.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), faces);
mergeAndWrite(*surfWriter, faces);
}
}
}
@ -702,7 +701,7 @@ Foam::label Foam::checkGeometry
faces.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), faces);
mergeAndWrite(*surfWriter, faces);
}
}
}
@ -726,7 +725,7 @@ Foam::label Foam::checkGeometry
faces.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), faces);
mergeAndWrite(*surfWriter, faces);
}
}
}
@ -759,7 +758,7 @@ Foam::label Foam::checkGeometry
faces.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), faces);
mergeAndWrite(*surfWriter, faces);
}
}
}
@ -784,7 +783,7 @@ Foam::label Foam::checkGeometry
points.write();
if (setWriter.valid())
{
mergeAndWrite(setWriter(), points);
mergeAndWrite(*setWriter, points);
}
}
}
@ -807,7 +806,7 @@ Foam::label Foam::checkGeometry
nearPoints.write();
if (setWriter.valid())
{
mergeAndWrite(setWriter(), nearPoints);
mergeAndWrite(*setWriter, nearPoints);
}
}
}
@ -831,7 +830,7 @@ Foam::label Foam::checkGeometry
faces.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), faces);
mergeAndWrite(*surfWriter, faces);
}
}
}
@ -854,7 +853,7 @@ Foam::label Foam::checkGeometry
faces.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), faces);
mergeAndWrite(*surfWriter, faces);
}
}
}
@ -875,7 +874,7 @@ Foam::label Foam::checkGeometry
cells.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), cells);
mergeAndWrite(*surfWriter, cells);
}
}
}
@ -895,7 +894,7 @@ Foam::label Foam::checkGeometry
cells.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), cells);
mergeAndWrite(*surfWriter, cells);
}
}
}
@ -916,7 +915,7 @@ Foam::label Foam::checkGeometry
faces.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), faces);
mergeAndWrite(*surfWriter, faces);
}
}
}
@ -937,7 +936,7 @@ Foam::label Foam::checkGeometry
faces.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), faces);
mergeAndWrite(*surfWriter, faces);
}
}
}
@ -952,14 +951,10 @@ Foam::label Foam::checkGeometry
autoPtr<surfaceWriter> patchWriter;
if (!surfWriter.valid())
{
patchWriter.reset(new vtkSurfaceWriter());
patchWriter.reset(new surfaceWriters::vtkWriter());
}
const surfaceWriter& wr =
(
surfWriter.valid()
? surfWriter()
: patchWriter()
);
surfaceWriter& wr = (surfWriter.valid() ? *surfWriter : *patchWriter);
// Currently only do AMI checks
@ -1017,22 +1012,22 @@ Foam::label Foam::checkGeometry
if (Pstream::master())
{
wr.write
(
outputDir,
const word fName
(
"patch" + Foam::name(cpp.index())
+ "-src_" + tmName
),
meshedSurfRef
);
wr.open
(
mergedPoints,
mergedFaces
),
"weightsSum",
mergedWeights,
false
mergedFaces,
(outputDir / fName),
false // serial - already merged
);
wr.write("weightsSum", mergedWeights);
wr.clear();
}
if (isA<cyclicACMIPolyPatch>(pbm[patchi]))
@ -1049,22 +1044,22 @@ Foam::label Foam::checkGeometry
if (Pstream::master())
{
wr.write
(
outputDir,
const word fName
(
"patch" + Foam::name(cpp.index())
+ "-src_" + tmName
),
meshedSurfRef
);
wr.open
(
mergedPoints,
mergedFaces
),
"mask",
mergedMask,
false
mergedFaces,
(outputDir / fName),
false // serial - already merged
);
wr.write("mask", mergedMask);
wr.clear();
}
}
}
@ -1101,22 +1096,22 @@ Foam::label Foam::checkGeometry
if (Pstream::master())
{
wr.write
(
outputDir,
const word fName
(
"patch" + Foam::name(cpp.index())
+ "-tgt_" + tmName
),
meshedSurfRef
);
wr.open
(
mergedPoints,
mergedFaces
),
"weightsSum",
mergedWeights,
false
mergedFaces,
(outputDir / fName),
false // serial - already merged
);
wr.write("weightsSum", mergedWeights);
wr.clear();
}
if (isA<cyclicACMIPolyPatch>(pbm[patchi]))
@ -1129,24 +1124,25 @@ Foam::label Foam::checkGeometry
pp.neighbPatch().mask(),
mergedMask
);
if (Pstream::master())
{
wr.write
(
outputDir,
const word fName
(
"patch" + Foam::name(cpp.index())
+ "-tgt_" + tmName
),
meshedSurfRef
);
wr.open
(
mergedPoints,
mergedFaces
),
"mask",
mergedMask,
false
mergedFaces,
(outputDir / fName),
false // serial - already merged
);
wr.write("mask", mergedMask);
wr.clear();
}
}
}

View File

@ -27,7 +27,7 @@ namespace Foam
(
const polyMesh& mesh,
const bool allGeometry,
const autoPtr<surfaceWriter>&,
const autoPtr<writer<scalar>>&
autoPtr<surfaceWriter>& surfWriter,
const autoPtr<writer<scalar>>& setWriter
);
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2004-2010, 2015-2017 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2004-2010, 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2017 OpenFOAM Foundation
@ -67,8 +67,8 @@ Usage
#include "Time.H"
#include "fvMesh.H"
#include "globalMeshData.H"
#include "surfaceWriter.H"
#include "vtkSetWriter.H"
#include "vtkSurfaceWriter.H"
#include "IOdictionary.H"
#include "checkTools.H"
@ -149,16 +149,19 @@ int main(int argc, char *argv[])
);
if (!writeFields && args.found("writeAllFields"))
{
selectedFields.insert("nonOrthoAngle");
selectedFields.insert("faceWeight");
selectedFields.insert("skewness");
selectedFields.insert("cellDeterminant");
selectedFields.insert("aspectRatio");
selectedFields.insert("cellShapes");
selectedFields.insert("cellVolume");
selectedFields.insert("cellVolumeRatio");
selectedFields.insert("minTetVolume");
selectedFields.insert("cellRegion");
selectedFields.insert
({
"nonOrthoAngle",
"faceWeight",
"skewness",
"cellDeterminant",
"aspectRatio",
"cellShapes",
"cellVolume",
"cellVolumeRatio",
"minTetVolume",
"cellRegion"
});
}

View File

@ -10,7 +10,7 @@ Foam::label Foam::checkMeshQuality
(
const polyMesh& mesh,
const dictionary& dict,
const autoPtr<surfaceWriter>& writer
autoPtr<surfaceWriter>& writer
)
{
label noFailedChecks = 0;
@ -29,9 +29,10 @@ Foam::label Foam::checkMeshQuality
<< " faces in error to set " << faces.name() << endl;
faces.instance() = mesh.pointsInstance();
faces.write();
if (writer.valid())
{
mergeAndWrite(writer(), faces);
mergeAndWrite(*writer, faces);
}
}
}

View File

@ -6,8 +6,8 @@ namespace Foam
label checkMeshQuality
(
const polyMesh&,
const dictionary&,
const autoPtr<surfaceWriter>&
const polyMesh& mesh,
const dictionary& dict,
autoPtr<surfaceWriter>& writer
);
}

View File

@ -209,7 +209,7 @@ void Foam::printMeshStats(const polyMesh& mesh, const bool allTopology)
void Foam::mergeAndWrite
(
const polyMesh& mesh,
const surfaceWriter& writer,
surfaceWriter& writer,
const word& name,
const indirectPrimitivePatch& setPatch,
const fileName& outputDir
@ -242,37 +242,37 @@ void Foam::mergeAndWrite
// Write
if (Pstream::master())
{
writer.write
(
outputDir,
name,
meshedSurfRef
writer.open
(
mergedPoints,
mergedFaces
)
mergedFaces,
(outputDir / name),
false // serial - already merged
);
writer.writeGeometry();
writer.clear();
}
}
else
{
writer.write
(
outputDir,
name,
meshedSurfRef
writer.open
(
setPatch.localPoints(),
setPatch.localFaces()
)
setPatch.localFaces(),
(outputDir / name),
false // serial - already merged
);
writer.writeGeometry();
writer.clear();
}
}
void Foam::mergeAndWrite
(
const surfaceWriter& writer,
surfaceWriter& writer,
const faceSet& set
)
{
@ -299,7 +299,7 @@ void Foam::mergeAndWrite
void Foam::mergeAndWrite
(
const surfaceWriter& writer,
surfaceWriter& writer,
const cellSet& set
)
{

View File

@ -5,12 +5,12 @@
namespace Foam
{
class polyMesh;
class surfaceWriter;
class pointSet;
class faceSet;
class cellSet;
class fileName;
class polyMesh;
class surfaceWriter;
void printMeshStats(const polyMesh& mesh, const bool allTopology);
@ -19,7 +19,7 @@ namespace Foam
void mergeAndWrite
(
const polyMesh& mesh,
const surfaceWriter& writer,
surfaceWriter& writer,
const word& name,
const indirectPrimitivePatch& setPatch,
const fileName& outputDir
@ -27,15 +27,15 @@ namespace Foam
//- Write vtk representation of (assembled) faceSet to surface file in
// postProcessing/ directory
void mergeAndWrite(const surfaceWriter&, const faceSet&);
void mergeAndWrite(surfaceWriter& writer, const faceSet& set);
//- Write vtk representation of (assembled) cellSet to surface file in
// postProcessing/ directory
void mergeAndWrite(const surfaceWriter&, const cellSet&);
void mergeAndWrite(surfaceWriter& writer, const cellSet& set);
//- Write vtk representation of (assembled) pointSet to 'set' file in
// postProcessing/ directory
void mergeAndWrite(const writer<scalar>&, const pointSet&);
void mergeAndWrite(const writer<scalar>& writer, const pointSet& set);
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2017-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2016 OpenFOAM Foundation
@ -35,7 +35,7 @@ License
#include "IOmanip.H"
#include "emptyPolyPatch.H"
#include "processorPolyPatch.H"
#include "surfaceWriter.H"
#include "vtkSurfaceWriter.H"
#include "checkTools.H"
#include "treeBoundBox.H"
@ -114,7 +114,7 @@ Foam::label Foam::checkTopology
const polyMesh& mesh,
const bool allTopology,
const bool allGeometry,
const autoPtr<surfaceWriter>& surfWriter,
autoPtr<surfaceWriter>& surfWriter,
const autoPtr<writer<scalar>>& setWriter
)
{
@ -203,7 +203,7 @@ Foam::label Foam::checkTopology
cells.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), cells);
mergeAndWrite(*surfWriter, cells);
}
}
else
@ -227,7 +227,7 @@ Foam::label Foam::checkTopology
points.write();
if (setWriter.valid())
{
mergeAndWrite(setWriter(), points);
mergeAndWrite(*setWriter, points);
}
}
}
@ -249,7 +249,7 @@ Foam::label Foam::checkTopology
faces.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), faces);
mergeAndWrite(*surfWriter, faces);
}
}
}
@ -269,7 +269,7 @@ Foam::label Foam::checkTopology
faces.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), faces);
mergeAndWrite(*surfWriter, faces);
}
}
}
@ -290,7 +290,7 @@ Foam::label Foam::checkTopology
cells.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), cells);
mergeAndWrite(*surfWriter, cells);
}
}
@ -314,7 +314,7 @@ Foam::label Foam::checkTopology
faces.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), faces);
mergeAndWrite(*surfWriter, faces);
}
}
}
@ -369,7 +369,7 @@ Foam::label Foam::checkTopology
oneCells.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), oneCells);
mergeAndWrite(*surfWriter, oneCells);
}
}
@ -385,7 +385,7 @@ Foam::label Foam::checkTopology
twoCells.write();
if (surfWriter.valid())
{
mergeAndWrite(surfWriter(), twoCells);
mergeAndWrite(*surfWriter, twoCells);
}
}
}
@ -530,7 +530,7 @@ Foam::label Foam::checkTopology
points.write();
if (setWriter.valid())
{
mergeAndWrite(setWriter(), points);
mergeAndWrite(*setWriter, points);
}
}
}
@ -641,7 +641,7 @@ Foam::label Foam::checkTopology
points.write();
if (setWriter.valid())
{
mergeAndWrite(setWriter(), points);
mergeAndWrite(*setWriter, points);
}
}

View File

@ -5,8 +5,8 @@
namespace Foam
{
class polyMesh;
class surfaceWriter;
class pointSet;
class surfaceWriter;
template<class PatchType>
void checkPatch
@ -19,10 +19,10 @@ namespace Foam
label checkTopology
(
const polyMesh&,
const bool,
const bool,
const autoPtr<surfaceWriter>&,
const autoPtr<writer<scalar>>&
const polyMesh& mesh,
const bool allTopology,
const bool allGeometry,
autoPtr<surfaceWriter>& surfWriter,
const autoPtr<writer<scalar>>& setWriter
);
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2004-2011, 2016-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2004-2011, 2016-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2016 OpenFOAM Foundation
@ -128,7 +128,7 @@ labelList countBins
void writeZoning
(
const surfaceWriter& writer,
surfaceWriter& writer,
const triSurface& surf,
const labelList& faceZone,
const word& fieldName,
@ -136,43 +136,23 @@ void writeZoning
const fileName& surfFileNameBase
)
{
Info<< "Writing zoning to "
<< fileName
(
surfFilePath
/ fieldName
+ '_'
+ surfFileNameBase
+ '.'
+ writer.type()
)
<< " ..." << endl << endl;
// Transcribe faces
faceList faces;
surf.triFaceFaces(faces);
// Convert data
scalarField scalarFaceZone(faceZone.size());
forAll(faceZone, i)
{
scalarFaceZone[i] = faceZone[i];
}
faceList faces(surf.size());
forAll(surf, i)
{
faces[i] = surf[i];
}
writer.write
(
surfFilePath,
surfFileNameBase,
meshedSurfRef
writer.open
(
surf.points(),
faces
),
fieldName,
scalarFaceZone,
false // face based data
faces,
(surfFilePath / surfFileNameBase),
false // serial - already merged
);
fileName outputName = writer.write(fieldName, labelField(faceZone));
writer.clear();
Info<< "Wrote zoning to " << outputName << nl << endl;
}
@ -213,7 +193,7 @@ void writeParts
fileName subName
(
surfFilePath
/surfFileNameBase + "_" + name(zone) + ".obj"
/ surfFileNameBase + "_" + name(zone) + ".obj"
);
Info<< "writing part " << zone << " size " << subSurf.size()
@ -377,6 +357,7 @@ int main(int argc, char *argv[])
if (writeSets)
{
surfWriter = surfaceWriter::New(surfaceFormat);
// Option1: hard-coded format
edgeFormat = "obj";
//// Option2: same type as surface format. Problem is e.g. .obj format
@ -514,38 +495,29 @@ int main(int argc, char *argv[])
)
);
const fileName qualityName
(
surfFilePath
/ "illegal"
+ '_'
+ surfFileNameBase
+ '.'
+ surfWriter().type()
);
Info<< "Writing illegal triangles to "
<< qualityName << " ..." << endl << endl;
// Convert data
faceList faces(subSurf.size());
forAll(subSurf, i)
{
faces[i] = subSurf[i];
}
// Transcribe faces
faceList faces;
subSurf.triFaceFaces(faces);
surfWriter().write
(
surfFilePath,
surfFileNameBase,
meshedSurfRef
surfWriter->open
(
subSurf.points(),
faces
),
"illegal",
scalarField(subSurf.size(), Zero),
false // face based data
faces,
(surfFilePath / surfFileNameBase),
false // serial - already merged
);
fileName outputName = surfWriter->write
(
"illegal",
scalarField(subSurf.size(), Zero)
);
surfWriter->clear();
Info<< "Wrote illegal triangles to "
<< outputName << nl << endl;
}
else if (outputThreshold > 0)
{
@ -645,38 +617,24 @@ int main(int argc, char *argv[])
// Dump for subsetting
if (surfWriter.valid())
{
const fileName qualityName
(
surfFilePath
/ "quality"
+ '_'
+ surfFileNameBase
+ '.'
+ surfWriter().type()
);
Info<< "Writing triangle-quality to "
<< qualityName << " ..." << endl << endl;
// Convert data
// Transcribe faces
faceList faces(surf.size());
forAll(surf, i)
{
faces[i] = surf[i];
}
surf.triFaceFaces(faces);
surfWriter().write
(
surfFilePath,
surfFileNameBase,
meshedSurfRef
surfWriter->open
(
surf.points(),
faces
),
"quality",
triQ,
false // face based data
faces,
(surfFilePath / surfFileNameBase),
false // serial - already merged
);
fileName outputName = surfWriter->write("quality", triQ);
surfWriter->clear();
Info<< "Wrote triangle-quality to "
<< outputName << nl << endl;
}
else if (outputThreshold > 0)
{
@ -926,11 +884,12 @@ int main(int argc, char *argv[])
if (!surfWriter.valid())
{
surfWriter.reset(new vtkSurfaceWriter());
surfWriter.reset(new surfaceWriters::vtkWriter());
}
writeZoning
(
surfWriter(),
*surfWriter,
surf,
faceZone,
"zone",
@ -991,11 +950,12 @@ int main(int argc, char *argv[])
{
if (!surfWriter.valid())
{
surfWriter.reset(new vtkSurfaceWriter());
surfWriter.reset(new surfaceWriters::vtkWriter());
}
writeZoning
(
surfWriter(),
*surfWriter,
surf,
normalZone,
"normal",

View File

@ -0,0 +1,281 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1812 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object runTimePostProcessingDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Type of functionObject
type runTimePostProcessing;
// Where to load it from
libs ("librunTimePostProcessing.so");
// Function object enabled flag
enabled true;
// When to output the average fields
writeControl writeTime;
//- Optionally disable parallel VTK rendering, default = true
// parallel true;
//- The output characteristics
output
{
//- The name stem for output images
name image;
//- The image dimensions
width 1400;
height 1050;
}
//- The camera settings
camera
{
// If camera is moving, optionally provide start and end times
// startPosition 0.2;
// endPosition 0.75;
// Total number of frames to generate
nFrameTotal 1;
// Parallel projection flag
parallelProjection yes;
// clipBox is optional
position (385 -560 650);
focalPoint (160 90 60);
up (0.06 0.7 0.7);
position ( -41.95 -247.55 426.87 );
focalPoint ( 146 76 40 );
up ( 0.3646 0.6194 0.6953 );
zoom 1.5;
// clipBox (-10 18 0)(280 160 76);
clipBox (-30 0 0)(300 200 80);
}
// Default colours
// - If select to colourBy colour, these values are used unless
// they are locally overridden
colours
{
background (0.317647 0.341176 0.431373);
background2 (0.317647 0.341176 0.431373);
text (0.75 0.75 0.75);
edge (1 0 0);
surface (0.5 0.5 0.5);
line (1 0 0);
point (0.5 0.5 0.5);
}
// Line data
lines
{
streamline
{
type functionObjectLine;
functionObject streamLines;
colourMap rainbow;
representation tube;
visible true;
tubeRadius 0.5;
colourBy field;
field U;
range (0 20);
opacity 1;
scalarBar
{
visible no;
}
}
}
// Surface data
surfaces
{
geom
{
type geometry;
files ("<case>/myGeometry.vtp");
renderMode phong;
representation surface;
edgeColour (0.5 0.5 0.5);
visible yes;
featureEdges none;
opacity 1.0;
}
surf1
{
type functionObjectSurface;
functionObject planes.plane0;
liveObject true;
colourMap coolToWarm;
representation surface;
maxGlyphLength 0.1;
smooth true;
visible yes;
featureEdges none;
colourBy field;
field U;
range (0 20);
opacity 1;
scalarBar
{
visible no;
}
}
patches
{
type patches;
patches ( buildings ground );
nearCellValue true;
smooth true;
colourMap coolToWarm;
representation surface;
representation glyph;
// maxGlyphLength 5;
maxGlyphLength 0;
visible yes;
featureEdges none;
colourBy field;
field U;
range (0 20);
opacity 1;
scalarBar
{
visible no;
position (0.8 0.1);
vertical yes;
fontSize 16;
titleSize 18;
title "velocity [m/s]";
labelFormat "%6.2f";
numberOfLabels 5;
bold yes;
italic yes;
shadow yes;
}
}
cutting
{
type plane;
planeType pointAndNormal;
pointAndNormalDict
{
point (100 100 50);
normal (1 0 0);
}
offsets (0 100 200);
smooth true;
colourMap coolToWarm;
representation surface;
representation glyph;
// maxGlyphLength 5;
maxGlyphLength 0;
visible yes;
featureEdges none;
colourBy field;
colourField U;
field U;
range (0 20);
opacity 1;
scalarBar
{
visible no;
}
}
iso
{
type iso;
values (0 4 8);
smooth true;
colourMap coolToWarm;
representation surface;
representation glyph;
// maxGlyphLength 5;
maxGlyphLength 0;
visible yes;
featureEdges none;
colourBy field;
colourField U;
field U;
range (0 20);
colourField k;
field k;
range (0 20);
colourBy field;
colourField U;
field U;
range (0 20);
opacity 1;
scalarBar
{
visible no;
}
}
}
// Text data
text
{
text1
{
string "buildings";
position (0.5 0.15);
halign centre;
size 18;
opacity 0.4;
bold yes;
italic yes;
shadow yes;
visible yes;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,107 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1812 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
type runTimePostProcessing;
libs ("librunTimePostProcessing.so");
writeControl writeTime;
// Output characteristics
output
{
//- The name stem for output images
name image;
//- The image dimensions
width 1400;
height 1050;
}
// Some convenient colour schemes
colourScheme
{
black
{
background (0 0 0);
text (0.75 0.75 0.75);
edge (1 0 0);
surface (0.5 0.5 0.5);
line (1 0 0);
point (0.5 0.5 0.5);
}
blueGradient
{
background (1 1 1);
background2 (0 0 1);
text (0 0 0);
edge (1 0 0);
surface (0.5 0.5 0.5);
line (1 0 0);
point (0.5 0.5 0.5);
}
greyGradient
{
background (0.5 0.5 0.5);
background2 (0.7 0.7 0.7);
text (1 1 1);
edge (1 0 0);
surface (0.5 0.5 0.5);
line (1 0 0);
point (0.5 0.5 0.5);
}
paraview
{
background (0.317647 0.341176 0.431373);
text (0.75 0.75 0.75);
edge (1 0 0);
surface (0.5 0.5 0.5);
line (1 0 0);
point (0.5 0.5 0.5);
}
}
// Some typical scalarBar settings
scalarBar
{
right
{
visible true;
vertical true;
position (0.8 0.1);
size (0.1 0.75);
fontSize 16;
labelFormat "%f";
numberOfLabels 5;
bold yes;
italic yes;
shadow yes;
}
bottom
{
visible true;
vertical false;
position (0.2 0.1);
size (0.6 0.1);
fontSize 16;
labelFormat "%f";
numberOfLabels 5;
bold yes;
italic yes;
shadow yes;
}
}
// ************************************************************************* //

View File

@ -820,6 +820,7 @@ DebugSwitches
rotatedBoxToCell 0;
rotatingPressureInletOutletVelocity 0;
rotatingTotalPressure 0;
runTimePostPro::geometryBase 0;
sampledPatch 0;
sampledPlane 0;
sampledSet 0;

View File

@ -32,7 +32,9 @@ Group
Description
Calculates average quantities for a user-specified selection of volumetric
and surface fields.
With the %subRegion option, also supports fields on a surfMesh.
With the %subRegion option, also supports fields on functionObject
surface output (eg, sampledSurfaces).
Fields are entered as a list of sub-dictionaries, which indicate the type of
averages to perform, and can be updated during the calculation. The current
@ -105,14 +107,14 @@ Usage
Where the entries comprise:
\table
Property | Description | Required | Default
type | type name: fieldAverage | yes |
restartOnRestart | Restart the averaging on restart | no | no
type | Type name: fieldAverage | yes |
restartOnRestart| Restart the averaging on restart | no | no
restartOnOutput | Restart the averaging on output | no | no
periodicRestart | Periodically restart the averaging | no | no
restartPeriod | Periodic restart period | conditional |
restartTime | One-shot reset of the averaging | no | great
fields | list of fields and averaging options | yes |
subRegion | name of a sub-region such as a surface name | no |
subRegion | Name for alternative objectRegistry | no | ""
\endtable

View File

@ -28,7 +28,7 @@ License
#include "fieldAverageItem.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "surfFields.H"
#include "polySurfaceFields.H"
#include "OFstream.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -99,7 +99,7 @@ void Foam::functionObjects::fieldAverage::addMeanField
{
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
typedef DimensionedField<Type, surfGeoMesh> SurfFieldType;
typedef DimensionedField<Type, polySurfaceGeoMesh> SurfFieldType;
if (item.mean())
{
@ -169,7 +169,7 @@ void Foam::functionObjects::fieldAverage::restoreWindowFields
{
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
typedef DimensionedField<Type, surfGeoMesh> SurfFieldType;
typedef DimensionedField<Type, polySurfaceGeoMesh> SurfFieldType;
if (item.window() > 0)
{
@ -243,11 +243,11 @@ void Foam::functionObjects::fieldAverage::addPrime2MeanField
{
typedef GeometricField<Type1, fvPatchField, volMesh> VolFieldType1;
typedef GeometricField<Type1, fvsPatchField, surfaceMesh> SurfaceFieldType1;
typedef DimensionedField<Type1, surfGeoMesh> SurfFieldType1;
typedef DimensionedField<Type1, polySurfaceGeoMesh> SurfFieldType1;
typedef GeometricField<Type2, fvPatchField, volMesh> VolFieldType2;
typedef GeometricField<Type2, fvsPatchField, surfaceMesh> SurfaceFieldType2;
typedef DimensionedField<Type2, surfGeoMesh> SurfFieldType2;
typedef DimensionedField<Type2, polySurfaceGeoMesh> SurfFieldType2;
if (item.prime2Mean())
{
@ -312,7 +312,7 @@ void Foam::functionObjects::fieldAverage::storeWindowFields()
{
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
typedef DimensionedField<Type, surfGeoMesh> SurfFieldType;
typedef DimensionedField<Type, polySurfaceGeoMesh> SurfFieldType;
for (fieldAverageItem& item : faItems_)
{
@ -331,7 +331,7 @@ void Foam::functionObjects::fieldAverage::calculateMeanFields() const
{
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
typedef DimensionedField<Type, surfGeoMesh> SurfFieldType;
typedef DimensionedField<Type, polySurfaceGeoMesh> SurfFieldType;
for (const fieldAverageItem& item : faItems_)
{
@ -347,11 +347,11 @@ void Foam::functionObjects::fieldAverage::calculatePrime2MeanFields() const
{
typedef GeometricField<Type1, fvPatchField, volMesh> VolFieldType1;
typedef GeometricField<Type1, fvsPatchField, surfaceMesh> SurfaceFieldType1;
typedef DimensionedField<Type1, surfGeoMesh> SurfFieldType1;
typedef DimensionedField<Type1, polySurfaceGeoMesh> SurfFieldType1;
typedef GeometricField<Type2, fvPatchField, volMesh> VolFieldType2;
typedef GeometricField<Type2, fvsPatchField, surfaceMesh> SurfaceFieldType2;
typedef DimensionedField<Type2, surfGeoMesh> SurfFieldType2;
typedef DimensionedField<Type2, polySurfaceGeoMesh> SurfFieldType2;
for (const fieldAverageItem& item : faItems_)
{
@ -391,11 +391,11 @@ void Foam::functionObjects::fieldAverage::addMeanSqrToPrime2Mean() const
{
typedef GeometricField<Type1, fvPatchField, volMesh> VolFieldType1;
typedef GeometricField<Type1, fvsPatchField, surfaceMesh> SurfaceFieldType1;
typedef DimensionedField<Type1, surfGeoMesh> SurfFieldType1;
typedef DimensionedField<Type1, polySurfaceGeoMesh> SurfFieldType1;
typedef GeometricField<Type2, fvPatchField, volMesh> VolFieldType2;
typedef GeometricField<Type2, fvsPatchField, surfaceMesh> SurfaceFieldType2;
typedef DimensionedField<Type2, surfGeoMesh> SurfFieldType2;
typedef DimensionedField<Type2, polySurfaceGeoMesh> SurfFieldType2;
for (const fieldAverageItem& item : faItems_)
{
@ -431,7 +431,7 @@ void Foam::functionObjects::fieldAverage::writeFields() const
{
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
typedef DimensionedField<Type, surfGeoMesh> SurfFieldType;
typedef DimensionedField<Type, polySurfaceGeoMesh> SurfFieldType;
for (const fieldAverageItem& item : faItems_)
{

View File

@ -60,7 +60,7 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::regionTypeNames_
({
{ regionTypes::stFaceZone, "faceZone" },
{ regionTypes::stPatch, "patch" },
{ regionTypes::stSurface, "surface" },
{ regionTypes::stObject, "functionObjectSurface" },
{ regionTypes::stSampled, "sampledSurface" },
});
@ -118,9 +118,9 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::postOperationTypeNames_
const Foam::objectRegistry&
Foam::functionObjects::fieldValues::surfaceFieldValue::obr() const
{
if (stSurface == regionType_)
if (stObject == regionType_)
{
return mesh_.lookupObject<objectRegistry>(regionName_);
return storedObjects().lookupObject<polySurface>(regionName_);
}
return mesh_;
@ -368,9 +368,9 @@ combineSurfaceGeometry
pointField& points
) const
{
if (stSurface == regionType_)
if (stObject == regionType_)
{
const surfMesh& s = dynamicCast<const surfMesh>(obr());
const polySurface& s = dynamicCast<const polySurface>(obr());
if (Pstream::parRun())
{
@ -436,9 +436,9 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::totalArea() const
{
scalar totalArea = 0;
if (stSurface == regionType_)
if (stObject == regionType_)
{
const surfMesh& s = dynamicCast<const surfMesh>(obr());
const polySurface& s = dynamicCast<const polySurface>(obr());
totalArea = gSum(s.magSf());
}
@ -505,9 +505,9 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::update()
setPatchFaces();
break;
}
case stSurface:
case stObject:
{
const surfMesh& s = dynamicCast<const surfMesh>(obr());
const polySurface& s = dynamicCast<const polySurface>(obr());
nFaces_ = returnReduce(s.size(), sumOp<label>());
break;
}
@ -953,20 +953,23 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::read
{
const word formatName(dict.get<word>("surfaceFormat"));
if (formatName != "none")
{
surfaceWriterPtr_.reset
(
surfaceWriter::New
(
formatName,
dict.subOrEmptyDict("formatOptions")
.subOrEmptyDict(formatName)
dict.subOrEmptyDict("formatOptions").subOrEmptyDict(formatName)
)
);
if (surfaceWriterPtr_->enabled())
{
Info<< " surfaceFormat = " << formatName << nl;
}
else
{
surfaceWriterPtr_->clear();
}
}
Info<< nl << endl;
@ -1004,9 +1007,9 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::write()
vectorField Sf;
if (usesSf())
{
if (stSurface == regionType_)
if (stObject == regionType_)
{
const surfMesh& s = dynamicCast<const surfMesh>(obr());
const polySurface& s = dynamicCast<const polySurface>(obr());
Sf = s.Sf();
}
else if (sampledPtr_.valid())

View File

@ -98,7 +98,7 @@ Usage
\plaintable
faceZone | The \b name entry to specify the faceZone
patch | The \b name entry to specify the patch
surface | The \b name entry to specify the surfMesh
functionObjectSurface | The \b name entry to specify a polySurface
sampledSurface | A \b sampledSurfaceDict sub-dictionary and \b name
\endplaintable
@ -134,13 +134,14 @@ Note
- The values reported by the areaNormalAverage and areaNormalIntegrate
operations are written as the first component of a field with the same
rank as the input field.
- faces on empty patches get ignored
- if the field is a volField the \c faceZone can only consist of boundary
- Faces on empty patches get ignored
- If the field is a volField the \c faceZone can only consist of boundary
faces
- Using \c surface:
- Using \c functionObjectSurface:
- The keyword %subRegion should not be used to select surfaces.
Specify instead the regionType 'surface' and provide the surface name.
- using \c sampledSurface:
Instead specify the regionType 'functionObjectSurface' and provide
the name.
- Using \c sampledSurface:
- not available for surface fields
- if interpolate=true they use \c interpolationCellPoint
otherwise they use cell values
@ -180,11 +181,11 @@ SourceFiles
#include "fieldValue.H"
#include "Enum.H"
#include "meshedSurf.H"
#include "surfaceMesh.H"
#include "polySurface.H"
#include "fvsPatchField.H"
#include "volFieldsFwd.H"
#include "surfFieldsFwd.H"
#include "polySurfaceFieldsFwd.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -217,7 +218,7 @@ public:
{
stFaceZone = 0x01, //!< Calculate on a faceZone
stPatch = 0x02, //!< Calculate on a patch
stSurface = 0x11, //!< Calculate with fields on a surfMesh
stObject = 0x11, //!< Calculate with function object surface
stSampled = 0x12 //!< Sample onto surface and calculate
};

View File

@ -26,13 +26,19 @@ License
\*---------------------------------------------------------------------------*/
#include "Time.H"
#include "sampledSurface.H"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
inline bool Foam::functionObjects::fieldValues::surfaceFieldValue::
withSurfaceFields() const
{
return (stFaceZone == regionType_ || stPatch == regionType_);
return
(
stFaceZone == regionType_
|| stPatch == regionType_
|| (sampledPtr_.valid() && sampledPtr_->withSurfaceFields())
);
}

View File

@ -27,7 +27,7 @@ License
#include "surfaceFieldValue.H"
#include "surfaceFields.H"
#include "surfFields.H"
#include "polySurfaceFields.H"
#include "volFields.H"
#include "sampledSurface.H"
#include "surfaceWriter.H"
@ -58,7 +58,7 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::validField
{
typedef GeometricField<Type, fvsPatchField, surfaceMesh> sf;
typedef GeometricField<Type, fvPatchField, volMesh> vf;
typedef DimensionedField<Type, surfGeoMesh> smt;
typedef DimensionedField<Type, polySurfaceGeoMesh> smt;
return
(
@ -79,7 +79,7 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::getFieldValues
{
typedef GeometricField<Type, fvsPatchField, surfaceMesh> sf;
typedef GeometricField<Type, fvPatchField, volMesh> vf;
typedef DimensionedField<Type, surfGeoMesh> smt;
typedef DimensionedField<Type, polySurfaceGeoMesh> smt;
if (foundObject<smt>(fieldName))
{
@ -384,22 +384,26 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::writeValues
Field<Type> values(getFieldValues<Type>(fieldName, true));
// Write raw values on surface if specified
if (surfaceWriterPtr_.valid())
if (surfaceWriterPtr_.valid() && surfaceWriterPtr_->enabled())
{
Field<Type> allValues(values);
combineFields(allValues);
if (Pstream::master())
{
surfaceWriterPtr_->write
surfaceWriterPtr_->open
(
outputDir(),
regionTypeNames_[regionType_] + ("_" + regionName_),
surfToWrite,
fieldName,
allValues,
false
(
outputDir()
/ regionTypeNames_[regionType_] + ("_" + regionName_)
),
false // serial - already merged
);
surfaceWriterPtr_->write(fieldName, allValues);
surfaceWriterPtr_->clear();
}
}

View File

@ -27,7 +27,7 @@ License
#include "volFields.H"
#include "surfaceFields.H"
#include "surfFields.H"
#include "polySurfaceFields.H"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
@ -36,7 +36,7 @@ bool Foam::functionObjects::fieldsExpression::calcFieldTypes(FOType& fo)
{
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
typedef DimensionedField<Type, surfGeoMesh> SurfFieldType;
typedef DimensionedField<Type, polySurfaceGeoMesh> SurfFieldType;
if (foundObject<VolFieldType>(fieldNames_[0]))
{

View File

@ -27,8 +27,7 @@ License
#include "fluxSummary.H"
#include "surfaceFields.H"
#include "surfFields.H"
#include "surfMesh.H"
#include "polySurfaceFields.H"
#include "dictionary.H"
#include "Time.H"
#include "syncTools.H"
@ -65,6 +64,7 @@ Foam::functionObjects::fluxSummary::modeTypeNames_
{ modeType::mdFaceZone , "faceZone" },
{ modeType::mdFaceZoneAndDirection, "faceZoneAndDirection" },
{ modeType::mdCellZoneAndDirection, "cellZoneAndDirection" },
{ modeType::mdSurface, "functionObjectSurface" },
{ modeType::mdSurface, "surface" },
{ modeType::mdSurfaceAndDirection, "surfaceAndDirection" },
});
@ -116,14 +116,15 @@ void Foam::functionObjects::fluxSummary::initialiseSurface
DynamicList<boolList>& faceFlip
) const
{
const surfMesh* surfptr = mesh_.cfindObject<surfMesh>(surfName);
const polySurface* surfptr =
storedObjects().cfindObject<polySurface>(surfName);
if (!surfptr)
{
FatalErrorInFunction
<< "Unable to find surface " << surfName
<< ". Valid surfaces: "
<< mesh_.sortedNames<surfMesh>() << nl
<< storedObjects().sortedNames<polySurface>() << nl
<< exit(FatalError);
}
@ -142,14 +143,15 @@ void Foam::functionObjects::fluxSummary::initialiseSurfaceAndDirection
DynamicList<boolList>& faceFlip
) const
{
const surfMesh* surfptr = mesh_.cfindObject<surfMesh>(surfName);
const polySurface* surfptr =
storedObjects().cfindObject<polySurface>(surfName);
if (!surfptr)
{
FatalErrorInFunction
<< "Unable to find surface " << surfName
<< ". Valid surfaces: "
<< mesh_.sortedNames<surfMesh>() << nl
<< storedObjects().sortedNames<polySurface>() << nl
<< exit(FatalError);
}
@ -661,7 +663,9 @@ Foam::scalar Foam::functionObjects::fluxSummary::totalArea
if (isSurfaceMode())
{
const surfMesh& s = mesh_.lookupObject<surfMesh>(zoneNames_[idx]);
const polySurface& s =
storedObjects().lookupObject<polySurface>(zoneNames_[idx]);
sumMagSf = sum(s.magSf());
}
else
@ -693,11 +697,12 @@ Foam::scalar Foam::functionObjects::fluxSummary::totalArea
bool Foam::functionObjects::fluxSummary::surfaceModeWrite()
{
if (zoneNames_.size())
for (const word& surfName : zoneNames_)
{
const label surfi = 0;
const surfMesh& s = mesh_.lookupObject<surfMesh>(zoneNames_[surfi]);
const surfVectorField& phi = s.lookupObject<surfVectorField>(phiName_);
const polySurface& s =
storedObjects().lookupObject<polySurface>(surfName);
const auto& phi = s.lookupObject<polySurfaceVectorField>(phiName_);
Log << type() << ' ' << name() << ' '
<< checkFlowType(phi.dimensions(), phi.name()) << " write:" << nl;
@ -706,8 +711,10 @@ bool Foam::functionObjects::fluxSummary::surfaceModeWrite()
forAll(zoneNames_, surfi)
{
const surfMesh& s = mesh_.lookupObject<surfMesh>(zoneNames_[surfi]);
const surfVectorField& phi = s.lookupObject<surfVectorField>(phiName_);
const polySurface& s =
storedObjects().lookupObject<polySurface>(zoneNames_[surfi]);
const auto& phi = s.lookupObject<polySurfaceVectorField>(phiName_);
checkFlowType(phi.dimensions(), phi.name());

View File

@ -120,14 +120,14 @@ public:
//- Face mode type
enum modeType
{
mdFaceZone, //!< face zone
mdFaceZoneAndDirection, //!< face zone with prescribed direction
mdCellZoneAndDirection, //!< cell zone with prescribed direction
mdSurface, //!< surfMesh
mdSurfaceAndDirection //!< surfMesh with prescribed direction
mdFaceZone, //!< Face zone
mdFaceZoneAndDirection, //!< Face zone with prescribed direction
mdCellZoneAndDirection, //!< Cell zone with prescribed direction
mdSurface, //!< A functionObject surface
mdSurfaceAndDirection //!< A surface with prescribed direction
};
//- Mode type names
//- Face mode names
static const Enum<modeType> modeTypeNames_;

View File

@ -34,7 +34,8 @@ Description
The operation can be applied to any volume or surface fields generating a
volume or surface scalar field.
With the %subRegion option, also supports fields on a surfMesh.
With the %subRegion option, also supports fields on functionObject
surface output (eg, sampledSurfaces).
See also
Foam::functionObjects::fvMeshFunctionObject

View File

@ -27,7 +27,7 @@ License
#include "volFields.H"
#include "surfaceFields.H"
#include "surfFields.H"
#include "polySurfaceFields.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
@ -36,7 +36,7 @@ bool Foam::functionObjects::mag::calcMag()
{
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
typedef DimensionedField<Type, surfGeoMesh> SurfFieldType;
typedef DimensionedField<Type, polySurfaceGeoMesh> SurfFieldType;
if (foundObject<VolFieldType>(fieldName_, false))
{

View File

@ -34,7 +34,8 @@ Description
The operation can be applied to any volume or surface field generating a
volume or surface scalar field.
With the %subRegion option, also supports fields on a surfMesh.
With the %subRegion option, also supports fields on functionObject
surface output (eg, sampledSurfaces).
See also
Foam::functionObjects::fvMeshFunctionObject

View File

@ -27,7 +27,7 @@ License
#include "volFields.H"
#include "surfaceFields.H"
#include "surfFields.H"
#include "polySurfaceFields.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
@ -36,7 +36,7 @@ bool Foam::functionObjects::magSqr::calcMagSqr()
{
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
typedef DimensionedField<Type, surfGeoMesh> SurfFieldType;
typedef DimensionedField<Type, polySurfaceGeoMesh> SurfFieldType;
if (foundObject<VolFieldType>(fieldName_, false))
{

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2010, 2015-2017 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2010, 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2016 OpenFOAM Foundation
@ -28,7 +28,6 @@ License
#include "readFields.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "surfFields.H"
#include "Time.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -38,7 +37,7 @@ bool Foam::functionObjects::readFields::loadField(const word& fieldName)
{
typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
typedef DimensionedField<Type, surfGeoMesh> SurfFieldType;
/// typedef DimensionedField<Type, surfGeoMesh> SurfFieldType;
if (foundObject<VolFieldType>(fieldName))
{
@ -54,13 +53,13 @@ bool Foam::functionObjects::readFields::loadField(const word& fieldName)
<< " " << fieldName << " already exists in database"
<< " already in database" << endl;
}
else if (foundObject<SurfFieldType>(fieldName))
{
DebugInfo
<< "readFields: " << SurfFieldType::typeName
<< " " << fieldName << " already exists in database"
<< " already in database" << endl;
}
/// else if (foundObject<SurfFieldType>(fieldName))
/// {
/// DebugInfo
/// << "readFields: " << SurfFieldType::typeName
/// << " " << fieldName << " already exists in database"
/// << " already in database" << endl;
/// }
else
{
IOobject fieldHeader
@ -76,35 +75,32 @@ bool Foam::functionObjects::readFields::loadField(const word& fieldName)
{
// Store field on mesh database
Log << " Reading " << fieldName << endl;
VolFieldType* vfPtr(new VolFieldType(fieldHeader, mesh_));
mesh_.objectRegistry::store(vfPtr);
VolFieldType* fldPtr(new VolFieldType(fieldHeader, mesh_));
mesh_.objectRegistry::store(fldPtr);
return true;
}
else if (fieldHeader.typeHeaderOk<SurfaceFieldType>(true, true, false))
{
// Store field on mesh database
Log << " Reading " << fieldName << endl;
SurfaceFieldType* sfPtr(new SurfaceFieldType(fieldHeader, mesh_));
mesh_.objectRegistry::store(sfPtr);
SurfaceFieldType* fldPtr(new SurfaceFieldType(fieldHeader, mesh_));
mesh_.objectRegistry::store(fldPtr);
return true;
}
else if (fieldHeader.typeHeaderOk<SurfFieldType>(true, true, false))
{
if (isA<surfMesh>(obr()))
{
const surfMesh& s = dynamicCast<const surfMesh>(obr());
// Store field on surfMesh database
Log << " Reading " << fieldName << endl;
SurfFieldType* sfPtr(new SurfFieldType(fieldHeader, s));
s.store(sfPtr);
return true;
}
else
{
return false;
}
}
/// else if (fieldHeader.typeHeaderOk<SurfFieldType>(true, true, false))
/// {
/// const surfMesh* surfptr = isA<surfMesh>(obr());
/// if (surfptr)
/// {
/// const surfMesh& s = surfptr;
///
/// // Store field on surfMesh database
/// Log << " Reading " << fieldName << endl;
/// SurfFieldType* fldPtr(new SurfFieldType(fieldHeader, s));
/// s.store(fldPtr);
/// return true;
/// }
/// }
}
return false;

View File

@ -13,13 +13,40 @@ else()
message(FATAL_ERROR " VTK version is too old - requires VTK6 or newer")
endif()
#-----------------------------------------------------------------------------
# Test some characteristics
set(test_file ${CMAKE_CURRENT_BINARY_DIR}/check_mpi.cxx)
file(WRITE ${test_file}
"#include <vtkMPICommunicator.h>\n"
"int main() {\n"
" vtkMPICommunicator* p = vtkMPICommunicator::New();\n"
" p->Delete();\n"
" return 0;\n"
"}"
)
try_compile(FOAM_USING_VTK_MPI
${CMAKE_CURRENT_BINARY_DIR} ${test_file}
LINK_LIBRARIES vtkParallelMPI
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${PARAVIEW_INCLUDE_DIRS}"
)
if (FOAM_USING_VTK_MPI)
add_definitions(-DFOAM_USING_VTK_MPI)
message("Building with VTK MPI")
include(vtkMPI)
else()
message(WARNING "==== Building without VTK MPI ====")
endif()
#-----------------------------------------------------------------------------
include_directories(
${LIB_SRC}/OpenFOAM/include
${LIB_SRC}/OpenFOAM/lnInclude
${LIB_SRC}/OSspecific/${WM_OSTYPE}/lnInclude
${LIB_SRC}/finiteVolume/lnInclude
${LIB_SRC}/surfMesh/lnInclude
${LIB_SRC}/fileFormats/lnInclude
${LIB_SRC}/conversion/lnInclude
${LIB_SRC}/surfMesh/lnInclude
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
)
@ -45,12 +72,16 @@ set(LIBRARY_OUTPUT_PATH $ENV{FOAM_LIBBIN}
file(GLOB SOURCE_FILES
fieldVisualisationBase.C
scalarBar.C
functionObjectBase.C
functionObjectCloud.C
functionObjectLine.C
functionObjectSurface.C
geometryBase.C
geometryCloud.C
geometryCloudGather.C
geometryPatches.C
geometryPatchesGather.C
geometrySurface.C
pathline.C
pointData.C
@ -58,16 +89,27 @@ file(GLOB SOURCE_FILES
runTimePostProcessingFunctionObject.C
scene.C
surface.C
surfaceGather.C
text.C
contourFilter.C
cuttingPlaneFilter.C
volumeFilter.C
)
set(OPENFOAM_LIBRARIES
OpenFOAM
finiteVolume
surfMesh
fileFormats
conversion
)
if (FOAM_USING_VTK_MPI)
set(LINK_LIBRARIES vtkParallelMPI)
else()
set(LINK_LIBRARIES)
endif()
add_library(
runTimePostProcessing
SHARED
@ -84,6 +126,7 @@ set_target_properties(
target_link_libraries(
runTimePostProcessing
${VTK_LIBRARIES}
${LINK_LIBRARIES}
${OPENFOAM_LIBRARIES}
)

View File

@ -0,0 +1,303 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
// OpenFOAM includes
#include "contourFilter.H"
#include "runTimePostProcessing.H"
#include "addToRunTimeSelectionTable.H"
// VTK includes
#include "vtkActor.h"
#include "vtkCellDataToPointData.h"
#include "vtkCompositeDataGeometryFilter.h"
#include "vtkCompositeDataSet.h"
#include "vtkCompositePolyDataMapper.h"
#include "vtkContourFilter.h"
#include "vtkMultiPieceDataSet.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkRenderer.h"
#include "vtkSmartPointer.h"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
namespace runTimePostPro
{
defineTypeName(contourFilter);
addToRunTimeSelectionTable(surface, contourFilter, dictionary);
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::runTimePostPro::contourFilter::contourFilter
(
const runTimePostProcessing& parent,
const dictionary& dict,
const HashPtrTable<Function1<vector>>& colours
)
:
volumeFilter(parent, dict, colours),
fieldVisualisationBase(dict, colours),
colourFieldName_(dict.get<word>("colourField")),
values_()
{
dict.readEntry("values", values_);
// Extra safety
if (values_.empty())
{
values_.resize(1);
values_.first() = Zero;
}
}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
bool Foam::functionObjects::runTimePostPro::contourFilter::
addGeometry
(
const scalar position,
vtkRenderer* renderer
)
{
if (!visible_)
{
return false;
}
if (needsCollective())
{
Info<< type() << " : Not available for collective operation" << endl;
return false;
}
DebugInfo << " Adding iso-surface" << endl;
// Bookkeeping for vtkUnstructuredGrid
vtk::vtuAdaptor adaptor;
vtkSmartPointer<vtkMultiPieceDataSet> multiPiece = mesh(adaptor);
// Add (scalar/vector) field.
// - always need field(s) for glyphs or colourByField:
int nCmpt = 0;
{
const auto* ioptr =
parent().mesh().cfindObject<regIOobject>(fieldName_);
if (!nCmpt)
{
nCmpt = addDimField<scalar>
(
multiPiece, adaptor, ioptr, fieldName_
);
}
if (!nCmpt)
{
nCmpt = addDimField<vector>
(
multiPiece, adaptor, ioptr, fieldName_
);
}
}
// If the input is vector, need magnitude
word magFieldName = fieldName_;
if (nCmpt == 3)
{
addMagField(fieldName_, multiPiece);
magFieldName = "mag(" + fieldName_ + ")";
}
// Colouring
nCmpt = 0;
if (colourBy_ == cbField && fieldName_ != colourFieldName_)
{
const auto* ioptr =
parent().mesh().cfindObject<regIOobject>(fieldName_);
if (!nCmpt)
{
nCmpt = addDimField<scalar>
(
multiPiece, adaptor, ioptr, colourFieldName_
);
}
if (!nCmpt)
{
nCmpt = addDimField<vector>
(
multiPiece, adaptor, ioptr, colourFieldName_
);
}
}
// Now have a multi-piece dataset that is one of the following:
//
// - one-piece per processor (OpenFOAM = parallel, VTK=parallel)
// Re-query field information - we may have stored it differently
// than the original source.
fieldSummary fieldInfo = queryFieldSummary(magFieldName, multiPiece);
fieldInfo.reduce();
fieldSummary colourFieldInfo =
queryFieldSummary(colourFieldName_, multiPiece);
colourFieldInfo.reduce();
// Not rendered on this processor?
// This is where we stop, but could also have an MPI barrier
if (!renderer)
{
return true;
}
// Rendering
{
auto contour = vtkSmartPointer<vtkContourFilter>::New();
vtkSmartPointer<vtkCellDataToPointData> cellToPoint;
// CellData - Need a cell->point filter
if (!fieldInfo.hasPointData() || !colourFieldInfo.hasPointData())
{
cellToPoint = vtkSmartPointer<vtkCellDataToPointData>::New();
cellToPoint->SetInputData(multiPiece);
contour->SetInputConnection(cellToPoint->GetOutputPort());
}
else
{
contour->SetInputData(multiPiece);
}
contour->SetNumberOfContours(values_.size());
forAll(values_, valuei)
{
contour->SetValue(valuei, values_[valuei]);
}
contour->SetInputArrayToProcess
(
0, // index: scalars(0)
0, // port
0, // connection
vtkDataObject::FIELD_ASSOCIATION_POINTS,
magFieldName.c_str()
);
contour->Modified();
contour->Update();
auto polyData = vtkSmartPointer<vtkCompositeDataGeometryFilter>::New();
polyData->SetInputConnection(contour->GetOutputPort());
polyData->Update();
auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(polyData->GetOutputPort());
if (representation_ == rtGlyph)
{
addGlyphs
(
position,
colourFieldName_, colourFieldInfo, // scaling
colourFieldName_, colourFieldInfo, // colouring
maxGlyphLength_,
polyData->GetOutput(),
surfaceActor_,
renderer
);
}
else
{
setField
(
position,
colourFieldName_,
FieldAssociation::POINT_DATA,
mapper,
renderer
);
surfaceActor_->SetMapper(mapper);
setRepresentation(surfaceActor_);
renderer->AddActor(surfaceActor_);
}
}
return true;
}
void Foam::functionObjects::runTimePostPro::contourFilter::
addGeometryToScene
(
const scalar position,
vtkRenderer* renderer
)
{
if (visible_)
{
// Live source
if (addGeometry(position, renderer))
{
return;
}
WarningInFunction
<< "Unsupported for OpenFOAM parallel and VTK serial"
<< endl;
}
}
bool Foam::functionObjects::runTimePostPro::contourFilter::clear()
{
return true;
}
// ************************************************************************* //

View File

@ -0,0 +1,140 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::functionObjects::runTimePostPro::contourFilter
Description
Iso-surface contours of OpenFOAM volume fields.
Dictionary controls
\table
Property | Description | Required | Default
type | The surface type: isoSurface | yes |
field | The field defining the surface | yes |
colourField | The field to display on the surface | yes |
values | List of iso-values to define the surface(s) | yes |
\endtable
SourceFiles
contourFilter.C
\*---------------------------------------------------------------------------*/
#ifndef functionObjects_runTimePostPro_contourFilter_H
#define functionObjects_runTimePostPro_contourFilter_H
#include "volumeFilter.H"
#include "fieldVisualisationBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
namespace runTimePostPro
{
/*---------------------------------------------------------------------------*\
Class contourFilter Declaration
\*---------------------------------------------------------------------------*/
class contourFilter
:
public volumeFilter,
public fieldVisualisationBase
{
protected:
// Protected Data
//- Name of field to colour by
word colourFieldName_;
//- The iso values
List<scalar> values_;
// Protected Member Functions
//- No copy construct
contourFilter(const contourFilter&) = delete;
//- No copy assignment
void operator=(const contourFilter&) = delete;
public:
//- Run-time type information
TypeNameNoDebug("isoSurface");
// Constructors
//- Construct from dictionary
contourFilter
(
const runTimePostProcessing& parent,
const dictionary& dict,
const HashPtrTable<Function1<vector>>& colours
);
//- Destructor
virtual ~contourFilter() = default;
// Member Functions
//- Add cutting planes to scene (using simulation source)
bool addGeometry
(
const scalar position,
vtkRenderer* renderer
);
//- Add cutting planes to scene (using simulation source)
virtual void addGeometryToScene
(
const scalar position,
vtkRenderer* renderer
);
//- Add cutting planes to scene (using simulation source)
virtual bool clear();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace runTimePostPro
} // End namespace functionObjects
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,292 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
// OpenFOAM includes
#include "cuttingPlaneFilter.H"
#include "runTimePostProcessing.H"
#include "addToRunTimeSelectionTable.H"
// VTK includes
#include "vtkActor.h"
#include "vtkCellDataToPointData.h"
#include "vtkCompositeDataGeometryFilter.h"
#include "vtkCompositeDataSet.h"
#include "vtkCompositePolyDataMapper.h"
#include "vtkCutter.h"
#include "vtkMultiPieceDataSet.h"
#include "vtkPlane.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkRenderer.h"
#include "vtkSmartPointer.h"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
namespace runTimePostPro
{
defineTypeName(cuttingPlaneFilter);
addToRunTimeSelectionTable(surface, cuttingPlaneFilter, dictionary);
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::runTimePostPro::cuttingPlaneFilter::cuttingPlaneFilter
(
const runTimePostProcessing& parent,
const dictionary& dict,
const HashPtrTable<Function1<vector>>& colours
)
:
volumeFilter(parent, dict, colours),
fieldVisualisationBase(dict, colours),
plane_(dict),
values_()
{
dict.readIfPresent("offsets", values_);
if (values_.empty())
{
values_.resize(1);
values_.first() = Zero;
}
}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
bool Foam::functionObjects::runTimePostPro::cuttingPlaneFilter::
addGeometry
(
const scalar position,
vtkRenderer* renderer
)
{
if (!visible_)
{
return false;
}
if (needsCollective())
{
Info<< type() << " : Not available for collective operation" << endl;
return false;
}
DebugInfo << " Adding cutting plane" << endl;
// Bookkeeping for vtkUnstructuredGrid
vtk::vtuAdaptor adaptor;
vtkSmartPointer<vtkMultiPieceDataSet> multiPiece = mesh(adaptor);
// Add (scalar/vector) field.
// - Need field(s) for glyphs or colourByField:
int nCmpt = 0;
if (representation_ == rtGlyph || colourBy_ == cbField)
{
const auto* ioptr =
parent().mesh().cfindObject<regIOobject>(fieldName_);
if (!nCmpt)
{
nCmpt = addDimField<scalar>
(
multiPiece, adaptor, ioptr, fieldName_
);
}
if (!nCmpt)
{
nCmpt = addDimField<vector>
(
multiPiece, adaptor, ioptr, fieldName_
);
}
}
// Now have a multi-piece dataset that is one of the following:
//
// - one-piece per processor (OpenFOAM = parallel, VTK=parallel)
// Re-query field information - we may have stored it differently
// than the original source.
fieldSummary fieldInfo = queryFieldSummary(fieldName_, multiPiece);
fieldInfo.reduce();
// Not rendered on this processor?
// This is where we stop, but could also have an MPI barrier
if (!renderer)
{
return true;
}
// Rendering
{
// OpenFOAM plane -> vtkPlane definition
auto pln = vtkSmartPointer<vtkPlane>::New();
pln->SetNormal
(
plane_.normal().x(),
plane_.normal().y(),
plane_.normal().z()
);
pln->SetOrigin
(
plane_.origin().x(),
plane_.origin().y(),
plane_.origin().z()
);
// Plane cutting algorithm
auto cutter = vtkSmartPointer<vtkCutter>::New();
cutter->SetInputData(multiPiece);
cutter->SetCutFunction(pln);
cutter->SetNumberOfContours(values_.size());
forAll(values_, pointi)
{
cutter->SetValue(pointi, values_[pointi]);
}
cutter->SetInputArrayToProcess
(
(nCmpt == 3 ? 1 : 0), // index: scalars(0), vectors(1)
0, // port
0, // connection
vtkDataObject::FIELD_ASSOCIATION_CELLS,
fieldName_.c_str()
);
cutter->Modified();
cutter->Update();
auto polyData = vtkSmartPointer<vtkCompositeDataGeometryFilter>::New();
polyData->SetInputConnection(cutter->GetOutputPort());
polyData->Update();
auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(polyData->GetOutputPort());
if (representation_ == rtGlyph)
{
addGlyphs
(
position,
fieldName_, fieldInfo, // scaling
fieldName_, fieldInfo, // colouring
maxGlyphLength_,
polyData->GetOutput(),
surfaceActor_,
renderer
);
}
else
{
vtkSmartPointer<vtkCellDataToPointData> cellToPoint;
// CellData - Need a cell->point filter
if (smooth_ && !fieldInfo.hasPointData())
{
cellToPoint = vtkSmartPointer<vtkCellDataToPointData>::New();
cellToPoint->SetInputConnection(cutter->GetOutputPort());
polyData->SetInputConnection(cellToPoint->GetOutputPort());
polyData->Update();
}
setField
(
position,
fieldName_,
(
smooth_
? FieldAssociation::POINT_DATA
: FieldAssociation(fieldInfo.association_)
),
mapper,
renderer
);
surfaceActor_->SetMapper(mapper);
setRepresentation(surfaceActor_);
renderer->AddActor(surfaceActor_);
}
}
return true;
}
void Foam::functionObjects::runTimePostPro::cuttingPlaneFilter::
addGeometryToScene
(
const scalar position,
vtkRenderer* renderer
)
{
if (visible_)
{
// Live source
if (addGeometry(position, renderer))
{
return;
}
WarningInFunction
<< "Unsupported for OpenFOAM parallel and VTK serial"
<< endl;
}
}
bool Foam::functionObjects::runTimePostPro::cuttingPlaneFilter::clear()
{
return true;
}
// ************************************************************************* //

View File

@ -0,0 +1,160 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::functionObjects::runTimePostPro::cuttingPlaneFilter
Description
Cutting planes of OpenFOAM volume fields.
Example of text object specification:
\verbatim
planes
{
type plane;
planeType pointAndNormal;
pointAndNormalDict
{
point (0 0 0);
normal (1 0 0);
}
offsets (0 10 20);
field T;
}
\endverbatim
Dictionary controls
\table
Property | Description | Required | Default
type | The surface type: plane | yes |
planeType | Selector for plane description | yes |
offsets | Offets of the origin in the normal direction | no | (0)
field | The field to display | yes |
\endtable
SourceFiles
cuttingPlaneFilter.C
\*---------------------------------------------------------------------------*/
#ifndef functionObjects_runTimePostPro_cuttingPlaneFilter_H
#define functionObjects_runTimePostPro_cuttingPlaneFilter_H
#include "plane.H"
#include "volumeFilter.H"
#include "fieldVisualisationBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
namespace runTimePostPro
{
/*---------------------------------------------------------------------------*\
Class cuttingPlaneFilter Declaration
\*---------------------------------------------------------------------------*/
class cuttingPlaneFilter
:
public volumeFilter,
public fieldVisualisationBase
{
protected:
// Protected Data
//- The definition of the plane
plane plane_;
//- The offsets to the plane - defaults to (0).
List<scalar> values_;
// Protected Member Functions
//- No copy construct
cuttingPlaneFilter(const cuttingPlaneFilter&) = delete;
//- No copy assignment
void operator=(const cuttingPlaneFilter&) = delete;
public:
//- Run-time type information
TypeNameNoDebug("plane");
// Constructors
//- Construct from dictionary
cuttingPlaneFilter
(
const runTimePostProcessing& parent,
const dictionary& dict,
const HashPtrTable<Function1<vector>>& colours
);
//- Destructor
virtual ~cuttingPlaneFilter() = default;
// Member Functions
//- Add cutting planes to scene (using simulation source)
bool addGeometry
(
const scalar position,
vtkRenderer* renderer
);
//- Add cutting planes to scene (using simulation source)
virtual void addGeometryToScene
(
const scalar position,
vtkRenderer* renderer
);
//- Cleanup files etc.
virtual bool clear();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace runTimePostPro
} // End namespace functionObjects
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -29,25 +27,27 @@ License
#include "fieldVisualisationBase.H"
#include "runTimePostProcessing.H"
#include "doubleVector.H"
#include "foamVtkTools.H"
// VTK includes
#include "vtkArrowSource.h"
#include "vtkCellDataToPointData.h"
#include "vtkCellData.h"
#include "vtkColorTransferFunction.h"
#include "vtkFloatArray.h"
#include "vtkCompositeDataSet.h"
#include "vtkDataObjectTreeIterator.h"
#include "vtkFieldData.h"
#include "vtkGlyph3D.h"
#include "vtkLookupTable.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkRenderer.h"
#include "vtkScalarBarActor.h"
#include "vtkSmartPointer.h"
#include "vtkSphereSource.h"
#include "vtkTextActor.h"
#include "vtkTextProperty.h"
#include "vtkCellDataToPointData.h"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
const Foam::Enum
<
@ -69,13 +69,323 @@ const Foam::Enum
Foam::functionObjects::runTimePostPro::fieldVisualisationBase::
colourMapTypeNames
({
{ colourMapType::cmRainbow, "rainbow" },
{ colourMapType::cmBlueWhiteRed, "blueWhiteRed" },
{ colourMapType::cmCoolToWarm, "coolToWarm" },
{ colourMapType::cmCoolToWarm, "blueWhiteRed" },
{ colourMapType::cmColdAndHot, "coldAndHot" },
{ colourMapType::cmFire, "fire" },
{ colourMapType::cmRainbow, "rainbow" },
{ colourMapType::cmGreyscale, "greyscale" },
{ colourMapType::cmGreyscale, "grayscale" },
{ colourMapType::cmXray, "xray" },
});
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
Foam::functionObjects::runTimePostPro::fieldVisualisationBase::fieldSummary
Foam::functionObjects::runTimePostPro::fieldVisualisationBase::
queryFieldSummary
(
const word& fieldName,
vtkDataSet* dataset
)
{
fieldSummary queried;
if (dataset)
{
vtkDataArray* array;
array = vtkDataArray::SafeDownCast
(
dataset->GetCellData()->GetAbstractArray(fieldName.c_str())
);
if (array)
{
queried.nComponents_ = array->GetNumberOfComponents();
queried.association_ |= FieldAssociation::CELL_DATA;
queried.range_ += vtk::Tools::rangeOf(array);
}
array = vtkDataArray::SafeDownCast
(
dataset->GetPointData()->GetAbstractArray(fieldName.c_str())
);
if (array)
{
queried.nComponents_ = array->GetNumberOfComponents();
queried.association_ |= FieldAssociation::POINT_DATA;
queried.range_ += vtk::Tools::rangeOf(array);
}
}
return queried;
}
Foam::functionObjects::runTimePostPro::fieldVisualisationBase::fieldSummary
Foam::functionObjects::runTimePostPro::fieldVisualisationBase::
queryFieldSummary
(
const word& fieldName,
vtkCompositeDataSet* data
)
{
fieldSummary queried;
auto iter = vtkSmartPointer<vtkDataObjectTreeIterator>::New();
iter->SetDataSet(data);
iter->VisitOnlyLeavesOn();
iter->SkipEmptyNodesOn();
for
(
iter->InitTraversal();
!iter->IsDoneWithTraversal();
iter->GoToNextItem()
)
{
vtkDataSet* dataset = vtkDataSet::SafeDownCast
(
iter->GetCurrentDataObject()
);
if (dataset)
{
fieldSummary local(queryFieldSummary(fieldName, dataset));
if (!queried.nComponents_)
{
queried.nComponents_ = local.nComponents_;
}
queried.association_ |= local.association_;
queried.range_ += local.range_;
}
}
return queried;
}
Foam::functionObjects::runTimePostPro::fieldVisualisationBase::FieldAssociation
Foam::functionObjects::runTimePostPro::fieldVisualisationBase::
queryFieldAssociation
(
const word& fieldName,
vtkDataSet* dataset
)
{
unsigned where(FieldAssociation::NO_DATA);
if (dataset)
{
if (dataset->GetCellData()->HasArray(fieldName.c_str()))
{
where |= FieldAssociation::CELL_DATA;
}
if (dataset->GetPointData()->HasArray(fieldName.c_str()))
{
where |= FieldAssociation::POINT_DATA;
}
}
return FieldAssociation(where);
}
Foam::functionObjects::runTimePostPro::fieldVisualisationBase::FieldAssociation
Foam::functionObjects::runTimePostPro::fieldVisualisationBase::
queryFieldAssociation
(
const word& fieldName,
vtkCompositeDataSet* data
)
{
unsigned where(FieldAssociation::NO_DATA);
auto iter = vtkSmartPointer<vtkDataObjectTreeIterator>::New();
iter->SetDataSet(data);
iter->VisitOnlyLeavesOn();
iter->SkipEmptyNodesOn();
for
(
iter->InitTraversal();
!iter->IsDoneWithTraversal();
iter->GoToNextItem()
)
{
vtkDataSet* dataset = vtkDataSet::SafeDownCast
(
iter->GetCurrentDataObject()
);
where |= queryFieldAssociation(fieldName, dataset);
}
return FieldAssociation(where);
}
void Foam::functionObjects::runTimePostPro::fieldVisualisationBase::addMagField
(
const word& fieldName,
vtkFieldData* fieldData
)
{
if (!fieldData)
{
return;
}
vtkDataArray* input = vtkDataArray::SafeDownCast
(
fieldData->GetAbstractArray(fieldName.c_str())
);
if (!input)
{
return;
}
const word magFieldName = "mag(" + fieldName + ")";
vtkDataArray* output = vtkDataArray::SafeDownCast
(
fieldData->GetAbstractArray(magFieldName.c_str())
);
if (output)
{
return;
}
// Simplfy and only handle scalar/vector input
const int nCmpt = input->GetNumberOfComponents();
const vtkIdType len = input->GetNumberOfTuples();
if (nCmpt == 1)
{
auto data = vtkSmartPointer<vtkFloatArray>::New();
data->SetName(magFieldName.c_str());
data->SetNumberOfComponents(1);
data->SetNumberOfTuples(len);
double scratch;
for (vtkIdType i=0; i < len; ++i)
{
input->GetTuple(i, &scratch);
scratch = Foam::mag(scratch);
data->SetTuple(i, &scratch);
}
fieldData->AddArray(data);
}
else if (nCmpt == 3)
{
auto data = vtkSmartPointer<vtkFloatArray>::New();
data->SetName(magFieldName.c_str());
data->SetNumberOfComponents(1);
data->SetNumberOfTuples(len);
doubleVector scratch;
for (vtkIdType i=0; i < len; ++i)
{
input->GetTuple(i, scratch.v_);
scratch.x() = Foam::mag(scratch);
data->SetTuple(i, scratch.v_);
}
fieldData->AddArray(data);
}
}
void Foam::functionObjects::runTimePostPro::fieldVisualisationBase::addMagField
(
const word& fieldName,
vtkDataSet* dataset
)
{
if (dataset)
{
addMagField(fieldName, dataset->GetCellData());
addMagField(fieldName, dataset->GetPointData());
}
}
void Foam::functionObjects::runTimePostPro::fieldVisualisationBase::addMagField
(
const word& fieldName,
vtkCompositeDataSet* data
)
{
auto iter = vtkSmartPointer<vtkDataObjectTreeIterator>::New();
iter->SetDataSet(data);
iter->VisitOnlyLeavesOn();
iter->SkipEmptyNodesOn();
for
(
iter->InitTraversal();
!iter->IsDoneWithTraversal();
iter->GoToNextItem()
)
{
vtkDataSet* dataset = vtkDataSet::SafeDownCast
(
iter->GetCurrentDataObject()
);
addMagField(fieldName, dataset);
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::functionObjects::runTimePostPro::fieldVisualisationBase::
fieldSummary::reduce()
{
if (Pstream::parRun())
{
Foam::reduce(nComponents_, maxOp<int>());
Foam::reduce(association_, bitOrOp<unsigned>());
Foam::reduce(range_, minMaxOp<scalar>());
}
}
Foam::Ostream& Foam::operator<<
(
Ostream& os,
const InfoProxy
<
functionObjects::runTimePostPro::fieldVisualisationBase::fieldSummary
>& proxy
)
{
os << "nComponents:" << proxy.t_.nComponents_
<< " association:" << label(proxy.t_.association_)
<< " min/max:" << proxy.t_.range_;
return os;
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::functionObjects::runTimePostPro::fieldVisualisationBase::
@ -84,7 +394,7 @@ setColourMap
vtkLookupTable* lut
) const
{
label nColours = 256;
constexpr label nColours = 256;
lut->SetNumberOfColors(nColours);
@ -92,47 +402,73 @@ setColourMap
switch (colourMap_)
{
case cmCoolToWarm: // ParaView: "Cool To Warm"
{
ctf->SetColorSpaceToDiverging();
ctf->AddRGBPoint(0.0, 0.231372, 0.298039, 0.752941);
ctf->AddRGBPoint(0.5, 0.865003, 0.865003, 0.865003);
ctf->AddRGBPoint(1.0, 0.705882, 0.0156863, 0.14902);
// ctf->SetNanColor(1, 1, 0);
break;
}
case cmColdAndHot: // ParaView : "Cold and Hot"
{
ctf->SetColorSpaceToRGB();
ctf->AddRGBPoint(0, 0, 1, 1);
ctf->AddRGBPoint(0.45, 0, 0, 1);
ctf->AddRGBPoint(0.5, 0, 0, 0.5019608);
ctf->AddRGBPoint(0.55, 1, 0, 0);
ctf->AddRGBPoint(1, 1, 1, 0);
break;
}
case cmFire: // ParaView: Black-Body Radiation
{
ctf->SetColorSpaceToRGB();
ctf->AddRGBPoint(0, 0, 0, 0);
ctf->AddRGBPoint(0.4, 0.901961, 0, 0);
ctf->AddRGBPoint(0.8, 0.901961, 0.901961, 0);
ctf->AddRGBPoint(1, 1, 1, 1);
// ctf->SetNanColor(0, 0.49804, 1);
break;
}
case cmRainbow:
{
ctf->SetColorSpaceToHSV();
ctf->AddRGBPoint(0, 0, 0, 1);
ctf->AddRGBPoint(0.5, 0, 1, 0);
ctf->AddRGBPoint(1, 1, 0, 0);
// ctf->SetNanColor(0.498039, 0.498039, 0.498039);
break;
}
case cmBlueWhiteRed:
{
// Values taken from ParaView settings
ctf->SetColorSpaceToDiverging();
ctf->AddRGBPoint(0.0, 0.231373, 0.298039, 0.752941);
ctf->AddRGBPoint(0.5, 0.865003, 0.865003, 0.865003);
ctf->AddRGBPoint(1.0, 0.705882, 0.0156863, 0.14902);
break;
}
case cmFire:
{
// Values taken from ParaView settings
ctf->SetColorSpaceToRGB();
ctf->AddRGBPoint(0, 0, 0, 0);
ctf->AddRGBPoint(0.4, 0.901961, 0, 0);
ctf->AddRGBPoint(0.8, 0.901961, 0.901961, 0);
ctf->AddRGBPoint(1, 1, 1, 1);
break;
}
case cmGreyscale:
case cmGreyscale: // ParaView: grayscale
{
ctf->SetColorSpaceToRGB();
ctf->AddRGBPoint(0, 0, 0, 0);
ctf->AddRGBPoint(1, 1, 1, 1);
// ctf->SetNanColor(1, 0, 0);
break;
}
case cmXray: // ParaView: "X ray"
{
ctf->SetColorSpaceToRGB();
ctf->AddRGBPoint(0, 1, 1, 1);
ctf->AddRGBPoint(1, 0, 0, 0);
// ctf->SetNanColor(1, 0, 0);
break;
}
}
for (label i = 0; i < nColours; i++)
double rgba[4] = { 0, 0, 0, 1 };
for (label i = 0; i < nColours; ++i)
{
double* c = ctf->GetColor(scalar(i)/scalar(nColours));
lut->SetTableValue(i, c[0], c[1], c[2], 1.0);
ctf->GetColor(scalar(i)/scalar(nColours), rgba);
lut->SetTableValue(i, rgba);
}
}
@ -145,105 +481,11 @@ addScalarBar
vtkLookupTable* lut
) const
{
// Add scalar bar legend
if (!scalarBar_.visible_)
// Add the scalar bar - only once!
if (renderer && Pstream::master())
{
return;
scalarBar_.add(colours_["text"]->value(position), renderer, lut);
}
auto sbar = vtkSmartPointer<vtkScalarBarActor>::New();
sbar->SetLookupTable(lut);
sbar->SetNumberOfLabels(scalarBar_.numberOfLabels_);
const vector textColour = colours_["text"]->value(position);
// Work-around to supply our own scalarbar title
// - Default scalar bar title text is scales by the scalar bar box
// dimensions so if the title is a long string, the text is shrunk to fit
// Instead, suppress title and set the title using a vtkTextActor
auto titleActor = vtkSmartPointer<vtkTextActor>::New();
sbar->SetTitle(" ");
titleActor->SetInput(scalarBar_.title_.c_str());
titleActor->GetTextProperty()->SetFontFamilyToArial();
titleActor->GetTextProperty()->SetFontSize(3*scalarBar_.fontSize_);
titleActor->GetTextProperty()->SetJustificationToCentered();
titleActor->GetTextProperty()->SetVerticalJustificationToBottom();
titleActor->GetTextProperty()->BoldOn();
titleActor->GetTextProperty()->ItalicOff();
titleActor->GetTextProperty()->SetColor
(
textColour[0],
textColour[1],
textColour[2]
);
titleActor->GetPositionCoordinate()->
SetCoordinateSystemToNormalizedViewport();
// How to use the standard scalar bar text
// sbar->SetTitle(scalarBar_.title_.c_str());
// sbar->GetTitleTextProperty()->SetColor
// (
// textColour[0],
// textColour[1],
// textColour[2]
// );
// sbar->GetTitleTextProperty()->SetFontSize(scalarBar_.fontSize_);
// sbar->GetTitleTextProperty()->ShadowOff();
// sbar->GetTitleTextProperty()->BoldOn();
// sbar->GetTitleTextProperty()->ItalicOff();
sbar->GetLabelTextProperty()->SetColor
(
textColour[0],
textColour[1],
textColour[2]
);
sbar->GetLabelTextProperty()->SetFontSize(scalarBar_.fontSize_);
sbar->GetLabelTextProperty()->ShadowOff();
sbar->GetLabelTextProperty()->BoldOff();
sbar->GetLabelTextProperty()->ItalicOff();
sbar->SetLabelFormat(scalarBar_.labelFormat_.c_str());
sbar->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport();
sbar->GetPositionCoordinate()->SetValue
(
scalarBar_.position_.first(),
scalarBar_.position_.second()
);
if (scalarBar_.vertical_)
{
sbar->SetOrientationToVertical();
sbar->SetWidth(0.1);
sbar->SetHeight(0.75);
sbar->SetTextPositionToSucceedScalarBar();
}
else
{
sbar->SetOrientationToHorizontal();
// Adjustments since not using scalarbar title property
sbar->SetWidth(0.75);
sbar->SetHeight(0.07);
sbar->SetBarRatio(0.5);
// sbar->SetHeight(0.1);
// sbar->SetTitleRatio(0.01);
sbar->SetTextPositionToPrecedeScalarBar();
}
titleActor->GetPositionCoordinate()->SetValue
(
scalarBar_.position_.first() + 0.5*sbar->GetWidth(),
scalarBar_.position_.second() + sbar->GetHeight()
);
// sbar->DrawFrameOn();
// sbar->DrawBackgroundOn();
// sbar->UseOpacityOff();
// sbar->VisibilityOff();
sbar->VisibilityOn();
renderer->AddActor(sbar);
renderer->AddActor2D(titleActor);
}
@ -252,9 +494,9 @@ setField
(
const scalar position,
const word& colourFieldName,
vtkPolyDataMapper* mapper,
vtkRenderer* renderer,
vtkPolyData* pData
const FieldAssociation fieldAssociation,
vtkMapper* mapper,
vtkRenderer* renderer
) const
{
mapper->InterpolateScalarsBeforeMappingOn();
@ -266,6 +508,7 @@ setField
mapper->ScalarVisibilityOff();
break;
}
case cbField:
{
// Create look-up table for colours
@ -277,15 +520,15 @@ setField
const char* fieldName = colourFieldName.c_str();
mapper->SelectColorArray(fieldName);
// Set to use either point or cell data
// Note: if both point and cell data exists, preferentially
// choosing point data. This is often the case when using
// glyphs
if (pData->GetPointData()->HasArray(fieldName))
// Use either point or cell data
// - if both point and cell data exists, preferentially choose
// point data. This is often the case when using glyphs.
if (fieldAssociation & FieldAssociation::POINT_DATA)
{
mapper->SetScalarModeToUsePointFieldData();
}
else if (pData->GetCellData()->HasArray(fieldName))
else if (fieldAssociation & FieldAssociation::CELL_DATA)
{
mapper->SetScalarModeToUseCellFieldData();
}
@ -301,7 +544,7 @@ setField
mapper->SetLookupTable(lut);
mapper->ScalarVisibilityOn();
// Add the bar
// Add the scalar bar
addScalarBar(position, renderer, lut);
break;
}
@ -316,43 +559,20 @@ addGlyphs
(
const scalar position,
const word& scaleFieldName,
const fieldSummary& scaleFieldInfo,
const word& colourFieldName,
const fieldSummary& colourFieldInfo,
const scalar maxGlyphLength,
vtkPolyData* data,
vtkActor* actor,
vtkRenderer* renderer
) const
{
auto glyph = vtkSmartPointer<vtkGlyph3D>::New();
auto glyphMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
glyphMapper->SetInputConnection(glyph->GetOutputPort());
// Determine whether we have CellData/PointData and (scalar/vector)
// or if we need to a cell->point data filter.
glyph->SetInputData(data);
glyph->ScalingOn();
bool needPointData = false;
// Determine whether we have scalar or vector data
// and if we need to convert CellData -> PointData
label nComponents = -1;
const char* scaleFieldNameChar = scaleFieldName.c_str();
if (data->GetPointData()->HasArray(scaleFieldNameChar))
{
nComponents =
data->GetPointData()->GetArray(scaleFieldNameChar)
->GetNumberOfComponents();
}
else if (data->GetCellData()->HasArray(scaleFieldNameChar))
{
// Need to convert CellData to PointData
needPointData = true;
nComponents =
data->GetCellData()->GetArray(scaleFieldNameChar)
->GetNumberOfComponents();
}
else
if (!scaleFieldInfo.exists())
{
WarningInFunction
<< "Cannot add glyphs. No such cell or point field: "
@ -360,30 +580,46 @@ addGlyphs
return;
}
const bool ok = (nComponents == 1 || nComponents == 3);
if (!ok)
if (!scaleFieldInfo.isScalar() && !scaleFieldInfo.isVector())
{
WarningInFunction
<< "Glyphs can only be added to scalar or vector data. "
<< "Unable to process field " << scaleFieldName << endl;
return;
}
else if (needPointData)
{
auto cellToPoint = vtkSmartPointer<vtkCellDataToPointData>::New();
cellToPoint->SetInputData(data);
cellToPoint->Update();
vtkDataSet* pds = cellToPoint->GetOutput();
vtkDataArray* pData = pds->GetPointData()->GetArray(scaleFieldNameChar);
// Store in main vtkPolyData
data->GetPointData()->AddArray(pData);
// Setup glyphs
// The min/max data range for the input data (cell or point),
// which will be slightly less after using a cell->point filter
// (since it averages), but is still essentially OK.
auto glyph = vtkSmartPointer<vtkGlyph3D>::New();
glyph->ScalingOn();
auto glyphMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
glyphMapper->SetInputConnection(glyph->GetOutputPort());
vtkSmartPointer<vtkCellDataToPointData> cellToPoint;
// The data source is filtered or original (PointData)
if (!scaleFieldInfo.hasPointData() || !colourFieldInfo.hasPointData())
{
// CellData - Need a cell->point filter
cellToPoint = vtkSmartPointer<vtkCellDataToPointData>::New();
cellToPoint->SetInputData(data);
glyph->SetInputConnection(cellToPoint->GetOutputPort());
}
else
{
glyph->SetInputData(data);
}
if (nComponents == 1)
if (scaleFieldInfo.nComponents_ == 1)
{
auto sphere = vtkSmartPointer<vtkSphereSource>::New();
sphere->SetCenter(0, 0, 0);
@ -397,12 +633,12 @@ addGlyphs
if (maxGlyphLength > 0)
{
// Can get range from point data:
// double range[2];
// vtkDataArray* values =
// data->GetPointData()->GetScalars(scaleFieldNameChar);
// values->GetRange(range);
// Using range from the data:
// glyph->SetRange
// (
// scaleFieldInfo.range_.first(),
// scaleFieldInfo.range_.second()
// );
// Set range according to user-supplied limits
glyph->ClampingOn();
@ -421,14 +657,14 @@ addGlyphs
glyph->SetColorModeToColorByScalar();
glyph->SetInputArrayToProcess
(
0, // scalars
0,
0,
0, // index (0) = scalars
0, // port
0, // connection
vtkDataObject::FIELD_ASSOCIATION_POINTS,
scaleFieldNameChar
scaleFieldName.c_str()
);
}
else if (nComponents == 3)
else if (scaleFieldInfo.nComponents_ == 3)
{
auto arrow = vtkSmartPointer<vtkArrowSource>::New();
arrow->SetTipResolution(10);
@ -441,24 +677,13 @@ addGlyphs
if (maxGlyphLength > 0)
{
vtkDataArray* values =
data->GetPointData()->GetVectors(scaleFieldNameChar);
double range[6];
values->GetRange(range);
// Attempt to set range for vectors...
// scalar x0 = sqrt(sqr(range_.first())/3.0);
// scalar x1 = sqrt(sqr(range_.second())/3.0);
// range[0] = x0;
// range[1] = x0;
// range[2] = x0;
// range[3] = x1;
// range[4] = x1;
// range[5] = x1;
// Set range according data limits
glyph->ClampingOn();
glyph->SetRange(range);
glyph->SetRange
(
scaleFieldInfo.range_.first(),
scaleFieldInfo.range_.second()
);
glyph->SetScaleFactor(maxGlyphLength);
}
else
@ -471,20 +696,30 @@ addGlyphs
glyph->SetColorModeToColorByVector();
glyph->SetInputArrayToProcess
(
1, // vectors
0,
0,
1, // index (1) = vectors
0, // port
0, // connection
vtkDataObject::FIELD_ASSOCIATION_POINTS,
scaleFieldNameChar
scaleFieldName.c_str()
);
}
if (ok)
// Apply colouring etc.
// We already established PointData, which as either in the original,
// or generated with vtkCellDataToPointData filter.
{
glyph->Update();
setField(position, colourFieldName, glyphMapper, renderer, data);
setField
(
position,
colourFieldName,
FieldAssociation::POINT_DATA, // Original or after filter
glyphMapper,
renderer
);
glyphMapper->Update();
@ -506,9 +741,11 @@ fieldVisualisationBase
:
colours_(colours),
fieldName_(dict.get<word>("field")),
smooth_(dict.lookupOrDefault("smooth", false)),
colourBy_(cbColour),
colourMap_(cmRainbow),
range_()
range_(),
scalarBar_()
{
colourByTypeNames.readEntry("colourBy", dict, colourBy_);
@ -516,26 +753,24 @@ fieldVisualisationBase
{
case cbColour:
{
scalarBar_.visible_ = false;
scalarBar_.hide();
break;
}
case cbField:
{
dict.readEntry("range", range_);
colourMapTypeNames.readIfPresent("colourMap", dict, colourMap_);
const dictionary& sbDict = dict.subDict("scalarBar");
sbDict.readEntry("visible", scalarBar_.visible_);
const dictionary* sbar = dict.findDict("scalarBar");
if (scalarBar_.visible_)
if (sbar)
{
sbDict.readEntry("vertical", scalarBar_.vertical_);
sbDict.readEntry("position", scalarBar_.position_);
sbDict.readEntry("title", scalarBar_.title_);
sbDict.readEntry("fontSize", scalarBar_.fontSize_);
sbDict.readEntry("labelFormat", scalarBar_.labelFormat_);
sbDict.readEntry("numberOfLabels", scalarBar_.numberOfLabels_);
scalarBar_.read(*sbar);
}
else
{
scalarBar_.hide();
}
break;
}

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -29,6 +27,20 @@ Class
Description
Base class for scene objects
Dictionary controls - colour by field
\table
Property | Description | Required | Default
colourBy | Colouring type (color / field) | yes |
range | Lower/upper range to display | yes |
smooth | Request smoother output | no | false
colourMap | Colour map for rendering | no | rainbow
scalarBar | Scalar-bar sub-dictionary | yes |
\endtable
Colour maps include "coolToWarm" ("blueWhiteRed"), "coldAndHot",
"fire", "rainbow", "greyscale" ("grayscale"), "xray". For historical
reasons, the default is still "rainbow".
SourceFiles
fieldVisualisationBase.C
@ -41,27 +53,35 @@ SourceFiles
#include "Tuple2.H"
#include "Enum.H"
#include "vector.H"
#include "MinMax.H"
#include "HashPtrTable.H"
#include "scalarBar.H"
#include "Function1.H"
// VTK includes
#include "vtkSmartPointer.h"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Forward declarations
// Forward Declarations
class vtkActor;
class vtkCompositeDataSet;
class vtkCompositeDataGeometryFilter;
class vtkCompositePolyDataMapper;
class vtkDataSet;
class vtkDataSetAlgorithm;
class vtkFieldData;
class vtkLookupTable;
class vtkMapper;
class vtkPolyData;
class vtkPolyDataMapper;
class vtkRenderer;
namespace Foam
{
namespace functionObjects
{
// Forward declarations
// Forward Declarations
class runTimePostProcessing;
namespace runTimePostPro
@ -75,48 +95,110 @@ class fieldVisualisationBase
{
public:
// Public enumerations
// Public Enumerations
//- Colouring type
enum colourByType
{
cbColour,
cbField
cbColour, //!< "colour" : Use specified colour
cbField //!< "field" : Use named field
};
//- Enumeration names for colourByType
static const Enum<colourByType> colourByTypeNames;
//- Colour map enumerations
enum colourMapType
{
cmRainbow,
cmBlueWhiteRed,
cmFire,
cmGreyscale
cmCoolToWarm, //!< ParaView "Cool To Warm" blue-white-read
cmBlueWhiteRed = cmCoolToWarm,
cmColdAndHot, //!< ParaView "Cold and Hot"
cmFire, //!< ParaView "Black-Body Radiation"
cmRainbow, //!< "rainbow"
cmGreyscale, //!< ParaView "Grayscale"
cmXray //!< ParaView "X Ray"
};
//- Enumeration names for colourMapType
static const Enum<colourMapType> colourMapTypeNames;
//- Enumeration of the data field associations
// These values are used internally and do NOT correspond to the
// vtkDataObject::FieldAssociations enumeration.
enum FieldAssociation
{
NO_DATA = 0, //!< No associated data
CELL_DATA = 0x1, //!< Associated with cells (faces)
POINT_DATA = 0x2, //!< Associated with points
CELL_POINT_DATA = 0x3 //!< Associated with cells and/or points
};
//- General field characteristics.
// For convenience, the interface is exposed but external use is
// highly discouraged.
struct fieldSummary
{
int nComponents_;
unsigned association_;
scalarMinMax range_;
//- Construct null
fieldSummary()
:
nComponents_(0),
association_(0u),
range_()
{}
//- Parallel reduction. A no-op if Pstream::parRun() is false
void reduce();
//- True if nComponents_ == 1
bool isScalar() const
{
return nComponents_ == 1;
}
//- True if nComponents_ == 3
bool isVector() const
{
return nComponents_ == 3;
}
//- True if association_ is non-zero
bool exists() const
{
return association_;
}
//- True if there is a POINT_DATA association
bool hasPointData() const
{
return (association_ & FieldAssociation::POINT_DATA);
}
InfoProxy<fieldSummary> info() const
{
return InfoProxy<fieldSummary>(*this);
}
};
protected:
// Protected Data
struct scalarBar
{
bool visible_;
bool vertical_;
Tuple2<scalar, scalar> position_;
string title_;
label fontSize_;
string labelFormat_;
label numberOfLabels_;
};
//- Colours
const HashPtrTable<Function1<vector>>& colours_;
//- Field name
word fieldName_;
//- Requested smoother fields (eg, interpolate cell -> point values)
bool smooth_;
//- Colour by type
colourByType colourBy_;
@ -126,16 +208,67 @@ protected:
//- Range of values
Tuple2<scalar, scalar> range_;
//- Scalar bar
//- Scalar bar characteristics
scalarBar scalarBar_;
// Protected Member Functions
//- Query DataSet for field name and its field association
static fieldSummary queryFieldSummary
(
const word& fieldName,
vtkDataSet* dataset
);
//- Query composite DataSet for field name and its FieldAssociation
static fieldSummary queryFieldSummary
(
const word& fieldName,
vtkCompositeDataSet* data
);
//- Query DataSet for field name and its field association
static FieldAssociation queryFieldAssociation
(
const word& fieldName,
vtkDataSet* dataset
);
//- Query composite DataSet for field name and its FieldAssociation
static FieldAssociation queryFieldAssociation
(
const word& fieldName,
vtkCompositeDataSet* data
);
//- Add "mag(..)" field for filters that only accept scalars
static void addMagField
(
const word& fieldName,
vtkFieldData* fieldData
);
//- Add "mag(..)" field for filters that only accept scalars
static void addMagField
(
const word& fieldName,
vtkDataSet* dataset
);
//- Add "mag(..)" field for filters that only accept scalars
static void addMagField
(
const word& fieldName,
vtkCompositeDataSet* data
);
//- Set the colour map
void setColourMap(vtkLookupTable* lut) const;
//- Add scalar bar to renderer
//- Add scalar bar (if visible) to renderer
void addScalarBar
(
const scalar position,
@ -148,9 +281,9 @@ protected:
(
const scalar position,
const word& colourFieldName,
vtkPolyDataMapper* mapper,
vtkRenderer* renderer,
vtkPolyData* pData
const FieldAssociation fieldAssociation,
vtkMapper* mapper,
vtkRenderer* renderer
) const;
//- Add glyphs
@ -158,13 +291,17 @@ protected:
(
const scalar position,
const word& scaleFieldName,
const fieldSummary& scaleFieldInfo,
const word& colourFieldName,
const fieldSummary& colourFieldInfo,
const scalar maxGlyphLength,
vtkPolyData* data,
vtkActor* actor,
vtkRenderer* renderer
) const;
//- No copy construct
fieldVisualisationBase(const fieldVisualisationBase&) = delete;
@ -204,6 +341,19 @@ public:
} // End namespace runTimePostPro
} // End namespace functionObjects
// Ostream
Ostream& operator<<
(
Ostream& os,
const InfoProxy
<
functionObjects::runTimePostPro::fieldVisualisationBase::fieldSummary
>& proxy
);
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -25,20 +25,6 @@ License
#include "functionObjectBase.H"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
namespace runTimePostPro
{
defineTypeNameAndDebug(functionObjectBase, 0);
}
}
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
Foam::fileName
@ -69,7 +55,12 @@ bool Foam::functionObjects::runTimePostPro::functionObjectBase::removeFile
{
// Foam::rm() ignores empty names etc.
if (Pstream::master())
{
return Foam::rm(getFileName(keyword, subDictName));
}
return false;
}
@ -85,6 +76,7 @@ Foam::functionObjects::runTimePostPro::functionObjectBase::functionObjectBase
fieldVisualisationBase(dict, colours),
state_(state),
functionObjectName_(dict.get<word>("functionObject")),
liveObject_(dict.lookupOrDefault("liveObject", true)),
clearObjects_(dict.lookupOrDefault("clearObjects", false))
{}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -32,8 +32,12 @@ Description
Property | Description | Required | Default
functionObject | The data source | yes |
clearObjects | Remove file after use | no | no
liveObject | Prefer simulation data source | no | true
\endtable
The "live" keyword indiates that from within the simulation (in memory)
is preferred over data from disk (for example).
SourceFiles
functionObjectBase.C
@ -64,14 +68,17 @@ class functionObjectBase
{
protected:
// Protected data
// Protected Data
//- Reference to the state
const stateFunctionObject& state_;
//- The function object name which provides the source data
//- The function object name that provides the source data
word functionObjectName_;
//- Flag to indicate "live" (simulation) data source should be used
bool liveObject_;
//- Flag to indicate that source data should be cleared after use
bool clearObjects_;
@ -109,6 +116,7 @@ protected:
// \note does not change the stateFunctionObject
bool removeFile(const word& keyword, const word& subDictName);
//- No copy construct
functionObjectBase(const functionObjectBase&) = delete;
@ -118,10 +126,6 @@ protected:
public:
//- Run-time type information
TypeName("functionObjectBase");
// Constructors
//- Construct from dictionary

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -33,11 +31,11 @@ License
// VTK includes
#include "vtkActor.h"
#include "vtkRenderer.h"
#include "vtkSmartPointer.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkSmartPointer.h"
// VTK Readers
#include "vtkPolyDataReader.h"
@ -51,13 +49,42 @@ namespace functionObjects
{
namespace runTimePostPro
{
defineTypeNameAndDebug(functionObjectCloud, 0);
defineTypeName(functionObjectCloud);
addToRunTimeSelectionTable(pointData, functionObjectCloud, dictionary);
}
}
}
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace
{
static vtkSmartPointer<vtkPolyData> getPolyDataFile(const Foam::fileName& fName)
{
// Very simple - we only support vtp files, which are expected to have
// the scaling and colouring fields.
vtkSmartPointer<vtkPolyData> dataset;
if (fName.ext() == "vtp")
{
auto reader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
reader->SetFileName(fName.c_str());
reader->Update();
dataset = reader->GetOutput();
return dataset;
}
return dataset;
}
} // End anonymous namespace
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::runTimePostPro::functionObjectCloud::functionObjectCloud
@ -73,9 +100,7 @@ Foam::functionObjects::runTimePostPro::functionObjectCloud::functionObjectCloud
inputFileName_(),
colourFieldName_(dict.get<word>("colourField")),
actor_()
{
actor_ = vtkSmartPointer<vtkActor>::New();
}
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
@ -87,8 +112,8 @@ Foam::functionObjects::runTimePostPro::functionObjectCloud::
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
void Foam::functionObjects::runTimePostPro::functionObjectCloud::
addGeometryToScene
bool Foam::functionObjects::runTimePostPro::functionObjectCloud::
addGeometryFromFile
(
const scalar position,
vtkRenderer* renderer
@ -96,72 +121,118 @@ addGeometryToScene
{
if (!visible_)
{
return;
return false;
}
vtkSmartPointer<vtkPolyData> polyData;
bool good = true;
// The vtkCloud stores 'file' via the stateFunctionObject
// (lookup by cloudName).
// It only generates VTP format, which means there is a single file
// containing all fields.
if (Pstream::master())
{
inputFileName_ = getFileName("file", cloudName_);
if (inputFileName_.empty())
if (inputFileName_.size())
{
polyData = getPolyDataFile(inputFileName_);
if (!polyData || polyData->GetNumberOfPoints() == 0)
{
good = false;
WarningInFunction
<< "Could not read "<< inputFileName_ << nl
<< "Only VTK (.vtp) files are supported"
<< endl;
}
else
{
DebugInfo
<< " Resolved cloud file "
<< inputFileName_ << endl;
}
}
else
{
good = false;
WarningInFunction
<< "Unable to find function object " << functionObjectName_
<< " output for field " << fieldName_
<< ". Cloud will not be processed"
<< endl;
return;
}
vtkSmartPointer<vtkPolyData> dataset;
if (inputFileName_.hasExt("vtp"))
{
auto reader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
reader->SetFileName(inputFileName_.c_str());
reader->Update();
dataset = reader->GetOutput();
}
else
{
// Invalid name - ignore.
// Don't support VTK legacy format at all - it is too wasteful
// and cumbersome.
WarningInFunction
<< "Could not read "<< inputFileName_ << nl
<< "Only VTK (.vtp) files are supported"
<< ". Cloud will not be processed"
<< endl;
inputFileName_.clear();
}
reduce(good, andOp<bool>());
if (dataset)
if (!good)
{
return false;
}
// Only render on master
if (!renderer || !Pstream::master())
{
return true;
}
// Rendering
actor_ = vtkSmartPointer<vtkActor>::New();
{
fieldSummary scaleFieldInfo =
queryFieldSummary(fieldName_, polyData);
fieldSummary colourFieldInfo =
queryFieldSummary(colourFieldName_, polyData);
// No reduction
auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
actor_->SetMapper(mapper);
/// dataset->Print(std::cout);
addGlyphs
(
position,
fieldName_,
colourFieldName_,
fieldName_, scaleFieldInfo, // scaling
colourFieldName_, colourFieldInfo, // colour
maxGlyphLength_,
dataset,
polyData,
actor_,
renderer
);
renderer->AddActor(actor_);
}
return true;
}
void Foam::functionObjects::runTimePostPro::functionObjectCloud::
addGeometryToScene
(
const scalar position,
vtkRenderer* renderer
)
{
// File source
addGeometryFromFile(position, renderer);
}
@ -170,10 +241,16 @@ void Foam::functionObjects::runTimePostPro::functionObjectCloud::updateActors
const scalar position
)
{
actor_->GetProperty()->SetOpacity(opacity(position));
if (actor_)
{
const vector colour = pointColour_->value(position);
vector pc = pointColour_->value(position);
actor_->GetProperty()->SetColor(pc[0], pc[1], pc[2]);
vtkProperty* prop = actor_->GetProperty();
prop->SetOpacity(opacity(position));
prop->SetColor(colour[0], colour[1], colour[2]);
}
}

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,7 +25,17 @@ Class
Foam::functionObjects::runTimePostPro::functionObjectCloud
Description
Visualisation of cloud data from function object output
Visualisation of cloud data from function object output (file-based only).
Dictionary controls
\table
Property | Description | Required | Default
type | The point type: functionObjectCloud | yes |
functionObject | The data source | yes |
cloud | The cloud name | no |
field | The field for glyphs scaling | no |
colourField | The field to display | no |
\endtable
SourceFiles
functionObjectCloud.C
@ -87,7 +95,7 @@ protected:
public:
//- Run-time type information
TypeName("functionObjectCloud");
TypeNameNoDebug("functionObjectCloud");
// Constructors
@ -107,7 +115,14 @@ public:
// Member Functions
//- Add tube(s) to scene
//- Add cloud to scene (using file source)
bool addGeometryFromFile
(
const scalar position,
vtkRenderer* renderer
);
//- Add cloud to scene
virtual void addGeometryToScene
(
const scalar position,

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -50,7 +48,7 @@ namespace functionObjects
{
namespace runTimePostPro
{
defineTypeNameAndDebug(functionObjectLine, 0);
defineTypeName(functionObjectLine);
addToRunTimeSelectionTable(pathline, functionObjectLine, dictionary);
}
}
@ -67,7 +65,7 @@ static vtkSmartPointer<vtkPolyData> getPolyDataFile(const Foam::fileName& fName)
// Not extremely elegant...
vtkSmartPointer<vtkPolyData> dataset;
if (fName.ext() == "vtk")
if ("vtk" == fName.ext())
{
auto reader = vtkSmartPointer<vtkPolyDataReader>::New();
@ -78,7 +76,7 @@ static vtkSmartPointer<vtkPolyData> getPolyDataFile(const Foam::fileName& fName)
return dataset;
}
if (fName.ext() == "vtp")
if ("vtp" == fName.ext())
{
auto reader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
@ -127,7 +125,8 @@ addGeometryToScene
vtkRenderer* renderer
)
{
if (!visible_)
// Currently master-only
if (!visible_ || !renderer || !Pstream::master())
{
return;
}
@ -155,10 +154,19 @@ addGeometryToScene
return;
}
DebugInfo << " Resolved lines " << fName << endl;
auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
setField(position, fieldName_, mapper, renderer, polyData);
setField
(
position,
fieldName_,
queryFieldAssociation(fieldName_, polyData),
mapper,
renderer
);
actor_->SetMapper(mapper);

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,7 +25,13 @@ Class
Foam::functionObjects::runTimePostPro::functionObjectLine
Description
Visualisation of line data from function object output
Visualisation of line data from function object output (file-based only).
Dictionary controls
\table
Property | Description | Required | Default
type | The line type: functionObjectLine | yes |
\endtable
SourceFiles
functionObjectLine.C
@ -78,7 +82,7 @@ protected:
public:
//- Run-time type information
TypeName("functionObjectLine");
TypeNameNoDebug("functionObjectLine");
// Constructors

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2016 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -32,6 +30,13 @@ License
// VTK includes
#include "vtkActor.h"
#include "vtkCellData.h"
#include "vtkCellDataToPointData.h"
#include "vtkCompositeDataGeometryFilter.h"
#include "vtkCompositeDataSet.h"
#include "vtkCompositePolyDataMapper.h"
#include "vtkMultiPieceDataSet.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h"
@ -50,7 +55,7 @@ namespace functionObjects
{
namespace runTimePostPro
{
defineTypeNameAndDebug(functionObjectSurface, 0);
defineTypeName(functionObjectSurface);
addToRunTimeSelectionTable(surface, functionObjectSurface, dictionary);
}
}
@ -67,7 +72,7 @@ static vtkSmartPointer<vtkPolyData> getPolyDataFile(const Foam::fileName& fName)
// Not extremely elegant...
vtkSmartPointer<vtkPolyData> dataset;
if (fName.ext() == "vtk")
if ("vtk" == fName.ext())
{
auto reader = vtkSmartPointer<vtkPolyDataReader>::New();
@ -78,7 +83,7 @@ static vtkSmartPointer<vtkPolyData> getPolyDataFile(const Foam::fileName& fName)
return dataset;
}
if (fName.ext() == "vtp")
if ("vtp" == fName.ext())
{
auto reader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
@ -110,17 +115,10 @@ functionObjectSurface
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::functionObjects::runTimePostPro::functionObjectSurface::
~functionObjectSurface()
{}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
void Foam::functionObjects::runTimePostPro::functionObjectSurface::
addGeometryToScene
bool Foam::functionObjects::runTimePostPro::functionObjectSurface::
addGeometry
(
const scalar position,
vtkRenderer* renderer
@ -128,39 +126,291 @@ addGeometryToScene
{
if (!visible_)
{
return;
return false;
}
fileName fName = getFileName("file", fieldName_);
if (fName.empty())
DebugInfo << " Resolve surface " << functionObjectName_ << endl;
const polySurface* surf =
(
geometryBase::parent_.storedObjects()
.cfindObject<polySurface>(functionObjectName_)
);
// Treat surface with no faces/points like a missing surface
surf = ((surf && surf->nPoints()) ? surf : nullptr);
bool hasSurface = surf;
// Retrieve the field association (CELL, POINT) for the given field
unsigned fieldAssociation(0u);
if (surf)
{
unsigned queried = surf->queryFieldAssociation(fieldName_);
if (queried & polySurface::FACE_DATA)
{
fieldAssociation |= FieldAssociation::CELL_DATA;
}
if (queried & polySurface::POINT_DATA)
{
fieldAssociation |= FieldAssociation::POINT_DATA;
}
}
// Reduce the information
if (Pstream::parRun())
{
if (!hasSurface)
{
// No geometry - set all field association bits ON to ensure
// it does not affect bitwise reduction.
fieldAssociation = (~0u);
}
reduce(hasSurface, orOp<bool>());
reduce(fieldAssociation, bitAndOp<unsigned>());
}
if (!hasSurface)
{
WarningInFunction
<< "Unable to read file name from function object "
<< functionObjectName_ << " for field " << fieldName_
<< ". Surface will not be processed"
<< "No functionObject surface, or has no faces: "
<< functionObjectName_
<< endl;
return;
}
auto polyData = getPolyDataFile(fName);
if (!polyData || polyData->GetNumberOfPoints() == 0)
if (debug)
{
WarningInFunction
<< "Could not read "<< fName << nl
<< "Only VTK (.vtp, .vtk) files are supported"
<< endl;
return;
Info<< " Available surfaces:" << nl
<< geometryBase::parent_.storedObjects()
.sortedNames<polySurface>() << endl;
}
return false;
}
//// Pout<< "local surface = " << (surf ? surf->nFaces() : 0) << nl;
// Create a vtkMultiPieceDataSet with vtkPolyData on the leaves
vtkSmartPointer<vtkMultiPieceDataSet> multiPiece;
// Requesting glyphs on the surface AND only have face data?
// - just use the faceCentres directly and attach fields as CellData
// (not PointData).
if
(
representation_ == rtGlyph
&& (fieldAssociation == FieldAssociation::CELL_DATA)
)
{
multiPiece = gatherFaceCentres(surf);
}
else
{
multiPiece = gatherSurfacePieces(surf);
}
// Add the field (the information is consistent after last reduction).
// Need field(s) for glyphs or colourByField:
if (representation_ == rtGlyph || colourBy_ == cbField)
{
if (fieldAssociation == FieldAssociation::CELL_DATA)
{
addDimField<polySurfaceGeoMesh>
(
multiPiece,
surf,
fieldName_
);
}
else if (fieldAssociation & FieldAssociation::POINT_DATA)
{
addDimField<polySurfacePointGeoMesh>
(
multiPiece,
surf,
fieldName_
);
}
}
// Now have a multi-piece dataset that is one of the following:
//
// - one-piece per processor (OpenFOAM = parallel, VTK=parallel)
// - all pieces on master only (OpenFOAM = parallel, VTK=serial)
// Re-query field information - we may have stored it differently
// than the original source.
fieldSummary fieldInfo = queryFieldSummary(fieldName_, multiPiece);
fieldInfo.reduce();
// Not rendered on this processor?
// This is where we stop, but could also have an MPI barrier
if (!renderer)
{
return true;
}
// Rendering
{
auto polyData = vtkSmartPointer<vtkCompositeDataGeometryFilter>::New();
polyData->SetInputData(multiPiece);
polyData->Update();
if (representation_ == rtGlyph)
{
addGlyphs
(
position,
fieldName_, fieldInfo, // scaling
fieldName_, fieldInfo, // colouring
maxGlyphLength_,
polyData->GetOutput(),
surfaceActor_,
renderer
);
}
else
{
vtkSmartPointer<vtkCellDataToPointData> cellToPoint;
// CellData - Need a cell->point filter
if (smooth_ && !fieldInfo.hasPointData())
{
cellToPoint = vtkSmartPointer<vtkCellDataToPointData>::New();
cellToPoint->SetInputData(multiPiece);
polyData->SetInputConnection(cellToPoint->GetOutputPort());
}
else
{
polyData->SetInputData(multiPiece);
}
polyData->Update();
if (!smooth_)
{
addFeatureEdges(renderer, polyData);
}
auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(polyData->GetOutputPort());
setField
(
position,
fieldName_,
fieldName_,
(
smooth_
? FieldAssociation::POINT_DATA
: FieldAssociation(fieldInfo.association_)
),
mapper,
renderer
);
surfaceActor_->SetMapper(mapper);
setRepresentation(surfaceActor_);
renderer->AddActor(surfaceActor_);
}
}
return true;
}
bool Foam::functionObjects::runTimePostPro::functionObjectSurface::
addGeometryFromFile
(
const scalar position,
vtkRenderer* renderer
)
{
if (!visible_)
{
return false;
}
vtkSmartPointer<vtkPolyData> polyData;
bool good = true;
// File reading is serial (master only)
if (Pstream::master())
{
fileName fName = getFileName("file", fieldName_);
if (fName.size())
{
polyData = getPolyDataFile(fName);
if (!polyData || polyData->GetNumberOfPoints() == 0)
{
good = false;
WarningInFunction
<< "Could not read "<< fName << nl
<< "Only VTK (.vtp, .vtk) files are supported"
<< endl;
}
else
{
DebugInfo << " Resolved surface " << fName << endl;
}
}
else
{
good = false;
WarningInFunction
<< "Unable to read file name from function object "
<< functionObjectName_ << " for field " << fieldName_
<< ". Surface will not be processed"
<< endl;
}
}
reduce(good, andOp<bool>());
if (!good)
{
return false;
}
// Only render on master
if (!renderer || !Pstream::master())
{
return true;
}
fieldSummary fieldInfo = queryFieldSummary(fieldName_, polyData);
// No reduction (serial)
// Render
if (representation_ == rtGlyph)
{
addGlyphs
(
position,
fieldName_, fieldInfo, // scaling
fieldName_, fieldInfo, // colouring
maxGlyphLength_,
polyData,
surfaceActor_,
@ -174,7 +424,14 @@ addGeometryToScene
auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputData(polyData);
setField(position, fieldName_, mapper, renderer, polyData);
setField
(
position,
fieldName_,
queryFieldAssociation(fieldName_, polyData),
mapper,
renderer
);
surfaceActor_->SetMapper(mapper);
@ -182,6 +439,44 @@ addGeometryToScene
renderer->AddActor(surfaceActor_);
}
return true;
}
void Foam::functionObjects::runTimePostPro::functionObjectSurface::
addGeometryToScene
(
const scalar position,
vtkRenderer* renderer
)
{
if (!visible_)
{
return;
}
if (liveObject_)
{
// Live source
if (addGeometry(position, renderer))
{
return;
}
WarningInFunction
<< "No functionObject live source, or is empty: "
<< functionObjectName_
<< " ... attempting with file source"
<< endl;
}
else
{
DebugInfo << "Using file source only" << nl;
}
// File source
addGeometryFromFile(position, renderer);
}
@ -189,6 +484,8 @@ bool Foam::functionObjects::runTimePostPro::functionObjectSurface::clear()
{
if (functionObjectBase::clear())
{
// Even for a "live" data source we allow file cleanup
// (eg, from a previous run, etc)
return removeFile("file", fieldName_);
}

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,7 +25,22 @@ Class
Foam::functionObjects::runTimePostPro::functionObjectSurface
Description
Visualisation of surface data from function object output
Visualisation of surface data from function object output,
typically the result of a prior sampled surfaces operation.
Operates in a "live" mode, in which the previously sampled surfaces
are retrieved from the functionObject registry.
Or in the traditional file-based mode, in which the sampling is used
to generate a file and its name is retrieved from the functionObject
properties.
File-based import is restricted to "vtk" and "vtp" formats.
Dictionary controls
\table
Property | Description | Required | Default
type | The type: functionObjectSurface | yes |
\endtable
SourceFiles
functionObjectfunctionObjectSurface.C
@ -72,7 +85,7 @@ protected:
public:
//- Run-time type information
TypeName("functionObjectSurface");
TypeNameNoDebug("functionObjectSurface");
// Constructors
@ -87,11 +100,25 @@ public:
//- Destructor
virtual ~functionObjectSurface();
virtual ~functionObjectSurface() = default;
// Member Functions
//- Add functionObjectSurface to scene (using simulation source)
bool addGeometry
(
const scalar position,
vtkRenderer* renderer
);
//- Add functionObjectSurface to scene (using file source)
bool addGeometryFromFile
(
const scalar position,
vtkRenderer* renderer
);
//- Add functionObjectSurface(s) to scene
virtual void addGeometryToScene
(

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -35,6 +33,18 @@ License
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
namespace runTimePostPro
{
defineDebugSwitchWithName(geometryBase, "runTimePostPro::geometryBase", 0);
}
}
}
const Foam::Enum
<
Foam::functionObjects::runTimePostPro::geometryBase::renderModeType
@ -89,7 +99,7 @@ Foam::functionObjects::runTimePostPro::geometryBase::geometryBase
:
parent_(parent),
name_(dict.dictName()),
visible_(dict.get<bool>("visible")),
visible_(dict.lookupOrDefault("visible", true)),
renderMode_
(
renderModeTypeNames.lookupOrDefault("renderMode", dict, rmGouraud)
@ -123,6 +133,13 @@ Foam::functionObjects::runTimePostPro::geometryBase::parent() const
}
bool Foam::functionObjects::runTimePostPro::geometryBase::
needsCollective() const
{
return parent_.needsCollective();
}
const Foam::word&
Foam::functionObjects::runTimePostPro::geometryBase::name() const
{

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,12 +25,12 @@ Class
Foam::functionObjects::runTimePostPro::geometryBase
Description
Base class for surface, text handling
Base class for surface, text handling etc.
Dictionary controls
\table
Property | Description | Required | Default
visible | Display the object | yes |
visible | Display the object | no | yes
renderMode | Shading (flat/gouraud/phong) | no | gouraud
opacity | Object opacity | no | 1.0
\endtable
@ -53,7 +51,7 @@ SourceFiles
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Forward declarations
// Forward Declarations (VTK)
class vtkRenderer;
class vtkActor;
@ -62,7 +60,7 @@ namespace Foam
namespace functionObjects
{
// Forward declarations
// Forward Declarations
class runTimePostProcessing;
namespace runTimePostPro
@ -75,11 +73,11 @@ namespace runTimePostPro
class geometryBase
{
public:
// Public enumerations
// Public Enumerations
//- Surface shading types
enum renderModeType
{
rmFlat, //!< Flat shading
@ -87,6 +85,7 @@ public:
rmPhong //!< Phong shading
};
//- Names for surface shading types
static const Enum<renderModeType> renderModeTypeNames;
@ -97,7 +96,7 @@ protected:
//- Reference to the parent function object
const runTimePostProcessing& parent_;
//- Name
//- The surface name
word name_;
//- Visible flag
@ -113,7 +112,7 @@ protected:
const HashPtrTable<Function1<vector>>& colours_;
// Protected functions
// Protected Functions
//- Initialise actor
void initialiseActor(vtkActor* actor) const;
@ -127,6 +126,9 @@ protected:
public:
//- Debug switch
static int debug;
// Constructors
//- Construct from dictionary
@ -149,6 +151,10 @@ public:
//- Return the reference to the parent function object
const runTimePostProcessing& parent() const;
//- May need to gather geometry parts to render on single-processor
// True when OpenFOAM is running in parallel but VTK is not.
bool needsCollective() const;
//- Return the name
const word& name() const;
@ -162,7 +168,7 @@ public:
const HashPtrTable<Function1<vector>>& colours() const;
// Scene interaction
// Scene Interaction
//- Add geometry to scene
virtual void addGeometryToScene
@ -174,7 +180,7 @@ public:
//- Update the actors
virtual void updateActors(const scalar position) = 0;
//- Clear files used to create the object(s)
//- Clear any files used to create the object(s)
virtual bool clear() = 0;
};

View File

@ -0,0 +1,263 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
// OpenFOAM includes
#include "geometryCloud.H"
#include "cloud.H"
#include "fvMesh.H"
#include "runTimePostProcessing.H"
#include "addToRunTimeSelectionTable.H"
// VTK includes
#include "vtkActor.h"
#include "vtkCompositeDataGeometryFilter.h"
#include "vtkCompositeDataSet.h"
#include "vtkCompositePolyDataMapper.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkSmartPointer.h"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
namespace runTimePostPro
{
defineTypeName(geometryCloud);
addToRunTimeSelectionTable(pointData, geometryCloud, dictionary);
}
}
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
bool Foam::functionObjects::runTimePostPro::geometryCloud::addCloudField
(
vtkMultiPieceDataSet* multiPiece,
const objectRegistry& obrTmp,
const word& fieldName
) const
{
const regIOobject* ioptr = obrTmp.cfindObject<regIOobject>(fieldName);
return (multiPiece) &&
(
addCloudField<label>
(
multiPiece, ioptr, fieldName
)
|| addCloudField<scalar>
(
multiPiece, ioptr, fieldName
)
|| addCloudField<vector>
(
multiPiece, ioptr, fieldName
)
|| addCloudField<sphericalTensor>
(
multiPiece, ioptr, fieldName
)
|| addCloudField<symmTensor>
(
multiPiece, ioptr, fieldName
)
|| addCloudField<tensor>
(
multiPiece, ioptr, fieldName
)
);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::runTimePostPro::geometryCloud::geometryCloud
(
const runTimePostProcessing& parent,
const dictionary& dict,
const HashPtrTable<Function1<vector>>& colours
)
:
pointData(parent, dict, colours),
fieldVisualisationBase(dict, colours),
cloudName_(dict.get<word>("cloud")),
colourFieldName_(dict.get<word>("colourField")),
actor_()
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::functionObjects::runTimePostPro::geometryCloud::
~geometryCloud()
{}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
bool Foam::functionObjects::runTimePostPro::geometryCloud::
addGeometry
(
const scalar position,
vtkRenderer* renderer
)
{
if (!visible_)
{
return false;
}
// This is similar (almost identical) to vtkCloud
const auto* objPtr = parent().mesh().cfindObject<cloud>(cloudName_);
if (!objPtr)
{
return false;
}
objectRegistry obrTmp
(
IOobject
(
"runTimePostPro::cloud::" + cloudName_,
parent().mesh().time().constant(),
parent().mesh(),
IOobject::NO_READ,
IOobject::NO_WRITE,
false
)
);
objPtr->writeObjects(obrTmp);
const auto* pointsPtr = obrTmp.findObject<vectorField>("position");
if (!pointsPtr)
{
// This should be impossible
return false;
}
// Create a vtkMultiPieceDataSet with vtkPolyData on the leaves
auto multiPiece = gatherCloud(obrTmp);
// Add in scaleField and colourField
addCloudField(multiPiece, obrTmp, fieldName_);
addCloudField(multiPiece, obrTmp, colourFieldName_);
// Not rendered on this processor?
// This is where we stop, but could also have an MPI barrier
if (!renderer)
{
return true;
}
// Rendering
actor_ = vtkSmartPointer<vtkActor>::New();
{
fieldSummary scaleFieldInfo =
queryFieldSummary(fieldName_, multiPiece);
fieldSummary colourFieldInfo =
queryFieldSummary(colourFieldName_, multiPiece);
auto polyData = vtkSmartPointer<vtkCompositeDataGeometryFilter>::New();
polyData->SetInputData(multiPiece);
polyData->Update();
auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
actor_->SetMapper(mapper);
/// dataset->Print(std::cout);
addGlyphs
(
position,
fieldName_, scaleFieldInfo, // scaling
colourFieldName_, colourFieldInfo, // colour
maxGlyphLength_,
polyData->GetOutput(),
actor_,
renderer
);
renderer->AddActor(actor_);
}
return true;
}
void Foam::functionObjects::runTimePostPro::geometryCloud::
addGeometryToScene
(
const scalar position,
vtkRenderer* renderer
)
{
// Live source
addGeometry(position, renderer);
}
void Foam::functionObjects::runTimePostPro::geometryCloud::updateActors
(
const scalar position
)
{
if (actor_)
{
const vector colour = pointColour_->value(position);
vtkProperty* prop = actor_->GetProperty();
prop->SetOpacity(opacity(position));
prop->SetColor(colour[0], colour[1], colour[2]);
}
}
bool Foam::functionObjects::runTimePostPro::geometryCloud::clear()
{
return false;
}
// ************************************************************************* //

View File

@ -0,0 +1,201 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::functionObjects::runTimePostPro::geometryCloud
Description
Visualisation of cloud data from function object output (file-based only).
Dictionary controls
\table
Property | Description | Required | Default
type | The point type: geometryCloud | yes |
cloud | The cloud name | no |
field | The field for glyphs scaling | no |
colourField | The field to display | no |
\endtable
SourceFiles
geometryCloud.C
\*---------------------------------------------------------------------------*/
#ifndef functionObjects_runTimePostPro_geometryCloud_H
#define functionObjects_runTimePostPro_geometryCloud_H
#include "pointData.H"
#include "functionObjectBase.H"
#include "IOField.H"
#include "vtkSmartPointer.h"
#include "vtkMultiPieceDataSet.h"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
namespace runTimePostPro
{
/*---------------------------------------------------------------------------*\
Class geometryCloud Declaration
\*---------------------------------------------------------------------------*/
class geometryCloud
:
public pointData,
public fieldVisualisationBase
{
protected:
// Protected Data
//- Name of geometryCloud
word cloudName_;
//- Name of field to colour by
word colourFieldName_;
//- Actor
vtkSmartPointer<vtkActor> actor_;
// Protected Member Functions
//- Gather and convert cloud positions with vtkPolyData for the leaves.
// If VTK is also running in parallel, each cloud is left
// as a processor-local piece. Otherwise all processor-local
// parts are gathered onto the master in their correponding
// slots.
vtkSmartPointer<vtkMultiPieceDataSet>
gatherCloud(const objectRegistry& obrTmp) const;
//- Add field
template<class Type>
bool addField
(
vtkDataSet* piece,
const Field<Type>& fld,
const word& fieldName
) const;
//- Add field
template<class Type>
bool addCloudField
(
vtkMultiPieceDataSet* multiPiece,
const IOField<Type>* fldptr,
const word& fieldName
) const;
//- Add field
template<class Type>
bool addCloudField
(
vtkMultiPieceDataSet* multiPiece,
const regIOobject* fieldPtr,
const word& fieldName
) const;
//- Add field
bool addCloudField
(
vtkMultiPieceDataSet* multiPiece,
const objectRegistry& obrTmp,
const word& fieldName
) const;
//- No copy construct
geometryCloud(const geometryCloud&) = delete;
//- No copy assignment
void operator=(const geometryCloud&) = delete;
public:
//- Run-time type information
TypeNameNoDebug("geometryCloud");
// Constructors
//- Construct from dictionary
geometryCloud
(
const runTimePostProcessing& parent,
const dictionary& dict,
const HashPtrTable<Function1<vector>>& colours
);
//- Destructor
virtual ~geometryCloud();
// Member Functions
//- Add cloud to scene (from simulation)
bool addGeometry
(
const scalar position,
vtkRenderer* renderer
);
//- Add cloud to scene
virtual void addGeometryToScene
(
const scalar position,
vtkRenderer* renderer
);
//- Update actors
virtual void updateActors(const scalar position);
//- No-op
virtual bool clear();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace runTimePostPro
} // End namespace functionObjects
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "geometryCloudTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,129 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
// OpenFOAM includes
#include "geometryCloud.H"
#include "cloud.H"
#include "runTimePostProcessing.H"
#include "foamVtkTools.H"
// VTK includes
#include "vtkMultiPieceDataSet.h"
#include "vtkPolyData.h"
#include "vtkSmartPointer.h"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
vtkSmartPointer<vtkMultiPieceDataSet>
Foam::functionObjects::runTimePostPro::geometryCloud::gatherCloud
(
const objectRegistry& obrTmp
) const
{
auto multiPiece = vtkSmartPointer<vtkMultiPieceDataSet>::New();
multiPiece->SetNumberOfPieces(Pstream::nProcs());
const auto* pointsPtr = obrTmp.findObject<vectorField>("position");
if (!needsCollective())
{
// Simple case (serial-serial, parallel-parallel)
if (pointsPtr && pointsPtr->size())
{
multiPiece->SetPiece
(
Pstream::myProcNo(),
Foam::vtk::Tools::Vertices(*pointsPtr)
);
}
}
else if (Pstream::master())
{
// Gather pieces on master
if (pointsPtr && pointsPtr->size())
{
// Add myself
multiPiece->SetPiece
(
Pstream::myProcNo(),
Foam::vtk::Tools::Vertices(*pointsPtr)
);
}
// Receive points
pointField points;
for
(
int slave=Pstream::firstSlave();
slave<=Pstream::lastSlave();
++slave
)
{
IPstream fromSlave(Pstream::commsTypes::scheduled, slave);
points.clear();
fromSlave >> points;
if (points.size())
{
multiPiece->SetPiece
(
slave,
Foam::vtk::Tools::Vertices(points)
);
}
}
}
else
{
// Slave - send points
OPstream toMaster
(
Pstream::commsTypes::scheduled,
Pstream::masterNo()
);
if (pointsPtr)
{
toMaster << *pointsPtr;
}
else
{
toMaster << pointField();
}
}
return multiPiece;
}
// ************************************************************************* //

View File

@ -0,0 +1,168 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "foamVtkTools.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
bool Foam::functionObjects::runTimePostPro::geometryCloud::addField
(
vtkDataSet* piece,
const Field<Type>& fld,
const word& fieldName
) const
{
if (!piece) return false;
auto vtkfield = Foam::vtk::Tools::convertFieldToVTK<Type>(fieldName, fld);
// Only has verts
piece->GetPointData()->AddArray(vtkfield);
return true;
}
template<class Type>
bool Foam::functionObjects::runTimePostPro::geometryCloud::addCloudField
(
vtkMultiPieceDataSet* multiPiece,
const IOField<Type>* fldptr,
const word& fieldName
) const
{
if (!multiPiece)
{
return false;
}
if (!needsCollective())
{
// Simple case (serial-serial, parallel-parallel)
return fldptr &&
addField<Type>
(
multiPiece->GetPiece(Pstream::myProcNo()),
*fldptr,
fieldName
);
}
// Gather fields
const bool ok = returnReduce((fldptr != nullptr), orOp<bool>());
if (!ok)
{
return false;
}
if (Pstream::master())
{
if (fldptr)
{
// My field data
addField<Type>
(
multiPiece->GetPiece(Pstream::myProcNo()),
*fldptr,
fieldName
);
}
// Receive field data
Field<Type> recv;
for
(
int slave=Pstream::firstSlave();
slave<=Pstream::lastSlave();
++slave
)
{
IPstream fromSlave(Pstream::commsTypes::scheduled, slave);
recv.clear();
fromSlave
>> recv;
if (recv.size())
{
addField<Type>
(
multiPiece->GetPiece(slave),
recv,
fieldName
);
}
}
}
else
{
// Slave - send field data
OPstream toMaster
(
Pstream::commsTypes::scheduled,
Pstream::masterNo()
);
if (fldptr)
{
toMaster
<< *fldptr;
}
else
{
toMaster
<< List<Type>();
}
}
return ok;
}
template<class Type>
bool Foam::functionObjects::runTimePostPro::geometryCloud::addCloudField
(
vtkMultiPieceDataSet* multiPiece,
const regIOobject* ioptr,
const word& fieldName
) const
{
return addCloudField<Type>
(
multiPiece,
dynamic_cast<const IOField<Type>*>(ioptr),
fieldName
);
}
// ************************************************************************* //

View File

@ -0,0 +1,315 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
// OpenFOAM includes
#include "geometryPatches.H"
#include "fvMesh.H"
#include "volFields.H"
#include "emptyPolyPatch.H"
#include "processorPolyPatch.H"
#include "foamVtkTools.H"
#include "runTimePostProcessing.H"
#include "addToRunTimeSelectionTable.H"
// VTK includes
#include "vtkActor.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkCellDataToPointData.h"
#include "vtkCompositeDataGeometryFilter.h"
#include "vtkCompositeDataSet.h"
#include "vtkCompositePolyDataMapper.h"
#include "vtkMultiPieceDataSet.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkSmartPointer.h"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
namespace runTimePostPro
{
defineTypeName(geometryPatches);
addToRunTimeSelectionTable(surface, geometryPatches, dictionary);
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::runTimePostPro::geometryPatches::geometryPatches
(
const runTimePostProcessing& parent,
const dictionary& dict,
const HashPtrTable<Function1<vector>>& colours
)
:
geometrySurface(parent, dict, colours, List<fileName>()),
fieldVisualisationBase(dict, colours),
selectPatches_(),
nearCellValue_(dict.lookupOrDefault("nearCellValue", false))
{
dict.readEntry("patches", selectPatches_);
}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
void Foam::functionObjects::runTimePostPro::geometryPatches::addGeometryToScene
(
const scalar position,
vtkRenderer* renderer
)
{
if (!visible_ || selectPatches_.empty())
{
return;
}
const polyBoundaryMesh& patches = parent().mesh().boundaryMesh();
bitSet selectedPatchIds(patches.size());
for (const polyPatch& pp : patches)
{
if (isType<emptyPolyPatch>(pp) || pp.empty())
{
continue;
}
else if (isA<processorPolyPatch>(pp))
{
break; // No processor patches
}
if (selectPatches_.match(pp.name()))
{
selectedPatchIds.set(pp.index());
}
}
labelListList patchIds(Pstream::nProcs());
patchIds[Pstream::myProcNo()] = selectedPatchIds.sortedToc();
Pstream::gatherList(patchIds);
Pstream::scatterList(patchIds);
label nPieces = 0;
for (const labelList& ids : patchIds)
{
nPieces += ids.size();
}
/// Pout<< "add patches: " << selectPatches_ << nl
/// << " = " << patchIds << " == " << nPieces << " total" << nl;
if (!nPieces)
{
WarningInFunction
<< "No patches selected: " << flatOutput(selectPatches_)
<< endl;
return;
}
DebugInfo << " Add geometry patches" << nl;
// Create a vtkMultiPieceDataSet with vtkPolyData on the leaves
// When adding fields, only map scalar/vector fields.
// - this is easier and all we mostly ever need
vtkSmartPointer<vtkMultiPieceDataSet> multiPiece;
// Requesting glyphs on the surface - just use the faceCentres directly
// and attach fields as CellData (not PointData).
if (representation_ == rtGlyph)
{
multiPiece = gatherPatchFaceCentres(patchIds);
}
else
{
multiPiece = gatherPatchPieces(patchIds);
}
// Add (scalar/vector) field.
// - Need field(s) for glyphs or colourByField:
int nCmpt = 0;
if (representation_ == rtGlyph || colourBy_ == cbField)
{
if (!nCmpt)
{
nCmpt = addPatchField<scalar>
(
multiPiece,
patchIds,
parent().mesh().cfindObject<volScalarField>(fieldName_),
fieldName_
);
}
if (!nCmpt)
{
nCmpt = addPatchField<vector>
(
multiPiece,
patchIds,
parent().mesh().cfindObject<volVectorField>(fieldName_),
fieldName_
);
}
}
// Now have a multi-piece dataset with
// one piece per patch and processor.
//
// For VTK=parallel, these pieces reside on their original processors.
// For VTK=serial, they are master only
// Re-query actually field information, since we may have stored it
// somewhere slightly different than the original source.
fieldSummary fieldInfo = queryFieldSummary(fieldName_, multiPiece);
fieldInfo.reduce();
// Not rendering on this processor?
// This is where we stop, but could also have a MPI barrier
if (!renderer)
{
return;
}
// Rendering
{
auto polyData = vtkSmartPointer<vtkCompositeDataGeometryFilter>::New();
polyData->SetInputData(multiPiece);
polyData->Update();
if (representation_ == rtGlyph)
{
addGlyphs
(
position,
fieldName_, fieldInfo, // scaling
fieldName_, fieldInfo, // colouring
maxGlyphLength_,
polyData->GetOutput(),
surfaceActor_,
renderer
);
}
else
{
vtkSmartPointer<vtkCellDataToPointData> cellToPoint;
// CellData - Need a cell->point filter
if (smooth_ && !fieldInfo.hasPointData())
{
cellToPoint = vtkSmartPointer<vtkCellDataToPointData>::New();
cellToPoint->SetInputData(multiPiece);
polyData->SetInputConnection(cellToPoint->GetOutputPort());
}
else
{
polyData->SetInputData(multiPiece);
}
polyData->Update();
if (!smooth_)
{
addFeatureEdges(renderer, polyData);
}
auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(polyData->GetOutputPort());
setField
(
position,
fieldName_,
(
smooth_
? FieldAssociation::POINT_DATA
: FieldAssociation::CELL_DATA
),
mapper,
renderer
);
surfaceActor_->SetMapper(mapper);
setRepresentation(surfaceActor_);
renderer->AddActor(surfaceActor_);
}
}
}
void Foam::functionObjects::runTimePostPro::geometryPatches::updateActors
(
const scalar position
)
{
if (!visible_)
{
return;
}
surface::updateActors(position);
surfaceActor_->GetProperty()->SetOpacity(opacity(position));
vector sc = surfaceColour_->value(position);
surfaceActor_->GetProperty()->SetColor(sc[0], sc[1], sc[2]);
vector ec = edgeColour_->value(position);
surfaceActor_->GetProperty()->SetEdgeColor(ec[0], ec[1], ec[2]);
}
bool Foam::functionObjects::runTimePostPro::geometryPatches::clear()
{
return true;
}
// ************************************************************************* //

View File

@ -0,0 +1,171 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::functionObjects::runTimePostPro::geometryPatches
Description
Visualisation of OpenFOAM patches and fields.
\heading Basic Usage
\table
Property | Description | Required | Default
type | The surface type: patches | yes |
patches | Patches to display (wordRe list) | yes |
\endtable
SourceFiles
geometryPatches.C
\*---------------------------------------------------------------------------*/
#ifndef functionObjects_runTimePostPro_geometryPatches_H
#define functionObjects_runTimePostPro_geometryPatches_H
#include "surface.H"
#include "geometrySurface.H"
#include "fieldVisualisationBase.H"
#include "volFieldsFwd.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
namespace runTimePostPro
{
/*---------------------------------------------------------------------------*\
Class geometryPatches Declaration
\*---------------------------------------------------------------------------*/
class geometryPatches
:
public geometrySurface,
public fieldVisualisationBase
{
protected:
// Protected Data
//- Requested names of patches to process
wordRes selectPatches_;
//- Use cell value on patches instead of patch value itself
bool nearCellValue_;
// Protected Member Functions
//- Gather and convert patches to multi-piece dataset with
//- vtkPolyData for each patch/processor.
// For serial, the pieces are gathered to the master.
vtkSmartPointer<vtkMultiPieceDataSet>
gatherPatchPieces(const labelListList& patchIds) const;
//- Gather and convert patch face centres to multi-piece dataset with
//- vtkPolyData for each patch/processor.
// For serial, the pieces are gathered to the master.
vtkSmartPointer<vtkMultiPieceDataSet>
gatherPatchFaceCentres(const labelListList& patchIds) const;
// Adding Fields - multi-piece
//- Add patch values.
// For nCells == nPoints (eg, only has face centres) add as PointData.
// \return 0 on failure to map and nCmpt (eg, 1=scalar, 3=vector)
// on success.
template<class Type>
int addPatchField
(
vtkMultiPieceDataSet* multiPiece,
const labelListList& patchIds,
const GeometricField<Type, fvPatchField, volMesh>* fldptr,
const word& fieldName
) const;
//- No copy construct
geometryPatches(const geometryPatches&) = delete;
//- No copy assignment
void operator=(const geometryPatches&) = delete;
public:
//- Run-time type information
TypeNameNoDebug("patches");
// Constructors
//- Construct from dictionary
geometryPatches
(
const runTimePostProcessing& parent,
const dictionary& dict,
const HashPtrTable<Function1<vector>>& colours
);
//- Destructor
virtual ~geometryPatches() = default;
// Member Functions
//- Add geometry surface(s) to scene
virtual void addGeometryToScene
(
const scalar position,
vtkRenderer* renderer
);
//- Update actors
virtual void updateActors(const scalar position);
//- Clear files used to create the object(s)
virtual bool clear();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace runTimePostPro
} // End namespace functionObjects
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "geometryPatchesTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,293 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
// OpenFOAM includes
#include "geometryPatches.H"
#include "fvMesh.H"
#include "volFields.H"
#include "emptyPolyPatch.H"
#include "processorPolyPatch.H"
#include "foamVtkTools.H"
#include "runTimePostProcessing.H"
// VTK includes
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkCompositeDataSet.h"
#include "vtkMultiPieceDataSet.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkSmartPointer.h"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
vtkSmartPointer<vtkMultiPieceDataSet>
Foam::functionObjects::runTimePostPro::geometryPatches::gatherPatchPieces
(
const labelListList& patchIds
) const
{
const polyBoundaryMesh& patches = parent().mesh().boundaryMesh();
label nPieces = 0;
for (const labelList& ids : patchIds)
{
nPieces += ids.size();
}
auto multiPiece = vtkSmartPointer<vtkMultiPieceDataSet>::New();
multiPiece->SetNumberOfPieces(nPieces);
label pieceId = 0;
if (!needsCollective())
{
// Simple case
for (int proci=0; proci < Pstream::myProcNo(); ++proci)
{
pieceId += patchIds[proci].size();
}
for (const label patchId : patchIds[Pstream::myProcNo()])
{
const polyPatch& pp = patches[patchId];
multiPiece->SetPiece
(
pieceId,
Foam::vtk::Tools::Patch::mesh(pp)
);
++pieceId;
}
}
else if (Pstream::master())
{
// Gather pieces on master
// Add myself
for (const label patchId : patchIds[Pstream::myProcNo()])
{
const polyPatch& pp = patches[patchId];
multiPiece->SetPiece
(
pieceId,
Foam::vtk::Tools::Patch::mesh(pp)
);
++pieceId;
}
// Receive surfaces
pointField points;
faceList faces;
for
(
int slave=Pstream::firstSlave();
slave<=Pstream::lastSlave();
++slave
)
{
const label nSlavePatches = patchIds[slave].size();
if (!nSlavePatches)
{
continue;
}
IPstream fromSlave(Pstream::commsTypes::scheduled, slave);
for (label recvi=0; recvi < nSlavePatches; ++recvi)
{
points.clear();
faces.clear();
fromSlave
>> points >> faces;
multiPiece->SetPiece
(
pieceId,
Foam::vtk::Tools::Patch::mesh(points, faces)
);
++pieceId;
}
}
}
else
{
// Slave - send surfaces
const labelList& slavePatchIds = patchIds[Pstream::myProcNo()];
if (slavePatchIds.size())
{
OPstream toMaster
(
Pstream::commsTypes::scheduled,
Pstream::masterNo()
);
for (const label patchId : patchIds[Pstream::myProcNo()])
{
const polyPatch& pp = patches[patchId];
toMaster
<< pp.localPoints() << pp.localFaces();
}
}
}
return multiPiece;
}
vtkSmartPointer<vtkMultiPieceDataSet>
Foam::functionObjects::runTimePostPro::geometryPatches::gatherPatchFaceCentres
(
const labelListList& patchIds
) const
{
const polyBoundaryMesh& patches = parent().mesh().boundaryMesh();
label nPieces = 0;
for (const labelList& ids : patchIds)
{
nPieces += ids.size();
}
auto multiPiece = vtkSmartPointer<vtkMultiPieceDataSet>::New();
multiPiece->SetNumberOfPieces(nPieces);
label pieceId = 0;
if (!needsCollective())
{
// Simple case
for (int proci=0; proci < Pstream::myProcNo(); ++proci)
{
pieceId += patchIds[proci].size();
}
for (const label patchId : patchIds[Pstream::myProcNo()])
{
const polyPatch& pp = patches[patchId];
auto geom = vtkSmartPointer<vtkPolyData>::New();
geom->SetPoints(Foam::vtk::Tools::Patch::faceCentres(pp));
geom->SetVerts(Foam::vtk::Tools::identityVertices(pp.size()));
multiPiece->SetPiece(pieceId, geom);
++pieceId;
}
}
else if (Pstream::master())
{
// Gather pieces (face centres) on master
// Add myself
for (const label patchId : patchIds[Pstream::myProcNo()])
{
const polyPatch& pp = patches[patchId];
auto geom = vtkSmartPointer<vtkPolyData>::New();
geom->SetPoints(Foam::vtk::Tools::Patch::faceCentres(pp));
geom->SetVerts(Foam::vtk::Tools::identityVertices(pp.size()));
multiPiece->SetPiece(pieceId, geom);
++pieceId;
}
// Receive points
pointField points;
for
(
int slave=Pstream::firstSlave();
slave<=Pstream::lastSlave();
++slave
)
{
const label nSlavePatches = patchIds[slave].size();
if (!nSlavePatches)
{
continue;
}
IPstream fromSlave(Pstream::commsTypes::scheduled, slave);
for (label recvi=0; recvi < nSlavePatches; ++recvi)
{
points.clear();
fromSlave >> points;
multiPiece->SetPiece
(
pieceId,
Foam::vtk::Tools::Vertices(points)
);
++pieceId;
}
}
}
else
{
// Slave - send face centres
const labelList& slavePatchIds = patchIds[Pstream::myProcNo()];
if (slavePatchIds.size())
{
OPstream toMaster
(
Pstream::commsTypes::scheduled,
Pstream::masterNo()
);
for (const label patchId : patchIds[Pstream::myProcNo()])
{
const polyPatch& pp = patches[patchId];
toMaster << pp.faceCentres();
}
}
}
return multiPiece;
}
// ************************************************************************* //

View File

@ -0,0 +1,221 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
// OpenFOAM includes
#include "geometryPatches.H"
#include "fvMesh.H"
#include "volFields.H"
#include "foamVtkTools.H"
// VTK includes
#include "vtkCellData.h"
#include "vtkMultiPieceDataSet.h"
#include "vtkPointData.h"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<class Type>
int Foam::functionObjects::runTimePostPro::geometryPatches::addPatchField
(
vtkMultiPieceDataSet* multiPiece,
const labelListList& patchIds,
const GeometricField<Type, fvPatchField, volMesh>* fldptr,
const word& fieldName
) const
{
if (!multiPiece || !fldptr)
{
return 0;
}
const int nCmpt(pTraits<Type>::nComponents);
const auto& bf = fldptr->boundaryField();
label pieceId = 0;
if (!needsCollective())
{
// Simple case (serial-serial, parallel-parallel)
for (int proci=0; proci < Pstream::myProcNo(); ++proci)
{
pieceId += patchIds[proci].size();
}
for (const label patchId : patchIds[Pstream::myProcNo()])
{
const auto& pf = bf[patchId];
auto vtkfield =
(
nearCellValue_
? Foam::vtk::Tools::convertFieldToVTK<Type>
(
fieldName,
pf.patchInternalField()()
)
: Foam::vtk::Tools::convertFieldToVTK<Type>
(
fieldName,
pf
)
);
auto piece = multiPiece->GetPiece(pieceId);
if (piece->GetNumberOfCells() == piece->GetNumberOfPoints())
{
// Only has verts
piece->GetPointData()->AddArray(vtkfield);
}
else
{
piece->GetCellData()->AddArray(vtkfield);
}
++pieceId;
}
}
else if (Pstream::master())
{
// Gather pieces on master
// Add myself
for (const label patchId : patchIds[Pstream::myProcNo()])
{
const auto& pf = bf[patchId];
auto vtkfield =
(
nearCellValue_
? Foam::vtk::Tools::convertFieldToVTK<Type>
(
fieldName,
pf.patchInternalField()()
)
: Foam::vtk::Tools::convertFieldToVTK<Type>
(
fieldName,
pf
)
);
auto piece = multiPiece->GetPiece(pieceId);
if (piece->GetNumberOfCells() == piece->GetNumberOfPoints())
{
// Only has verts
piece->GetPointData()->AddArray(vtkfield);
}
else
{
piece->GetCellData()->AddArray(vtkfield);
}
++pieceId;
}
// Receive field
Field<Type> recv;
for
(
int slave=Pstream::firstSlave();
slave<=Pstream::lastSlave();
++slave
)
{
const label nSlavePatches = patchIds[slave].size();
if (!nSlavePatches)
{
continue;
}
IPstream fromSlave(Pstream::commsTypes::scheduled, slave);
for (label recvi=0; recvi < nSlavePatches; ++recvi)
{
recv.clear();
fromSlave >> recv;
auto vtkfield = Foam::vtk::Tools::convertFieldToVTK<Type>
(
fieldName,
recv
);
auto piece = multiPiece->GetPiece(pieceId);
if (piece->GetNumberOfCells() == piece->GetNumberOfPoints())
{
// Only has verts
piece->GetPointData()->AddArray(vtkfield);
}
else
{
piece->GetCellData()->AddArray(vtkfield);
}
++pieceId;
}
}
}
else
{
// Slave - send fields
const labelList& slavePatchIds = patchIds[Pstream::myProcNo()];
if (slavePatchIds.size())
{
OPstream toMaster
(
Pstream::commsTypes::scheduled,
Pstream::masterNo()
);
for (const label patchId : patchIds[Pstream::myProcNo()])
{
const auto& pf = bf[patchId];
if (nearCellValue_)
{
toMaster << pf.patchInternalField()();
}
else
{
toMaster << pf;
}
}
}
}
return nCmpt;
}
// ************************************************************************* //

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -77,7 +75,7 @@ static vtkSmartPointer<vtkPolyData> getPolyDataFile(const Foam::fileName& fName)
// Not extremely elegant...
vtkSmartPointer<vtkPolyData> dataset;
if (fName.ext() == "vtk")
if ("vtk" == fName.ext())
{
auto reader = vtkSmartPointer<vtkPolyDataReader>::New();
@ -88,7 +86,7 @@ static vtkSmartPointer<vtkPolyData> getPolyDataFile(const Foam::fileName& fName)
return dataset;
}
if (fName.ext() == "vtp")
if ("vtp" == fName.ext())
{
auto reader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
@ -99,7 +97,7 @@ static vtkSmartPointer<vtkPolyData> getPolyDataFile(const Foam::fileName& fName)
return dataset;
}
if (fName.ext() == "obj")
if ("obj" == fName.ext())
{
auto reader = vtkSmartPointer<vtkOBJReader>::New();
@ -110,7 +108,7 @@ static vtkSmartPointer<vtkPolyData> getPolyDataFile(const Foam::fileName& fName)
return dataset;
}
if (fName.ext() == "stl" || fName.ext() == "stlb")
if ("stl" == fName.ext() || "stlb" == fName.ext())
{
auto reader = vtkSmartPointer<vtkSTLReader>::New();
@ -147,6 +145,12 @@ void Foam::functionObjects::runTimePostPro::geometrySurface::addGeometryToScene
const fileName& fName
) const
{
// Master-only, since that is where the files are.
if (!visible_ || !renderer || !Pstream::master())
{
return;
}
if (representation_ == rtGlyph)
{
FatalErrorInFunction
@ -154,9 +158,11 @@ void Foam::functionObjects::runTimePostPro::geometrySurface::addGeometryToScene
<< " object" << exit(FatalError);
}
DebugInfo << " Add geometry surface: " << fName << nl;
auto surf = getPolyDataFile(fName);
if (!surf || surf->GetNumberOfPoints() == 0)
if (!surf || !surf->GetNumberOfPoints())
{
FatalErrorInFunction
<< "Could not read "<< fName << nl

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,7 +25,18 @@ Class
Foam::functionObjects::runTimePostPro::geometrySurface
Description
Visualisation of surface geometry data
Read and visualize surface geometry files.
Dictionary controls
\table
Property | Description | Required | Default
type | The type: geometry | yes |
files | The files to read | yes |
\endtable
Standard file types (vtk, vtp, obj, stl, stlb) are read with the
VTK-native readers. Other file types use the OpenFOAM surfMesh
readers and convert to VTK.
SourceFiles
geometrySurface.C
@ -41,7 +50,7 @@ SourceFiles
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Forward declarations
// Forward Declarations
class vtkPolyData;
namespace Foam
@ -61,7 +70,7 @@ class geometrySurface
{
protected:
// Protected data
// Protected Data
//- File names
List<fileName> fileNames_;
@ -126,7 +135,7 @@ public:
//- Update actors
virtual void updateActors(const scalar position);
//- Clear files used to create the object(s)
//- Clear files used to create the object(s) - no-op
virtual bool clear();
};

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -46,7 +44,7 @@ namespace functionObjects
{
namespace runTimePostPro
{
defineTypeNameAndDebug(pathline, 0);
defineTypeName(pathline);
defineRunTimeSelectionTable(pathline, dictionary);
}
}
@ -94,7 +92,6 @@ void Foam::functionObjects::runTimePostPro::pathline::addLines
mapper->SetInputData(data);
mapper->Update();
break;
}
case rtTube:
{
@ -107,9 +104,7 @@ void Foam::functionObjects::runTimePostPro::pathline::addLines
mapper->SetInputConnection(tubes->GetOutputPort());
mapper->Update();
break;
}
case rtVector:
{
@ -133,7 +128,7 @@ Foam::functionObjects::runTimePostPro::pathline::pathline
(
representationTypeNames.get("representation", dict)
),
tubeRadius_(0.0),
tubeRadius_(0.001),
lineColour_(nullptr)
{
if (dict.found("lineColour"))
@ -165,7 +160,6 @@ Foam::functionObjects::runTimePostPro::pathline::pathline
break;
}
}
}
@ -180,10 +174,7 @@ Foam::functionObjects::runTimePostPro::pathline::New
const word& pathlineType
)
{
if (debug)
{
Info<< "Selecting pathline " << pathlineType << endl;
}
DebugInfo << "Selecting pathline " << pathlineType << endl;
auto cstrIter = dictionaryConstructorTablePtr_->cfind(pathlineType);

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -29,6 +27,14 @@ Class
Description
Visualisation of line data (eg, streamlines)
Dictionary controls
\table
Property | Description | Required | Default
representation| none/line/tube/vector | yes |
lineColour | Override line colour | no |
tubeRadius | Radius for tube representation | yes |
\endtable
SourceFiles
pathline.C
@ -65,16 +71,18 @@ class pathline
{
public:
// Public enumerations
// Public Enumerations
//- Line representations
enum representationType
{
rtNone,
rtLine,
rtTube,
rtVector
rtNone, //!< "none"
rtLine, //!< "line"
rtTube, //!< "tube"
rtVector //!< "vector"
};
//- Names for line representations
static const Enum<representationType> representationTypeNames;
@ -112,7 +120,7 @@ protected:
public:
//- Run-time type information
TypeName("pathline");
TypeNameNoDebug("pathline");
// Declare run-time constructor selection table
@ -144,7 +152,7 @@ public:
// Selectors
//- Return a reference to the selected RAS model
//- Return selected pathline
static autoPtr<pathline> New
(
const runTimePostProcessing& parent,

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2004-2010, 2015-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2004-2010, 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -35,8 +33,6 @@ License
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkSmartPointer.h"
#include "vtkTubeFilter.h"
#include "vtkLookupTable.h"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
@ -46,7 +42,7 @@ namespace functionObjects
{
namespace runTimePostPro
{
defineTypeNameAndDebug(pointData, 0);
defineTypeName(pointData);
defineRunTimeSelectionTable(pointData, dictionary);
}
}
@ -141,10 +137,7 @@ Foam::functionObjects::runTimePostPro::pointData::New
const word& pointDataType
)
{
if (debug)
{
Info<< "Selecting pointData " << pointDataType << endl;
}
DebugInfo << "Selecting pointData " << pointDataType << endl;
auto cstrIter = dictionaryConstructorTablePtr_->cfind(pointDataType);

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2004-2010, 2015-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2004-2010, 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -29,6 +27,14 @@ Class
Description
Visualisation of point data
Dictionary controls
\table
Property | Description | Required | Default
representation| sphere/vector | yes |
pointColour | Override point colour | no |
maxGlyphLength | Limit for glyph representation | yes |
\endtable
SourceFiles
pointData.C
@ -43,7 +49,7 @@ SourceFiles
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Forward declarations
// Forward Declarations
class vtkActor;
class vtkPolyData;
class vtkPolyDataMapper;
@ -65,20 +71,22 @@ class pointData
{
public:
// Public enumerations
// Public Enumerations
//- Point representation types
enum representationType
{
rtSphere, //!< Sphere
rtVector //!< Vector
rtSphere, //!< "sphere"
rtVector //!< "vector"
};
//- Names for point representation types
static const Enum<representationType> representationTypeNames;
protected:
// Protected data
// Protected Data
//- Representation type
representationType representation_;
@ -111,7 +119,7 @@ protected:
public:
//- Run-time type information
TypeName("pointData");
TypeNameNoDebug("pointData");
// Declare run-time constructor selection table
@ -143,7 +151,7 @@ public:
// Selectors
//- Return a reference to the selected RAS model
//- Return selected pointData
static autoPtr<pointData> New
(
const runTimePostProcessing& parent,

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -34,6 +32,7 @@ License
#include "text.H"
#include "Time.H"
#include "sigFpe.H"
#include "polySurfaceFields.H"
#include "addToRunTimeSelectionTable.H"
// VTK includes
@ -43,6 +42,16 @@ License
#include "vtkSmartPointer.h"
#include "vtkLight.h"
#ifdef FOAM_USING_VTK_MPI
# include "vtkMPICommunicator.h"
# include "vtkMPIController.h"
#endif
#include "vtkDummyController.h"
#include "vtkSynchronizedRenderWindows.h"
#include "vtkCompositedSynchronizedRenderers.h"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
@ -103,6 +112,168 @@ static void cleanup(PtrList<Type>& objects)
} // End namespace Foam
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::functionObjects::runTimePostProcessing::render
(
vtkMultiProcessController* controller
)
{
// Some feedback
if (controller)
{
Log << name() << " render (" << controller->GetNumberOfProcesses()
<< " processes)" << endl;
}
else
{
Log << name() << " render" << endl;
}
// Normal rendering elements
vtkSmartPointer<vtkRenderer> renderer;
vtkSmartPointer<vtkRenderWindow> renderWindow;
// Multi-process synchronization
vtkSmartPointer<vtkSynchronizedRenderWindows> syncWindows;
vtkSmartPointer<vtkCompositedSynchronizedRenderers> syncRenderers;
// Disable any floating point trapping
// (some low-level rendering functionality does not like it)
sigFpe::ignore sigFpeHandling; //<- disable in local scope
// Initialise render window
if (controller || Pstream::master())
{
renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderer = vtkSmartPointer<vtkRenderer>::New();
renderWindow->OffScreenRenderingOn();
renderWindow->SetSize(output_.width_, output_.height_);
// Legacy rendering - was deprecated for 8.1.0
#if (VTK_MAJOR_VERSION < 8) || \
((VTK_MAJOR_VERSION == 8) && (VTK_MINOR_VERSION < 2))
renderWindow->SetAAFrames(10);
#endif
renderWindow->SetAlphaBitPlanes(true);
renderWindow->SetMultiSamples(0);
// renderWindow->PolygonSmoothingOn();
renderWindow->AddRenderer(renderer);
}
// Synchronization
if (controller)
{
syncWindows =
vtkSmartPointer<vtkSynchronizedRenderWindows>::New();
syncRenderers =
vtkSmartPointer<vtkCompositedSynchronizedRenderers>::New();
syncWindows->SetRenderWindow(renderWindow);
syncWindows->SetParallelController(controller);
syncWindows->SetIdentifier(1);
// false = Call Render() manually on each process - don't use RMI
syncWindows->SetParallelRendering(true);
syncRenderers->SetRenderer(renderer);
syncRenderers->SetParallelController(controller);
}
// ---------------------
scene_.initialise(renderer, output_.name_);
addGeometryToScene(points_, 0, renderer);
addGeometryToScene(lines_, 0, renderer);
addGeometryToScene(surfaces_, 0, renderer);
addGeometryToScene(text_, 0, renderer);
while (scene_.loop(renderer))
{
const scalar position = scene_.position();
updateActors(text_, position);
updateActors(points_, position);
updateActors(lines_, position);
updateActors(surfaces_, position);
}
// Cleanup
cleanup(text_);
cleanup(points_);
cleanup(lines_);
cleanup(surfaces_);
// Instead of relying on the destructor, manually restore the previous
// SIGFPE state.
// This is only to avoid compiler complaints about unused variables.
sigFpeHandling.restore();
}
void Foam::functionObjects::runTimePostProcessing::render
(
vtkMultiProcessController* controller,
void* processData
)
{
reinterpret_cast<runTimePostProcessing*>(processData)->render(controller);
}
void Foam::functionObjects::runTimePostProcessing::render()
{
#ifdef FOAM_USING_VTK_MPI
if (parallel_)
{
// Create vtkMPIController if MPI is configured,
// vtkThreadedController otherwise.
auto ctrl = vtkSmartPointer<vtkMPIController>::New();
ctrl->Initialize(nullptr, nullptr, 1);
ctrl->SetSingleMethod(runTimePostProcessing::render, this);
ctrl->SingleMethodExecute();
ctrl->Finalize(1);
}
else
#endif
{
// Normally we would have a fallback controller like this:
// if (Pstream::master())
// {
// auto ctrl = vtkSmartPointer<vtkDummyController>::New();
// ctrl->Initialize(nullptr, nullptr, 1);
//
// ctrl->SetSingleMethod(runTimePostProcessing::render, this);
// ctrl->SingleMethodExecute();
//
// ctrl->Finalize(1);
// }
// However, this would prevent us from doing any of our own MPI
// since this would only be spawned the master.
// Instead pass in nullptr for the controller and handling
// logic internally.
vtkDummyController* dummy = nullptr;
render(dummy);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::runTimePostProcessing::runTimePostProcessing
@ -113,6 +284,8 @@ Foam::functionObjects::runTimePostProcessing::runTimePostProcessing
)
:
fvMeshFunctionObject(name, runTime, dict),
output_(),
parallel_(false),
scene_(runTime, name),
points_(),
lines_(),
@ -129,7 +302,20 @@ bool Foam::functionObjects::runTimePostProcessing::read(const dictionary& dict)
{
fvMeshFunctionObject::read(dict);
Info<< type() << " " << name() << ": reading post-processing data" << endl;
#ifdef FOAM_USING_VTK_MPI
parallel_ = (Pstream::parRun() && dict.lookupOrDefault("parallel", true));
#else
parallel_ = false;
#endif
Info<< type() << " " << name() << ": reading post-processing data ("
<< (parallel_ ? "parallel" : "serial") << " rendering)" << endl;
if (dict.lookupOrDefault("debug", false))
{
runTimePostPro::geometryBase::debug = 1;
Info<< " debugging on" << endl;
}
scene_.read(dict);
@ -179,68 +365,7 @@ bool Foam::functionObjects::runTimePostProcessing::execute()
bool Foam::functionObjects::runTimePostProcessing::write()
{
if (!Pstream::master())
{
return true;
}
Info<< type() << " " << name() << " output:" << nl
<< " Constructing scene" << endl;
// Disable any floating point trapping
// (some low-level rendering functionality does not like it)
sigFpe::ignore sigFpeHandling; //<- disable in local scope
// Initialise render window
auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->OffScreenRenderingOn();
renderWindow->SetSize(output_.width_, output_.height_);
// Legacy rendering - was deprecated for 8.1.0
#if (VTK_MAJOR_VERSION < 8) || \
((VTK_MAJOR_VERSION == 8) && (VTK_MINOR_VERSION < 2))
renderWindow->SetAAFrames(10);
#endif
renderWindow->SetAlphaBitPlanes(true);
renderWindow->SetMultiSamples(0);
// renderWindow->PolygonSmoothingOn();
auto renderer = vtkSmartPointer<vtkRenderer>::New();
scene_.initialise(renderer, output_.name_);
renderWindow->AddRenderer(renderer);
addGeometryToScene(points_, 0, renderer);
addGeometryToScene(lines_, 0, renderer);
addGeometryToScene(surfaces_, 0, renderer);
addGeometryToScene(text_, 0, renderer);
while (scene_.loop(renderer))
{
const scalar position = scene_.position();
updateActors(text_, position);
updateActors(points_, position);
updateActors(lines_, position);
updateActors(surfaces_, position);
}
// Cleanup
cleanup(text_);
cleanup(points_);
cleanup(lines_);
cleanup(surfaces_);
// Instead of relying on the destructor, manually restore the previous
// SIGFPE state.
// This is only to avoid compiler complaints about unused variables.
sigFpeHandling.restore();
render();
return true;
}

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -56,9 +54,53 @@ Description
- Selection of colour maps
.
Scene configuration is performed using standard OpenFOAM dictionaries, using
the main headings of: output=, camera, colours, points, lines,
surfaces and text.
Mandatory entries:
\verbatim
output
{
name image;
width 800;
height 600;
}
camera
{
...
}
colours
{
...
}
text
{
}
\endverbatim
Optional entries:
\verbatim
points
{
}
lines
{
...
}
surfaces
{
...
}
\endverbatim
Dictionary controls
\table
Property | Description | Required | Default
type | Type-name: runTimePostProcessing | yes |
debug | Additional debug information | no | false
\endtable
SourceFiles
runTimePostProcessing.C
@ -76,14 +118,20 @@ SourceFiles
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Forward declarations
class vtkRenderer;
// Forward Declarations
class vtkMultiPieceDataSet;
class vtkMultiProcessController;
class vtkRenderWindow;
class vtkRenderer;
template<class T> class vtkSmartPointer;
namespace Foam
{
namespace functionObjects
{
// Forward declarations
class runTimePostProcessing;
namespace runTimePostPro
{
// Forward declarations
@ -101,11 +149,9 @@ class runTimePostProcessing
:
public fvMeshFunctionObject
{
private:
// Private Data
// Private data
// Output
//- Output information
struct outputType
{
word name_;
@ -116,6 +162,9 @@ private:
//- Output instance
outputType output_;
//- Parallel rendering
bool parallel_;
//- Scene manager
runTimePostPro::scene scene_;
@ -138,6 +187,15 @@ private:
template<class Type>
void readObjects(const dictionary& dict, PtrList<Type>& objects) const;
//- Construct controller and dispatch to render
void render();
//- Static function for SetSingleMethod binding
static void render(vtkMultiProcessController* ctrl, void* data);
//- Render scene using given controller
void render(vtkMultiProcessController* ctrl);
public:
@ -162,11 +220,26 @@ public:
// Member Functions
//- Parallel rendering
bool parallel() const
{
return parallel_;
}
//- May need to gather parts to render on single-processor
// True when OpenFOAM is running in parallel but VTK is not.
bool needsCollective() const
{
return Pstream::parRun() && !parallel_;
}
//- Reference to the underlying OpenFOAM mesh
const fvMesh& mesh() const
{
return mesh_;
}
//- Read the post-processing controls
virtual bool read(const dictionary& dict);

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.

View File

@ -0,0 +1,250 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
// OpenFOAM includes
#include "scalarBar.H"
// #include "doubleVector.H"
// #include "foamVtkTools.H"
// VTK includes
#include "vtkCoordinate.h"
#include "vtkLookupTable.h"
#include "vtkRenderer.h"
#include "vtkScalarBarActor.h"
#include "vtkSmartPointer.h"
#include "vtkTextActor.h"
#include "vtkTextProperty.h"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::runTimePostPro::scalarBar::scalarBar()
{
clear();
}
void Foam::functionObjects::runTimePostPro::scalarBar::clear()
{
visible_ = true;
vertical_ = true;
bold_ = true;
shadow_ = false;
italic_ = false;
titleHack_ = true;
position_ = {0.8, 0.1};
size_ = {0.1, 0.5};
title_ = "";
fontSize_ = 12;
titleSize_ = 0; // 0 == Auto-sizing (factor 3)
nLabels_ = 5;
labelFormat_ = "%f";
}
void Foam::functionObjects::runTimePostPro::scalarBar::hide()
{
visible_ = false;
}
void Foam::functionObjects::runTimePostPro::scalarBar::read
(
const dictionary& dict
)
{
clear();
dict.readIfPresent("visible", visible_);
if (visible_)
{
dict.readIfPresent("vertical", vertical_);
dict.readIfPresent("bold", bold_);
dict.readIfPresent("italic", italic_);
dict.readIfPresent("shadow", shadow_);
dict.readIfPresent("titleHack", titleHack_);
if (vertical_)
{
size_ = { 0.1, 0.75 };
}
else
{
size_ = { 0.75, 0.1 };
}
dict.readEntry("position", position_);
dict.readIfPresent("size", size_);
dict.readEntry("title", title_);
dict.readIfPresent("fontSize", fontSize_);
dict.readIfPresent("titleSize", titleSize_);
dict.readIfPresent("labelFormat", labelFormat_);
dict.readIfPresent("numberOfLabels", nLabels_);
}
}
bool Foam::functionObjects::runTimePostPro::scalarBar::add
(
const vector& textColour,
vtkRenderer* renderer,
vtkLookupTable* lut
) const
{
// Add scalar bar legend
if (!visible_ || !renderer)
{
return false;
}
auto sbar = vtkSmartPointer<vtkScalarBarActor>::New();
sbar->SetLookupTable(lut);
sbar->SetNumberOfLabels(nLabels_);
sbar->SetLabelFormat(labelFormat_.c_str());
/// const vector textColour = colours_["text"]->value(position);
// Work-around to supply our own scalarbar title
// - Default scalar bar title text is scales by the scalar bar box
// dimensions so if the title is a long string, the text is shrunk to fit
// Instead, suppress title and set the title using a vtkTextActor
vtkSmartPointer<vtkTextActor> titleActor;
vtkTextProperty* titleProp;
if (titleHack_)
{
// Place the scalar bar title ourselves
titleActor = vtkSmartPointer<vtkTextActor>::New();
titleActor->SetInput(title_.c_str());
titleProp = titleActor->GetTextProperty();
titleProp->SetJustificationToCentered();
}
else
{
// Use the standard scalar bar title
sbar->SetTitle(title_.c_str());
titleProp = sbar->GetTitleTextProperty();
}
titleProp->SetFontFamilyToArial();
// Title size was supplied by user (absolute size)
// or use preset factor (3) of label font size
if (titleSize_)
{
titleProp->SetFontSize(titleSize_);
}
else
{
// Auto = Factor 3 of fontSize
titleProp->SetFontSize(3*fontSize_);
// Or this??
// if (!titleHack_) titleProp->SetFontSize(fontSize_);
}
titleProp->SetJustificationToCentered();
titleProp->SetVerticalJustificationToBottom();
titleProp->SetBold(bold_);
titleProp->SetItalic(italic_);
titleProp->SetShadow(shadow_);
titleProp->SetColor(textColour[0], textColour[1], textColour[2]);
auto labProp = sbar->GetLabelTextProperty();
labProp->SetColor(textColour[0], textColour[1], textColour[2]);
labProp->SetFontSize(fontSize_);
labProp->ShadowOff();
labProp->BoldOff();
labProp->ItalicOff();
// Positioning
{
vtkCoordinate* coord = sbar->GetPositionCoordinate();
coord->SetCoordinateSystemToNormalizedViewport();
coord->SetValue(position_.first(), position_.second());
}
if (vertical_)
{
sbar->SetOrientationToVertical();
sbar->SetTextPositionToSucceedScalarBar();
sbar->SetWidth(size_.first());
sbar->SetHeight(size_.second());
// Standard is sbar->SetBarRatio(0.375);
}
else
{
sbar->SetOrientationToHorizontal();
sbar->SetTextPositionToPrecedeScalarBar();
// Adjustments since not using scalarbar title property
sbar->SetWidth(size_.first());
sbar->SetHeight(size_.second());
// sbar->SetBarRatio(0.5);
// Standard is sbar->SetBarRatio(0.375);
// sbar->SetTitleRatio(0.01);
}
if (titleActor)
{
vtkCoordinate* coord = titleActor->GetPositionCoordinate();
coord->SetCoordinateSystemToNormalizedViewport();
coord->SetValue
(
position_.first() + (0.5 * sbar->GetWidth()),
position_.second() + (1.01 * sbar->GetHeight())
);
}
// sbar->DrawFrameOn();
// sbar->DrawBackgroundOn();
// sbar->UseOpacityOff();
// sbar->VisibilityOff();
sbar->VisibilityOn();
renderer->AddActor(sbar);
if (titleActor)
{
renderer->AddActor2D(titleActor);
}
return true;
}
// ************************************************************************* //

View File

@ -0,0 +1,138 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::functionObjects::runTimePostPro::scalarBar
Description
Handling of scalar bar setup.
Dictionary controls - scalar-bar entries (when \c visible is true)
\table
Property | Description | Required | Default
visible | Display scalar bar | no | true
title | The title for the scalar bar | yes |
position | Viewport position (x y) of scalar bar | yes |
vertical | Vertical scalar bar | no | true
size | Viewport size (x y) of scalar bar | no | auto
fontSize | Label size | no | 12
titleSize | Title font size | no | 0 == auto
labelFormat | Label format string (eg, "%f") | no | "%f"
numberOfLabels | Total number of labels | no | 5
bold | Title in bold | no | yes
italic | Title in italic font | no | no
shadow | Title with shadowont | no | no
titleHack | Alternative placement strategy | no | yes
\endtable
SourceFiles
scalarBar.C
\*---------------------------------------------------------------------------*/
#ifndef functionObjects_runTimePostPro_scalarBar_H
#define functionObjects_runTimePostPro_scalarBar_H
#include "dictionary.H"
#include "Tuple2.H"
#include "vector.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Forward Declarations
class vtkLookupTable;
class vtkRenderer;
namespace Foam
{
namespace functionObjects
{
namespace runTimePostPro
{
/*---------------------------------------------------------------------------*\
Class scalarBar Declaration
\*---------------------------------------------------------------------------*/
class scalarBar
{
bool visible_;
bool vertical_;
bool bold_;
bool italic_;
bool shadow_;
bool titleHack_;
Tuple2<scalar, scalar> position_;
Tuple2<scalar, scalar> size_;
string title_;
label fontSize_;
label titleSize_;
label nLabels_;
string labelFormat_;
public:
//- Construct with sensible defaults
scalarBar();
//- Reset to sensible defaults
void clear();
//- Make non-visible
void hide();
//- Read dictionary settings
void read(const dictionary& dict);
//- Add colour bar, when visible.
bool add
(
const vector& textColour,
vtkRenderer* renderer,
vtkLookupTable* lut
) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace runTimePostPro
} // End namespace functionObjects
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -137,6 +135,8 @@ void Foam::functionObjects::runTimePostPro::scene::setActorVisibility
const bool visible
) const
{
if (!renderer) return;
vtkActorCollection *actors = renderer->GetActors();
for (int i = 0; i < actors->GetNumberOfItems(); ++i)
{
@ -157,27 +157,30 @@ void Foam::functionObjects::runTimePostPro::scene::initialise
outputName_ = outputName;
if (!renderer) return;
// Set the background
const vector backgroundColour = colours_["background"]->value(position_);
renderer->SetBackground
(
backgroundColour.x(),
backgroundColour.y(),
backgroundColour.z()
);
const vector bgColour = colours_["background"]->value(position_);
renderer->SetBackground(bgColour.x(), bgColour.y(), bgColour.z());
// Apply gradient background if "background2" defined
if (colours_.found("background2"))
{
renderer->GradientBackgroundOn();
vector backgroundColour2 = colours_["background2"]->value(position_);
const vector bg2Colour = colours_["background2"]->value(position_);
renderer->SetBackground2
(
backgroundColour2.x(),
backgroundColour2.y(),
backgroundColour2.z()
);
renderer->GradientBackgroundOn();
renderer->SetBackground2(bg2Colour.x(), bg2Colour.y(), bg2Colour.z());
}
else if (Pstream::parRun())
{
// Oddly enough we seem a gradient background for parallel rendering,
// otherwise the colours look quite funny.
// Doesn't seem to matter if we use SetBackground2() though
renderer->GradientBackgroundOn();
renderer->SetBackground2(bgColour.x(), bgColour.y(), bgColour.z());
}
// Depth peeling
@ -224,6 +227,8 @@ void Foam::functionObjects::runTimePostPro::scene::setCamera
vtkRenderer* renderer
) const
{
if (!renderer) return;
vtkCamera* camera = renderer->GetActiveCamera();
if (parallelProjection_)
@ -355,14 +360,18 @@ bool Foam::functionObjects::runTimePostPro::scene::loop(vtkRenderer* renderer)
return true;
}
if (renderer)
{
// Ensure that all objects can be seen without clipping
// Note: can only be done after all objects have been added!
renderer->ResetCameraClippingRange();
// Save image from last iteration
saveImage(renderer->GetRenderWindow());
}
currentFrameI_++;
++currentFrameI_;
position_ = startPosition_ + currentFrameI_*dPosition_;
@ -390,16 +399,15 @@ void Foam::functionObjects::runTimePostPro::scene::saveImage
const Time& runTime = obr_.time();
const fileName prefix
const fileName fName
(
runTime.globalPath()
/ functionObject::outputPrefix
/ name_
/ runTime.timeName()
/ outputName_ + '.' + frameIndexStr() + ".png"
);
mkDir(prefix);
renderWindow->Render();
// Set up off-screen rendering
@ -415,15 +423,21 @@ void Foam::functionObjects::runTimePostPro::scene::saveImage
windowToImageFilter->Update();
// Save the image
if (Pstream::master())
{
mkDir(fName.path());
auto writer = vtkSmartPointer<vtkPNGWriter>::New();
fileName fName(prefix/outputName_ + '.' + frameIndexStr() + ".png");
writer->SetFileName(fName.c_str());
writer->SetInputConnection(windowToImageFilter->GetOutputPort());
Info<< " Generating image: " << fName << endl;
Info<< " Generating image: " << runTime.relativePath(fName) << endl;
writer->Write();
}
}
// ************************************************************************* //

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -48,6 +46,10 @@ Usage
viewAngle 20;
zoom 1.1;
}
colours
{
}
\endverbatim
SourceFiles

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2016 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -29,9 +27,15 @@ License
#include "surface.H"
#include "runTimePostProcessing.H"
#include "foamVtkTools.H"
#include "polySurfaceFields.H"
#include "polySurfacePointFields.H"
// VTK includes
#include "vtkActor.h"
#include "vtkCompositeDataGeometryFilter.h"
#include "vtkFeatureEdges.h"
#include "vtkMultiPieceDataSet.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h"
@ -46,7 +50,7 @@ namespace functionObjects
{
namespace runTimePostPro
{
defineTypeNameAndDebug(surface, 0);
defineTypeName(surface);
defineRunTimeSelectionTable(surface, dictionary);
}
}
@ -60,13 +64,30 @@ const Foam::Enum
Foam::functionObjects::runTimePostPro::surface::representationTypeNames
({
{ representationType::rtNone, "none" },
{ representationType::rtGlyph, "glyph" },
{ representationType::rtWireframe, "wireframe" },
{ representationType::rtSurface, "surface" },
{ representationType::rtSurfaceWithEdges, "surfaceWithEdges" },
{ representationType::rtGlyph, "glyph" },
});
// * * * * * * * * * * * * * * * Specializations * * * * * * * * * * * * * * //
// These need to shift elsewhere
vtkCellData* Foam::vtk::Tools::GetCellData(vtkDataSet* dataset)
{
if (dataset) return dataset->GetCellData();
return nullptr;
}
vtkPointData* Foam::vtk::Tools::GetPointData(vtkDataSet* dataset)
{
if (dataset) return dataset->GetPointData();
return nullptr;
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::functionObjects::runTimePostPro::surface::setRepresentation
@ -85,7 +106,7 @@ void Foam::functionObjects::runTimePostPro::surface::setRepresentation
}
case rtWireframe:
{
// note: colour is set using general SetColor, not SetEdgeColor
// Note: colour is set using general SetColor, not SetEdgeColor
actor->GetProperty()->SetRepresentationToWireframe();
break;
}
@ -108,21 +129,19 @@ void Foam::functionObjects::runTimePostPro::surface::setRepresentation
void Foam::functionObjects::runTimePostPro::surface::addFeatureEdges
(
vtkRenderer* renderer,
vtkPolyData* data
vtkFeatureEdges* featureEdges
) const
{
if (!featureEdges_)
if (!featureEdges)
{
return;
}
auto featureEdges = vtkSmartPointer<vtkFeatureEdges>::New();
featureEdges->SetInputData(data);
featureEdges->BoundaryEdgesOn();
featureEdges->FeatureEdgesOn();
featureEdges->ManifoldEdgesOff();
featureEdges->NonManifoldEdgesOff();
// featureEdges->SetFeatureAngle(60);
/// featureEdges->SetFeatureAngle(60);
featureEdges->ColoringOff();
featureEdges->Update();
@ -139,6 +158,38 @@ void Foam::functionObjects::runTimePostPro::surface::addFeatureEdges
}
void Foam::functionObjects::runTimePostPro::surface::addFeatureEdges
(
vtkRenderer* renderer,
vtkPolyData* data
) const
{
if (featureEdges_)
{
auto featureEdges = vtkSmartPointer<vtkFeatureEdges>::New();
featureEdges->SetInputData(data);
addFeatureEdges(renderer, featureEdges);
}
}
void Foam::functionObjects::runTimePostPro::surface::addFeatureEdges
(
vtkRenderer* renderer,
vtkCompositeDataGeometryFilter* input
) const
{
if (featureEdges_)
{
auto featureEdges = vtkSmartPointer<vtkFeatureEdges>::New();
featureEdges->SetInputConnection(input->GetOutputPort());
addFeatureEdges(renderer, featureEdges);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::runTimePostPro::surface::surface
@ -153,12 +204,12 @@ Foam::functionObjects::runTimePostPro::surface::surface
(
representationTypeNames.get("representation", dict)
),
featureEdges_(false),
featureEdges_(dict.lookupOrDefault("featureEdges", false)),
surfaceColour_(nullptr),
edgeColour_(nullptr),
surfaceActor_(),
edgeActor_(),
maxGlyphLength_(0.0)
maxGlyphLength_(0)
{
surfaceActor_ = vtkSmartPointer<vtkActor>::New();
edgeActor_ = vtkSmartPointer<vtkActor>::New();
@ -185,10 +236,6 @@ Foam::functionObjects::runTimePostPro::surface::surface
{
dict.readEntry("maxGlyphLength", maxGlyphLength_);
}
else
{
dict.readEntry("featureEdges", featureEdges_);
}
}
@ -203,10 +250,7 @@ Foam::functionObjects::runTimePostPro::surface::New
const word& surfaceType
)
{
if (debug)
{
Info<< "Selecting surface " << surfaceType << endl;
}
DebugInfo << "Selecting surface " << surfaceType << endl;
auto cstrIter = dictionaryConstructorTablePtr_->cfind(surfaceType);
@ -242,22 +286,14 @@ void Foam::functionObjects::runTimePostPro::surface::updateActors
return;
}
edgeActor_->GetProperty()->SetLineWidth(2);
edgeActor_->GetProperty()->SetOpacity(opacity(position));
vtkProperty* edgeProp = edgeActor_->GetProperty();
const vector colour = edgeColour_->value(position);
edgeActor_->GetProperty()->SetColor
(
colour[0],
colour[1],
colour[2]
);
edgeActor_->GetProperty()->SetEdgeColor
(
colour[0],
colour[1],
colour[2]
);
edgeProp->SetLineWidth(2);
edgeProp->SetOpacity(opacity(position));
const vector ec = edgeColour_->value(position);
edgeProp->SetColor(ec[0], ec[1], ec[2]);
edgeProp->SetEdgeColor(ec[0], ec[1], ec[2]);
}

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,10 +25,23 @@ Class
Foam::functionObjects::runTimePostPro::surface
Description
Visualisation of surface data
Visualisation of surface data with additional routines for handling
parallel distributed data.
Dictionary controls
\table
Property | Description | Required | Default
representation| none/glyph/wireframe/surface/surfaceWithEdges | yes |
surfaceColour | Override surface colour | no |
edgeColour | Override edge colour | no |
featureEdges | Display surface feature edges | no | false
maxGlyphLength | Limit for glyph representation | yes | 0
\endtable
SourceFiles
surface.C
surfaceGather.C
surfaceTemplates.C
\*---------------------------------------------------------------------------*/
@ -38,17 +49,80 @@ SourceFiles
#define functionObjects_runTimePostPro_surface_H
#include "geometryBase.H"
#include "DimensionedField.H"
#include "Enum.H"
#include "runTimeSelectionTables.H"
#include "vtkSmartPointer.h"
#include "vtkMultiPieceDataSet.h"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Forward declarations
// Forward Declarations
class vtkActor;
class vtkRenderer;
class vtkCellData;
class vtkCompositeDataGeometryFilter;
class vtkFeatureEdges;
class vtkPointData;
class vtkPolyData;
namespace Foam
{
// Forward Declarations
class polySurface;
class polySurfaceGeoMesh;
class polySurfacePointGeoMesh;
}
// These need to shift elsewhere
namespace Foam
{
namespace vtk
{
namespace Tools
{
//- Functional call with null-pointer check
vtkCellData* GetCellData(vtkDataSet* dataset);
//- Functional call with null-pointer check
vtkPointData* GetPointData(vtkDataSet* dataset);
//- Default field access is vtkCellData
template<class Type>
struct FieldAccess
{
vtkCellData* operator()(vtkDataSet* dataset) const
{
return Tools::GetCellData(dataset);
}
};
// Specializations on OpenFOAM type
//- PointAccess for point fields (on polySurfacePointGeoMesh)
template<>
struct FieldAccess<::Foam::polySurfacePointGeoMesh>
{
vtkPointData* operator()(vtkDataSet* dataset) const
{
return Tools::GetPointData(dataset);
}
};
} // End namespace Tools
} // End namespace vtk
} // End namespace Foam
// More
namespace Foam
{
namespace functionObjects
@ -68,21 +142,23 @@ public:
// Public enumerations
//- Surface representation types
enum representationType
{
rtNone,
rtWireframe,
rtSurface,
rtSurfaceWithEdges,
rtGlyph
rtNone, //!< "none"
rtGlyph, //!< "glyph"
rtWireframe, //!< "wireframe"
rtSurface, //!< "surface"
rtSurfaceWithEdges //!< "surfaceWithEdges"
};
//- Names for surface representation types
static const Enum<representationType> representationTypeNames;
protected:
// Protected data
// Protected Data
//- Representation type
representationType representation_;
@ -111,6 +187,13 @@ protected:
//- Set the representation
void setRepresentation(vtkActor* actor) const;
//- Add feature edges to scene
void addFeatureEdges
(
vtkRenderer* renderer,
vtkFeatureEdges* featureEdges
) const;
//- Add feature edges to scene
void addFeatureEdges
(
@ -118,6 +201,110 @@ protected:
vtkPolyData* data
) const;
//- Add feature edges to scene
void addFeatureEdges
(
vtkRenderer* renderer,
vtkCompositeDataGeometryFilter* input
) const;
//- Gather and convert polySurface to multi-piece dataset with
//- vtkPolyData for the leaves.
// If VTK is also running in parallel, each surface is left
// as a processor-local piece. Otherwise all processor-local
// surfaces are gathered onto the master in their correponding
// slots.
vtkSmartPointer<vtkMultiPieceDataSet>
gatherSurfacePieces(const polySurface* surf) const;
//- Gather and convert polySurface to multi-piece dataset with
//- vtkPolyData for the leaves.
// If VTK is also running in parallel, each surface is left
// as a processor-local piece. Otherwise all processor-local
// surfaces are gathered onto the master in their correponding
// slots.
vtkSmartPointer<vtkMultiPieceDataSet>
gatherFaceCentres(const polySurface* surf) const;
// Adding Fields - single-piece
//- Add field of Type to piece as VTK field data in GeoMeshType slot.
// GeoMeshType distinguishes between vtkCellData and vtkPointData
template<class Type, class GeoMeshType>
bool addField
(
vtkDataSet* piece, //!< The VTK piece (null protected)
const Field<Type>& fld, //!< The field values to add
const word& fieldName //!< The field name to use
) const;
//- Attempt cast of regIOobject to DimensionedField\<Type\> and
//- add to piece as VTK field data in GeoMeshType slot.
// GeoMeshType distinguishes between vtkCellData and vtkPointData
template<class Type, class GeoMeshType>
bool addDimField
(
vtkDataSet* piece, //!< The VTK piece (null protected)
const regIOobject* ioptr, //!< The field values to add
const word& fieldName //!< The field name to use
) const;
//- Attempt cast of regIOobject to standard DimensionedField types
//- and add to piece when possible
template<class GeoMeshType>
bool addDimField
(
vtkDataSet* piece, //!< The VTK piece (null protected)
const regIOobject* ioptr, //!< The field values to add
const word& fieldName //!< The field name to use
) const;
// Adding Fields - multi-piece
//- Add DimensionedField of Type to multi-piece as VTK field data in
//- GeoMeshType slot (CELL | POINT).
template<class Type, class GeoMeshType>
bool addDimField
(
vtkMultiPieceDataSet* multiPiece,
const DimensionedField<Type, GeoMeshType>* fldptr,
const word& fieldName
) const;
//- Attempt cast of regIOobject to DimensionedField\<Type\> and
//- add in multi-piece as VTK field data in
//- GeoMeshType slot (CELL | POINT).
template<class Type, class GeoMeshType>
bool addDimField
(
vtkMultiPieceDataSet* multiPiece, //!< The VTK pieces
const regIOobject* ioptr, //!< The field values to add
const word& fieldName //!< The field name to use
) const;
//- Attempt cast of regIOobject to standard DimensionedField types
//- and add when possible in GeoMeshType slot (CELL | POINT).
template<class GeoMeshType>
bool addDimField
(
vtkMultiPieceDataSet* multiPiece, //!< The VTK pieces
const regIOobject* ioptr, //!< The field values to add
const word& fieldName //!< The field name to use
) const;
//- Add using regIOobject information obtained from surface
template<class GeoMeshType>
bool addDimField
(
vtkMultiPieceDataSet* multiPiece,
const polySurface* surf,
const word& fieldName
) const;
//- No copy construct
surface(const surface&) = delete;
@ -128,7 +315,7 @@ protected:
public:
//- Run-time type information
TypeName("surface");
TypeNameNoDebug("surface");
// Declare run-time constructor selection table
@ -160,7 +347,7 @@ public:
// Selectors
//- Return a reference to the selected RAS model
//- Return selected surface
static autoPtr<surface> New
(
const runTimePostProcessing& parent,
@ -189,6 +376,12 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "surfaceTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,222 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
// OpenFOAM includes
#include "surface.H"
#include "runTimePostProcessing.H"
#include "foamVtkTools.H"
#include "polySurface.H"
// VTK includes
#include "vtkMultiPieceDataSet.h"
#include "vtkPolyData.h"
#include "vtkSmartPointer.h"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
vtkSmartPointer<vtkMultiPieceDataSet>
Foam::functionObjects::runTimePostPro::surface::gatherSurfacePieces
(
const polySurface* surf
) const
{
auto multiPiece = vtkSmartPointer<vtkMultiPieceDataSet>::New();
multiPiece->SetNumberOfPieces(Pstream::nProcs());
if (!needsCollective())
{
// Simple case (serial-serial, parallel-parallel)
if (surf)
{
multiPiece->SetPiece
(
Pstream::myProcNo(),
Foam::vtk::Tools::Patch::mesh(*surf)
);
}
}
else if (Pstream::master())
{
// Gather pieces on master
if (surf)
{
// Add myself
multiPiece->SetPiece
(
Pstream::myProcNo(),
Foam::vtk::Tools::Patch::mesh(*surf)
);
}
// Receive surfaces
pointField points;
faceList faces;
for
(
int slave=Pstream::firstSlave();
slave<=Pstream::lastSlave();
++slave
)
{
IPstream fromSlave(Pstream::commsTypes::scheduled, slave);
points.clear();
faces.clear();
fromSlave >> points >> faces;
if (points.size())
{
multiPiece->SetPiece
(
slave,
Foam::vtk::Tools::Patch::mesh(points, faces)
);
}
}
}
else
{
// Slave - send surfaces
OPstream toMaster
(
Pstream::commsTypes::scheduled,
Pstream::masterNo()
);
if (surf)
{
toMaster
<< surf->points() << surf->faces();
}
else
{
toMaster
<< pointField() << faceList();
}
}
return multiPiece;
}
vtkSmartPointer<vtkMultiPieceDataSet>
Foam::functionObjects::runTimePostPro::surface::gatherFaceCentres
(
const polySurface* surf
) const
{
auto multiPiece = vtkSmartPointer<vtkMultiPieceDataSet>::New();
multiPiece->SetNumberOfPieces(Pstream::nProcs());
if (!needsCollective())
{
// Simple case
if (surf)
{
auto dataset = vtkSmartPointer<vtkPolyData>::New();
auto geom = vtkSmartPointer<vtkPolyData>::New();
geom->SetPoints(Foam::vtk::Tools::Patch::faceCentres(*surf));
geom->SetVerts(Foam::vtk::Tools::identityVertices(surf->nFaces()));
multiPiece->SetPiece(Pstream::myProcNo(), geom);
}
}
else if (Pstream::master())
{
// Gather pieces (face centres) on master
if (surf)
{
// Add myself
auto geom = vtkSmartPointer<vtkPolyData>::New();
geom->SetPoints(Foam::vtk::Tools::Patch::faceCentres(*surf));
geom->SetVerts(Foam::vtk::Tools::identityVertices(surf->nFaces()));
multiPiece->SetPiece(Pstream::myProcNo(), geom);
}
// Receive points
pointField points;
for
(
int slave=Pstream::firstSlave();
slave<=Pstream::lastSlave();
++slave
)
{
IPstream fromSlave(Pstream::commsTypes::scheduled, slave);
points.clear();
fromSlave >> points;
if (points.size())
{
multiPiece->SetPiece
(
slave,
Foam::vtk::Tools::Vertices(points)
);
}
}
}
else
{
// Slave - send face centres
OPstream toMaster
(
Pstream::commsTypes::scheduled,
Pstream::masterNo()
);
if (surf)
{
toMaster << surf->faceCentres();
}
else
{
toMaster << pointField();
}
}
return multiPiece;
}
// ************************************************************************* //

View File

@ -0,0 +1,289 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "foamVtkTools.H"
#include "polySurfaceFields.H"
#include "polySurfacePointFields.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type, class GeoMeshType>
bool Foam::functionObjects::runTimePostPro::surface::addField
(
vtkDataSet* piece,
const Field<Type>& fld,
const word& fieldName
) const
{
if (!piece) return false;
auto vtkfield = Foam::vtk::Tools::convertFieldToVTK<Type>(fieldName, fld);
if (piece->GetNumberOfCells() == piece->GetNumberOfPoints())
{
// Only has verts
piece->GetPointData()->AddArray(vtkfield);
}
else
{
Foam::vtk::Tools::FieldAccess<GeoMeshType>()(piece)->AddArray(vtkfield);
}
return true;
}
template<class Type, class GeoMeshType>
bool Foam::functionObjects::runTimePostPro::surface::addDimField
(
vtkDataSet* piece,
const regIOobject* ioptr,
const word& fieldName
) const
{
const auto* fldptr =
dynamic_cast<const DimensionedField<Type, GeoMeshType>*>(ioptr);
if (fldptr)
{
return addField<Type, GeoMeshType>
(
piece,
fldptr->field(),
fieldName
);
}
return false;
}
template<class GeoMeshType>
bool Foam::functionObjects::runTimePostPro::surface::addDimField
(
vtkDataSet* piece,
const regIOobject* ioptr,
const word& fieldName
) const
{
return (piece && ioptr) &&
(
addDimField<scalar, GeoMeshType>
(
piece, ioptr, fieldName
)
|| addDimField<vector, GeoMeshType>
(
piece, ioptr, fieldName
)
|| addDimField<sphericalTensor, GeoMeshType>
(
piece, ioptr, fieldName
)
|| addDimField<symmTensor, GeoMeshType>
(
piece, ioptr, fieldName
)
|| addDimField<tensor, GeoMeshType>
(
piece, ioptr, fieldName
)
);
}
template<class Type, class GeoMeshType>
bool Foam::functionObjects::runTimePostPro::surface::addDimField
(
vtkMultiPieceDataSet* multiPiece,
const DimensionedField<Type, GeoMeshType>* fldptr,
const word& fieldName
) const
{
if (!multiPiece)
{
return false;
}
if (!needsCollective())
{
// Simple case (serial-serial, parallel-parallel)
return fldptr &&
addField<Type, GeoMeshType>
(
multiPiece->GetPiece(Pstream::myProcNo()),
fldptr->field(),
fieldName
);
}
// Gather fields
const bool ok = returnReduce((fldptr != nullptr), orOp<bool>());
if (!ok)
{
return false;
}
if (Pstream::master())
{
if (fldptr)
{
// My field data
addField<Type, GeoMeshType>
(
multiPiece->GetPiece(Pstream::myProcNo()),
fldptr->field(),
fieldName
);
}
// Receive field data
Field<Type> recv;
for
(
int slave=Pstream::firstSlave();
slave<=Pstream::lastSlave();
++slave
)
{
IPstream fromSlave(Pstream::commsTypes::scheduled, slave);
recv.clear();
fromSlave
>> recv;
if (recv.size())
{
addField<Type, GeoMeshType>
(
multiPiece->GetPiece(slave),
recv,
fieldName
);
}
}
}
else
{
// Slave - send field data
OPstream toMaster
(
Pstream::commsTypes::scheduled,
Pstream::masterNo()
);
if (fldptr)
{
toMaster
<< fldptr->field();
}
else
{
toMaster
<< List<Type>();
}
}
return ok;
}
template<class Type, class GeoMeshType>
bool Foam::functionObjects::runTimePostPro::surface::addDimField
(
vtkMultiPieceDataSet* multiPiece,
const regIOobject* ioptr,
const word& fieldName
) const
{
return addDimField<Type, GeoMeshType>
(
multiPiece,
dynamic_cast<const DimensionedField<Type, GeoMeshType>*>(ioptr),
fieldName
);
}
template<class GeoMeshType>
bool Foam::functionObjects::runTimePostPro::surface::addDimField
(
vtkMultiPieceDataSet* multiPiece,
const regIOobject* ioptr,
const word& fieldName
) const
{
return (multiPiece) &&
(
addDimField<scalar, GeoMeshType>
(
multiPiece, ioptr, fieldName
)
|| addDimField<vector, GeoMeshType>
(
multiPiece, ioptr, fieldName
)
|| addDimField<sphericalTensor, GeoMeshType>
(
multiPiece, ioptr, fieldName
)
|| addDimField<symmTensor, GeoMeshType>
(
multiPiece, ioptr, fieldName
)
|| addDimField<tensor, GeoMeshType>
(
multiPiece, ioptr, fieldName
)
);
}
template<class GeoMeshType>
bool Foam::functionObjects::runTimePostPro::surface::addDimField
(
vtkMultiPieceDataSet* multiPiece,
const polySurface* surf,
const word& fieldName
) const
{
const regIOobject* ioptr =
(
surf
? surf->findFieldObject<GeoMeshType>(fieldName)
: nullptr
);
return addDimField<GeoMeshType>(multiPiece, ioptr, fieldName);
}
// ************************************************************************* //

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,10 +25,12 @@ License
// OpenFOAM includes
#include "text.H"
#include "stringOps.H"
#include "fvMesh.H"
#include "runTimePostProcessing.H"
// VTK includes
#include "vtkCoordinate.h"
#include "vtkRenderer.h"
#include "vtkSmartPointer.h"
#include "vtkTextActor.h"
@ -62,7 +62,7 @@ Foam::functionObjects::runTimePostPro::text::text
:
geometryBase(parent, dict, colours),
string_(dict.get<string>("string")),
position_(),
positions_(),
size_(dict.get<scalar>("size")),
colour_(nullptr),
halign_
@ -74,7 +74,20 @@ Foam::functionObjects::runTimePostPro::text::text
shadow_(dict.lookupOrDefault("shadow", false)),
timeStamp_(dict.lookupOrDefault("timeStamp", false))
{
dict.readEntry("position", position_);
if (!dict.readIfPresent("positions", positions_))
{
positions_.resize(1);
dict.readEntry("position", positions_.first());
}
// Additional safety
if (positions_.empty())
{
positions_.resize(1);
positions_.first() = {0, 0};
}
stringOps::inplaceExpand(string_, dict, true, true);
if (dict.found("colour"))
{
@ -101,12 +114,13 @@ void Foam::functionObjects::runTimePostPro::text::addGeometryToScene
vtkRenderer* renderer
)
{
if (!visible_)
if (!visible_ || !renderer || !Pstream::master())
{
// Add text on master only!
return;
}
auto actor = vtkSmartPointer<vtkTextActor>::New();
DebugInfo << " Add text: " << string_ << nl;
// Concatenate string with timeStamp if true
string str = string_;
@ -114,6 +128,15 @@ void Foam::functionObjects::runTimePostPro::text::addGeometryToScene
{
str += " " + geometryBase::parent_.mesh().time().timeName();
}
const vector textColour = colour_->value(position);
const scalar textOpacity = opacity(position);
for (const auto& textPosition : positions_)
{
auto actor = vtkSmartPointer<vtkTextActor>::New();
actor->SetInput(str.c_str());
vtkTextProperty* prop = actor->GetTextProperty();
@ -126,19 +149,19 @@ void Foam::functionObjects::runTimePostPro::text::addGeometryToScene
prop->SetItalic(italic_);
prop->SetShadow(shadow_);
const vector colour = colour_->value(position);
prop->SetColor(textColour[0], textColour[1], textColour[2]);
prop->SetOpacity(textOpacity);
prop->SetColor(colour[0], colour[1], colour[2]);
prop->SetOpacity(opacity(position));
// Positioning
{
vtkCoordinate* coord = actor->GetPositionCoordinate();
actor->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport();
actor->GetPositionCoordinate()->SetValue
(
position_.first(),
position_.second()
);
coord->SetCoordinateSystemToNormalizedViewport();
coord->SetValue(textPosition.first(), textPosition.second());
}
renderer->AddActor2D(actor);
}
}

View File

@ -2,10 +2,8 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -41,7 +39,6 @@ Description
// Optional entry
shadow false;
visible yes;
// Optionally override default colour
// colour (0 1 1);
@ -56,6 +53,7 @@ Description
Property | Description | Required | Default
string | Text to display | yes |
position | The (x y) viewport position | yes |
positions | Multiple (x y) viewport positions | no |
size | The font size in points | yes |
halign | Text justification (left/centre/ right) | no | left
bold | Use bold font | yes |
@ -68,10 +66,14 @@ Description
Inherited controls
\table
Property | Description | Required | Default
visible | Display the object | yes |
visible | Display the object | no | true
opacity | Object opacity | no | 1.0
\endtable
Note
The string text is expanded on input using stringOps::inplaceExpand()
to expand dictionary and environment variable entries.
SourceFiles
text.C
@ -85,7 +87,7 @@ SourceFiles
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Forward declarations
// Forward Declarations
class vtkRenderer;
namespace Foam
@ -105,9 +107,9 @@ class text
{
public:
// Public enumerations
// Public Enumerations
//- Horizontal alignment type
//- Horizontal alignment type. Values to match VTK definitions
enum halignType
{
LEFT = 0, //!< Left-justified text - default ("left")
@ -126,13 +128,13 @@ protected:
//- Text
string string_;
//- Position
Tuple2<scalar, scalar> position_;
//- Position(s)
List<Tuple2<scalar, scalar>> positions_;
//- Size
//- Font size
scalar size_;
//- Colour
//- Text colour
autoPtr<Function1<vector>> colour_;
//- Horizontal alignment
@ -179,7 +181,7 @@ public:
// Member Functions
//- Add surface(s) to scene
//- Add text to scene
virtual void addGeometryToScene
(
const scalar position,
@ -189,7 +191,7 @@ public:
//- Update actors
virtual void updateActors(const scalar position);
//- Clear files used to create the object(s)
//- Clear files used to create the object(s) - no-op
virtual bool clear();
};

View File

@ -0,0 +1,144 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
// OpenFOAM includes
#include "volumeFilter.H"
#include "runTimePostProcessing.H"
// VTK includes
#include "vtkCellData.h"
#include "vtkCellDataToPointData.h"
#include "vtkCompositeDataGeometryFilter.h"
#include "vtkCompositeDataSet.h"
#include "vtkCompositePolyDataMapper.h"
#include "vtkMultiPieceDataSet.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkSmartPointer.h"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::runTimePostPro::volumeFilter::volumeFilter
(
const runTimePostProcessing& parent,
const dictionary& dict,
const HashPtrTable<Function1<vector>>& colours
)
:
surface(parent, dict, colours)
{}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
vtkSmartPointer<vtkMultiPieceDataSet>
Foam::functionObjects::runTimePostPro::volumeFilter::mesh
(
Foam::vtk::vtuAdaptor& adaptor
) const
{
auto multiPiece = vtkSmartPointer<vtkMultiPieceDataSet>::New();
multiPiece->SetNumberOfPieces(Pstream::nProcs());
multiPiece->SetPiece
(
Pstream::myProcNo(),
adaptor.internal(parent().mesh())
);
return multiPiece;
}
bool Foam::functionObjects::runTimePostPro::volumeFilter::addDimField
(
vtkDataSet* piece,
const vtk::vtuAdaptor& adaptor,
const regIOobject* ioptr,
const word& fieldName
) const
{
return (piece && ioptr) &&
(
addDimField<scalar>
(
piece, adaptor, ioptr, fieldName
)
|| addDimField<vector>
(
piece, adaptor, ioptr, fieldName
)
|| addDimField<sphericalTensor>
(
piece, adaptor, ioptr, fieldName
)
|| addDimField<symmTensor>
(
piece, adaptor, ioptr, fieldName
)
|| addDimField<tensor>
(
piece, adaptor, ioptr, fieldName
)
);
}
int Foam::functionObjects::runTimePostPro::volumeFilter::addDimField
(
vtkMultiPieceDataSet* piece,
const vtk::vtuAdaptor& adaptor,
const regIOobject* ioptr,
const word& fieldName
) const
{
return (piece && ioptr) &&
(
addDimField<scalar>
(
piece, adaptor, ioptr, fieldName
)
|| addDimField<vector>
(
piece, adaptor, ioptr, fieldName
)
|| addDimField<sphericalTensor>
(
piece, adaptor, ioptr, fieldName
)
|| addDimField<symmTensor>
(
piece, adaptor, ioptr, fieldName
)
|| addDimField<tensor>
(
piece, adaptor, ioptr, fieldName
)
);
}
// ************************************************************************* //

View File

@ -0,0 +1,162 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::functionObjects::runTimePostPro::volumeFilter
Description
Visualisation of OpenFOAM volume fields as surface data using
a VTK filter cascade.
Note
Since this filter includes an OpenFOAM/VTK adaptor level,
it is ill-suited to mismatches in data parallelization.
If OpenFOAM is running in parallel but VTK is not, it would be rather
expensive to collect all the data on the master node for this filter.
That approach is acceptable for smaller amounts of data, but do not
allow for volume meshes.
SourceFiles
volumeFilter.C
\*---------------------------------------------------------------------------*/
#ifndef functionObjects_runTimePostPro_volumeFilter_H
#define functionObjects_runTimePostPro_volumeFilter_H
#include "runTimePostProcessing.H"
#include "surface.H"
#include "foamVtkVtuAdaptor.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
class vtkDataSet;
class vtkMultiPieceDataSet;
template<class T> class vtkSmartPointer;
namespace Foam
{
namespace vtk
{
class vtuAdaptor;
}
namespace functionObjects
{
namespace runTimePostPro
{
/*---------------------------------------------------------------------------*\
Class volumeFilter Declaration
\*---------------------------------------------------------------------------*/
class volumeFilter
:
public surface
{
protected:
// Protected Member Functions
//- Return a vtu mesh with addressing information stored in adaptor
vtkSmartPointer<vtkMultiPieceDataSet> mesh
(
Foam::vtk::vtuAdaptor& adaptor
) const;
bool addDimField
(
vtkDataSet* piece,
const vtk::vtuAdaptor& adaptor,
const regIOobject* ioptr,
const word& fieldName
) const;
int addDimField
(
vtkMultiPieceDataSet* multiPiece,
const vtk::vtuAdaptor& adaptor,
const regIOobject* ioptr,
const word& fieldName
) const;
template<class Type>
bool addDimField
(
vtkDataSet* piece,
const vtk::vtuAdaptor& adaptor,
const regIOobject* ioptr,
const word& fieldName
) const;
template<class Type>
int addDimField
(
vtkMultiPieceDataSet* multiPiece,
const vtk::vtuAdaptor& adaptor,
const regIOobject* ioptr,
const word& fieldName
) const;
//- No copy construct
volumeFilter(const volumeFilter&) = delete;
//- No copy assignment
void operator=(const volumeFilter&) = delete;
public:
// Constructors
//- Construct from dictionary
volumeFilter
(
const runTimePostProcessing& parent,
const dictionary& dict,
const HashPtrTable<Function1<vector>>& colours
);
//- Destructor
virtual ~volumeFilter() = default;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace runTimePostPro
} // End namespace functionObjects
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "volumeFilterTemplates.C"
#endif
#endif
// ************************************************************************* //

View File

@ -0,0 +1,120 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
// OpenFOAM includes
#include "volumeFilter.H"
#include "fvMesh.H"
#include "volFields.H"
#include "foamVtkTools.H"
// VTK includes
#include "vtkCellData.h"
#include "vtkMultiPieceDataSet.h"
#include "vtkPointData.h"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<class Type>
bool Foam::functionObjects::runTimePostPro::volumeFilter::addDimField
(
vtkDataSet* piece,
const vtk::vtuAdaptor& adaptor,
const regIOobject* ioptr,
const word& fieldName
) const
{
vtkSmartPointer<vtkFloatArray> vtkdata;
const auto* dimptr =
dynamic_cast<const DimensionedField<Type, volMesh>*>(ioptr);
if (dimptr && !vtkdata)
{
vtkdata = adaptor.convertField(*dimptr);
}
const auto* volptr =
dynamic_cast<const GeometricField<Type, fvPatchField, volMesh>*>(ioptr);
if (volptr && !vtkdata)
{
vtkdata = adaptor.convertField(volptr->internalField());
}
if (vtkdata)
{
piece->GetCellData()->AddArray(vtkdata);
return true;
}
return false;
}
template<class Type>
int Foam::functionObjects::runTimePostPro::volumeFilter::addDimField
(
vtkMultiPieceDataSet* multiPiece,
const vtk::vtuAdaptor& adaptor,
const regIOobject* ioptr,
const word& fieldName
) const
{
if (!multiPiece)
{
return 0;
}
const int nCmpt(pTraits<Type>::nComponents);
if (!needsCollective())
{
// Simple case (serial-serial, parallel-parallel)
auto piece = multiPiece->GetPiece(Pstream::myProcNo());
if
(
addDimField<Type>
(
piece,
adaptor,
ioptr,
fieldName
)
)
{
return nCmpt;
}
}
else
{
}
return 0;
}
// ************************************************************************* //

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2011, 2016 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2011-2011, 2016-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2017 OpenFOAM Foundation
@ -28,8 +28,8 @@ License
#include "FacePostProcessing.H"
#include "Pstream.H"
#include "ListListOps.H"
#include "surfaceWriter.H"
#include "globalIndex.H"
#include "surfaceWriter.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -194,35 +194,26 @@ void Foam::FacePostProcessing<CloudType>::write()
)
);
autoPtr<surfaceWriter> writer
(
surfaceWriter::New
auto writer = surfaceWriter::New
(
surfaceFormat_,
this->coeffDict().subOrEmptyDict("formatOptions").
subOrEmptyDict(surfaceFormat_)
)
this->coeffDict().subOrEmptyDict("formatOptions")
.subOrEmptyDict(surfaceFormat_)
);
writer->write
writer->open
(
this->writeTimeDir(),
fZone.name(),
meshedSurfRef(allPoints, allFaces),
"massTotal",
zoneMassTotal[zoneI],
false
allPoints,
allFaces,
(this->writeTimeDir() / fZone.name()),
false // serial - already merged
);
writer->write
(
this->writeTimeDir(),
fZone.name(),
meshedSurfRef(allPoints, allFaces),
"massFlowRate",
zoneMassFlowRate[zoneI],
false
);
writer->write("massTotal", zoneMassTotal[zoneI]);
writer->write("massFlowRate", zoneMassFlowRate[zoneI]);
writer->clear();
}
}
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2016 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2012-2017 OpenFOAM Foundation
@ -462,40 +462,26 @@ void Foam::ParticleCollector<CloudType>::write()
<< endl;
if (surfaceFormat_ != "none")
if (surfaceFormat_ != "none" && Pstream::master())
{
if (Pstream::master())
{
autoPtr<surfaceWriter> writer
(
surfaceWriter::New
auto writer = surfaceWriter::New
(
surfaceFormat_,
this->coeffDict().subOrEmptyDict("formatOptions").
subOrEmptyDict(surfaceFormat_)
)
this->coeffDict().subOrEmptyDict("formatOptions")
.subOrEmptyDict(surfaceFormat_)
);
writer->write
writer->open
(
this->writeTimeDir(),
"collector",
meshedSurfRef(points_, faces_),
"massTotal",
faceMassTotal,
false
points_,
faces_,
(this->writeTimeDir() / "collector"),
false // serial - already merged
);
writer->write
(
this->writeTimeDir(),
"collector",
meshedSurfRef(points_, faces_),
"massFlowRate",
faceMassFlowRate,
false
);
}
writer->write("massFlowRate", faceMassFlowRate);
writer->write("massTotal", faceMassTotal);
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -275,22 +275,19 @@ Foam::scalar surfaceNoise::writeSurfaceData
}
}
// Could also have meshedSurface implement meshedSurf
if (writeSurface)
{
fileName outFileName = writerPtr_->write
(
outDir,
fName,
meshedSurfRef
writerPtr_->open
(
surf.points(),
surf.surfFaces()
),
title,
allData,
false
surf.surfFaces(),
(outDir / fName),
false // serial - already merged
);
writerPtr_->write(title, allData);
writerPtr_->clear();
}
// TO BE VERIFIED: area-averaged values
@ -305,22 +302,19 @@ Foam::scalar surfaceNoise::writeSurfaceData
{
const meshedSurface& surf = readerPtr_->geometry();
// Could also have meshedSurface implement meshedSurf
if (writeSurface)
{
writerPtr_->write
(
outDir,
fName,
meshedSurfRef
writerPtr_->open
(
surf.points(),
surf.surfFaces()
),
title,
data,
false
surf.surfFaces(),
(outDir / fName),
false // serial - already merged
);
writerPtr_->write(title, data);
writerPtr_->clear();
}
// TO BE VERIFIED: area-averaged values
@ -442,13 +436,12 @@ bool surfaceNoise::read(const dictionary& dict)
const word writerType(dict.get<word>("writer"));
dictionary optDict
writerPtr_ = surfaceWriter::New
(
writerType,
dict.subOrEmptyDict("writeOptions").subOrEmptyDict(writerType)
);
writerPtr_ = surfaceWriter::New(writerType, optDict);
return true;
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -111,7 +111,7 @@ SeeAlso
namespace Foam
{
// Forward declaration of classes
// Forward declarations
class surfaceReader;
class surfaceWriter;

View File

@ -50,8 +50,8 @@ sampledSurface/distanceSurface/sampledDistanceSurface.C
sampledSurface/sampledCuttingPlane/sampledCuttingPlane.C
sampledSurface/sampledCuttingSurface/sampledCuttingSurface.C
sampledSurface/sampledSurface/sampledSurface.C
sampledSurface/sampledSurface/sampledSurfaceRegister.C
sampledSurface/sampledSurfaces/sampledSurfaces.C
sampledSurface/sampledSurfaces/sampledSurfacesGrouping.C
sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMesh.C
sampledSurface/sampledTriSurfaceMesh/sampledTriSurfaceMeshNormal.C
sampledSurface/thresholdCellFaces/sampledThresholdCellFaces.C
@ -59,24 +59,11 @@ sampledSurface/thresholdCellFaces/sampledThresholdCellFaces.C
/* Proof-of-concept: */
/* sampledSurface/triSurfaceMesh/sampledDiscreteSurface.C */
readers = sampledSurface/readers
surfWriters = sampledSurface/writers
$(surfWriters)/surfaceWriter.C
$(surfWriters)/ensight/ensightSurfaceWriter.C
$(surfWriters)/foam/foamSurfaceWriter.C
$(surfWriters)/nastran/nastranSurfaceWriter.C
$(surfWriters)/proxy/proxySurfaceWriter.C
$(surfWriters)/raw/rawSurfaceWriter.C
$(surfWriters)/starcd/starcdSurfaceWriter.C
$(surfWriters)/vtk/vtkSurfaceWriter.C
$(surfWriters)/boundaryData/boundaryDataSurfaceWriter.C
surfReaders = sampledSurface/readers
$(surfReaders)/surfaceReader.C
$(surfReaders)/surfaceReaderNew.C
$(surfReaders)/ensight/ensightSurfaceReader.C
$(readers)/surfaceReader.C
$(readers)/surfaceReaderNew.C
$(readers)/ensight/ensightSurfaceReader.C
graphField/writePatchGraph.C
graphField/writeCellGraph.C

View File

@ -38,6 +38,17 @@ namespace Foam
}
const Foam::wordList Foam::sampledSurface::surfaceFieldTypes
({
"surfaceScalarField",
"surfaceVectorField",
"surfaceSphericalTensorField",
"surfaceSymmTensorField",
"surfaceTensorField"
});
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::sampledSurface::clearGeom() const
@ -57,10 +68,8 @@ Foam::autoPtr<Foam::sampledSurface> Foam::sampledSurface::New
{
const word sampleType(dict.get<word>("type"));
if (debug)
{
Info<< "Selecting sampledType " << sampleType << endl;
}
DebugInfo
<< "Selecting sampledType " << sampleType << endl;
auto cstrIter = wordConstructorTablePtr_->cfind(sampleType);

View File

@ -65,17 +65,15 @@ SourceFiles
#ifndef sampledSurface_H
#define sampledSurface_H
#include "meshedSurf.H"
#include "word.H"
#include "labelList.H"
#include "faceList.H"
#include "polySurface.H"
#include "surfMesh.H"
#include "typeInfo.H"
#include "runTimeSelectionTables.H"
#include "autoPtr.H"
#include "polyMesh.H"
#include "volFieldsFwd.H"
#include "surfaceFieldsFwd.H"
#include "surfaceMesh.H"
#include "polyMesh.H"
#include "interpolation.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -91,11 +89,19 @@ class sampledSurface
:
public meshedSurf
{
public:
// Public Static Data
//- Class names for surface field types
static const wordList surfaceFieldTypes;
private:
// Private Data
//- Name of sample surface
//- The name of the sample surface
word name_;
//- Reference to mesh
@ -104,15 +110,13 @@ private:
//- Should surface sampling be enabled?
bool enabled_;
//- Do we intend to interpolate the information?
const bool interpolate_;
//- Interpolate information to the nodes?
bool interpolate_;
//- Total surface area (demand-driven)
mutable scalar area_;
protected:
// Protected Member Functions
@ -163,9 +167,7 @@ public:
);
// iNew helper class
//- Class for PtrList read-construction
//- PtrList read-construction helper
class iNew
{
//- Reference to the volume mesh
@ -188,6 +190,34 @@ public:
};
//- PtrList read-construction helper that captures dictionaries used
//- during creation.
class iNewCapture
{
//- Reference to the volume mesh
const polyMesh& mesh_;
//- Captured (recorded) dictionaries
DynamicList<dictionary>& capture_;
public:
iNewCapture(const polyMesh& mesh, DynamicList<dictionary>& capture)
:
mesh_(mesh),
capture_(capture)
{}
autoPtr<sampledSurface> operator()(Istream& is) const
{
word name(is);
capture_.append(dictionary(is));
return sampledSurface::New(name, mesh_, capture_.last());
}
};
// Constructors
//- Construct from name, mesh
@ -245,13 +275,13 @@ public:
return name_;
}
//- Sampling is enabled
//- Surface is enabled
bool enabled() const
{
return enabled_;
}
//- Interpolation requested for surface
//- interpolation to nodes requested for surface
bool interpolate() const
{
return interpolate_;
@ -301,6 +331,99 @@ public:
}
// General registry storage (optional)
//- Get surface from registry if available.
// \param obr The objectRegistry to use
// \param lookupName Optional lookup name, use surface name if empty
// \return surface or nullptr
polySurface* getRegistrySurface
(
const objectRegistry& obr,
word lookupName = ""
) const;
//- Copy surface into registry.
// \param obr The objectRegistry to use
// \param lookupName Optional lookup name, use surface name if empty
// \return surface or nullptr it surface should not be stored
polySurface* storeRegistrySurface
(
objectRegistry& obr,
word lookupName = ""
) const;
//- Remove surface from registry.
// \param obr The objectRegistry to use
// \param lookupName Optional lookup name, use surface name if empty
// \return True if surface existed and was removed
bool removeRegistrySurface
(
objectRegistry& obr,
word lookupName = ""
) const;
//- Copy/store sampled field onto registered surface (if it exists)
template<class Type, class GeoMeshType>
bool storeRegistryField
(
const objectRegistry& obr,
const word& fieldName,
const dimensionSet& dims,
const Field<Type>& values,
word lookupName = ""
) const;
//- Move/store sampled field onto registered surface (if it exists)
template<class Type, class GeoMeshType>
bool storeRegistryField
(
const objectRegistry& obr,
const word& fieldName,
const dimensionSet& dims,
Field<Type>&& values,
word lookupName = ""
) const;
// Specialized surfMesh storage (optional)
//- Get surface from registry if available.
// \param lookupName Optional lookup name, use surface name if empty
// \return surface or nullptr
surfMesh* getSurfMesh(word lookupName = "") const;
//- Copy surface into registry.
// \param lookupName Optional lookup name, use surface name if empty
// \return surface or nullptr it surface should not be stored
surfMesh* storeSurfMesh(word lookupName = "") const;
//- Remove surface from registry.
// \param lookupName Optional lookup name, use surface name if empty
// \return True if surface existed and was removed
bool removeSurfMesh(word lookupName = "") const;
//- Copy/store sampled Face field onto surfMesh (if it exists)
template<class Type, class GeoMeshType>
bool storeSurfMeshField
(
const word& fieldName,
const dimensionSet& dims,
const Field<Type>& values,
word lookupName = ""
) const;
//- Move/store sampled Face field onto surfMesh (if it exists)
template<class Type, class GeoMeshType>
bool storeSurfMeshField
(
const word& fieldName,
const dimensionSet& dims,
Field<Type>&& values,
word lookupName = ""
) const;
// Sample (faces)
//- Sample volume field onto surface faces

View File

@ -0,0 +1,137 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "sampledSurface.H"
#include "fvMesh.H"
#include "MeshedSurface.H"
#include "demandDrivenData.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::polySurface* Foam::sampledSurface::getRegistrySurface
(
const objectRegistry& obr,
word lookupName
) const
{
if (lookupName.empty())
{
lookupName = this->name();
}
return obr.getObjectPtr<polySurface>(lookupName);
}
Foam::polySurface* Foam::sampledSurface::storeRegistrySurface
(
objectRegistry& obr,
word lookupName
) const
{
if (lookupName.empty())
{
lookupName = this->name();
}
polySurface* surfptr = getRegistrySurface(obr, lookupName);
if (!surfptr)
{
// Construct null and add to registry (owned by registry)
surfptr = new polySurface(lookupName, obr, true);
}
surfptr->copySurface(*this); // Copy in geometry (removes old fields)
return surfptr;
}
bool Foam::sampledSurface::removeRegistrySurface
(
objectRegistry& obr,
word lookupName
) const
{
polySurface* surfptr = getRegistrySurface(obr, lookupName);
if (surfptr)
{
return obr.checkOut(*surfptr);
}
return false;
}
Foam::surfMesh* Foam::sampledSurface::getSurfMesh(word lookupName) const
{
if (lookupName.empty())
{
lookupName = this->name();
}
return mesh().getObjectPtr<surfMesh>(lookupName);
}
Foam::surfMesh* Foam::sampledSurface::storeSurfMesh(word lookupName) const
{
if (lookupName.empty())
{
lookupName = this->name();
}
surfMesh* surfptr = getSurfMesh();
if (!surfptr)
{
// Construct null and add owned by registry
surfptr = new surfMesh(lookupName, mesh());
surfptr->store(); // Add to registry - owned by registry
}
surfptr->copySurface(*this); // Copy in geometry (removes old fields)
return surfptr;
}
bool Foam::sampledSurface::removeSurfMesh(word lookupName) const
{
surfMesh* surfptr = getSurfMesh(lookupName);
if (surfptr)
{
return mesh().checkOut(*surfptr);
}
return false;
}
// ************************************************************************* //

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2004-2010, 2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2004-2010, 2018-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2016 OpenFOAM Foundation
@ -116,4 +116,100 @@ Foam::sampledSurface::pointAverage
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type, class GeoMeshType>
bool Foam::sampledSurface::storeRegistryField
(
const objectRegistry& obr,
const word& fieldName,
const dimensionSet& dims,
const Field<Type>& values,
word lookupName
) const
{
polySurface* surfptr = this->getRegistrySurface(obr, lookupName);
if (surfptr)
{
surfptr->storeField<Type, GeoMeshType>
(
fieldName, dims, values
);
}
return surfptr;
}
template<class Type, class GeoMeshType>
bool Foam::sampledSurface::storeRegistryField
(
const objectRegistry& obr,
const word& fieldName,
const dimensionSet& dims,
Field<Type>&& values,
word lookupName
) const
{
polySurface* surfptr = this->getRegistrySurface(obr, lookupName);
if (surfptr)
{
surfptr->storeField<Type, GeoMeshType>
(
fieldName, dims, std::move(values)
);
}
return surfptr;
}
template<class Type, class GeoMeshType>
bool Foam::sampledSurface::storeSurfMeshField
(
const word& fieldName,
const dimensionSet& dims,
const Field<Type>& values,
word lookupName
) const
{
surfMesh* surfptr = this->getSurfMesh(lookupName);
if (surfptr)
{
surfptr->storeField<Type, GeoMeshType>
(
fieldName, dims, values
);
}
return surfptr;
}
template<class Type, class GeoMeshType>
bool Foam::sampledSurface::storeSurfMeshField
(
const word& fieldName,
const dimensionSet& dims,
Field<Type>&& values,
word lookupName
) const
{
surfMesh* surfptr = this->getSurfMesh(lookupName);
if (surfptr)
{
surfptr->storeField<Type, GeoMeshType>
(
fieldName, dims, std::move(values)
);
}
return surfptr;
}
// ************************************************************************* //

View File

@ -26,15 +26,15 @@ License
\*---------------------------------------------------------------------------*/
#include "sampledSurfaces.H"
#include "volFields.H"
#include "dictionary.H"
#include "Time.H"
#include "IOmanip.H"
#include "interpolationCell.H"
#include "volPointInterpolation.H"
#include "PatchTools.H"
#include "polySurface.H"
#include "mapPolyMesh.H"
#include "sampledTriSurfaceMesh.H"
#include "stringListOps.H"
#include "volFields.H"
#include "HashOps.H"
#include "PstreamCombineReduceOps.H"
#include "Time.H"
#include "UIndirectList.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -51,66 +51,154 @@ namespace Foam
);
}
bool Foam::sampledSurfaces::verbose_ = false;
Foam::scalar Foam::sampledSurfaces::mergeTol_ = 1e-10;
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::sampledSurfaces::writeGeometry() const
Foam::polySurface* Foam::sampledSurfaces::getRegistrySurface
(
const sampledSurface& s
) const
{
// Write to time directory under outputPath_
// Skip surfaces without faces (eg, a failed cut-plane)
return s.getRegistrySurface
(
storedObjects(),
IOobject::groupName(name(), s.name())
);
}
const fileName outputDir = outputPath_/time_.timeName();
forAll(*this, surfi)
Foam::polySurface* Foam::sampledSurfaces::storeRegistrySurface
(
const sampledSurface& s
)
{
return s.storeRegistrySurface
(
storedObjects(),
IOobject::groupName(name(), s.name())
);
}
bool Foam::sampledSurfaces::removeRegistrySurface
(
const sampledSurface& s
)
{
return s.removeRegistrySurface
(
storedObjects(),
IOobject::groupName(name(), s.name())
);
}
void Foam::sampledSurfaces::countFields()
{
wordList allFields; // Just needed for warnings
HashTable<wordHashSet> selected;
if (loadFromFiles_)
{
const sampledSurface& s = operator[](surfi);
// Check files for a particular time
IOobjectList objects(obr_, obr_.time().timeName());
allFields = objects.names();
selected = objects.classes(fieldSelection_);
}
else
{
// Check currently available fields
allFields = obr_.names();
selected = obr_.classes(fieldSelection_);
}
if (Pstream::parRun())
{
if (Pstream::master() && mergedList_[surfi].size())
Pstream::mapCombineGather(selected, HashSetOps::plusEqOp<word>());
Pstream::mapCombineScatter(selected);
}
DynamicList<label> missed(fieldSelection_.size());
// Detect missing fields
forAll(fieldSelection_, i)
{
formatter_->write
if (findStrings(fieldSelection_[i], allFields).empty())
{
missed.append(i);
}
}
if (missed.size())
{
WarningInFunction
<< nl
<< "Cannot find "
<< (loadFromFiles_ ? "field file" : "registered field")
<< " matching "
<< UIndirectList<wordRe>(fieldSelection_, missed) << endl;
}
// Currently only support volume and surface field types
label nVolumeFields = 0;
label nSurfaceFields = 0;
forAllConstIters(selected, iter)
{
const word& clsName = iter.key();
const label n = iter.val().size();
if (fieldTypes::volume.found(clsName))
{
nVolumeFields += n;
}
else if (sampledSurface::surfaceFieldTypes.found(clsName))
{
nSurfaceFields += n;
}
}
// Now propagate field counts (per surface)
label surfi = 0;
for (const sampledSurface& s : surfaces())
{
writers_[surfi].nFields() =
(
outputDir,
s.name(),
mergedList_[surfi]
nVolumeFields
+ (s.withSurfaceFields() ? nSurfaceFields : 0)
+ ((s.hasFaceIds() && !s.interpolate()) ? 1 : 0)
);
}
}
else if (s.faces().size())
{
formatter_->write(outputDir, s.name(), s);
}
++surfi;
}
}
void Foam::sampledSurfaces::writeOriginalIds()
Foam::autoPtr<Foam::surfaceWriter> Foam::sampledSurfaces::newWriter
(
word writeType,
const dictionary& formatOptions,
const dictionary& surfDict
)
{
const word fieldName = "Ids";
const fileName outputDir = outputPath_/time_.timeName();
// Per-surface adjustment
surfDict.readIfPresent<word>("surfaceFormat", writeType);
forAll(*this, surfi)
{
const sampledSurface& s = operator[](surfi);
dictionary options = formatOptions.subOrEmptyDict(writeType);
if (s.hasFaceIds())
{
const labelList& idLst = s.originalIds();
options.merge
(
surfDict.subOrEmptyDict("formatOptions").subOrEmptyDict(writeType)
);
// Transcribe from label to scalar
Field<scalar> ids(idLst.size());
forAll(idLst, i)
{
ids[i] = idLst[i];
}
writeSurface(ids, surfi, fieldName, outputDir);
}
}
return surfaceWriter::New(writeType, options);
}
@ -126,6 +214,8 @@ Foam::sampledSurfaces::sampledSurfaces
functionObjects::fvMeshFunctionObject(name, runTime, dict),
PtrList<sampledSurface>(),
loadFromFiles_(false),
verbose_(false),
onExecute_(false),
outputPath_
(
time_.globalPath()/functionObject::outputPrefix/name
@ -133,9 +223,9 @@ Foam::sampledSurfaces::sampledSurfaces
fieldSelection_(),
sampleFaceScheme_(),
sampleNodeScheme_(),
mergedList_(),
changedGeom_(),
formatter_(nullptr)
writers_(),
actions_(),
nFaces_()
{
outputPath_.clean(); // Remove unneeded ".."
@ -154,6 +244,8 @@ Foam::sampledSurfaces::sampledSurfaces
functionObjects::fvMeshFunctionObject(name, obr, dict),
PtrList<sampledSurface>(),
loadFromFiles_(loadFromFiles),
verbose_(false),
onExecute_(false),
outputPath_
(
time_.globalPath()/functionObject::outputPrefix/name
@ -161,9 +253,9 @@ Foam::sampledSurfaces::sampledSurfaces
fieldSelection_(),
sampleFaceScheme_(),
sampleNodeScheme_(),
mergedList_(),
changedGeom_(),
formatter_(nullptr)
writers_(),
actions_(),
nFaces_()
{
outputPath_.clean(); // Remove unneeded ".."
@ -179,60 +271,19 @@ void Foam::sampledSurfaces::verbose(const bool verbosity)
}
bool Foam::sampledSurfaces::execute()
{
return true;
}
bool Foam::sampledSurfaces::write()
{
if (empty())
{
return true;
}
// Finalize surfaces, merge points etc.
update();
const label nFields = classifyFields();
// Write geometry first if required,
// or when no fields would otherwise be written
if (formatter_->separateGeometry() || !nFields)
{
writeGeometry();
changedGeom_ = false;
}
const IOobjectList objects(obr_, obr_.time().timeName());
sampleAndWrite<volScalarField>(objects);
sampleAndWrite<volVectorField>(objects);
sampleAndWrite<volSphericalTensorField>(objects);
sampleAndWrite<volSymmTensorField>(objects);
sampleAndWrite<volTensorField>(objects);
sampleAndWrite<surfaceScalarField>(objects);
sampleAndWrite<surfaceVectorField>(objects);
sampleAndWrite<surfaceSphericalTensorField>(objects);
sampleAndWrite<surfaceSymmTensorField>(objects);
sampleAndWrite<surfaceTensorField>(objects);
return true;
}
bool Foam::sampledSurfaces::read(const dictionary& dict)
{
fvMeshFunctionObject::read(dict);
PtrList<sampledSurface>::clear();
mergedList_.clear();
changedGeom_.clear();
writers_.clear();
actions_.clear();
nFaces_.clear();
fieldSelection_.clear();
verbose_ = dict.lookupOrDefault("verbose", false);
onExecute_ = dict.lookupOrDefault("sampleOnExecute", false);
sampleFaceScheme_ =
dict.lookupOrDefault<word>("sampleScheme", "cell");
@ -241,82 +292,160 @@ bool Foam::sampledSurfaces::read(const dictionary& dict)
const entry* eptr = dict.findEntry("surfaces");
// Surface writer type and format options
const word writerType =
(eptr ? dict.get<word>("surfaceFormat") : word::null);
const dictionary formatOptions(dict.subOrEmptyDict("formatOptions"));
// Store on registry?
const bool dfltStore = dict.lookupOrDefault("store", false);
if (eptr && eptr->isDict())
{
PtrList<sampledSurface> surfs(eptr->dict().size());
actions_.resize(surfs.size(), ACTION_WRITE); // Default action
writers_.resize(surfs.size());
nFaces_.resize(surfs.size(), Zero);
label surfi = 0;
for (const entry& dEntry : eptr->dict())
{
if (dEntry.isDict())
if (!dEntry.isDict())
{
continue;
}
const dictionary& surfDict = dEntry.dict();
autoPtr<sampledSurface> surf =
sampledSurface::New
(
dEntry.keyword(),
mesh_,
dEntry.dict()
surfDict
);
if (surf.valid() && surf->enabled())
if (!surf.valid() || !surf->enabled())
{
continue;
}
// Define the surface
surfs.set(surfi, surf);
// Define additional action(s)
if (surfDict.lookupOrDefault("store", dfltStore))
{
actions_[surfi] |= ACTION_STORE;
}
if (surfDict.lookupOrDefault("surfMeshStore", false))
{
actions_[surfi] |= ACTION_SURF_MESH;
}
// Define surface writer, but do NOT yet attach a surface
writers_.set
(
surfi,
newWriter(writerType, formatOptions, surfDict)
);
writers_[surfi].isPointData() = surfs[surfi].interpolate();
// Use outputDir/TIME/surface-name
writers_[surfi].useTimeDir() = true;
writers_[surfi].verbose() = verbose_;
++surfi;
}
}
}
surfs.resize(surfi);
actions_.resize(surfi);
writers_.resize(surfi);
surfaces().transfer(surfs);
}
else if (eptr)
{
PtrList<sampledSurface> surfs
// This is slightly trickier.
// We want access to the individual dictionaries used for construction
DynamicList<dictionary> capture;
PtrList<sampledSurface> input
(
eptr->stream(),
sampledSurface::iNew(mesh_)
sampledSurface::iNewCapture(mesh_, capture)
);
forAll(surfs, surfi)
PtrList<sampledSurface> surfs(input.size());
actions_.resize(surfs.size(), ACTION_WRITE); // Default action
writers_.resize(surfs.size());
nFaces_.resize(surfs.size(), Zero);
label surfi = 0;
forAll(input, inputi)
{
if (!surfs[surfi].enabled())
const dictionary& surfDict = capture[inputi];
autoPtr<sampledSurface> surf = input.set(inputi, nullptr);
if (!surf.valid() || !surf->enabled())
{
surfs.set(surfi, nullptr);
}
continue;
}
surfs.resize(surfs.squeezeNull());
// Define the surface
surfs.set(surfi, surf);
// Define additional action(s)
if (surfDict.lookupOrDefault("store", dfltStore))
{
actions_[surfi] |= ACTION_STORE;
}
if (surfDict.lookupOrDefault("surfMeshStore", false))
{
actions_[surfi] |= ACTION_SURF_MESH;
}
// Define surface writer, but do NOT yet attach a surface
writers_.set
(
surfi,
newWriter(writerType, formatOptions, surfDict)
);
writers_[surfi].isPointData() = surfs[surfi].interpolate();
// Use outputDir/TIME/surface-name
writers_[surfi].useTimeDir() = true;
writers_[surfi].verbose() = verbose_;
++surfi;
}
surfs.resize(surfi);
actions_.resize(surfi);
writers_.resize(surfi);
surfaces().transfer(surfs);
}
const auto& surfs = surfaces();
// Have some surfaces, so sort out which fields are needed and report
if (surfs.size())
{
nFaces_.resize(surfs.size(), Zero);
dict.readEntry("fields", fieldSelection_);
fieldSelection_.uniq();
// The surface writer and format options
const word writerType(dict.get<word>("surfaceFormat"));
// Define the surface formatter
// Optionally defined extra controls for the output formats
formatter_ = surfaceWriter::New
(
writerType,
dict.subOrEmptyDict("formatOptions").subOrEmptyDict(writerType)
);
if (Pstream::parRun())
{
mergedList_.resize(size());
}
// Ensure all surfaces and merge information are expired
expire();
label surfi = 0;
for (const sampledSurface& s : surfs)
{
@ -324,7 +453,18 @@ bool Foam::sampledSurfaces::read(const dictionary& dict)
{
Info<< "Sampled surface:" << nl;
}
Info<< " " << s.name() << " -> " << writerType << nl;
Info<< " " << s.name() << " -> " << writers_[surfi].type();
if (actions_[surfi] & ACTION_STORE)
{
Info<< ", store on registry ("
<< IOobject::groupName(name(), s.name()) << ')';
}
if (actions_[surfi] & ACTION_SURF_MESH)
{
Info<< ", store as surfMesh (deprecated)";
}
Info<< nl;
++surfi;
}
@ -334,24 +474,171 @@ bool Foam::sampledSurfaces::read(const dictionary& dict)
if (debug && Pstream::master())
{
Pout<< "sample fields:" << fieldSelection_ << nl
<< "sample surfaces:" << nl << "(" << nl;
<< "sample surfaces:" << nl << '(' << nl;
for (const sampledSurface& s : surfaces())
{
Pout<< " " << s << nl;
}
Pout<< ")" << endl;
Pout<< ')' << endl;
}
// New geometry
changedGeom_.resize(size());
changedGeom_ = true;
// Ensure all surfaces and merge information are expired
expire();
return true;
}
bool Foam::sampledSurfaces::performAction(unsigned request)
{
if
(
empty()
|| (request == ACTION_NONE)
|| !testAny
(
actions_,
[=] (unsigned action) { return (request & action); }
)
)
{
return true;
}
// Finalize surfaces, update information, writer associations etc.
update();
bool noFaces = true;
for (const label n : nFaces_)
{
if (n) noFaces = false;
}
if (noFaces)
{
// No surfaces with faces at all.
return true;
}
// Determine the per-surface number of fields, including Ids etc.
// Only seems to be needed for VTK legacy
countFields();
forAll(*this, surfi)
{
const sampledSurface& s = (*this)[surfi];
if (!nFaces_[surfi])
{
continue;
}
if ((request & actions_[surfi]) & ACTION_STORE)
{
storeRegistrySurface(s);
}
if ((request & actions_[surfi]) & ACTION_SURF_MESH)
{
s.storeSurfMesh();
}
if ((request & actions_[surfi]) & ACTION_WRITE)
{
// Output writers
surfaceWriter& outWriter = writers_[surfi];
if (outWriter.needsUpdate())
{
outWriter.setSurface(s);
}
outWriter.open(outputPath_/s.name());
outWriter.beginTime(obr_.time());
// Write geometry if no fields would otherwise be written
if (!outWriter.nFields() || outWriter.separateGeometry())
{
outWriter.writeGeometry();
continue;
}
// Write original ids - as label or scalar field
const word fieldName("Ids");
if (s.hasFaceIds() && !s.interpolate())
{
writeSurface
(
outWriter,
Field<label>(s.originalIds()),
fieldName
);
}
}
}
const IOobjectList objects(obr_, obr_.time().timeName());
performAction<volScalarField>(objects, request);
performAction<volVectorField>(objects, request);
performAction<volSphericalTensorField>(objects, request);
performAction<volSymmTensorField>(objects, request);
performAction<volTensorField>(objects, request);
// Only bother with surface fields if a sampler supports them
if
(
testAny
(
surfaces(),
[] (const sampledSurface& s) { return s.withSurfaceFields(); }
)
)
{
performAction<surfaceScalarField>(objects, request);
performAction<surfaceVectorField>(objects, request);
performAction<surfaceSphericalTensorField>(objects, request);
performAction<surfaceSymmTensorField>(objects, request);
performAction<surfaceTensorField>(objects, request);
}
// Finish this time step
forAll(writers_, surfi)
{
if ((request & actions_[surfi]) & ACTION_WRITE)
{
writers_[surfi].endTime();
}
}
return true;
}
bool Foam::sampledSurfaces::execute()
{
if (onExecute_)
{
return performAction(ACTION_ALL & ~ACTION_WRITE);
}
return true;
}
bool Foam::sampledSurfaces::write()
{
return performAction(ACTION_ALL);
}
void Foam::sampledSurfaces::updateMesh(const mapPolyMesh& mpm)
{
if (&mpm.mesh() == &mesh_)
@ -383,9 +670,9 @@ void Foam::sampledSurfaces::readUpdate(const polyMesh::readUpdateState state)
bool Foam::sampledSurfaces::needsUpdate() const
{
forAll(*this, surfi)
for (const sampledSurface& s : surfaces())
{
if (operator[](surfi).needsUpdate())
if (s.needsUpdate())
{
return true;
}
@ -397,26 +684,29 @@ bool Foam::sampledSurfaces::needsUpdate() const
bool Foam::sampledSurfaces::expire()
{
bool justExpired = false;
// Dimension as fraction of mesh bounding box
const scalar mergeDim = mergeTol_ * mesh_.bounds().mag();
forAll(*this, surfi)
label nChanged = 0;
label surfi = 0;
for (sampledSurface& s : surfaces())
{
if (operator[](surfi).expire())
if (s.expire())
{
justExpired = true;
++nChanged;
}
// Clear merge information
if (Pstream::parRun())
{
mergedList_[surfi].clear();
}
writers_[surfi].expire();
writers_[surfi].mergeDim() = mergeDim;
nFaces_[surfi] = 0;
++surfi;
}
changedGeom_ = true;
// true if any surfaces just expired
return justExpired;
// True if any surfaces just expired
return nChanged;
}
@ -427,48 +717,24 @@ bool Foam::sampledSurfaces::update()
return false;
}
bool updated = false;
label nUpdated = 0;
// Serial: quick and easy, no merging required
if (!Pstream::parRun())
{
forAll(*this, surfi)
{
sampledSurface& s = operator[](surfi);
label surfi = 0;
for (sampledSurface& s : surfaces())
{
if (s.update())
{
updated = true;
changedGeom_[surfi] = true;
}
++nUpdated;
writers_[surfi].expire();
}
return updated;
nFaces_[surfi] = returnReduce(s.faces().size(), sumOp<label>());
++surfi;
}
// Dimension as fraction of mesh bounding box
const scalar mergeDim = mergeTol_*mesh_.bounds().mag();
if (Pstream::master() && debug)
{
Pout<< nl << "Merging all points within "
<< mergeDim << " metre" << endl;
}
forAll(*this, surfi)
{
sampledSurface& s = operator[](surfi);
if (s.update())
{
updated = true;
changedGeom_[surfi] = true;
mergedList_[surfi].merge(s, mergeDim);
}
}
return updated;
return nUpdated;
}

View File

@ -53,8 +53,12 @@ Description
// (only used if interpolate=true for the surfaces below)
interpolationScheme cell;
// Optional: registry storage
store true
// Output surface format
surfaceFormat vtk;
formatOptions
{
vtk
@ -76,6 +80,12 @@ Description
// Optional: generate values on points instead of faces
interpolate true;
// Optional: alternative output type
surfaceFormat ensight;
// Optional: registry storage
store true
}
);
}
@ -84,13 +94,24 @@ Description
Entries:
\table
Property | Description | Required | Default
type | surfaces | yes |
surfaces | list or dictionary of sample surfaces | recommended |
fields | word/regex list of fields to sampled | yes |
type | Type-name: surfaces | yes |
surfaces | Dictionary or list of sample surfaces | expected |
fields | word/regex list of fields to sample | yes |
sampleScheme | scheme to obtain face centre value | no | cell
interpolationScheme | scheme to obtain node values | no | cellPoint
surfaceFormat | output surface format | yes |
formatOptions | dictionary of format options | no |
sampleOnExecute | Sample (store) on execution as well | no | false
store | Store surface/fields on registry | no | false
\endtable
Additional per-surface entries:
\table
Property | Description | Required | Default
store | Store surface/fields on registry | no |
surfaceFormat | output surface format | no |
formatOptions | dictionary of format options | no |
surfMeshStore | Store surface/fields as surfMesh (transitional) | no |
\endtable
Note
@ -111,10 +132,8 @@ SourceFiles
#include "fvMeshFunctionObject.H"
#include "sampledSurface.H"
#include "surfaceWriter.H"
#include "mergedSurf.H"
#include "volFieldsFwd.H"
#include "surfaceFieldsFwd.H"
#include "wordRes.H"
#include "IOobjectList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -122,6 +141,9 @@ SourceFiles
namespace Foam
{
// Forward Declarations
class polySurface;
/*---------------------------------------------------------------------------*\
Class sampledSurfaces Declaration
\*---------------------------------------------------------------------------*/
@ -133,23 +155,36 @@ class sampledSurfaces
{
// Static Data Members
//- Output verbosity
static bool verbose_;
//- Tolerance for merging points (fraction of mesh bounding box)
static scalar mergeTol_;
//- Local control for sampling actions
enum sampleActionType : unsigned
{
ACTION_NONE = 0,
ACTION_WRITE = 0x1,
ACTION_STORE = 0x2,
ACTION_SURF_MESH = 0x4,
ACTION_ALL = 0xF
};
// Private Data
//- Load fields from files (not from objectRegistry)
const bool loadFromFiles_;
//- Output verbosity
bool verbose_;
//- Perform sample/store actions on execute as well
bool onExecute_;
//- Output path
fileName outputPath_;
// Read from dictonary
// Read from dictionary
//- Names of fields to sample
wordRes fieldSelection_;
@ -161,19 +196,16 @@ class sampledSurfaces
word sampleNodeScheme_;
// Surfaces
// Output control
//- Merged meshed surfaces (parallel only)
List<mergedSurf> mergedList_;
//- Surface writers (one per surface)
PtrList<surfaceWriter> writers_;
//- Track which surfaces have changed
List<bool> changedGeom_;
//- Per-surface selection of store/write actions
List<unsigned> actions_;
// Calculated
//- Surface formatter
autoPtr<surfaceWriter> formatter_;
//- Cached values of the global number of faces per-surface
labelList nFaces_;
// Private Member Functions
@ -190,42 +222,82 @@ class sampledSurfaces
return *this;
}
//- Return number of fields
label classifyFields();
//- A new surfaceWriter, with per-surface formatOptions
static autoPtr<surfaceWriter> newWriter
(
word writeType,
const dictionary& formatOptions,
const dictionary& surfDict
);
//- Write geometry only
void writeGeometry() const;
//- Write scalar field with original ids
void writeOriginalIds();
//- Perform sampling action with store/write
bool performAction(unsigned request);
//- Count selected/sampled fields per surface
void countFields();
//- Write sampled fieldName on surface and on outputDir path
template<class Type>
void writeSurface
(
surfaceWriter& writer,
const Field<Type>& values,
const label surfi,
const word& fieldName
);
//- Sample and store/write a specific volume field
template<class Type>
void performAction
(
const GeometricField<Type, fvPatchField, volMesh>& fld,
unsigned request
);
//- Sample and store/write a specific surface field
template<class Type>
void performAction
(
const GeometricField<Type, fvsPatchField, surfaceMesh>& fld,
unsigned request
);
//- Sample and write all applicable sampled fields
template<class GeoField>
void performAction
(
const IOobjectList& objects,
unsigned request
);
//- Get surface from registry if available.
// \return surface or nullptr
polySurface* getRegistrySurface(const sampledSurface& s) const;
//- Put surface onto registry, when enabled.
// \return surface or nullptr it surface should not be stored
polySurface* storeRegistrySurface(const sampledSurface& s);
//- Remove surface from registry.
// \return True if surface existed and was removed
bool removeRegistrySurface(const sampledSurface& s);
//- Store sampled field onto surface registry if it exists
template<class Type, class GeoMeshType>
bool storeRegistryField
(
const sampledSurface& s,
const word& fieldName,
const fileName& outputDir
const dimensionSet& dims,
Field<Type>&& values
);
//- Sample and write a particular volume field
template<class Type>
void sampleAndWrite
(
const GeometricField<Type, fvPatchField, volMesh>& vField
);
//- Sample and write a particular surface field
template<class Type>
void sampleAndWrite
(
const GeometricField<Type, fvsPatchField, surfaceMesh>& sField
);
//- Sample and write all sampled fields
template<class Type> void sampleAndWrite(const IOobjectList& objects);
//- Test surfaces for condition
template<class Container, class Predicate>
static bool testAny(const Container& items, const Predicate& pred);
//- No copy construct
sampledSurfaces(const sampledSurfaces&) = delete;

View File

@ -1,89 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2004-2010, 2017 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2015 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 "sampledSurfaces.H"
#include "IOobjectList.H"
#include "UIndirectList.H"
#include "ListOps.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::label Foam::sampledSurfaces::classifyFields()
{
label nFields = 0;
wordList allFields; // Just needed for warnings
HashTable<wordHashSet> available;
if (loadFromFiles_)
{
// Check files for a particular time
IOobjectList objects(obr_, obr_.time().timeName());
allFields = objects.names();
available = objects.classes(fieldSelection_);
}
else
{
// Check currently available fields
allFields = obr_.names();
available = obr_.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;
}
// Total number selected
forAllConstIters(available, iter)
{
nFields += iter.val().size();
}
return nFields;
}
// ************************************************************************* //

View File

@ -28,91 +28,23 @@ License
#include "sampledSurfaces.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "globalIndex.H"
#include "stringListOps.H"
#include "polySurface.H"
#include "polySurfaceFields.H"
#include "polySurfacePointFields.H"
#include "surfMesh.H"
#include "surfGeoMesh.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class Type>
void Foam::sampledSurfaces::writeSurface
(
surfaceWriter& writer,
const Field<Type>& values,
const label surfi,
const word& fieldName,
const fileName& outputDir
const word& fieldName
)
{
const sampledSurface& s = operator[](surfi);
if (changedGeom_[surfi])
{
// Trigger any changes
formatter_->updateMesh(outputDir, s.name());
changedGeom_[surfi] = false;
}
if (Pstream::parRun())
{
// Gather all values into single field
Field<Type> allValues;
globalIndex::gatherOp(values, allValues);
fileName sampleFile;
if (Pstream::master())
{
// Renumber (point data) to correspond to merged points
if (mergedList_[surfi].pointsMap().size() == allValues.size())
{
inplaceReorder(mergedList_[surfi].pointsMap(), allValues);
allValues.resize(mergedList_[surfi].points().size());
}
// Write to time directory under outputPath_
// skip surface without faces (eg, a failed cut-plane)
if (mergedList_[surfi].size())
{
sampleFile = formatter_->write
(
outputDir,
s.name(),
mergedList_[surfi],
fieldName,
allValues,
s.interpolate()
);
}
}
Pstream::scatter(sampleFile);
if (sampleFile.size())
{
// Case-local file name with "<case>" to make relocatable
dictionary propsDict;
propsDict.add
(
"file",
time_.relativePath(sampleFile, true)
);
setProperty(fieldName, propsDict);
}
}
else
{
// Write to time directory under outputPath_
// skip surface without faces (eg, a failed cut-plane)
if (s.faces().size())
{
fileName fName = formatter_->write
(
outputDir,
s.name(),
s,
fieldName,
values,
s.interpolate()
);
fileName outputName = writer.write(fieldName, values);
// Case-local file name with "<case>" to make relocatable
@ -120,18 +52,37 @@ void Foam::sampledSurfaces::writeSurface
propsDict.add
(
"file",
time_.relativePath(fName, true)
time_.relativePath(outputName, true)
);
setProperty(fieldName, propsDict);
}
}
}
template<class Type, class GeoMeshType>
bool Foam::sampledSurfaces::storeRegistryField
(
const sampledSurface& s,
const word& fieldName,
const dimensionSet& dims,
Field<Type>&& values
)
{
return s.storeRegistryField<Type, GeoMeshType>
(
storedObjects(),
fieldName,
dims,
std::move(values),
IOobject::groupName(name(), s.name())
);
}
template<class Type>
void Foam::sampledSurfaces::sampleAndWrite
void Foam::sampledSurfaces::performAction
(
const GeometricField<Type, fvPatchField, volMesh>& vField
const GeometricField<Type, fvPatchField, volMesh>& fld,
unsigned request
)
{
// The sampler for this field
@ -140,13 +91,20 @@ void Foam::sampledSurfaces::sampleAndWrite
// The interpolator for this field
autoPtr<interpolation<Type>> interpPtr;
const word& fieldName = vField.name();
const fileName outputDir = outputPath_/vField.time().timeName();
const word& fieldName = fld.name();
const dimensionSet& dims = fld.dimensions();
forAll(*this, surfi)
{
const sampledSurface& s = operator[](surfi);
// Skip surface without faces (eg, failed cut-plane)
if (!nFaces_[surfi])
{
continue;
}
Field<Type> values;
if (s.interpolate())
@ -156,7 +114,7 @@ void Foam::sampledSurfaces::sampleAndWrite
interpPtr = interpolation<Type>::New
(
sampleNodeScheme_,
vField
fld
);
}
@ -169,56 +127,117 @@ void Foam::sampledSurfaces::sampleAndWrite
samplePtr = interpolation<Type>::New
(
sampleFaceScheme_,
vField
fld
);
}
values = s.sample(*samplePtr);
}
writeSurface<Type>(values, surfi, fieldName, outputDir);
if ((request & actions_[surfi]) & ACTION_WRITE)
{
writeSurface<Type>(writers_[surfi], values, fieldName);
}
if ((request & actions_[surfi]) & ACTION_SURF_MESH)
{
// Face fields only!
s.storeSurfMeshField<Type, surfGeoMesh>
(
fieldName, dims, values
);
}
if ((request & actions_[surfi]) & ACTION_STORE)
{
if (s.interpolate())
{
storeRegistryField<Type, polySurfacePointGeoMesh>
(
s, fieldName, dims, std::move(values)
);
}
else
{
storeRegistryField<Type, polySurfaceGeoMesh>
(
s, fieldName, dims, std::move(values)
);
}
}
}
}
template<class Type>
void Foam::sampledSurfaces::sampleAndWrite
void Foam::sampledSurfaces::performAction
(
const GeometricField<Type, fvsPatchField, surfaceMesh>& sField
const GeometricField<Type, fvsPatchField, surfaceMesh>& fld,
unsigned request
)
{
const word& fieldName = sField.name();
const fileName outputDir = outputPath_/sField.time().timeName();
const word& fieldName = fld.name();
const dimensionSet& dims = fld.dimensions();
forAll(*this, surfi)
{
const sampledSurface& s = operator[](surfi);
Field<Type> values(s.sample(sField));
writeSurface<Type>(values, surfi, fieldName, outputDir);
const sampledSurface& s = (*this)[surfi];
// Skip surface without faces (eg, failed cut-plane)
if (!nFaces_[surfi])
{
continue;
}
Field<Type> values(s.sample(fld));
if ((request & actions_[surfi]) & ACTION_WRITE)
{
writeSurface<Type>(writers_[surfi], values, fieldName);
}
if ((request & actions_[surfi]) & ACTION_SURF_MESH)
{
s.storeSurfMeshField<Type, surfGeoMesh>
(
fieldName, dims, values
);
}
if ((request & actions_[surfi]) & ACTION_STORE)
{
storeRegistryField<Type, polySurfaceGeoMesh>
(
s, fieldName, dims, std::move(values)
);
}
}
}
template<class GeoField>
void Foam::sampledSurfaces::sampleAndWrite(const IOobjectList& objects)
void Foam::sampledSurfaces::performAction
(
const IOobjectList& objects,
unsigned request
)
{
wordList fieldNames;
if (loadFromFiles_)
{
fieldNames = objects.sortedNames(GeoField::typeName, fieldSelection_);
fieldNames = objects.sortedNames<GeoField>(fieldSelection_);
}
else
{
fieldNames = mesh_.thisDb().sortedNames<GeoField>(fieldSelection_);
writeOriginalIds();
}
for (const word& fieldName : fieldNames)
{
if (verbose_)
{
Info<< "sampleAndWrite: " << fieldName << endl;
Info<< "sampleWrite: " << fieldName << endl;
}
if (loadFromFiles_)
@ -235,17 +254,37 @@ void Foam::sampledSurfaces::sampleAndWrite(const IOobjectList& objects)
mesh_
);
sampleAndWrite(fld);
performAction(fld, request);
}
else
{
sampleAndWrite
performAction
(
mesh_.thisDb().lookupObject<GeoField>(fieldName)
mesh_.thisDb().lookupObject<GeoField>(fieldName),
request
);
}
}
}
template<class Container, class Predicate>
bool Foam::sampledSurfaces::testAny
(
const Container& items,
const Predicate& pred
)
{
for (const auto& item : items)
{
if (pred(item))
{
return true;
}
}
return false;
}
// ************************************************************************* //

View File

@ -1,116 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 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 "boundaryDataSurfaceWriter.H"
#include "makeSurfaceWriterMethods.H"
#include "argList.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
makeSurfaceWriterType(boundaryDataSurfaceWriter);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Field writing implementation
#include "boundaryDataSurfaceWriterImpl.C"
// Field writing methods
defineSurfaceWriterWriteFields(Foam::boundaryDataSurfaceWriter);
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::fileName Foam::boundaryDataSurfaceWriter::write
(
const fileName& outputDir,
const fileName& surfaceName,
const meshedSurf& surf,
const bool verbose
) const
{
// geometry: rootdir/surfaceName/"points"
// field: rootdir/surfaceName/time/field
const fileName baseDir(outputDir.path()/surfaceName);
const fileName timeName(outputDir.name());
const pointField& points = surf.points();
// Dummy time to use as an objectRegistry
const fileName caseDir(argList::envGlobalPath());
Time dummyTime
(
caseDir.path(), // root-path,
caseDir.name(), // case-name,
"system", //
"constant", //
false // no function objects
);
// Write points
if (verbose)
{
Info<< "Writing points to " << baseDir/"points" << endl;
}
pointIOField pts
(
IOobject
(
baseDir/"points",
dummyTime,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
points
);
{
// Do like regIOobject::writeObject but don't do instance() adaptation
// since this would write to e.g. 0/ instead of postProcessing/
// Try opening an OFstream for object
mkDir(pts.path());
OFstream os(pts.objectPath());
//pts.writeHeader(os);
pts.writeData(os);
//pts.writeEndDivider(os);
}
return baseDir;
}
// ************************************************************************* //

View File

@ -1,231 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2016 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::boundaryDataSurfaceWriter
Description
A surfaceWriter for outputting to a form useable for the
timeVaryingMapped boundary condition. This reads the data from
constant/boundaryData/\<patch\> directory
Typical way of working:
- use a sampledSurface of type 'patch' (to sample a patch):
\verbatim
surfaces
{
type surfaces;
surfaceFormat boundaryData;
fields ( p );
surfaces
(
outlet
{
type patch;
patches (outlet);
interpolate false;
}
);
}
\endverbatim
- write using this writer.
- move postProcessing/surfaces/outlet to constant/boundaryData/outlet
in your destination case.
- use a timeVaryingMappedFixedValue condition to read and interpolate
the profile:
type timeVaryingMappedFixedValue;
setAverage false; // do not use read average
offset 0; // do not apply offset to values
Note:
- with 'interpolate false' the data is on the face centres of the
patch. Take care that a 2D geometry will only have a single row
of face centres so might not provide a valid triangulation
(this is what timeVaryingMappedFixedValue uses to do interpolation)
(Alternatively use timeVaryingMappedFixedValue with mapMethod 'nearest')
\heading Output file locations
The \c rootdir normally corresponds to something like
\c postProcessing/\<name\>
where the geometry is written as:
\verbatim
rootdir
`-- surfaceName
`-- "points"
\endverbatim
and field data:
\verbatim
rootdir
`-- surfaceName
|-- "points"
`-- timeName
`-- field
\endverbatim
SourceFiles
boundaryDataSurfaceWriter.C
\*---------------------------------------------------------------------------*/
#ifndef boundaryDataSurfaceWriter_H
#define boundaryDataSurfaceWriter_H
#include "surfaceWriter.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class boundaryDataSurfaceWriter Declaration
\*---------------------------------------------------------------------------*/
class boundaryDataSurfaceWriter
:
public surfaceWriter
{
// Private Member Functions
//- Templated write operation
template<class Type>
fileName writeTemplate
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<Type>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const;
public:
//- Runtime type information
TypeName("boundaryData");
// Constructors
//- Construct null
boundaryDataSurfaceWriter() = default;
//- Destructor
virtual ~boundaryDataSurfaceWriter() = default;
// Member Functions
//- Write single surface geometry to file.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write scalarField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<scalar>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write vectorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<vector>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write sphericalTensorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<sphericalTensor>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write symmTensorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<symmTensor>& values,//!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write tensorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<tensor>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,132 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify i
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 "OFstream.H"
#include "OSspecific.H"
#include "IOmanip.H"
#include "Time.H"
#include "pointIOField.H"
#include "primitivePatch.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class Type>
Foam::fileName Foam::boundaryDataSurfaceWriter::writeTemplate
(
const fileName& outputDir,
const fileName& surfaceName,
const meshedSurf& surf,
const word& fieldName,
const Field<Type>& values,
const bool isNodeValues,
const bool verbose
) const
{
// geometry: rootdir/surfaceName/"points"
// field: rootdir/surfaceName/time/field
const fileName baseDir(outputDir.path()/surfaceName);
const fileName timeName(outputDir.name());
const pointField& points = surf.points();
const faceList& faces = surf.faces();
// Dummy time to use as an objectRegistry
const fileName caseDir(argList::envGlobalPath());
Time dummyTime
(
caseDir.path(), // root-path
caseDir.name(), // case-name
"system", //
"constant", //
false // no function objects
);
// Write points
pointIOField pts
(
IOobject
(
baseDir/"points",
dummyTime,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
label(0)
);
if (isNodeValues)
{
if (verbose)
{
Info<< "Writing points to " << baseDir/"points" << endl;
}
pts = points;
}
else
{
if (verbose)
{
Info<< "Writing face centres to " << baseDir/"points" << endl;
}
primitivePatch pp(SubList<face>(faces, faces.size()), points);
pts = pp.faceCentres();
}
{
// Do like regIOobject::writeObject but don't do instance() adaptation
// since this would write to e.g. 0/ instead of postProcessing/
// Try opening an OFstream for object
mkDir(pts.path());
OFstream os(pts.objectPath());
//pts.writeHeader(os);
pts.writeData(os);
//pts.writeEndDivider(os);
}
// Write field
{
fileName valsDir(baseDir/timeName);
mkDir(valsDir);
OFstream os(valsDir/fieldName);
os << values;
}
return baseDir;
}
// ************************************************************************* //

View File

@ -1,259 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2010-2011, 2015-2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011 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/>.
Class
Foam::ensightSurfaceWriter
Description
A surfaceWriter 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
ensightSurfaceWriter.C
\*---------------------------------------------------------------------------*/
#ifndef ensightSurfaceWriter_H
#define ensightSurfaceWriter_H
#include "surfaceWriter.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class ensightSurfaceWriter Declaration
\*---------------------------------------------------------------------------*/
class ensightSurfaceWriter
:
public surfaceWriter
{
// Private data
//- Write option (default: IOstream::ASCII)
IOstream::streamFormat writeFormat_;
//- Collate times (default: true)
bool collateTimes_;
// Private Member Functions
//- Print time-set for ensight case file
static void printTimeset
(
OSstream& os,
const label ts,
const scalar& timeValue
);
//- Print time-set for ensight case file
static void printTimeset
(
OSstream& os,
const label ts,
const UList<scalar>& times
);
//- Templated write operation - one file per timestep
template<class Type>
fileName writeCollated
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<Type>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const;
//- Templated write operation - all time steps in single file
template<class Type>
fileName writeUncollated
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<Type>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const;
//- Templated write operation
template<class Type>
fileName writeTemplate
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<Type>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const;
public:
//- Runtime type information
TypeName("ensight");
// Constructors
//- Construct null
ensightSurfaceWriter();
//- Construct with some output options
ensightSurfaceWriter(const dictionary& options);
//- Destructor
virtual ~ensightSurfaceWriter() = default;
// Member Functions
//- True if the surface format supports geometry in a separate file.
// False if geometry and field must be in a single file
virtual bool separateGeometry() const;
//- Trigger for geometry changes.
// \note this is a stop-gap solution
virtual void updateMesh
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName //!< Name of surface
) const; // override
//- Write single surface geometry to file.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write scalarField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<scalar>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write vectorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<vector>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write sphericalTensorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<sphericalTensor>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write symmTensorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<symmTensor>& values,//!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write tensorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<tensor>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,531 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2014 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 "IOmanip.H"
#include "Fstream.H"
#include "OSspecific.H"
#include "ensightCase.H"
#include "ensightPartFaces.H"
#include "ensightOutput.H"
#include "ensightPTraits.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class Type>
Foam::fileName Foam::ensightSurfaceWriter::writeUncollated
(
const fileName& outputDir,
const fileName& surfaceName,
const meshedSurf& surf,
const word& fieldName,
const Field<Type>& values,
const bool isNodeValues,
const bool verbose
) const
{
const ensight::FileName surfName(surfaceName);
const ensight::VarName varName(fieldName);
// geometry: rootdir/time/<field>/surfaceName.case
// geometry: rootdir/time/<field>/surfaceName.<index>.mesh
// field: rootdir/time/<field>/surfaceName.<index>.field
// Variable name as sub-directory for results
// eg, something like this:
// - VAR1/SURF1.case
// - VAR1/SURF1.0000.mesh
// - VAR1/SURF1.0001.VAR1
// - VAR1/SURF2.case
// - VAR1/SURF2.0000.mesh
// - VAR1/SURF2.0001.VAR1
// and
// - VAR2/SURF1.case
// - VAR2/SURF1.0000.mesh
// - VAR2/SURF1.0001.VAR2
const fileName baseDir = outputDir/varName;
const fileName timeDir = outputDir.name();
// Convert timeDir to a value (if possible - use 0.0 otherwise)
scalar timeValue = 0.0;
readScalar(timeDir, timeValue);
if (!isDir(baseDir))
{
mkDir(baseDir);
}
OFstream osCase(baseDir/surfName + ".case", IOstream::ASCII);
// Format options
osCase.setf(ios_base::left);
osCase.setf(ios_base::scientific, ios_base::floatfield);
osCase.precision(5);
ensightGeoFile osGeom
(
baseDir,
surfName + ".00000000.mesh",
writeFormat_
);
ensightFile osField
(
baseDir,
surfName + ".00000000." + varName,
writeFormat_
);
if (verbose)
{
Info<< "Writing case file to " << osCase.name() << endl;
}
osCase
<< "FORMAT" << nl
<< "type: ensight gold" << nl
<< nl
<< "GEOMETRY" << nl
<< "model: 1 " << osGeom.name().name() << nl
<< nl
<< "VARIABLE" << nl
<< ensightPTraits<Type>::typeName
<<
(
isNodeValues
? " per node: 1 " // time-set 1
: " per element: 1 " // time-set 1
)
<< setw(15) << varName << ' '
<< surfName.c_str() << ".********." << varName << nl;
osCase
<< nl
<< "TIME" << nl;
printTimeset(osCase, 1, timeValue);
osCase << "# end" << nl;
ensightPartFaces ensPart
(
0,
osGeom.name().name(),
surf.points(),
surf.faces(),
true // contiguous points
);
osGeom << ensPart;
// Write field
osField.writeKeyword(ensightPTraits<Type>::typeName);
if (isNodeValues)
{
ensightOutput::Serial::writePointField
(
values,
ensPart,
osField
// false // serial
);
}
else
{
ensightOutput::Detail::writeFaceField
(
values,
ensPart,
osField,
false // serial
);
}
return osCase.name();
}
template<class Type>
Foam::fileName Foam::ensightSurfaceWriter::writeCollated
(
const fileName& outputDir,
const fileName& surfaceName,
const meshedSurf& surf,
const word& fieldName,
const Field<Type>& values,
const bool isNodeValues,
const bool verbose
) const
{
const ensight::FileName surfName(surfaceName);
const ensight::VarName varName(fieldName);
// geometry: rootdir/surfaceName/surfaceName.case
// geometry: rootdir/surfaceName/surfaceName/data/<index>/geometry
// field: rootdir/surfaceName/surfaceName/data/<index>/field
// Use surface name as sub-directory for results
// eg, something like this:
// - SURF1/SURF1.case
// - SURF1/SURF1/data/00000000/geometry
// - SURF1/SURF1/data/00000000/VAR1
// - SURF1/SURF1/data/00000000/VAR2
// and
// - SURF2/SURF2.case
// - SURF2/SURF2/data/00000000/geometry
// - SURF2/SURF2/data/00000000/VAR1
// - SURF2/SURF2/data/00000000/VAR2
// Names "data" and "geometry" as per ensightCase:
const char* fmt = "%08d";
const char* mask = "data/********/";
const fileName baseDir = outputDir.path()/surfName;
const fileName timeDir = outputDir.name();
// Convert timeDir to a value (if possible - use 0.0 otherwise)
scalar timeValue = 0.0;
readScalar(timeDir, timeValue);
scalar meshValue = 0;
if (!isDir(baseDir))
{
mkDir(baseDir);
}
label meshIndex = 0;
label timeIndex = 0;
fileName geometryName;
// Do case file
{
dictionary dict;
scalarList meshes;
scalarList times;
bool stateChanged = false;
if (isFile(baseDir/"fieldsDict"))
{
IFstream is(baseDir/"fieldsDict");
if (is.good() && dict.read(is))
{
dict.readIfPresent("meshes", meshes);
dict.readIfPresent("times", times);
timeIndex = 1+findLower(times, timeValue);
if (dict.readIfPresent("updateMesh", meshValue))
{
meshIndex = 1+findLower(meshes, meshValue);
dict.remove("updateMesh");
stateChanged = true;
}
else if (meshes.size())
{
meshIndex = meshes.size()-1;
meshValue = meshes.last();
}
else
{
meshIndex = 0;
}
}
}
// Update stored times list
meshes.resize(meshIndex+1, -1);
times.resize(timeIndex+1, -1);
if (meshes[meshIndex] != meshValue)
{
stateChanged = true;
}
if (times[timeIndex] != timeValue)
{
stateChanged = true;
}
meshes[meshIndex] = meshValue;
times[timeIndex] = timeValue;
geometryName =
"data"/word::printf(fmt, meshIndex)/ensightCase::geometryName;
// Add my information to dictionary
{
dict.set("meshes", meshes);
dict.set("times", times);
if (dict.found("fields"))
{
dictionary& fieldsDict = dict.subDict("fields");
if (!fieldsDict.found(fieldName))
{
dictionary fieldDict;
fieldDict.set("type", ensightPTraits<Type>::typeName);
fieldDict.set("name", varName); // ensight variable name
fieldsDict.set(fieldName, fieldDict);
stateChanged = true;
}
}
else
{
dictionary fieldDict;
fieldDict.set("type", ensightPTraits<Type>::typeName);
fieldDict.set("name", varName); // ensight variable name
dictionary fieldsDict;
fieldsDict.set(fieldName, fieldDict);
dict.set("fields", fieldsDict);
stateChanged = true;
}
}
if (stateChanged)
{
if (verbose)
{
Info<< "Writing state file to fieldsDict" << endl;
}
{
OFstream os(baseDir/"fieldsDict");
os << "// Summary of Ensight fields, times" << nl << nl;
dict.write(os, false);
}
OFstream osCase(baseDir/surfName + ".case", 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 =
(meshes.size() == 1 ? 0 : meshes == times ? 1 : 2);
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;
const dictionary& fieldsDict = dict.subDict("fields");
for (const entry& dEntry : fieldsDict)
{
const dictionary& subDict = dEntry.dict();
const word fieldType(subDict.get<word>("type"));
const word varName = subDict.lookupOrDefault
(
"name",
dEntry.keyword() // fieldName as fallback
);
osCase
<< fieldType
<<
(
isNodeValues
? " per node: 1 " // time-set 1
: " per element: 1 " // time-set 1
)
<< setw(15) << varName << ' '
<< mask << varName << nl;
}
osCase
<< nl
<< "TIME" << nl;
printTimeset(osCase, 1, times);
if (tsGeom == 2)
{
printTimeset(osCase, 2, meshes);
}
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 meshFile(baseDir/geometryName);
// Write geometry
ensightPartFaces ensPart
(
0,
meshFile.name(),
surf.points(),
surf.faces(),
true // contiguous points
);
if (!exists(meshFile))
{
if (verbose)
{
Info<< "Writing mesh file to " << meshFile.name() << endl;
}
// Use two-argument form for path-name to avoid validating the base-dir
ensightGeoFile osGeom(meshFile.path(), meshFile.name(), writeFormat_);
osGeom << ensPart;
}
// Write field
ensightFile osField
(
dataDir,
varName,
writeFormat_
);
if (verbose)
{
Info<< "Writing field file to " << osField.name() << endl;
}
// Write field
osField.writeKeyword(ensightPTraits<Type>::typeName);
if (isNodeValues)
{
ensightOutput::Serial::writePointField
(
values,
ensPart,
osField
// serial
);
}
else
{
ensightOutput::Detail::writeFaceField
(
values,
ensPart,
osField,
false // serial
);
}
// Place a timestamp in the directory for future reference
{
OFstream timeStamp(dataDir/"time");
timeStamp
<< "# timestep time" << nl
<< dataDir.name() << " " << timeValue << nl;
}
return baseDir/surfName + ".case";
}
template<class Type>
Foam::fileName Foam::ensightSurfaceWriter::writeTemplate
(
const fileName& outputDir,
const fileName& surfaceName,
const meshedSurf& surf,
const word& fieldName,
const Field<Type>& values,
const bool isNodeValues,
const bool verbose
) const
{
if (collateTimes_)
{
return writeCollated
(
outputDir,
surfaceName,
surf,
fieldName,
values,
isNodeValues,
verbose
);
}
else
{
return writeUncollated
(
outputDir,
surfaceName,
surf,
fieldName,
values,
isNodeValues,
verbose
);
}
}
// ************************************************************************* //

View File

@ -1,98 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2016 OpenCFD Ltd.
\\/ 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/>.
\*---------------------------------------------------------------------------*/
#include "foamSurfaceWriter.H"
#include "OFstream.H"
#include "makeSurfaceWriterMethods.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
makeSurfaceWriterType(foamSurfaceWriter);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Field writing implementation
#include "foamSurfaceWriterImpl.C"
// Field writing methods
defineSurfaceWriterWriteFields(Foam::foamSurfaceWriter);
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::fileName Foam::foamSurfaceWriter::write
(
const fileName& outputDir,
const fileName& surfaceName,
const meshedSurf& surf,
const bool verbose
) const
{
// Output:
// - rootdir/time/surfaceName/{points,faces}
fileName surfaceDir(outputDir/surfaceName);
if (!isDir(surfaceDir))
{
mkDir(surfaceDir);
}
if (verbose)
{
Info<< "Writing geometry to " << surfaceDir << endl;
}
const pointField& points = surf.points();
const faceList& faces = surf.faces();
// Points
OFstream(surfaceDir/"points")() << points;
// Faces
OFstream(surfaceDir/"faces")() << faces;
// Face centers. Not really necessary but very handy when reusing as inputs
// for e.g. timeVaryingMapped bc.
pointField faceCentres(faces.size(), Zero);
forAll(faces, facei)
{
faceCentres[facei] = faces[facei].centre(points);
}
OFstream(surfaceDir/"faceCentres")() << faceCentres;
return surfaceDir;
}
// ************************************************************************* //

View File

@ -1,209 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\/ 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/>.
Class
Foam::foamSurfaceWriter
Description
A surfaceWriter for OpenFOAM surfaces
\heading Output file locations
The \c rootdir normally corresponds to something like
\c postProcessing/\<name\>
\subheading Geometry
\verbatim
rootdir
`-- timeName
`-- surfaceName
|-- "points"
|-- "faceCentres"
`-- "faces"
\endverbatim
\subheading Fields
\verbatim
rootdir
`-- timeName
`-- surfaceName
|-- scalarField
| |-- field
| `-- field
|-- vectorField
|-- field
`-- field
\endverbatim
SourceFiles
foamSurfaceWriter.C
\*---------------------------------------------------------------------------*/
#ifndef foamSurfaceWriter_H
#define foamSurfaceWriter_H
#include "surfaceWriter.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class foamSurfaceWriter Declaration
\*---------------------------------------------------------------------------*/
class foamSurfaceWriter
:
public surfaceWriter
{
// Private Member Functions
//- Templated write operation
template<class Type>
fileName writeTemplate
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<Type>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const;
public:
//- Runtime type information
TypeName("foam");
// Constructors
//- Construct null
foamSurfaceWriter() = default;
//- Destructor
virtual ~foamSurfaceWriter() = default;
// Member Functions
//- True if the surface format supports geometry in a separate file.
// False if geometry and field must be in a single file
virtual bool separateGeometry() const
{
return true;
}
//- Write single surface geometry to file.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write scalarField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<scalar>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write vectorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<vector>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write sphericalTensorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<sphericalTensor>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write symmTensorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<symmTensor>& values,//!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write tensorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<tensor>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,77 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2014 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 "OFstream.H"
#include "OSspecific.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class Type>
Foam::fileName Foam::foamSurfaceWriter::writeTemplate
(
const fileName& outputDir,
const fileName& surfaceName,
const meshedSurf& surf,
const word& fieldName,
const Field<Type>& values,
const bool isNodeValues,
const bool verbose
) const
{
// Geometry should already have been written
// Values to separate directory (e.g. "scalarField/p")
// field: rootdir/time/surfaceName/fieldType/field
const word fieldTypeName
(
word(pTraits<Type>::typeName) + FieldBase::typeName
);
const fileName base(outputDir/surfaceName);
const fileName outputFile(base / fieldTypeName / fieldName);
if (verbose)
{
Info<< "Writing field " << fieldName << " to " << base << endl;
}
if (!isDir(outputFile.path()))
{
mkDir(outputFile.path());
}
// Write field
OFstream os(outputFile);
os << values;
return os.name();
}
// ************************************************************************* //

View File

@ -1,136 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2011, 2015-2016 OpenCFD Ltd.
\\/ 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/>.
\*---------------------------------------------------------------------------*/
#include "rawSurfaceWriter.H"
#include "OFstream.H"
#include "OSspecific.H"
#include "makeSurfaceWriterMethods.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
makeSurfaceWriterType(rawSurfaceWriter);
addToRunTimeSelectionTable(surfaceWriter, rawSurfaceWriter, wordDict);
}
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam
{
// Emit x,y,z
static inline void writePoint(Ostream& os, const point& p)
{
os << p.x() << ' ' << p.y() << ' ' << p.z();
}
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Field writing implementation
#include "rawSurfaceWriterImpl.C"
// Field writing methods
defineSurfaceWriterWriteFields(Foam::rawSurfaceWriter);
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::rawSurfaceWriter::rawSurfaceWriter()
:
surfaceWriter(),
writeCompression_(IOstream::UNCOMPRESSED)
{}
Foam::rawSurfaceWriter::rawSurfaceWriter(const dictionary& options)
:
surfaceWriter(),
writeCompression_(IOstream::UNCOMPRESSED)
{
if (options.found("compression"))
{
writeCompression_ =
IOstream::compressionEnum(options.get<word>("compression"));
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::fileName Foam::rawSurfaceWriter::write
(
const fileName& outputDir,
const fileName& surfaceName,
const meshedSurf& surf,
const bool verbose
) const
{
// geometry: rootdir/time/surfaceName.raw
const pointField& points = surf.points();
const faceList& faces = surf.faces();
if (!isDir(outputDir))
{
mkDir(outputDir);
}
OFstream os
(
outputDir/surfaceName + ".raw",
IOstream::ASCII,
IOstream::currentVersion,
writeCompression_
);
if (verbose)
{
Info<< "Writing geometry to " << os.name() << endl;
}
// Header
os << "# geometry NO_DATA " << faces.size() << nl
<< "# x y z" << nl;
// Write faces centres
for (const face& f : faces)
{
writePoint(os, f.centre(points));
os << nl;
}
os << nl;
return os.name();
}
// ************************************************************************* //

View File

@ -1,220 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2011, 2015-2018 OpenCFD Ltd.
\\/ 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/>.
Class
Foam::rawSurfaceWriter
Description
A surfaceWriter for raw output.
The formatOptions for raw:
\table
Property | Description | Required | Default
compression | on / off | no | off
\endtable
For example,
\verbatim
formatOptions
{
raw
{
compression on;
}
}
\endverbatim
\heading Output file locations
The \c rootdir normally corresponds to something like
\c postProcessing/\<name\>
\subheading Geometry
\verbatim
rootdir
`-- timeName
`-- surfaceName.{raw}
\endverbatim
\subheading Fields
\verbatim
rootdir
`-- timeName
|-- <field0>_surfaceName.{raw}
`-- <field1>_surfaceName.{raw}
\endverbatim
SourceFiles
rawSurfaceWriter.C
\*---------------------------------------------------------------------------*/
#ifndef rawSurfaceWriter_H
#define rawSurfaceWriter_H
#include "surfaceWriter.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class rawSurfaceWriter Declaration
\*---------------------------------------------------------------------------*/
class rawSurfaceWriter
:
public surfaceWriter
{
// Private data
//- Output compression (default: uncompressed)
IOstream::compressionType writeCompression_;
// Private Member Functions
//- Templated write operation
template<class Type>
fileName writeTemplate
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<Type>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const;
public:
//- Runtime type information
TypeName("raw");
// Constructors
//- Construct null
rawSurfaceWriter();
//- Construct with some output options
rawSurfaceWriter(const dictionary& options);
//- Destructor
virtual ~rawSurfaceWriter() = default;
// Member Functions
//- Write single surface geometry to file.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write scalarField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<scalar>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write vectorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<vector>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write sphericalTensorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<sphericalTensor>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write symmTensorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<symmTensor>& values,//!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write tensorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<tensor>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,215 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2011, 2015-2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011 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/>.
Class
Foam::starcdSurfaceWriter
Description
A surfaceWriter for STARCD files.
The geometry is written via the MeshedSurfaceProxy, the fields
are written in a trivial ASCII format with ID and VALUE as
so-called user data. These \c .usr files can be read into proSTAR
with these types of commands. For element data:
\verbatim
getuser FILENAME.usr cell scalar free
getuser FILENAME.usr cell vector free
\endverbatim
and for vertex data:
\verbatim
getuser FILENAME.usr vertex scalar free
getuser FILENAME.usr vertex vector free
\endverbatim
\heading Output file locations
The \c rootdir normally corresponds to something like
\c postProcessing/\<name\>
\subheading Geometry
\verbatim
rootdir
`-- timeName
`-- surfaceName.{cel,vrt,inp}
\endverbatim
\subheading Fields
\verbatim
rootdir
`-- timeName
|-- <field0>_surfaceName.{usr}
`-- <field1>_surfaceName.{usr}
\endverbatim
SourceFiles
starcdSurfaceWriter.C
\*---------------------------------------------------------------------------*/
#ifndef starcdSurfaceWriter_H
#define starcdSurfaceWriter_H
#include "surfaceWriter.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class starcdSurfaceWriter Declaration
\*---------------------------------------------------------------------------*/
class starcdSurfaceWriter
:
public surfaceWriter
{
// Private Member Functions
//- Templated write operation
template<class Type>
fileName writeTemplate
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<Type>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const;
public:
//- Runtime type information
TypeName("starcd");
// Constructors
//- Construct null
starcdSurfaceWriter() = default;
//- Destructor
virtual ~starcdSurfaceWriter() = default;
// Member Functions
//- True if the surface format supports geometry in a separate file.
// False if geometry and field must be in a single file
virtual bool separateGeometry() const
{
return true;
}
//- Write single surface geometry to file.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write scalarField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<scalar>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write vectorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<vector>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write sphericalTensorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<sphericalTensor>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write symmTensorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<symmTensor>& values,//!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
//- Write tensorField for a single surface to file.
// One value per face or vertex.
virtual fileName write
(
const fileName& outputDir, //!< output-dir
const fileName& surfaceName, //!< Name of surface
const meshedSurf& surf, //!< Surface geometry
const word& fieldName, //!< Name of field
const Field<tensor>& values, //!< Field values to write
const bool isNodeValues = false,//!< Values are per-vertex
const bool verbose = false //!< Additional verbosity
) const; // override
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,94 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2014 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 "OFstream.H"
#include "OSspecific.H"
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam
{
// Emit each component
template<class Type>
static inline void writeData(Ostream& os, const Type& val)
{
const direction ncmpt = pTraits<Type>::nComponents;
for (direction cmpt=0; cmpt < ncmpt; ++cmpt)
{
os << ' ' << component(val, cmpt);
}
os << nl;
}
} // End namespace Foam
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class Type>
Foam::fileName Foam::starcdSurfaceWriter::writeTemplate
(
const fileName& outputDir,
const fileName& surfaceName,
const meshedSurf&,
const word& fieldName,
const Field<Type>& values,
const bool isNodeValues,
const bool verbose
) const
{
// field: rootdir/time/<field>_surfaceName.usr
if (!isDir(outputDir))
{
mkDir(outputDir);
}
OFstream os(outputDir/fieldName + '_' + surfaceName + ".usr");
if (verbose)
{
Info<< "Writing field " << fieldName << " to " << os.name() << endl;
}
// 1-based ids
label elemId = 1;
// No header, just write values
for (const Type& val : values)
{
os << elemId;
writeData(os, val);
++elemId;
}
return os.name();
}
// ************************************************************************* //

View File

@ -1,126 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2004-2011, 2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2015 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 "surfaceWriter.H"
#include "MeshedSurfaceProxy.H"
#include "proxySurfaceWriter.H"
#include "HashTable.H"
#include "word.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(surfaceWriter, 0);
defineRunTimeSelectionTable(surfaceWriter, word);
defineRunTimeSelectionTable(surfaceWriter, wordDict);
addNamedToRunTimeSelectionTable
(
surfaceWriter,
surfaceWriter,
word,
null
);
}
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
Foam::autoPtr<Foam::surfaceWriter>
Foam::surfaceWriter::New(const word& writeType)
{
const auto cstrIter = wordConstructorTablePtr_->cfind(writeType);
if (cstrIter.found())
{
return autoPtr<surfaceWriter>(cstrIter()());
}
else if (MeshedSurfaceProxy<face>::canWriteType(writeType))
{
// Unknown, but proxy handler can manage it
return autoPtr<surfaceWriter>(new proxySurfaceWriter(writeType));
}
FatalErrorInFunction
<< "Unknown write type \"" << writeType << "\"\n\n"
<< "Valid types : "
<< wordConstructorTablePtr_->sortedToc() << nl
<< "Valid proxy types : "
<< MeshedSurfaceProxy<face>::writeTypes() << endl
<< exit(FatalError);
return nullptr;
}
Foam::autoPtr<Foam::surfaceWriter>
Foam::surfaceWriter::New(const word& writeType, const dictionary& options)
{
{
// Constructor with options (dictionary)
const auto cstrIter = wordDictConstructorTablePtr_->cfind(writeType);
if (cstrIter.found())
{
return autoPtr<surfaceWriter>(cstrIter()(options));
}
}
// Drop through to version without options
const auto cstrIter = wordConstructorTablePtr_->cfind(writeType);
if (cstrIter.found())
{
return autoPtr<surfaceWriter>(cstrIter()());
}
else if (MeshedSurfaceProxy<face>::canWriteType(writeType))
{
// Unknown, but proxy handler can manage it
return autoPtr<surfaceWriter>
(
new proxySurfaceWriter(writeType, options)
);
}
FatalErrorInFunction
<< "Unknown write type \"" << writeType << "\"\n\n"
<< "Valid types : "
<< wordConstructorTablePtr_->sortedToc() << nl
<< "Valid proxy types : "
<< MeshedSurfaceProxy<face>::writeTypes() << endl
<< exit(FatalError);
return nullptr;
}
// ************************************************************************* //

Some files were not shown because too many files have changed in this diff Show More