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; rotatedBoxToCell 0;
rotatingPressureInletOutletVelocity 0; rotatingPressureInletOutletVelocity 0;
rotatingTotalPressure 0; rotatingTotalPressure 0;
runTimePostPro::geometryBase 0;
sampledPatch 0; sampledPatch 0;
sampledPlane 0; sampledPlane 0;
sampledSet 0; sampledSet 0;

View File

@ -13,13 +13,40 @@ else()
message(FATAL_ERROR " VTK version is too old - requires VTK6 or newer") message(FATAL_ERROR " VTK version is too old - requires VTK6 or newer")
endif() 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( include_directories(
${LIB_SRC}/OpenFOAM/include ${LIB_SRC}/OpenFOAM/include
${LIB_SRC}/OpenFOAM/lnInclude ${LIB_SRC}/OpenFOAM/lnInclude
${LIB_SRC}/OSspecific/${WM_OSTYPE}/lnInclude ${LIB_SRC}/OSspecific/${WM_OSTYPE}/lnInclude
${LIB_SRC}/finiteVolume/lnInclude ${LIB_SRC}/finiteVolume/lnInclude
${LIB_SRC}/surfMesh/lnInclude ${LIB_SRC}/fileFormats/lnInclude
${LIB_SRC}/conversion/lnInclude ${LIB_SRC}/conversion/lnInclude
${LIB_SRC}/surfMesh/lnInclude
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}
) )
@ -45,12 +72,16 @@ set(LIBRARY_OUTPUT_PATH $ENV{FOAM_LIBBIN}
file(GLOB SOURCE_FILES file(GLOB SOURCE_FILES
fieldVisualisationBase.C fieldVisualisationBase.C
scalarBar.C
functionObjectBase.C functionObjectBase.C
functionObjectCloud.C functionObjectCloud.C
functionObjectLine.C functionObjectLine.C
functionObjectSurface.C functionObjectSurface.C
geometryBase.C geometryBase.C
geometryCloud.C
geometryCloudGather.C
geometryPatches.C geometryPatches.C
geometryPatchesGather.C
geometrySurface.C geometrySurface.C
pathline.C pathline.C
pointData.C pointData.C
@ -58,16 +89,27 @@ file(GLOB SOURCE_FILES
runTimePostProcessingFunctionObject.C runTimePostProcessingFunctionObject.C
scene.C scene.C
surface.C surface.C
surfaceGather.C
text.C text.C
contourFilter.C
cuttingPlaneFilter.C
volumeFilter.C
) )
set(OPENFOAM_LIBRARIES set(OPENFOAM_LIBRARIES
OpenFOAM OpenFOAM
finiteVolume finiteVolume
surfMesh surfMesh
fileFormats
conversion conversion
) )
if (FOAM_USING_VTK_MPI)
set(LINK_LIBRARIES vtkParallelMPI)
else()
set(LINK_LIBRARIES)
endif()
add_library( add_library(
runTimePostProcessing runTimePostProcessing
SHARED SHARED
@ -84,6 +126,7 @@ set_target_properties(
target_link_libraries( target_link_libraries(
runTimePostProcessing runTimePostProcessing
${VTK_LIBRARIES} ${VTK_LIBRARIES}
${LINK_LIBRARIES}
${OPENFOAM_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 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -29,25 +27,27 @@ License
#include "fieldVisualisationBase.H" #include "fieldVisualisationBase.H"
#include "runTimePostProcessing.H" #include "runTimePostProcessing.H"
#include "doubleVector.H"
#include "foamVtkTools.H"
// VTK includes // VTK includes
#include "vtkArrowSource.h" #include "vtkArrowSource.h"
#include "vtkCellDataToPointData.h"
#include "vtkCellData.h" #include "vtkCellData.h"
#include "vtkColorTransferFunction.h" #include "vtkColorTransferFunction.h"
#include "vtkFloatArray.h" #include "vtkCompositeDataSet.h"
#include "vtkDataObjectTreeIterator.h"
#include "vtkFieldData.h"
#include "vtkGlyph3D.h" #include "vtkGlyph3D.h"
#include "vtkLookupTable.h" #include "vtkLookupTable.h"
#include "vtkPointData.h" #include "vtkPointData.h"
#include "vtkPolyData.h" #include "vtkPolyData.h"
#include "vtkPolyDataMapper.h" #include "vtkPolyDataMapper.h"
#include "vtkRenderer.h" #include "vtkRenderer.h"
#include "vtkScalarBarActor.h"
#include "vtkSmartPointer.h" #include "vtkSmartPointer.h"
#include "vtkSphereSource.h" #include "vtkSphereSource.h"
#include "vtkTextActor.h"
#include "vtkTextProperty.h"
#include "vtkCellDataToPointData.h"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
const Foam::Enum const Foam::Enum
< <
@ -69,13 +69,323 @@ const Foam::Enum
Foam::functionObjects::runTimePostPro::fieldVisualisationBase:: Foam::functionObjects::runTimePostPro::fieldVisualisationBase::
colourMapTypeNames colourMapTypeNames
({ ({
{ colourMapType::cmRainbow, "rainbow" }, { colourMapType::cmCoolToWarm, "coolToWarm" },
{ colourMapType::cmBlueWhiteRed, "blueWhiteRed" }, { colourMapType::cmCoolToWarm, "blueWhiteRed" },
{ colourMapType::cmColdAndHot, "coldAndHot" },
{ colourMapType::cmFire, "fire" }, { colourMapType::cmFire, "fire" },
{ colourMapType::cmRainbow, "rainbow" },
{ colourMapType::cmGreyscale, "greyscale" }, { 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 * * * * * * * * * * * // // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::functionObjects::runTimePostPro::fieldVisualisationBase:: void Foam::functionObjects::runTimePostPro::fieldVisualisationBase::
@ -84,7 +394,7 @@ setColourMap
vtkLookupTable* lut vtkLookupTable* lut
) const ) const
{ {
label nColours = 256; constexpr label nColours = 256;
lut->SetNumberOfColors(nColours); lut->SetNumberOfColors(nColours);
@ -92,47 +402,73 @@ setColourMap
switch (colourMap_) 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: case cmRainbow:
{ {
ctf->SetColorSpaceToHSV(); ctf->SetColorSpaceToHSV();
ctf->AddRGBPoint(0, 0, 0, 1); ctf->AddRGBPoint(0, 0, 0, 1);
ctf->AddRGBPoint(0.5, 0, 1, 0); ctf->AddRGBPoint(0.5, 0, 1, 0);
ctf->AddRGBPoint(1, 1, 0, 0); ctf->AddRGBPoint(1, 1, 0, 0);
// ctf->SetNanColor(0.498039, 0.498039, 0.498039);
break; break;
} }
case cmBlueWhiteRed:
{ case cmGreyscale: // ParaView: grayscale
// 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:
{ {
ctf->SetColorSpaceToRGB(); ctf->SetColorSpaceToRGB();
ctf->AddRGBPoint(0, 0, 0, 0); ctf->AddRGBPoint(0, 0, 0, 0);
ctf->AddRGBPoint(1, 1, 1, 1); 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; 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)); ctf->GetColor(scalar(i)/scalar(nColours), rgba);
lut->SetTableValue(i, c[0], c[1], c[2], 1.0); lut->SetTableValue(i, rgba);
} }
} }
@ -145,105 +481,11 @@ addScalarBar
vtkLookupTable* lut vtkLookupTable* lut
) const ) const
{ {
// Add scalar bar legend // Add the scalar bar - only once!
if (!scalarBar_.visible_) 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 scalar position,
const word& colourFieldName, const word& colourFieldName,
vtkPolyDataMapper* mapper, const FieldAssociation fieldAssociation,
vtkRenderer* renderer, vtkMapper* mapper,
vtkPolyData* pData vtkRenderer* renderer
) const ) const
{ {
mapper->InterpolateScalarsBeforeMappingOn(); mapper->InterpolateScalarsBeforeMappingOn();
@ -266,6 +508,7 @@ setField
mapper->ScalarVisibilityOff(); mapper->ScalarVisibilityOff();
break; break;
} }
case cbField: case cbField:
{ {
// Create look-up table for colours // Create look-up table for colours
@ -277,15 +520,15 @@ setField
const char* fieldName = colourFieldName.c_str(); const char* fieldName = colourFieldName.c_str();
mapper->SelectColorArray(fieldName); mapper->SelectColorArray(fieldName);
// Set to use either point or cell data // Use either point or cell data
// Note: if both point and cell data exists, preferentially // - if both point and cell data exists, preferentially choose
// choosing point data. This is often the case when using // point data. This is often the case when using glyphs.
// glyphs
if (pData->GetPointData()->HasArray(fieldName)) if (fieldAssociation & FieldAssociation::POINT_DATA)
{ {
mapper->SetScalarModeToUsePointFieldData(); mapper->SetScalarModeToUsePointFieldData();
} }
else if (pData->GetCellData()->HasArray(fieldName)) else if (fieldAssociation & FieldAssociation::CELL_DATA)
{ {
mapper->SetScalarModeToUseCellFieldData(); mapper->SetScalarModeToUseCellFieldData();
} }
@ -301,7 +544,7 @@ setField
mapper->SetLookupTable(lut); mapper->SetLookupTable(lut);
mapper->ScalarVisibilityOn(); mapper->ScalarVisibilityOn();
// Add the bar // Add the scalar bar
addScalarBar(position, renderer, lut); addScalarBar(position, renderer, lut);
break; break;
} }
@ -316,43 +559,20 @@ addGlyphs
( (
const scalar position, const scalar position,
const word& scaleFieldName, const word& scaleFieldName,
const fieldSummary& scaleFieldInfo,
const word& colourFieldName, const word& colourFieldName,
const fieldSummary& colourFieldInfo,
const scalar maxGlyphLength, const scalar maxGlyphLength,
vtkPolyData* data, vtkPolyData* data,
vtkActor* actor, vtkActor* actor,
vtkRenderer* renderer vtkRenderer* renderer
) const ) const
{ {
auto glyph = vtkSmartPointer<vtkGlyph3D>::New(); // Determine whether we have CellData/PointData and (scalar/vector)
auto glyphMapper = vtkSmartPointer<vtkPolyDataMapper>::New(); // or if we need to a cell->point data filter.
glyphMapper->SetInputConnection(glyph->GetOutputPort());
glyph->SetInputData(data); if (!scaleFieldInfo.exists())
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
{ {
WarningInFunction WarningInFunction
<< "Cannot add glyphs. No such cell or point field: " << "Cannot add glyphs. No such cell or point field: "
@ -360,30 +580,46 @@ addGlyphs
return; return;
} }
if (!scaleFieldInfo.isScalar() && !scaleFieldInfo.isVector())
const bool ok = (nComponents == 1 || nComponents == 3);
if (!ok)
{ {
WarningInFunction WarningInFunction
<< "Glyphs can only be added to scalar or vector data. " << "Glyphs can only be added to scalar or vector data. "
<< "Unable to process field " << scaleFieldName << endl; << "Unable to process field " << scaleFieldName << endl;
return; 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(); auto sphere = vtkSmartPointer<vtkSphereSource>::New();
sphere->SetCenter(0, 0, 0); sphere->SetCenter(0, 0, 0);
@ -397,12 +633,12 @@ addGlyphs
if (maxGlyphLength > 0) if (maxGlyphLength > 0)
{ {
// Can get range from point data: // Using range from the data:
// glyph->SetRange
// double range[2]; // (
// vtkDataArray* values = // scaleFieldInfo.range_.first(),
// data->GetPointData()->GetScalars(scaleFieldNameChar); // scaleFieldInfo.range_.second()
// values->GetRange(range); // );
// Set range according to user-supplied limits // Set range according to user-supplied limits
glyph->ClampingOn(); glyph->ClampingOn();
@ -421,14 +657,14 @@ addGlyphs
glyph->SetColorModeToColorByScalar(); glyph->SetColorModeToColorByScalar();
glyph->SetInputArrayToProcess glyph->SetInputArrayToProcess
( (
0, // scalars 0, // index (0) = scalars
0, 0, // port
0, 0, // connection
vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataObject::FIELD_ASSOCIATION_POINTS,
scaleFieldNameChar scaleFieldName.c_str()
); );
} }
else if (nComponents == 3) else if (scaleFieldInfo.nComponents_ == 3)
{ {
auto arrow = vtkSmartPointer<vtkArrowSource>::New(); auto arrow = vtkSmartPointer<vtkArrowSource>::New();
arrow->SetTipResolution(10); arrow->SetTipResolution(10);
@ -441,24 +677,13 @@ addGlyphs
if (maxGlyphLength > 0) if (maxGlyphLength > 0)
{ {
vtkDataArray* values = // Set range according data limits
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;
glyph->ClampingOn(); glyph->ClampingOn();
glyph->SetRange(range); glyph->SetRange
(
scaleFieldInfo.range_.first(),
scaleFieldInfo.range_.second()
);
glyph->SetScaleFactor(maxGlyphLength); glyph->SetScaleFactor(maxGlyphLength);
} }
else else
@ -471,20 +696,30 @@ addGlyphs
glyph->SetColorModeToColorByVector(); glyph->SetColorModeToColorByVector();
glyph->SetInputArrayToProcess glyph->SetInputArrayToProcess
( (
1, // vectors 1, // index (1) = vectors
0, 0, // port
0, 0, // connection
vtkDataObject::FIELD_ASSOCIATION_POINTS, 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(); glyph->Update();
setField(position, colourFieldName, glyphMapper, renderer, data); setField
(
position,
colourFieldName,
FieldAssociation::POINT_DATA, // Original or after filter
glyphMapper,
renderer
);
glyphMapper->Update(); glyphMapper->Update();
@ -506,9 +741,11 @@ fieldVisualisationBase
: :
colours_(colours), colours_(colours),
fieldName_(dict.get<word>("field")), fieldName_(dict.get<word>("field")),
smooth_(dict.lookupOrDefault("smooth", false)),
colourBy_(cbColour), colourBy_(cbColour),
colourMap_(cmRainbow), colourMap_(cmRainbow),
range_() range_(),
scalarBar_()
{ {
colourByTypeNames.readEntry("colourBy", dict, colourBy_); colourByTypeNames.readEntry("colourBy", dict, colourBy_);
@ -516,26 +753,24 @@ fieldVisualisationBase
{ {
case cbColour: case cbColour:
{ {
scalarBar_.visible_ = false; scalarBar_.hide();
break; break;
} }
case cbField: case cbField:
{ {
dict.readEntry("range", range_); dict.readEntry("range", range_);
colourMapTypeNames.readIfPresent("colourMap", dict, colourMap_); colourMapTypeNames.readIfPresent("colourMap", dict, colourMap_);
const dictionary& sbDict = dict.subDict("scalarBar"); const dictionary* sbar = dict.findDict("scalarBar");
sbDict.readEntry("visible", scalarBar_.visible_);
if (scalarBar_.visible_) if (sbar)
{ {
sbDict.readEntry("vertical", scalarBar_.vertical_); scalarBar_.read(*sbar);
sbDict.readEntry("position", scalarBar_.position_); }
sbDict.readEntry("title", scalarBar_.title_); else
sbDict.readEntry("fontSize", scalarBar_.fontSize_); {
sbDict.readEntry("labelFormat", scalarBar_.labelFormat_); scalarBar_.hide();
sbDict.readEntry("numberOfLabels", scalarBar_.numberOfLabels_);
} }
break; break;
} }

View File

@ -2,10 +2,8 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -29,6 +27,20 @@ Class
Description Description
Base class for scene objects 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 SourceFiles
fieldVisualisationBase.C fieldVisualisationBase.C
@ -41,27 +53,35 @@ SourceFiles
#include "Tuple2.H" #include "Tuple2.H"
#include "Enum.H" #include "Enum.H"
#include "vector.H" #include "vector.H"
#include "MinMax.H"
#include "HashPtrTable.H" #include "HashPtrTable.H"
#include "scalarBar.H"
#include "Function1.H" #include "Function1.H"
// VTK includes
#include "vtkSmartPointer.h" #include "vtkSmartPointer.h"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Forward declarations // Forward Declarations
class vtkActor; class vtkActor;
class vtkCompositeDataSet;
class vtkCompositeDataGeometryFilter;
class vtkCompositePolyDataMapper;
class vtkDataSet;
class vtkDataSetAlgorithm;
class vtkFieldData;
class vtkLookupTable; class vtkLookupTable;
class vtkMapper; class vtkMapper;
class vtkPolyData; class vtkPolyData;
class vtkPolyDataMapper; class vtkPolyDataMapper;
class vtkRenderer; class vtkRenderer;
namespace Foam namespace Foam
{ {
namespace functionObjects namespace functionObjects
{ {
// Forward declarations // Forward Declarations
class runTimePostProcessing; class runTimePostProcessing;
namespace runTimePostPro namespace runTimePostPro
@ -75,48 +95,110 @@ class fieldVisualisationBase
{ {
public: public:
// Public enumerations // Public Enumerations
//- Colouring type
enum colourByType enum colourByType
{ {
cbColour, cbColour, //!< "colour" : Use specified colour
cbField cbField //!< "field" : Use named field
}; };
//- Enumeration names for colourByType
static const Enum<colourByType> colourByTypeNames; static const Enum<colourByType> colourByTypeNames;
//- Colour map enumerations
enum colourMapType enum colourMapType
{ {
cmRainbow, cmCoolToWarm, //!< ParaView "Cool To Warm" blue-white-read
cmBlueWhiteRed, cmBlueWhiteRed = cmCoolToWarm,
cmFire, cmColdAndHot, //!< ParaView "Cold and Hot"
cmGreyscale cmFire, //!< ParaView "Black-Body Radiation"
cmRainbow, //!< "rainbow"
cmGreyscale, //!< ParaView "Grayscale"
cmXray //!< ParaView "X Ray"
}; };
//- Enumeration names for colourMapType
static const Enum<colourMapType> colourMapTypeNames; 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:
// Protected Data // Protected Data
struct scalarBar
{
bool visible_;
bool vertical_;
Tuple2<scalar, scalar> position_;
string title_;
label fontSize_;
string labelFormat_;
label numberOfLabels_;
};
//- Colours //- Colours
const HashPtrTable<Function1<vector>>& colours_; const HashPtrTable<Function1<vector>>& colours_;
//- Field name //- Field name
word fieldName_; word fieldName_;
//- Requested smoother fields (eg, interpolate cell -> point values)
bool smooth_;
//- Colour by type //- Colour by type
colourByType colourBy_; colourByType colourBy_;
@ -126,16 +208,67 @@ protected:
//- Range of values //- Range of values
Tuple2<scalar, scalar> range_; Tuple2<scalar, scalar> range_;
//- Scalar bar //- Scalar bar characteristics
scalarBar scalarBar_; scalarBar scalarBar_;
// Protected Member Functions // 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 //- Set the colour map
void setColourMap(vtkLookupTable* lut) const; void setColourMap(vtkLookupTable* lut) const;
//- Add scalar bar to renderer //- Add scalar bar (if visible) to renderer
void addScalarBar void addScalarBar
( (
const scalar position, const scalar position,
@ -148,9 +281,9 @@ protected:
( (
const scalar position, const scalar position,
const word& colourFieldName, const word& colourFieldName,
vtkPolyDataMapper* mapper, const FieldAssociation fieldAssociation,
vtkRenderer* renderer, vtkMapper* mapper,
vtkPolyData* pData vtkRenderer* renderer
) const; ) const;
//- Add glyphs //- Add glyphs
@ -158,13 +291,17 @@ protected:
( (
const scalar position, const scalar position,
const word& scaleFieldName, const word& scaleFieldName,
const fieldSummary& scaleFieldInfo,
const word& colourFieldName, const word& colourFieldName,
const fieldSummary& colourFieldInfo,
const scalar maxGlyphLength, const scalar maxGlyphLength,
vtkPolyData* data, vtkPolyData* data,
vtkActor* actor, vtkActor* actor,
vtkRenderer* renderer vtkRenderer* renderer
) const; ) const;
//- No copy construct //- No copy construct
fieldVisualisationBase(const fieldVisualisationBase&) = delete; fieldVisualisationBase(const fieldVisualisationBase&) = delete;
@ -204,6 +341,19 @@ public:
} // End namespace runTimePostPro } // End namespace runTimePostPro
} // End namespace functionObjects } // End namespace functionObjects
// Ostream
Ostream& operator<<
(
Ostream& os,
const InfoProxy
<
functionObjects::runTimePostPro::fieldVisualisationBase::fieldSummary
>& proxy
);
} // End namespace Foam } // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

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

View File

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

View File

@ -2,10 +2,8 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -33,11 +31,11 @@ License
// VTK includes // VTK includes
#include "vtkActor.h" #include "vtkActor.h"
#include "vtkRenderer.h"
#include "vtkSmartPointer.h"
#include "vtkPolyData.h" #include "vtkPolyData.h"
#include "vtkPolyDataMapper.h" #include "vtkPolyDataMapper.h"
#include "vtkProperty.h" #include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkSmartPointer.h"
// VTK Readers // VTK Readers
#include "vtkPolyDataReader.h" #include "vtkPolyDataReader.h"
@ -51,13 +49,42 @@ namespace functionObjects
{ {
namespace runTimePostPro namespace runTimePostPro
{ {
defineTypeNameAndDebug(functionObjectCloud, 0); defineTypeName(functionObjectCloud);
addToRunTimeSelectionTable(pointData, functionObjectCloud, dictionary); 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 * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::runTimePostPro::functionObjectCloud::functionObjectCloud Foam::functionObjects::runTimePostPro::functionObjectCloud::functionObjectCloud
@ -73,9 +100,7 @@ Foam::functionObjects::runTimePostPro::functionObjectCloud::functionObjectCloud
inputFileName_(), inputFileName_(),
colourFieldName_(dict.get<word>("colourField")), colourFieldName_(dict.get<word>("colourField")),
actor_() actor_()
{ {}
actor_ = vtkSmartPointer<vtkActor>::New();
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
@ -87,8 +112,8 @@ Foam::functionObjects::runTimePostPro::functionObjectCloud::
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
void Foam::functionObjects::runTimePostPro::functionObjectCloud:: bool Foam::functionObjects::runTimePostPro::functionObjectCloud::
addGeometryToScene addGeometryFromFile
( (
const scalar position, const scalar position,
vtkRenderer* renderer vtkRenderer* renderer
@ -96,72 +121,118 @@ addGeometryToScene
{ {
if (!visible_) if (!visible_)
{ {
return; return false;
} }
vtkSmartPointer<vtkPolyData> polyData;
bool good = true;
// The vtkCloud stores 'file' via the stateFunctionObject // The vtkCloud stores 'file' via the stateFunctionObject
// (lookup by cloudName). // (lookup by cloudName).
// It only generates VTP format, which means there is a single file // It only generates VTP format, which means there is a single file
// containing all fields. // containing all fields.
inputFileName_ = getFileName("file", cloudName_); if (Pstream::master())
if (inputFileName_.empty())
{ {
WarningInFunction inputFileName_ = getFileName("file", cloudName_);
<< "Unable to find function object " << functionObjectName_
<< " output for field " << fieldName_
<< ". Cloud will not be processed"
<< endl;
return;
}
if (inputFileName_.size())
{
polyData = getPolyDataFile(inputFileName_);
vtkSmartPointer<vtkPolyData> dataset; if (!polyData || polyData->GetNumberOfPoints() == 0)
{
good = false;
if (inputFileName_.hasExt("vtp")) WarningInFunction
{ << "Could not read "<< inputFileName_ << nl
auto reader = vtkSmartPointer<vtkXMLPolyDataReader>::New(); << "Only VTK (.vtp) files are supported"
reader->SetFileName(inputFileName_.c_str()); << endl;
reader->Update(); }
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 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(); 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(); auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
actor_->SetMapper(mapper); actor_->SetMapper(mapper);
/// dataset->Print(std::cout);
addGlyphs addGlyphs
( (
position, position,
fieldName_, fieldName_, scaleFieldInfo, // scaling
colourFieldName_, colourFieldName_, colourFieldInfo, // colour
maxGlyphLength_, maxGlyphLength_,
dataset, polyData,
actor_, actor_,
renderer renderer
); );
renderer->AddActor(actor_); 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 const scalar position
) )
{ {
actor_->GetProperty()->SetOpacity(opacity(position)); if (actor_)
{
const vector colour = pointColour_->value(position);
vector pc = pointColour_->value(position); vtkProperty* prop = actor_->GetProperty();
actor_->GetProperty()->SetColor(pc[0], pc[1], pc[2]);
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 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -27,7 +25,17 @@ Class
Foam::functionObjects::runTimePostPro::functionObjectCloud Foam::functionObjects::runTimePostPro::functionObjectCloud
Description 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 SourceFiles
functionObjectCloud.C functionObjectCloud.C
@ -87,7 +95,7 @@ protected:
public: public:
//- Run-time type information //- Run-time type information
TypeName("functionObjectCloud"); TypeNameNoDebug("functionObjectCloud");
// Constructors // Constructors
@ -107,7 +115,14 @@ public:
// Member Functions // 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 virtual void addGeometryToScene
( (
const scalar position, const scalar position,

View File

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

View File

@ -2,10 +2,8 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -27,7 +25,13 @@ Class
Foam::functionObjects::runTimePostPro::functionObjectLine Foam::functionObjects::runTimePostPro::functionObjectLine
Description 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 SourceFiles
functionObjectLine.C functionObjectLine.C
@ -78,7 +82,7 @@ protected:
public: public:
//- Run-time type information //- Run-time type information
TypeName("functionObjectLine"); TypeNameNoDebug("functionObjectLine");
// Constructors // Constructors

View File

@ -2,10 +2,8 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2015-2016 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -32,6 +30,13 @@ License
// VTK includes // VTK includes
#include "vtkActor.h" #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 "vtkPolyData.h"
#include "vtkPolyDataMapper.h" #include "vtkPolyDataMapper.h"
#include "vtkProperty.h" #include "vtkProperty.h"
@ -50,7 +55,7 @@ namespace functionObjects
{ {
namespace runTimePostPro namespace runTimePostPro
{ {
defineTypeNameAndDebug(functionObjectSurface, 0); defineTypeName(functionObjectSurface);
addToRunTimeSelectionTable(surface, functionObjectSurface, dictionary); addToRunTimeSelectionTable(surface, functionObjectSurface, dictionary);
} }
} }
@ -67,7 +72,7 @@ static vtkSmartPointer<vtkPolyData> getPolyDataFile(const Foam::fileName& fName)
// Not extremely elegant... // Not extremely elegant...
vtkSmartPointer<vtkPolyData> dataset; vtkSmartPointer<vtkPolyData> dataset;
if (fName.ext() == "vtk") if ("vtk" == fName.ext())
{ {
auto reader = vtkSmartPointer<vtkPolyDataReader>::New(); auto reader = vtkSmartPointer<vtkPolyDataReader>::New();
@ -78,7 +83,7 @@ static vtkSmartPointer<vtkPolyData> getPolyDataFile(const Foam::fileName& fName)
return dataset; return dataset;
} }
if (fName.ext() == "vtp") if ("vtp" == fName.ext())
{ {
auto reader = vtkSmartPointer<vtkXMLPolyDataReader>::New(); auto reader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
@ -110,17 +115,10 @@ functionObjectSurface
{} {}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::functionObjects::runTimePostPro::functionObjectSurface::
~functionObjectSurface()
{}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
void Foam::functionObjects::runTimePostPro::functionObjectSurface:: bool Foam::functionObjects::runTimePostPro::functionObjectSurface::
addGeometryToScene addGeometry
( (
const scalar position, const scalar position,
vtkRenderer* renderer vtkRenderer* renderer
@ -128,39 +126,291 @@ addGeometryToScene
{ {
if (!visible_) if (!visible_)
{ {
return; return false;
} }
fileName fName = getFileName("file", fieldName_); DebugInfo << " Resolve surface " << functionObjectName_ << endl;
if (fName.empty())
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 WarningInFunction
<< "Unable to read file name from function object " << "No functionObject surface, or has no faces: "
<< functionObjectName_ << " for field " << fieldName_ << functionObjectName_
<< ". Surface will not be processed"
<< endl; << 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 multiPiece = gatherFaceCentres(surf);
<< "Could not read "<< fName << nl
<< "Only VTK (.vtp, .vtk) files are supported"
<< endl;
return;
} }
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) if (representation_ == rtGlyph)
{ {
addGlyphs addGlyphs
( (
position, position,
fieldName_, fieldName_, fieldInfo, // scaling
fieldName_, fieldName_, fieldInfo, // colouring
maxGlyphLength_, maxGlyphLength_,
polyData, polyData,
surfaceActor_, surfaceActor_,
@ -174,7 +424,14 @@ addGeometryToScene
auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputData(polyData); mapper->SetInputData(polyData);
setField(position, fieldName_, mapper, renderer, polyData); setField
(
position,
fieldName_,
queryFieldAssociation(fieldName_, polyData),
mapper,
renderer
);
surfaceActor_->SetMapper(mapper); surfaceActor_->SetMapper(mapper);
@ -182,6 +439,44 @@ addGeometryToScene
renderer->AddActor(surfaceActor_); 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()) if (functionObjectBase::clear())
{ {
// Even for a "live" data source we allow file cleanup
// (eg, from a previous run, etc)
return removeFile("file", fieldName_); return removeFile("file", fieldName_);
} }

View File

@ -2,10 +2,8 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -27,7 +25,22 @@ Class
Foam::functionObjects::runTimePostPro::functionObjectSurface Foam::functionObjects::runTimePostPro::functionObjectSurface
Description 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 SourceFiles
functionObjectfunctionObjectSurface.C functionObjectfunctionObjectSurface.C
@ -72,7 +85,7 @@ protected:
public: public:
//- Run-time type information //- Run-time type information
TypeName("functionObjectSurface"); TypeNameNoDebug("functionObjectSurface");
// Constructors // Constructors
@ -87,11 +100,25 @@ public:
//- Destructor //- Destructor
virtual ~functionObjectSurface(); virtual ~functionObjectSurface() = default;
// Member Functions // 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 //- Add functionObjectSurface(s) to scene
virtual void addGeometryToScene virtual void addGeometryToScene
( (

View File

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

View File

@ -2,10 +2,8 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -27,12 +25,12 @@ Class
Foam::functionObjects::runTimePostPro::geometryBase Foam::functionObjects::runTimePostPro::geometryBase
Description Description
Base class for surface, text handling Base class for surface, text handling etc.
Dictionary controls Dictionary controls
\table \table
Property | Description | Required | Default Property | Description | Required | Default
visible | Display the object | yes | visible | Display the object | no | yes
renderMode | Shading (flat/gouraud/phong) | no | gouraud renderMode | Shading (flat/gouraud/phong) | no | gouraud
opacity | Object opacity | no | 1.0 opacity | Object opacity | no | 1.0
\endtable \endtable
@ -53,7 +51,7 @@ SourceFiles
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Forward declarations // Forward Declarations (VTK)
class vtkRenderer; class vtkRenderer;
class vtkActor; class vtkActor;
@ -62,7 +60,7 @@ namespace Foam
namespace functionObjects namespace functionObjects
{ {
// Forward declarations // Forward Declarations
class runTimePostProcessing; class runTimePostProcessing;
namespace runTimePostPro namespace runTimePostPro
@ -75,11 +73,11 @@ namespace runTimePostPro
class geometryBase class geometryBase
{ {
public: public:
// Public enumerations // Public Enumerations
//- Surface shading types
enum renderModeType enum renderModeType
{ {
rmFlat, //!< Flat shading rmFlat, //!< Flat shading
@ -87,6 +85,7 @@ public:
rmPhong //!< Phong shading rmPhong //!< Phong shading
}; };
//- Names for surface shading types
static const Enum<renderModeType> renderModeTypeNames; static const Enum<renderModeType> renderModeTypeNames;
@ -97,7 +96,7 @@ protected:
//- Reference to the parent function object //- Reference to the parent function object
const runTimePostProcessing& parent_; const runTimePostProcessing& parent_;
//- Name //- The surface name
word name_; word name_;
//- Visible flag //- Visible flag
@ -113,7 +112,7 @@ protected:
const HashPtrTable<Function1<vector>>& colours_; const HashPtrTable<Function1<vector>>& colours_;
// Protected functions // Protected Functions
//- Initialise actor //- Initialise actor
void initialiseActor(vtkActor* actor) const; void initialiseActor(vtkActor* actor) const;
@ -127,6 +126,9 @@ protected:
public: public:
//- Debug switch
static int debug;
// Constructors // Constructors
//- Construct from dictionary //- Construct from dictionary
@ -149,6 +151,10 @@ public:
//- Return the reference to the parent function object //- Return the reference to the parent function object
const runTimePostProcessing& parent() const; 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 //- Return the name
const word& name() const; const word& name() const;
@ -162,7 +168,7 @@ public:
const HashPtrTable<Function1<vector>>& colours() const; const HashPtrTable<Function1<vector>>& colours() const;
// Scene interaction // Scene Interaction
//- Add geometry to scene //- Add geometry to scene
virtual void addGeometryToScene virtual void addGeometryToScene
@ -174,7 +180,7 @@ public:
//- Update the actors //- Update the actors
virtual void updateActors(const scalar position) = 0; 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; 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 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -77,7 +75,7 @@ static vtkSmartPointer<vtkPolyData> getPolyDataFile(const Foam::fileName& fName)
// Not extremely elegant... // Not extremely elegant...
vtkSmartPointer<vtkPolyData> dataset; vtkSmartPointer<vtkPolyData> dataset;
if (fName.ext() == "vtk") if ("vtk" == fName.ext())
{ {
auto reader = vtkSmartPointer<vtkPolyDataReader>::New(); auto reader = vtkSmartPointer<vtkPolyDataReader>::New();
@ -88,7 +86,7 @@ static vtkSmartPointer<vtkPolyData> getPolyDataFile(const Foam::fileName& fName)
return dataset; return dataset;
} }
if (fName.ext() == "vtp") if ("vtp" == fName.ext())
{ {
auto reader = vtkSmartPointer<vtkXMLPolyDataReader>::New(); auto reader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
@ -99,7 +97,7 @@ static vtkSmartPointer<vtkPolyData> getPolyDataFile(const Foam::fileName& fName)
return dataset; return dataset;
} }
if (fName.ext() == "obj") if ("obj" == fName.ext())
{ {
auto reader = vtkSmartPointer<vtkOBJReader>::New(); auto reader = vtkSmartPointer<vtkOBJReader>::New();
@ -110,7 +108,7 @@ static vtkSmartPointer<vtkPolyData> getPolyDataFile(const Foam::fileName& fName)
return dataset; return dataset;
} }
if (fName.ext() == "stl" || fName.ext() == "stlb") if ("stl" == fName.ext() || "stlb" == fName.ext())
{ {
auto reader = vtkSmartPointer<vtkSTLReader>::New(); auto reader = vtkSmartPointer<vtkSTLReader>::New();
@ -147,6 +145,12 @@ void Foam::functionObjects::runTimePostPro::geometrySurface::addGeometryToScene
const fileName& fName const fileName& fName
) const ) const
{ {
// Master-only, since that is where the files are.
if (!visible_ || !renderer || !Pstream::master())
{
return;
}
if (representation_ == rtGlyph) if (representation_ == rtGlyph)
{ {
FatalErrorInFunction FatalErrorInFunction
@ -154,9 +158,11 @@ void Foam::functionObjects::runTimePostPro::geometrySurface::addGeometryToScene
<< " object" << exit(FatalError); << " object" << exit(FatalError);
} }
DebugInfo << " Add geometry surface: " << fName << nl;
auto surf = getPolyDataFile(fName); auto surf = getPolyDataFile(fName);
if (!surf || surf->GetNumberOfPoints() == 0) if (!surf || !surf->GetNumberOfPoints())
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Could not read "<< fName << nl << "Could not read "<< fName << nl

View File

@ -2,10 +2,8 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -27,7 +25,18 @@ Class
Foam::functionObjects::runTimePostPro::geometrySurface Foam::functionObjects::runTimePostPro::geometrySurface
Description 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 SourceFiles
geometrySurface.C geometrySurface.C
@ -41,7 +50,7 @@ SourceFiles
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Forward declarations // Forward Declarations
class vtkPolyData; class vtkPolyData;
namespace Foam namespace Foam
@ -61,7 +70,7 @@ class geometrySurface
{ {
protected: protected:
// Protected data // Protected Data
//- File names //- File names
List<fileName> fileNames_; List<fileName> fileNames_;
@ -126,7 +135,7 @@ public:
//- Update actors //- Update actors
virtual void updateActors(const scalar position); 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(); virtual bool clear();
}; };

View File

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

View File

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

View File

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

View File

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

View File

@ -2,10 +2,8 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -34,6 +32,7 @@ License
#include "text.H" #include "text.H"
#include "Time.H" #include "Time.H"
#include "sigFpe.H" #include "sigFpe.H"
#include "polySurfaceFields.H"
#include "addToRunTimeSelectionTable.H" #include "addToRunTimeSelectionTable.H"
// VTK includes // VTK includes
@ -43,6 +42,16 @@ License
#include "vtkSmartPointer.h" #include "vtkSmartPointer.h"
#include "vtkLight.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 * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam namespace Foam
@ -103,6 +112,168 @@ static void cleanup(PtrList<Type>& objects)
} // End namespace Foam } // 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 * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::runTimePostProcessing::runTimePostProcessing Foam::functionObjects::runTimePostProcessing::runTimePostProcessing
@ -113,6 +284,8 @@ Foam::functionObjects::runTimePostProcessing::runTimePostProcessing
) )
: :
fvMeshFunctionObject(name, runTime, dict), fvMeshFunctionObject(name, runTime, dict),
output_(),
parallel_(false),
scene_(runTime, name), scene_(runTime, name),
points_(), points_(),
lines_(), lines_(),
@ -129,7 +302,20 @@ bool Foam::functionObjects::runTimePostProcessing::read(const dictionary& dict)
{ {
fvMeshFunctionObject::read(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); scene_.read(dict);
@ -179,68 +365,7 @@ bool Foam::functionObjects::runTimePostProcessing::execute()
bool Foam::functionObjects::runTimePostProcessing::write() bool Foam::functionObjects::runTimePostProcessing::write()
{ {
if (!Pstream::master()) render();
{
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();
return true; return true;
} }

View File

@ -2,10 +2,8 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -56,9 +54,53 @@ Description
- Selection of colour maps - Selection of colour maps
. .
Scene configuration is performed using standard OpenFOAM dictionaries, using Mandatory entries:
the main headings of: output=, camera, colours, points, lines, \verbatim
surfaces and text. 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 SourceFiles
runTimePostProcessing.C runTimePostProcessing.C
@ -76,14 +118,20 @@ SourceFiles
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Forward declarations // Forward Declarations
class vtkRenderer; class vtkMultiPieceDataSet;
class vtkMultiProcessController;
class vtkRenderWindow; class vtkRenderWindow;
class vtkRenderer;
template<class T> class vtkSmartPointer;
namespace Foam namespace Foam
{ {
namespace functionObjects namespace functionObjects
{ {
// Forward declarations
class runTimePostProcessing;
namespace runTimePostPro namespace runTimePostPro
{ {
// Forward declarations // Forward declarations
@ -101,11 +149,9 @@ class runTimePostProcessing
: :
public fvMeshFunctionObject public fvMeshFunctionObject
{ {
private: // Private Data
// Private data //- Output information
// Output
struct outputType struct outputType
{ {
word name_; word name_;
@ -116,6 +162,9 @@ private:
//- Output instance //- Output instance
outputType output_; outputType output_;
//- Parallel rendering
bool parallel_;
//- Scene manager //- Scene manager
runTimePostPro::scene scene_; runTimePostPro::scene scene_;
@ -138,6 +187,15 @@ private:
template<class Type> template<class Type>
void readObjects(const dictionary& dict, PtrList<Type>& objects) const; 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: public:
@ -162,11 +220,26 @@ public:
// Member Functions // 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 const fvMesh& mesh() const
{ {
return mesh_; return mesh_;
} }
//- Read the post-processing controls //- Read the post-processing controls
virtual bool read(const dictionary& dict); virtual bool read(const dictionary& dict);

View File

@ -2,10 +2,8 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. 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 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -137,6 +135,8 @@ void Foam::functionObjects::runTimePostPro::scene::setActorVisibility
const bool visible const bool visible
) const ) const
{ {
if (!renderer) return;
vtkActorCollection *actors = renderer->GetActors(); vtkActorCollection *actors = renderer->GetActors();
for (int i = 0; i < actors->GetNumberOfItems(); ++i) for (int i = 0; i < actors->GetNumberOfItems(); ++i)
{ {
@ -157,27 +157,30 @@ void Foam::functionObjects::runTimePostPro::scene::initialise
outputName_ = outputName; outputName_ = outputName;
if (!renderer) return;
// Set the background // Set the background
const vector backgroundColour = colours_["background"]->value(position_); const vector bgColour = colours_["background"]->value(position_);
renderer->SetBackground
( renderer->SetBackground(bgColour.x(), bgColour.y(), bgColour.z());
backgroundColour.x(),
backgroundColour.y(),
backgroundColour.z()
);
// Apply gradient background if "background2" defined // Apply gradient background if "background2" defined
if (colours_.found("background2")) if (colours_.found("background2"))
{ {
renderer->GradientBackgroundOn(); const vector bg2Colour = colours_["background2"]->value(position_);
vector backgroundColour2 = colours_["background2"]->value(position_);
renderer->SetBackground2 renderer->GradientBackgroundOn();
( renderer->SetBackground2(bg2Colour.x(), bg2Colour.y(), bg2Colour.z());
backgroundColour2.x(), }
backgroundColour2.y(), else if (Pstream::parRun())
backgroundColour2.z() {
); // 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 // Depth peeling
@ -224,6 +227,8 @@ void Foam::functionObjects::runTimePostPro::scene::setCamera
vtkRenderer* renderer vtkRenderer* renderer
) const ) const
{ {
if (!renderer) return;
vtkCamera* camera = renderer->GetActiveCamera(); vtkCamera* camera = renderer->GetActiveCamera();
if (parallelProjection_) if (parallelProjection_)
@ -355,14 +360,18 @@ bool Foam::functionObjects::runTimePostPro::scene::loop(vtkRenderer* renderer)
return true; return true;
} }
// Ensure that all objects can be seen without clipping if (renderer)
// Note: can only be done after all objects have been added! {
renderer->ResetCameraClippingRange();
// Save image from last iteration // Ensure that all objects can be seen without clipping
saveImage(renderer->GetRenderWindow()); // 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_; position_ = startPosition_ + currentFrameI_*dPosition_;
@ -390,16 +399,15 @@ void Foam::functionObjects::runTimePostPro::scene::saveImage
const Time& runTime = obr_.time(); const Time& runTime = obr_.time();
const fileName prefix const fileName fName
( (
runTime.globalPath() runTime.globalPath()
/ functionObject::outputPrefix / functionObject::outputPrefix
/ name_ / name_
/ runTime.timeName() / runTime.timeName()
/ outputName_ + '.' + frameIndexStr() + ".png"
); );
mkDir(prefix);
renderWindow->Render(); renderWindow->Render();
// Set up off-screen rendering // Set up off-screen rendering
@ -415,15 +423,21 @@ void Foam::functionObjects::runTimePostPro::scene::saveImage
windowToImageFilter->Update(); windowToImageFilter->Update();
// Save the image // 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 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -48,6 +46,10 @@ Usage
viewAngle 20; viewAngle 20;
zoom 1.1; zoom 1.1;
} }
colours
{
}
\endverbatim \endverbatim
SourceFiles SourceFiles

View File

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

View File

@ -2,10 +2,8 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -27,10 +25,23 @@ Class
Foam::functionObjects::runTimePostPro::surface Foam::functionObjects::runTimePostPro::surface
Description 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 SourceFiles
surface.C surface.C
surfaceGather.C
surfaceTemplates.C
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -38,17 +49,80 @@ SourceFiles
#define functionObjects_runTimePostPro_surface_H #define functionObjects_runTimePostPro_surface_H
#include "geometryBase.H" #include "geometryBase.H"
#include "DimensionedField.H"
#include "Enum.H" #include "Enum.H"
#include "runTimeSelectionTables.H" #include "runTimeSelectionTables.H"
#include "vtkSmartPointer.h" #include "vtkSmartPointer.h"
#include "vtkMultiPieceDataSet.h"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Forward declarations // Forward Declarations
class vtkActor; class vtkActor;
class vtkRenderer; class vtkRenderer;
class vtkCellData;
class vtkCompositeDataGeometryFilter;
class vtkFeatureEdges;
class vtkPointData;
class vtkPolyData; 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 Foam
{ {
namespace functionObjects namespace functionObjects
@ -68,21 +142,23 @@ public:
// Public enumerations // Public enumerations
//- Surface representation types
enum representationType enum representationType
{ {
rtNone, rtNone, //!< "none"
rtWireframe, rtGlyph, //!< "glyph"
rtSurface, rtWireframe, //!< "wireframe"
rtSurfaceWithEdges, rtSurface, //!< "surface"
rtGlyph rtSurfaceWithEdges //!< "surfaceWithEdges"
}; };
//- Names for surface representation types
static const Enum<representationType> representationTypeNames; static const Enum<representationType> representationTypeNames;
protected: protected:
// Protected data // Protected Data
//- Representation type //- Representation type
representationType representation_; representationType representation_;
@ -111,6 +187,13 @@ protected:
//- Set the representation //- Set the representation
void setRepresentation(vtkActor* actor) const; void setRepresentation(vtkActor* actor) const;
//- Add feature edges to scene
void addFeatureEdges
(
vtkRenderer* renderer,
vtkFeatureEdges* featureEdges
) const;
//- Add feature edges to scene //- Add feature edges to scene
void addFeatureEdges void addFeatureEdges
( (
@ -118,6 +201,110 @@ protected:
vtkPolyData* data vtkPolyData* data
) const; ) 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 //- No copy construct
surface(const surface&) = delete; surface(const surface&) = delete;
@ -128,7 +315,7 @@ protected:
public: public:
//- Run-time type information //- Run-time type information
TypeName("surface"); TypeNameNoDebug("surface");
// Declare run-time constructor selection table // Declare run-time constructor selection table
@ -160,7 +347,7 @@ public:
// Selectors // Selectors
//- Return a reference to the selected RAS model //- Return selected surface
static autoPtr<surface> New static autoPtr<surface> New
( (
const runTimePostProcessing& parent, const runTimePostProcessing& parent,
@ -189,6 +376,12 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "surfaceTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#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 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -27,10 +25,12 @@ License
// OpenFOAM includes // OpenFOAM includes
#include "text.H" #include "text.H"
#include "stringOps.H"
#include "fvMesh.H" #include "fvMesh.H"
#include "runTimePostProcessing.H" #include "runTimePostProcessing.H"
// VTK includes // VTK includes
#include "vtkCoordinate.h"
#include "vtkRenderer.h" #include "vtkRenderer.h"
#include "vtkSmartPointer.h" #include "vtkSmartPointer.h"
#include "vtkTextActor.h" #include "vtkTextActor.h"
@ -62,7 +62,7 @@ Foam::functionObjects::runTimePostPro::text::text
: :
geometryBase(parent, dict, colours), geometryBase(parent, dict, colours),
string_(dict.get<string>("string")), string_(dict.get<string>("string")),
position_(), positions_(),
size_(dict.get<scalar>("size")), size_(dict.get<scalar>("size")),
colour_(nullptr), colour_(nullptr),
halign_ halign_
@ -74,7 +74,20 @@ Foam::functionObjects::runTimePostPro::text::text
shadow_(dict.lookupOrDefault("shadow", false)), shadow_(dict.lookupOrDefault("shadow", false)),
timeStamp_(dict.lookupOrDefault("timeStamp", 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")) if (dict.found("colour"))
{ {
@ -101,12 +114,13 @@ void Foam::functionObjects::runTimePostPro::text::addGeometryToScene
vtkRenderer* renderer vtkRenderer* renderer
) )
{ {
if (!visible_) if (!visible_ || !renderer || !Pstream::master())
{ {
// Add text on master only!
return; return;
} }
auto actor = vtkSmartPointer<vtkTextActor>::New(); DebugInfo << " Add text: " << string_ << nl;
// Concatenate string with timeStamp if true // Concatenate string with timeStamp if true
string str = string_; string str = string_;
@ -114,31 +128,40 @@ void Foam::functionObjects::runTimePostPro::text::addGeometryToScene
{ {
str += " " + geometryBase::parent_.mesh().time().timeName(); str += " " + geometryBase::parent_.mesh().time().timeName();
} }
actor->SetInput(str.c_str());
vtkTextProperty* prop = actor->GetTextProperty(); const vector textColour = colour_->value(position);
prop->SetFontFamilyToArial(); const scalar textOpacity = opacity(position);
prop->SetFontSize(size_);
prop->SetJustification(int(halign_));
prop->SetVerticalJustificationToBottom();
prop->SetBold(bold_);
prop->SetItalic(italic_);
prop->SetShadow(shadow_);
const vector colour = colour_->value(position); for (const auto& textPosition : positions_)
{
auto actor = vtkSmartPointer<vtkTextActor>::New();
prop->SetColor(colour[0], colour[1], colour[2]); actor->SetInput(str.c_str());
prop->SetOpacity(opacity(position));
actor->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport(); vtkTextProperty* prop = actor->GetTextProperty();
actor->GetPositionCoordinate()->SetValue
(
position_.first(),
position_.second()
);
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 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\ / A nd | Copyright (C) 2015-2019 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2015 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -41,7 +39,6 @@ Description
// Optional entry // Optional entry
shadow false; shadow false;
visible yes;
// Optionally override default colour // Optionally override default colour
// colour (0 1 1); // colour (0 1 1);
@ -56,6 +53,7 @@ Description
Property | Description | Required | Default Property | Description | Required | Default
string | Text to display | yes | string | Text to display | yes |
position | The (x y) viewport position | yes | position | The (x y) viewport position | yes |
positions | Multiple (x y) viewport positions | no |
size | The font size in points | yes | size | The font size in points | yes |
halign | Text justification (left/centre/ right) | no | left halign | Text justification (left/centre/ right) | no | left
bold | Use bold font | yes | bold | Use bold font | yes |
@ -68,10 +66,14 @@ Description
Inherited controls Inherited controls
\table \table
Property | Description | Required | Default Property | Description | Required | Default
visible | Display the object | yes | visible | Display the object | no | true
opacity | Object opacity | no | 1.0 opacity | Object opacity | no | 1.0
\endtable \endtable
Note
The string text is expanded on input using stringOps::inplaceExpand()
to expand dictionary and environment variable entries.
SourceFiles SourceFiles
text.C text.C
@ -85,7 +87,7 @@ SourceFiles
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Forward declarations // Forward Declarations
class vtkRenderer; class vtkRenderer;
namespace Foam namespace Foam
@ -96,7 +98,7 @@ namespace runTimePostPro
{ {
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class text Declaration Class text Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
class text class text
@ -105,9 +107,9 @@ class text
{ {
public: public:
// Public enumerations // Public Enumerations
//- Horizontal alignment type //- Horizontal alignment type. Values to match VTK definitions
enum halignType enum halignType
{ {
LEFT = 0, //!< Left-justified text - default ("left") LEFT = 0, //!< Left-justified text - default ("left")
@ -126,13 +128,13 @@ protected:
//- Text //- Text
string string_; string string_;
//- Position //- Position(s)
Tuple2<scalar, scalar> position_; List<Tuple2<scalar, scalar>> positions_;
//- Size //- Font size
scalar size_; scalar size_;
//- Colour //- Text colour
autoPtr<Function1<vector>> colour_; autoPtr<Function1<vector>> colour_;
//- Horizontal alignment //- Horizontal alignment
@ -179,7 +181,7 @@ public:
// Member Functions // Member Functions
//- Add surface(s) to scene //- Add text to scene
virtual void addGeometryToScene virtual void addGeometryToScene
( (
const scalar position, const scalar position,
@ -189,7 +191,7 @@ public:
//- Update actors //- Update actors
virtual void updateActors(const scalar position); 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(); 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 functions
{ {
#include "sampling" // Demonstrate runTimePostProcessing
#include "streamLines" #include "visualization"
#include "runTimePostProcessing"
} }
// ************************************************************************* // // ************************************************************************* //

View File

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

View File

@ -10,7 +10,8 @@ streamLines
{ {
type streamLine; type streamLine;
writeControl writeTime; // Time control etc
${_visualization};
setFormat vtk; 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 functions
{ {
// Demonstrate runtime postprocessing // Demonstrate runTimePostProcessing
#include "streamLines" #include "visualization"
#include "cuttingPlane"
#include "runTimePostProcessing"
// Do some other functionObjects // Do some other functionObjects
#include "forceCoeffs" #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 postPro1
{ {
type runTimePostProcessing; #includeEtc "caseDicts/postProcessing/visualization/runTimePostPro.cfg"
libs ("librunTimePostProcessing.so");
writeControl writeTime; // Time control etc
${_visualization};
// debug true;
// parallel true;
output output
{ {
name image; name image;
width 2000; width 2000;
height 1200; height 1200;
} }
// Default colours. Used for colourBy == colour unless locally overridden
colours
{
${..colourScheme.blueGradient};
}
camera camera
{ {
// If camera is moving, optionally provide start and end times // If camera is moving, optionally provide start and end times
@ -19,27 +39,15 @@ postPro1
nFrameTotal 1; nFrameTotal 1;
// Parallel projection flag // Parallel projection flag
parallelProjection no; parallelProjection off;
clipBox (-0.2 -0.2 0)(1.65 0.2 1.25); // optional clipBox (-0.2 -0.2 0)(1.65 0.2 1.25); // optional
focalPoint (1.2 1.1 0.2); focalPoint (1.2 1.1 0.2);
up (0 0 1);
position (3.6 5.1 -1.3); 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 // Line data
lines lines
{ {
@ -47,8 +55,9 @@ postPro1
{ {
type functionObjectLine; type functionObjectLine;
functionObject streamLines; functionObject streamLines;
colourMap rainbow;
representation tube; representation tube;
visible yes; visible true;
tubeRadius 0.01; tubeRadius 0.01;
colourBy field; colourBy field;
field U; field U;
@ -56,13 +65,17 @@ postPro1
opacity 1; opacity 1;
scalarBar scalarBar
{ {
visible yes; visible true;
position (0.8 0.1); position (0.8 0.1);
vertical yes; vertical yes;
fontSize 16; fontSize 16;
title "velocity / [m/s]"; title "velocity [m/s]";
labelFormat "%6.2f"; labelFormat "%6.2f";
numberOfLabels 5; numberOfLabels 5;
bold true;
italic true;
italic true;
colour (0.75 0.75 0.75);
} }
} }
} }
@ -77,27 +90,40 @@ postPro1
renderMode phong; renderMode phong;
representation surface; representation surface;
edgeColour (0 0 0); edgeColour (0 0 0);
visible yes;
featureEdges yes; featureEdges yes;
opacity 1; 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; type functionObjectSurface;
functionObject cuttingPlane; functionObject samples.yNormal;
colourMap blueWhiteRed; colourMap coolToWarm;
representation glyph; representation glyph;
maxGlyphLength 0.1; maxGlyphLength 0.1;
visible yes; visible true;
featureEdges no; featureEdges no;
colourBy field; colourBy field;
field U; field U;
range (0 30); range (0 30);
opacity 1; opacity 1;
scalarBar
{
visible no;
}
} }
} }
@ -106,11 +132,14 @@ postPro1
{ {
text1 text1
{ {
string "Motorbike"; visible true;
position (0.1 0.05); string "Motorbike";
size 72; position (0.1 0.05);
bold yes; size 72;
visible yes; bold true;
italic true;
} }
} }
} }
// ************************************************************************* //

View File

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

View File

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

View File

@ -8,11 +8,10 @@
streamLines streamLines
{ {
type streamLine; type streamLine;
// Output every // Time control etc
writeControl writeTime; ${_visualization};
// writeInterval 10;
setFormat vtk; //gnuplot; //xmgr; //raw; //jplot; //csv; //ensight; 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 "ensightWrite"
#include "vtkWrite" #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 functions
{ {
#include "dataCloud"
#include "vtkCloud" #include "vtkCloud"
// #include "dataCloud"
#include "runTimePostProcessing" #include "runTimePostProcessing"
} }

View File

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