ENH: extended runTimePostProcessing (#1206)

- Extended runTimePostProcessing to include access to "live"
  simulation objects such a geometry patches and sampled surfaces
  stored on the "functionObjectObjects" registry.

- Add 'live' runTimePostProcessing of cloud data.
  Extracts position and fields from the cloud via its objectRegistry writer

- For the "live" simulation objects, there are two new volume filters
  that work directly with the OpenFOAM volume fields:
      * iso-surface
      * cutting planes
  Both use the VTK algorithms directly and support multiple values.
  Eg, can make multiple iso-levels or multiple planes parallel to each
  other.

- When VTK has been compiled with MPI-support, parallel rendering will
  be used.

- Additional title text properties (shadow, italic etc)

- Simplified handling of scalar-bar and visibility switches

- Support multiple text positions. Eg, for adding watermark text.
This commit is contained in:
Mark Olesen
2019-02-13 11:22:46 +01:00
committed by Andrew Heather
parent 03e6aa1a6d
commit 42fbf6d38c
68 changed files with 7123 additions and 847 deletions

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

@ -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.
return Foam::rm(getFileName(keyword, subDictName));
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
@ -29,11 +29,15 @@ Description
Dictionary controls
\table
Property | Description | Required | Default
functionObject | The data source | yes |
clearObjects | Remove file after use | no | no
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.
inputFileName_ = getFileName("file", cloudName_);
if (inputFileName_.empty())
if (Pstream::master())
{
WarningInFunction
<< "Unable to find function object " << functionObjectName_
<< " output for field " << fieldName_
<< ". Cloud will not be processed"
<< endl;
return;
}
inputFileName_ = getFileName("file", cloudName_);
if (inputFileName_.size())
{
polyData = getPolyDataFile(inputFileName_);
vtkSmartPointer<vtkPolyData> dataset;
if (!polyData || polyData->GetNumberOfPoints() == 0)
{
good = false;
if (inputFileName_.hasExt("vtp"))
{
auto reader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
reader->SetFileName(inputFileName_.c_str());
reader->Update();
WarningInFunction
<< "Could not read "<< inputFileName_ << nl
<< "Only VTK (.vtp) files are supported"
<< endl;
}
else
{
DebugInfo
<< " Resolved cloud file "
<< inputFileName_ << endl;
}
}
else
{
good = false;
dataset = reader->GetOutput();
WarningInFunction
<< "Unable to find function object " << functionObjectName_
<< " output for field " << fieldName_
<< ". Cloud will not be processed"
<< endl;
}
}
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;
if (debug)
{
Info<< " Available surfaces:" << nl
<< geometryBase::parent_.storedObjects()
.sortedNames<polySurface>() << endl;
}
return false;
}
//// Pout<< "local surface = " << (surf ? surf->nFaces() : 0) << nl;
auto polyData = getPolyDataFile(fName);
if (!polyData || polyData->GetNumberOfPoints() == 0)
// 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)
)
{
WarningInFunction
<< "Could not read "<< fName << nl
<< "Only VTK (.vtp, .vtk) files are supported"
<< endl;
return;
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_,
(
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_,
fieldName_,
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) 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.
@ -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) 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,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;
}
// Ensure that all objects can be seen without clipping
// Note: can only be done after all objects have been added!
renderer->ResetCameraClippingRange();
if (renderer)
{
// Save image from last iteration
saveImage(renderer->GetRenderWindow());
// Ensure that all objects can be seen without clipping
// Note: can only be done after all objects have been added!
renderer->ResetCameraClippingRange();
currentFrameI_++;
// Save image from last iteration
saveImage(renderer->GetRenderWindow());
}
++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
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;
if (Pstream::master())
{
mkDir(fName.path());
writer->Write();
auto writer = vtkSmartPointer<vtkPNGWriter>::New();
writer->SetFileName(fName.c_str());
writer->SetInputConnection(windowToImageFilter->GetOutputPort());
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,31 +128,40 @@ void Foam::functionObjects::runTimePostPro::text::addGeometryToScene
{
str += " " + geometryBase::parent_.mesh().time().timeName();
}
actor->SetInput(str.c_str());
vtkTextProperty* prop = actor->GetTextProperty();
const vector textColour = colour_->value(position);
prop->SetFontFamilyToArial();
prop->SetFontSize(size_);
prop->SetJustification(int(halign_));
prop->SetVerticalJustificationToBottom();
prop->SetBold(bold_);
prop->SetItalic(italic_);
prop->SetShadow(shadow_);
const scalar textOpacity = opacity(position);
const vector colour = colour_->value(position);
for (const auto& textPosition : positions_)
{
auto actor = vtkSmartPointer<vtkTextActor>::New();
prop->SetColor(colour[0], colour[1], colour[2]);
prop->SetOpacity(opacity(position));
actor->SetInput(str.c_str());
actor->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport();
actor->GetPositionCoordinate()->SetValue
(
position_.first(),
position_.second()
);
vtkTextProperty* prop = actor->GetTextProperty();
renderer->AddActor2D(actor);
prop->SetFontFamilyToArial();
prop->SetFontSize(size_);
prop->SetJustification(int(halign_));
prop->SetVerticalJustificationToBottom();
prop->SetBold(bold_);
prop->SetItalic(italic_);
prop->SetShadow(shadow_);
prop->SetColor(textColour[0], textColour[1], textColour[2]);
prop->SetOpacity(textOpacity);
// Positioning
{
vtkCoordinate* coord = actor->GetPositionCoordinate();
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
@ -96,7 +98,7 @@ namespace runTimePostPro
{
/*---------------------------------------------------------------------------*\
Class text Declaration
Class text Declaration
\*---------------------------------------------------------------------------*/
class text
@ -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

@ -53,9 +53,8 @@ maxCo 0.2;
functions
{
#include "sampling"
#include "streamLines"
#include "runTimePostProcessing"
// Demonstrate runTimePostProcessing
#include "visualization"
}
// ************************************************************************* //

View File

@ -8,15 +8,21 @@
postPro1
{
type runTimePostProcessing;
libs ("librunTimePostProcessing.so");
writeControl writeTime;
#includeEtc "caseDicts/postProcessing/visualization/runTimePostPro.cfg"
// Time control etc
${_visualization};
// debug true;
// parallel true;
output
{
name image;
width 800;
height 600;
}
camera
{
// If camera is moving, optionally provide start and end times
@ -42,14 +48,10 @@ postPro1
// they are locally overridden
colours
{
background (0.317647 0.341176 0.431373);
background2 ${background};
text (0.75 0.75 0.75);
edge (1 0 0);
surface (0.5 0.5 0.5);
line (1 0 0);
${..colourScheme.paraview};
}
// Line data
lines
{
streamline
@ -70,11 +72,11 @@ postPro1
}
}
_plane
// Surface data
_surface
{
type functionObjectSurface;
functionObject cuttingPlane;
colourMap blueWhiteRed;
colourMap coolToWarm;
representation glyph;
maxGlyphLength 0.1;
visible yes;
@ -83,13 +85,8 @@ postPro1
field U;
range (0 10);
opacity 1;
scalarBar
{
visible no;
}
}
surfaces
{
geom
@ -102,26 +99,51 @@ postPro1
visible yes;
featureEdges no;
opacity 0.8;
visible false;
}
patches
{
type patches;
patches (hole);
renderMode phong;
representation surface;
colourMap coolToWarm;
colourBy field;
field U;
range (0 10);
nearCellValue true;
smooth true;
}
plane0
{
${_plane};
functionObject plane0;
${_surface};
functionObject planes.plane0;
}
plane1
{
${_plane};
functionObject plane1;
${_surface};
functionObject planes.plane1;
}
plane2
cutting
{
${_plane};
functionObject plane2;
}
plane3
{
${_plane};
functionObject plane3;
// Same colours and scaling as surface
${_surface};
type plane;
planeType pointAndNormal;
pointAndNormalDict
{
point (0 0 0);
normal (1 0 0);
}
offsets (0.1 0.2 0.3 0.4 0.5);
colourMap coolToWarm;
}
}

View File

@ -6,94 +6,58 @@
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
plane0
planes
{
type surfaces;
libs ("libsampling.so");
writeControl writeTime;
surfaceFormat vtk;
// Time control etc
${_visualization};
fields ( p U );
// surfaceFormat vtk;
surfaceFormat none;
store true;
interpolationScheme cellPoint;
_plane
{
type plane; //cuttingPlane;
planeType pointAndNormal;
interpolate false;
pointAndNormalDict
{
point (0 0 0);
normal (1 0 0);
}
}
surfaces
(
{
plane0
{
type cuttingPlane;
planeType pointAndNormal;
interpolate true;
${_plane}
pointAndNormalDict
{
point (0 0 0);
normal (1 0 0);
}
}
);
}
plane1
{
${plane0}
surfaces
(
plane1
{
type cuttingPlane;
planeType pointAndNormal;
interpolate true;
${_plane}
pointAndNormalDict
{
point (0.1 0 0);
normal (1 0 0);
point (-0.1 0 0);
}
}
);
}
}
plane2
{
${plane0}
surfaces
(
plane2
{
type cuttingPlane;
planeType pointAndNormal;
interpolate true;
pointAndNormalDict
{
point (0.2 0 0);
normal (1 0 0);
}
}
);
}
plane3
{
${plane0}
surfaces
(
plane3
{
type cuttingPlane;
planeType pointAndNormal;
interpolate true;
pointAndNormalDict
{
point (0.3 0 0);
normal (1 0 0);
}
}
);
#remove _plane
}

View File

@ -10,7 +10,8 @@ streamLines
{
type streamLine;
writeControl writeTime;
// Time control etc
${_visualization};
setFormat vtk;

View File

@ -0,0 +1,29 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1812 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
// Demonstrate runTimePostProcessing
// Timing
_visualization
{
writeControl writeTime;
// enabled true;
// Debug: writeControl timeStep;
// Debug: writeInterval 4;
}
#include "streamLines"
#include "sampling"
#include "runTimePostProcessing"
#remove _visualization
// ************************************************************************* //

View File

@ -49,10 +49,8 @@ runTimeModifiable true;
functions
{
// Demonstrate runtime postprocessing
#include "streamLines"
#include "cuttingPlane"
#include "runTimePostProcessing"
// Demonstrate runTimePostProcessing
#include "visualization"
// Do some other functionObjects
#include "forceCoeffs"

View File

@ -1,14 +1,34 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1812 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
postPro1
{
type runTimePostProcessing;
libs ("librunTimePostProcessing.so");
writeControl writeTime;
#includeEtc "caseDicts/postProcessing/visualization/runTimePostPro.cfg"
// Time control etc
${_visualization};
// debug true;
// parallel true;
output
{
name image;
width 2000;
height 1200;
}
// Default colours. Used for colourBy == colour unless locally overridden
colours
{
${..colourScheme.blueGradient};
}
camera
{
// If camera is moving, optionally provide start and end times
@ -19,27 +39,15 @@ postPro1
nFrameTotal 1;
// Parallel projection flag
parallelProjection no;
parallelProjection off;
clipBox (-0.2 -0.2 0)(1.65 0.2 1.25); // optional
focalPoint (1.2 1.1 0.2);
up (0 0 1);
position (3.6 5.1 -1.3);
up (0 0 1);
}
// Default colours
// - If select to colourBy colour, these values are used unless
// they are locally overridden
colours
{
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);
}
// Line data
lines
{
@ -47,8 +55,9 @@ postPro1
{
type functionObjectLine;
functionObject streamLines;
colourMap rainbow;
representation tube;
visible yes;
visible true;
tubeRadius 0.01;
colourBy field;
field U;
@ -56,13 +65,17 @@ postPro1
opacity 1;
scalarBar
{
visible yes;
visible true;
position (0.8 0.1);
vertical yes;
fontSize 16;
title "velocity / [m/s]";
title "velocity [m/s]";
labelFormat "%6.2f";
numberOfLabels 5;
bold true;
italic true;
italic true;
colour (0.75 0.75 0.75);
}
}
}
@ -77,27 +90,40 @@ postPro1
renderMode phong;
representation surface;
edgeColour (0 0 0);
visible yes;
featureEdges yes;
opacity 1;
visible false;
}
cuttingPlane1
patches
{
type patches;
patches ("motorBike.*");
renderMode phong;
representation surface;
colourMap coolToWarm;
colourBy field;
field U;
range (0 30);
nearCellValue true;
smooth true;
featureEdges yes;
edgeColour (0 0 0);
}
plane1
{
type functionObjectSurface;
functionObject cuttingPlane;
colourMap blueWhiteRed;
functionObject samples.yNormal;
colourMap coolToWarm;
representation glyph;
maxGlyphLength 0.1;
visible yes;
visible true;
featureEdges no;
colourBy field;
field U;
range (0 30);
opacity 1;
scalarBar
{
visible no;
}
}
}
@ -106,11 +132,14 @@ postPro1
{
text1
{
string "Motorbike";
position (0.1 0.05);
size 72;
bold yes;
visible yes;
visible true;
string "Motorbike";
position (0.1 0.05);
size 72;
bold true;
italic true;
}
}
}
// ************************************************************************* //

View File

@ -6,31 +6,38 @@
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
cuttingPlane
samples
{
type surfaces;
libs ("libsampling.so");
writeControl writeTime;
surfaceFormat vtk;
// Time control etc
${_visualization};
fields (p U);
// surfaceFormat vtk;
surfaceFormat none;
verbose false;
interpolationScheme cellPoint;
surfaces
(
{
yNormal
{
type cuttingPlane;
planeType pointAndNormal;
interpolate true;
store true;
pointAndNormalDict
{
point (0 0 0);
normal (0 1 0);
}
interpolate true;
}
);
}
}

View File

@ -8,7 +8,7 @@
residuals
{
type residuals;
type solverInfo;
libs ("libutilityFunctionObjects.so");
writeFields true;
writeControl outputTime;

View File

@ -8,11 +8,10 @@
streamLines
{
type streamLine;
type streamLine;
// Output every
writeControl writeTime;
// writeInterval 10;
// Time control etc
${_visualization};
setFormat vtk; //gnuplot; //xmgr; //raw; //jplot; //csv; //ensight;

View File

@ -0,0 +1,30 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1812 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
// Demonstrate runTimePostProcessing
// Timing
_visualization
{
writeControl writeTime;
// enabled true;
// Debug: writeControl timeStep;
// Debug: writeInterval 10;
}
#include "streamLines"
#include "samples"
#include "runTimePostProcessing"
#remove _visualization
// ************************************************************************* //

View File

@ -52,6 +52,9 @@ functions
{
#include "ensightWrite"
#include "vtkWrite"
// Demonstrate runTimePostProcessing
#include "visualization"
}

View File

@ -0,0 +1,306 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1812 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
postPro1
{
#includeEtc "caseDicts/postProcessing/visualization/runTimePostPro.cfg"
// Time control etc
${_visualization};
// debug true;
// parallel true;
showIsoSurface false;
output
{
name image;
width 1280;
height 720;
}
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
colours
{
${..colourScheme.paraview};
}
// Line data
lines
{
streamline
{
type functionObjectLine;
functionObject streamLines;
colourMap rainbow;
representation tube;
visible yes;
tubeRadius 0.5;
colourBy field;
field U;
range (0 20);
opacity 1;
}
}
_sampled
{
type functionObjectSurface;
colourMap coolToWarm;
representation glyph;
representation surface;
maxGlyphLength 0.1;
visible yes;
featureEdges no;
colourBy field;
field U;
range (0 20);
opacity 1;
}
_velocity_scalarBar
{
visible yes;
vertical false;
titleHack false;
position (0.8 0);
size (0.2 0.1);
fontSize 8;
titleSize 24;
title "velocity [m/s]";
labelFormat "%.0f";
numberOfLabels 5;
bold yes;
italic yes;
shadow yes;
}
surfaces
{
/*
geom
{
type geometry;
files ("<case>/buildings.vtp");
renderMode phong;
representation surface;
edgeColour (0.5 0.5 0.5);
visible yes;
featureEdges none;
opacity 1.0;
}
*/
ground1
{
type patches;
patches ( ground );
nearCellValue true;
colourMap coolToWarm;
representation glyph;
// maxGlyphLength 5;
maxGlyphLength 0;
colourBy field;
field U;
range (0 20);
}
ground2
{
type patches;
patches ( ground );
nearCellValue true;
smooth true;
colourMap coolToWarm;
representation wireframe;
// maxGlyphLength 5;
maxGlyphLength 0;
visible yes;
colourBy field;
field U;
range (0 20);
}
buildings
{
type patches;
patches ( buildings );
nearCellValue true;
smooth true;
colourMap coolToWarm;
representation surface;
renderMode phong;
colourBy field;
field U;
range (0 20);
scalarBar
{
${_velocity_scalarBar};
}
}
// A cutting plane from sampled surfaces:
stored1
{
${_sampled};
functionObject planes.plane2;
smooth true;
}
// VTK cutting planes:
cutting
{
type plane;
planeType pointAndNormal;
pointAndNormalDict
{
point (100 100 50);
normal (1 0 0);
}
offsets (0 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);
}
// VTK iso surfaces of something
iso
{
visible ${showIsoSurface};
type isoSurface;
field U;
values (10);
smooth true;
colourMap coolToWarm;
representation surface;
// maxGlyphLength 5;
maxGlyphLength 0;
featureEdges none;
colourBy field;
colourField p;
range (-120 120);
}
}
// Text data
text
{
title
{
string "Wind around buildings";
position (0 0.95);
size 32;
bold yes;
italic yes;
shadow yes;
visible yes;
}
version
{
${title};
string "OpenFOAM ${FOAM_API}";
position (0 0);
size 24;
}
watermark
{
string "www.openfoam.com";
halign centre;
size 24;
opacity 0.3;
bold yes;
italic yes;
shadow yes;
positions
(
(0.50 0.05) (0.50 0.95)
(0.25 0.25) (0.75 0.25)
(0.25 0.50) (0.75 0.50)
(0.25 0.75) (0.75 0.75)
);
}
}
}
// ************************************************************************* //

View File

@ -0,0 +1,71 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1812 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
planes
{
type surfaces;
libs ("libsampling.so");
// Time control etc
${_visualization};
fields ( p U );
// surfaceFormat vtk;
surfaceFormat none;
store true;
interpolationScheme cellPoint;
_plane
{
type cuttingPlane;
planeType pointAndNormal;
interpolate false;
}
surfaces
{
plane0
{
${_plane}
pointAndNormalDict
{
point (100 100 50);
normal (1 -1 0);
}
enabled false;
}
plane1
{
${_plane}
pointAndNormalDict
{
point (100 100 50);
normal (1 1 0);
}
}
plane2
{
${_plane}
pointAndNormalDict
{
point (200 100 50);
normal (1 0 0);
}
}
};
#remove _plane
}
// ************************************************************************* //

View File

@ -0,0 +1,52 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1812 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
streamLines
{
type streamLine;
libs ("libfieldFunctionObjects.so");
// Time control etc
${_visualization};
setFormat vtk;
// Velocity field to use for tracking.
U U;
// Tracked forwards (+U) or backwards (-U)
trackForward true;
// Names of fields to sample. Should contain above velocity field!
fields (p U);
// Steps particles can travel before being removed
lifeTime 10000;
// Number of steps per cell (estimate). Set to 1 to disable subcycling.
nSubCycle 5;
// Cloud name to use
cloud particleTracks;
// Seeding method.
seedSampleSet
{
type uniform;
axis x; //distance;
// Note: tracks slightly offset so as not to be on a face
start (0 -20 15);
end (0 150 15);
nPoints 40;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,29 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1812 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
// Demonstrate runTimePostProcessing
// Timing
_visualization
{
writeControl writeTime;
// enabled true;
// Debug: writeControl timeStep;
// Debug: writeInterval 10;
}
#include "streamLines"
#include "sampling"
#include "runTimePostProcessing"
#remove _visualization
// ************************************************************************* //

View File

@ -53,8 +53,9 @@ maxDeltaT 1;
functions
{
#include "dataCloud"
#include "vtkCloud"
// #include "dataCloud"
#include "runTimePostProcessing"
}

View File

@ -2,9 +2,11 @@
postPro1
{
type runTimePostProcessing;
libs ("librunTimePostProcessing.so");
writeControl writeTime;
#includeEtc "caseDicts/postProcessing/visualization/runTimePostPro.cfg"
// parallel false;
// debug true;
output
{
name image;
@ -23,10 +25,10 @@ postPro1
parallelProjection yes;
focalPoint (0.251 0.415 0.05);
position (0.251 0.415 2.218);
focalPoint (0.25 0.42 0.05);
position (0.15 0.42 2.5);
up (0 1 0);
zoom 1;
zoom 1.5;
}
// Default colours
@ -34,13 +36,7 @@ postPro1
// they are locally overridden
colours
{
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);
${..colourScheme.greyGradient};
}
// Points (cloud) data
@ -48,55 +44,69 @@ postPro1
{
cloud1
{
type functionObjectCloud;
functionObject cloudWrite1;
type cloud;
cloud coalCloud1;
colourMap blueWhiteRed;
colourMap coolToWarm;
representation sphere;
maxGlyphLength 0.05;
visible yes;
maxGlyphLength 0.025;
featureEdges no;
colourBy field;
colourField T;
field T;
range (290 410);
opacity 1;
scalarBar
{
visible yes;
visible true;
vertical yes;
position (0.8 0.1);
fontSize 12;
titleSize 24;
title "Temperature [K]";
labelFormat "%.0f";
numberOfLabels 8;
numberOfLabels 9;
bold false;
}
}
}
/* Future...
// Surface data
surfaces
{
container
patches
{
type patches;
patches (".*");
renderMode phong;
representation surface;
edgeColour (0 0 0);
visible yes;
colourBy colour;
field U;
range (0 40);
featureEdges yes;
opacity 0.25;
edgeColour (0 0 0);
// Fails in parallel: opacity 0.25;
}
k
{
type isoSurface;
renderMode phong;
representation surface;
field k;
values ( 100 );
colourField T;
colourBy field;
range (290 410);
smooth true;
}
}
*/
// Text data
text
{
text1
{
visible yes;
string "simplifiedSiwek";
position (0.1 0.05);
size 24;