OpenFOAM: v1912 released! - For more information see https://www.openfoam.com/releases/openfoam-v1912

Commit 82a83cab authored by Mark Olesen's avatar Mark Olesen

Merge branch 'feature-unified-output' into 'develop'

Feature unified output

Closes #3 and #4

See merge request !1
parents 14eaf2dd 4f692e4d
What:
Library and function object for embedding the ParaView Catalyst
into OpenFOAM.
Requirements:
OpenFOAM.com development version (April-2018 or newer) or OpenFOAM-v1806.
ParaView or ParaView Catalyst 5.4 or newer, compiled with mpi and
python support.
Authors:
Mark Olesen <Mark.Olesen@esi-group.com>
Simone Bna <Simone.Bna@cineca.it>
License:
Same terms as OpenFOAM.
Licensed under GNU General Public License <http://www.gnu.org/licenses/>.
## What
Library and function object for embedding ParaView Catalyst into OpenFOAM.
## Requirements
1. OpenFOAM.com development version (11-May-2018 or newer) or OpenFOAM-v1806.
2. ParaView or ParaView Catalyst 5.5 or newer, compiled with mpi and
python support.
It is highly recommended to patch the ParaView 5.5 sources (eg,
using the OpenFOAM ThirdParty makeParaView script) to ensure that
they properly handle outputting results in directories other than
the main simulation directory:
* [MR2433]
* [MR2436]
## Authors
* Mark Olesen <Mark.Olesen@esi-group.com>
* Simone Bna <Simone.Bna@cineca.it>
## License
Same terms as OpenFOAM.
Licensed under GNU General Public License <http://www.gnu.org/licenses/>.
[MR2433]: https://gitlab.kitware.com/paraview/paraview/merge_requests/2433
[MR2436]: https://gitlab.kitware.com/paraview/paraview/merge_requests/2436
......@@ -10,7 +10,6 @@ def CreateCoProcessor():
def _CreatePipeline(coprocessor, datadescription):
class Pipeline:
for i in range(datadescription.GetNumberOfInputDescriptions()):
inputdescription = datadescription.GetInputDescription(i)
name = datadescription.GetInputDescriptionName(i)
adaptorinput = coprocessor.CreateProducer(datadescription, name)
grid = adaptorinput.GetClientSideObject().GetOutputDataObject(0)
......@@ -40,7 +39,7 @@ def CreateCoProcessor():
print("Don't know how to create a writer for a ", grid.GetClassName())
if extension:
coprocessor.RegisterWriter(writer, filename='insitu/'+name+'_%t'+extension, freq=outputfrequency)
coprocessor.RegisterWriter(writer, filename=name+'_%t'+extension, freq=outputfrequency)
return Pipeline()
......
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: plus |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
// Insitu processing of finiteArea fields with ParaView Catalyst
type catalyst::area;
libs ("libcatalystFoam.so");
executeControl timeStep;
writeControl none;
// ************************************************************************* //
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: plus |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
// Insitu processing of lagrangian clouds with ParaView Catalyst
type catalyst::cloud;
libs ("libcatalystFoam.so");
executeControl timeStep;
writeControl none;
// ************************************************************************* //
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: plus |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
// Insitu processing of finiteVolume fields with ParaView Catalyst
type catalyst;
libs ("libcatalystFoam.so");
executeControl timeStep;
writeControl none;
// ************************************************************************* //
from paraview.simple import *
from paraview import coprocessing
# ----------------------- CoProcessor definition -----------------------
def CreateCoProcessor():
def _CreatePipeline(coprocessor, datadescription):
class Pipeline:
input1 = coprocessor.CreateProducer(datadescription, 'input')
writer1 = servermanager.writers.XMLMultiBlockDataWriter(Input=input1)
coprocessor.RegisterWriter(writer1, filename='insitu/area_%t.vtm', freq=2)
return Pipeline()
class CoProcessor(coprocessing.CoProcessor):
def CreatePipeline(self, datadescription):
self.Pipeline = _CreatePipeline(self, datadescription)
coprocessor = CoProcessor()
freqs = {'input': [10]}
coprocessor.SetUpdateFrequencies(freqs)
return coprocessor
#--------------------------------------------------------------
# Global variables that will hold the pipeline for each timestep
# Creating the CoProcessor object, doesn't actually create the ParaView pipeline.
# It will be automatically setup when coprocessor.UpdateProducers() is called the
# first time.
coprocessor = CreateCoProcessor()
#--------------------------------------------------------------
# Enable Live-Visualizaton with ParaView
coprocessor.EnableLiveVisualization(True)
# ---------------------- Data Selection method ----------------------
def RequestDataDescription(datadescription):
'Callback to populate the request for current timestep'
global coprocessor
if datadescription.GetForceOutput() == True:
# We are just going to request all fields and meshes from the simulation
# code/adaptor.
for i in range(datadescription.GetNumberOfInputDescriptions()):
datadescription.GetInputDescription(i).AllFieldsOn()
datadescription.GetInputDescription(i).GenerateMeshOn()
return
# setup requests for all inputs based on the requirements of the
# pipeline.
coprocessor.LoadRequestedData(datadescription)
# ------------------------ Processing method ------------------------
def DoCoProcessing(datadescription):
'Callback to do co-processing for current timestep'
global coprocessor
# Update the coprocessor by providing it the newly generated simulation data.
# If the pipeline hasn't been setup yet, this will setup the pipeline.
coprocessor.UpdateProducers(datadescription)
# Write output data, if appropriate.
coprocessor.WriteData(datadescription);
# Write image capture (Last arg: rescale lookup table), if appropriate.
coprocessor.WriteImages(datadescription, rescale_lookuptable=False)
# Live Visualization, if enabled.
coprocessor.DoLiveVisualization(datadescription, 'localhost', 22222)
from paraview.simple import *
from paraview import coprocessing
# ----------------------- CoProcessor definition -----------------------
def CreateCoProcessor():
def _CreatePipeline(coprocessor, datadescription):
class Pipeline:
input1 = coprocessor.CreateProducer(datadescription, 'cloud')
writer1 = servermanager.writers.XMLMultiBlockDataWriter(Input=input1)
# register writer with coprocessor, with filename + output freq
coprocessor.RegisterWriter(writer1, filename='insitu/cloud_%t.vtm', freq=10)
return Pipeline()
class CoProcessor(coprocessing.CoProcessor):
def CreatePipeline(self, datadescription):
self.Pipeline = _CreatePipeline(self, datadescription)
coprocessor = CoProcessor()
freqs = {'cloud': [10]}
coprocessor.SetUpdateFrequencies(freqs)
return coprocessor
#--------------------------------------------------------------
# Global variables that will hold the pipeline for each timestep
# Creating the CoProcessor object, doesn't actually create the ParaView pipeline.
# It will be automatically setup when coprocessor.UpdateProducers() is called the
# first time.
coprocessor = CreateCoProcessor()
#--------------------------------------------------------------
# Enable Live-Visualizaton with ParaView
coprocessor.EnableLiveVisualization(True)
# ---------------------- Data Selection method ----------------------
def RequestDataDescription(datadescription):
'Callback to populate the request for current timestep'
global coprocessor
if datadescription.GetForceOutput() == True:
# We are just going to request all fields and meshes from the simulation
# code/adaptor.
for i in range(datadescription.GetNumberOfInputDescriptions()):
datadescription.GetInputDescription(i).AllFieldsOn()
datadescription.GetInputDescription(i).GenerateMeshOn()
return
# setup requests for all inputs based on the requirements of the
# pipeline.
coprocessor.LoadRequestedData(datadescription)
# ------------------------ Processing method ------------------------
def DoCoProcessing(datadescription):
'Callback to do co-processing for current timestep'
global coprocessor
# Update the coprocessor by providing it the newly generated simulation data.
# If the pipeline hasn't been setup yet, this will setup the pipeline.
coprocessor.UpdateProducers(datadescription)
# Write output data, if appropriate.
coprocessor.WriteData(datadescription);
# Write image capture (Last arg: rescale lookup table), if appropriate.
coprocessor.WriteImages(datadescription, rescale_lookuptable=False)
# Live Visualization, if enabled.
coprocessor.DoLiveVisualization(datadescription, 'localhost', 22222)
......@@ -35,6 +35,26 @@ set(CMAKE_CXX_FLAGS_RELEASE
"-O3 -std=c++11 -Wall -Wextra -Wno-unused-parameter -Wnon-virtual-dtor -Wno-overloaded-virtual")
set(CMAKE_C_FLAGS_RELEASE "-O3 -std=c++11")
# Some characteristics
set(test_file ${CMAKE_CURRENT_BINARY_DIR}/check_initialize.cxx)
file(WRITE ${test_file}
"#include <vtkCPProcessor.h>\n"
"int main() {\n"
" vtkCPProcessor* p = vtkCPProcessor::New();\n"
" p->Initialize(\"AAA\");\n"
" p->Delete();\n"
" return 0;\n"
"}")
try_compile(CATALYST_HAS_WORKING_DIRECTORY
${CMAKE_CURRENT_BINARY_DIR} ${test_file}
LINK_LIBRARIES vtkPVPythonCatalyst
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${PARAVIEW_INCLUDE_DIRS}"
)
if (CATALYST_HAS_WORKING_DIRECTORY)
add_definitions(-DUSE_CATALYST_WORKING_DIRECTORY)
endif()
# Set output library destination to OpenFOAM library directory
set(LIBRARY_OUTPUT_PATH $ENV{FOAM_LIBBIN}
CACHE INTERNAL
......@@ -43,6 +63,9 @@ set(LIBRARY_OUTPUT_PATH $ENV{FOAM_LIBBIN}
file(GLOB SOURCE_FILES
catalystCoprocess.C
catalystTools.C
catalystInput.C
catalystFunctionObject.C
cloud/catalystCloud.C
cloud/foamVtkCloudAdaptor.C
......
This diff is collapsed.
......@@ -22,51 +22,35 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::functionObjects::catalystFaMesh
Group
grpUtilitiesFunctionObjects
Foam::catalyst::faMeshInput
Description
A Paraview Catalyst adaptor for OpenFOAM faMesh regions.
A Paraview Catalyst source for OpenFOAM faMesh regions.
The output comprises a single "input" channel, which is a multi-block
dataset (one block per area mesh).
The source comprises a single internal "input" channel,
which is a multi-block dataset (one block per area mesh).
On output, the "input" sub-channel receives the name of the source.
Example of function object specification:
Example specification:
\verbatim
catalyst
myArea
{
type catalyst::area;
libs ("libcatalystFoam.so");
type area;
fields (U p);
scripts ( ... );
executeControl timeStep;
executeInterval 1;
}
\endverbatim
Usage
\table
Property | Description | Required | Default
type | catalyst::area | yes |
log | report extra information | no | false
mkdir | initial directory to create | no |
type | area | yes |
region | | no | region0
regions | wordRe list of regions | no |
fields | wordRe list of fields | yes |
scripts | Python pipeline scripts | yes |
\endtable
Note
The execution frequency can be defined by the functionObject and
by the Catalyst pipeline.
See also
Foam::functionObjects::functionObject
Foam::functionObjects::fvMeshFunctionObject
Foam::functionObjects::timeControl
Foam::catalystCoprocess
Foam::catalyst::catalystInput
Foam::vtk::faMeshAdaptor
SourceFiles
......@@ -75,82 +59,73 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef functionObjects_catalystFaMesh_H
#define functionObjects_catalystFaMesh_H
#ifndef catalyst_faMeshInput_H
#define catalyst_faMeshInput_H
#include "fvMeshFunctionObject.H"
#include "foamVtkFaMeshAdaptor.H"
#include "wordRes.H"
#include "HashPtrTable.H"
#include "catalystInput.H"
#include "foamVtkFaMeshAdaptor.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declarations
class catalystCoprocess;
namespace functionObjects
namespace catalyst
{
/*---------------------------------------------------------------------------*\
Class catalystFaMesh Declaration
Class catalyst::faMeshInput Declaration
\*---------------------------------------------------------------------------*/
class catalystFaMesh
class faMeshInput
:
public fvMeshFunctionObject
public catalystInput
{
protected:
// Protected data
//- Reference to the time database
const Time& time_;
//- The region name for the area meshes
word regionName_;
//- Requested names of areas to process
wordRes selectAreas_;
//- Names of fields to process
wordRes selectFields_;
//- Python scripts for the catalyst pipeline
stringList scripts_;
//- Pointers to the requested mesh regions
HashTable<const faMesh*> meshes_;
//- Backends for OpenFOAM to VTK translation (with internal caching)
HashPtrTable<vtk::faMeshAdaptor> backends_;
//- The catalyst coprocess
autoPtr<catalystCoprocess> adaptor_;
// Protected Member Functions
//- Common boilerplate settings
bool readBasics(const dictionary& dict);
//- On movement
void updateState(polyMesh::readUpdateState state);
//- Update/synchronize internals with catalyst backends
void update();
//- No copy construct
catalystFaMesh(const catalystFaMesh&) = delete;
faMeshInput(const faMeshInput&) = delete;
//- No copy assignment
void operator=(const catalystFaMesh&) = delete;
void operator=(const faMeshInput&) = delete;
public:
//- Runtime type information
TypeName("catalyst::area");
ClassName("catalyst::faMesh");
// Constructors
//- Construct from Time and dictionary
catalystFaMesh
faMeshInput
(
const word& name,
const Time& runTime,
......@@ -159,7 +134,7 @@ public:
//- Destructor
virtual ~catalystFaMesh();
virtual ~faMeshInput() = default;
// Member Functions
......@@ -167,27 +142,23 @@ public:
//- Read the specification
virtual bool read(const dictionary& dict);
//- Execute catalyst pipelines
virtual bool execute();
//- Write - does nothing
virtual bool write();
//- On end - provide feedback about disconnecting from catatyst.
virtual bool end();
//- Update for changes of mesh or mesh point-motion
virtual void update(polyMesh::readUpdateState state);
//- Update for changes of mesh
virtual void updateMesh(const mapPolyMesh& mpm);
//- Add available channels (with fields) to data query
virtual label addChannels(dataQuery& dataq);
//- Update for mesh point-motion
virtual void movePoints(const polyMesh& mesh);
//- Convert channels to vtkMultiBlockDataSet outputs
virtual bool convert(dataQuery& dataq, outputChannels& outputs);
//- Print information
virtual Ostream& print(Ostream& os) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace functionObjects
} // End namespace catalyst
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
......
......@@ -46,16 +46,6 @@ namespace vtk
}
}
const Foam::Enum
<
Foam::vtk::faMeshAdaptor::channel
>
Foam::vtk::faMeshAdaptor::channelNames
{
{ channel::INPUT, "input" },
};
const Foam::word Foam::vtk::faMeshAdaptor::internalName("internal");
......
......@@ -45,7 +45,6 @@ SourceFiles
#include "fileName.H"
#include "stringList.H"
#include "wordList.H"
#include "Enum.H"
#include "polyMesh.H"
#include "areaFieldsFwd.H"
#include "foamVtkTools.H"
......@@ -89,14 +88,6 @@ public:
//- Public Data Members
//- The Catalyst output channels
enum channel
{
INPUT = 0x3
};
static const Enum<channel> channelNames;
//- Name for internal mesh ("internal")
static const word internalName;
......
......@@ -28,11 +28,6 @@ License
// OpenFOAM includes
#include "error.H"
#include "emptyFvPatchField.H"
#include "wallPolyPatch.H"
#include "volPointInterpolation.H"
#include "zeroGradientFvPatchField.H"
#include "interpolatePointToCell.H"
// vtk includes
#include "vtkFloatArray.h"
......
......@@ -24,8 +24,6 @@ License
#include "catalystCoprocess.H"
#include "Time.H"
#include "stringOps.H"
#include "OSspecific.H"
// VTK includes
#include <vtkNew.h>
......@@ -42,135 +40,38 @@ License
namespace Foam
{
defineTypeNameAndDebug(catalystCoprocess, 0);
}
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam
namespace catalyst
{
namespace
{
#if 0
static void printInfo(vtkCPDataDescription* descrip)
{
if (!descrip)
{
return;
}
const unsigned nItems = descrip->GetNumberOfInputDescriptions();
for (unsigned itemi = 0; itemi < nItems; ++itemi)
{
vtkCPInputDataDescription* input = descrip->GetInputDescription(itemi);
if (!input) continue; // should not happen
Info<<"input: " << descrip->GetInputDescriptionName(itemi) << nl;
const unsigned nFields = input->GetNumberOfFields();
for (unsigned fieldi = 0; fieldi < nFields; ++fieldi)
{
Info<< " field: " << input->GetFieldName(fieldi) << nl;
}
if (!nFields) Info<<" no fields requested" << nl;
}
defineTypeNameAndDebug(coprocess, 0);
}
#endif
} // End anonymous namespace
} // End namespace Foam
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
Foam::label Foam::catalystCoprocess::expand
(
List<string>& scripts,
const dictionary& dict
)
{
label nscript = 0;
forAll(scripts, scripti)
{
string& s = scripts[scripti];
stringOps::inplaceExpand(s, dict, true, true);
fileName::clean(s); // Remove trailing, repeated slashes etc.
if (isFile(s))
{
if (nscript != scripti)
{
scripts[nscript] = std::move(s);
}
++nscript;
}
}
scripts.resize(nscript);
return nscript;
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class DataType>
bool Foam::catalystCoprocess::processImpl
(
const dataQuery& dataq,
vtkSmartPointer<DataType>& output
)
{
vtkCPDataDescription* descrip = dataq.get();
if (!coproc_->RequestDataDescription(descrip))
{
return false;
}
for (const word& chanName : dataq.channels())
{
auto* input = descrip->GetInputDescriptionByName(chanName.c_str());
if (input && input->GetIfGridIsNecessary())
{
input->SetGrid(output);
}
}
coproc_->CoProcess(descrip);
return true;
}
template<class DataType>
bool Foam::catalystCoprocess::processImpl
bool Foam::catalyst::coprocess::processImpl
(
const dataQuery& dataq,
HashTable<vtkSmartPointer<DataType>>& outputs
HashTable<vtkSmartPointer<DataType>, fileName>& outputs
)
{
vtkCPDataDescription* descrip = dataq.get();
auto* descrip = dataq.description();
if (!coproc_->RequestDataDescription(descrip))
{
return false;
}
for (const word& chanName : dataq.channels())
for (const fileName& channel : dataq.names())
{
if (outputs.found(chanName))
if (outputs.found(channel))
{
auto* input = descrip->GetInputDescriptionByName(chanName.c_str());
auto* input = descrip->GetInputDescriptionByName(channel.c_str());
if (input && input->GetIfGridIsNecessary())
{
input->SetGrid(outputs[chanName]);
input->SetGrid(outputs[channel]);
}
}
}
......@@ -180,21 +81,11 @@ bool Foam::catalystCoprocess::processImpl
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::catalystCoprocess::timeQuery::timeQuery(const Foam::Time& t)
:
timeValue(t.timeOutputValue()),
timeIndex(t.timeIndex()),
forced(t.timeOutputValue() >= t.endTime().value())
{}