Commit 16709019 authored by Mark Olesen's avatar Mark Olesen

ENH: overhaul of channel handling. Various bug fixes. (issue #6)

- removed fvMesh sub-channels if favour of selector flags.
  To enable/disable portions of the geometry:

      internal    true/false
      boundary    true/false

  This replaces the previous method of sub-channels in which restrictions
  were propagated from the pipeline through.

  Before
  ======
      Function Object:

          input
          {
              fields    (U p);
          }

      Pipeline:
          input = coprocessor.CreateProducer(datadescription, 'input/patches')

  Now
  ===
      Function Object:

          input
          {
              internal  false;
              fields    (U p);
          }

      Pipeline:
          input = coprocessor.CreateProducer(datadescription, 'input')
parent 5afad06e
...@@ -47,7 +47,7 @@ namespace catalyst ...@@ -47,7 +47,7 @@ namespace catalyst
area area
); );
} }
} } // End namespace Foam
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
...@@ -139,7 +139,7 @@ bool Foam::catalyst::faMeshInput::read(const dictionary& dict) ...@@ -139,7 +139,7 @@ bool Foam::catalyst::faMeshInput::read(const dictionary& dict)
// Restrict to specified meshes // Restrict to specified meshes
meshes_.filterKeys(selectAreas_); meshes_.filterKeys(selectAreas_);
dict.lookup("fields") >> selectFields_; dict.read("fields", selectFields_);
return true; return true;
} }
...@@ -153,18 +153,18 @@ void Foam::catalyst::faMeshInput::update(polyMesh::readUpdateState state) ...@@ -153,18 +153,18 @@ void Foam::catalyst::faMeshInput::update(polyMesh::readUpdateState state)
time_.lookupObject<objectRegistry>(regionName_); time_.lookupObject<objectRegistry>(regionName_);
// Be really paranoid and verify if the mesh actually exists // Be really paranoid and verify if the mesh actually exists
const wordList regionNames(backends_.toc()); const wordList areaNames(backends_.toc());
for (const word& regionName : regionNames) for (const word& areaName : areaNames)
{ {
if (meshes_.found(regionName) && obr.found(regionName)) if (meshes_.found(areaName) && obr.found(areaName))
{ {
backends_[regionName]->updateState(state); backends_[areaName]->updateState(state);
} }
else else
{ {
backends_.erase(regionName); backends_.erase(areaName);
meshes_.erase(regionName); meshes_.erase(areaName);
} }
} }
} }
...@@ -186,7 +186,6 @@ Foam::label Foam::catalyst::faMeshInput::addChannels(dataQuery& dataq) ...@@ -186,7 +186,6 @@ Foam::label Foam::catalyst::faMeshInput::addChannels(dataQuery& dataq)
allFields += iter.object()->knownFields(selectFields_); allFields += iter.object()->knownFields(selectFields_);
} }
dataq.set(name(), allFields); dataq.set(name(), allFields);
return 1; return 1;
...@@ -199,61 +198,41 @@ bool Foam::catalyst::faMeshInput::convert ...@@ -199,61 +198,41 @@ bool Foam::catalyst::faMeshInput::convert
outputChannels& outputs outputChannels& outputs
) )
{ {
const wordList regionNames(backends_.sortedToc()); const word channelName(name());
const wordList areaNames(backends_.sortedToc());
if (regionNames.empty()) if (areaNames.empty() || !dataq.found(channelName))
{ {
return false; // skip - not available // Not available, or not requested
return false;
} }
// Single channel only
label nChannels = 0; // A separate block for each area mesh
unsigned int blockNo = 0;
if (dataq.found(name()))
{
++nChannels;
}
if (!nChannels) for (const word& areaName : areaNames)
{ {
return false; // skip - not requested auto dataset = backends_[areaName]->output(selectFields_);
}
// TODO: currently don't rely on the results from expecting much at all // Existing or new
vtkSmartPointer<vtkMultiBlockDataSet> block =
outputs.lookup
(
channelName,
vtkSmartPointer<vtkMultiBlockDataSet>::New()
);
// Each region in a separate block block->SetBlock(blockNo, dataset);
unsigned int blockNo = 0;
for (const word& regionName : regionNames)
{
auto dataset =
backends_[regionName]->output(selectFields_);
{ block->GetMetaData(blockNo)->Set
const fileName channel = name(); (
vtkCompositeDataSet::NAME(),
areaName // block name = area mesh name
);
if (dataq.found(channel)) outputs.set(channelName, block); // overwrites existing
{
// Get existing or new
vtkSmartPointer<vtkMultiBlockDataSet> block =
outputs.lookup
(
channel,
vtkSmartPointer<vtkMultiBlockDataSet>::New()
);
block->SetBlock(blockNo, dataset);
block->GetMetaData(blockNo)->Set
(
vtkCompositeDataSet::NAME(),
regionName
);
outputs.set(channel, block); // overwrites existing
}
}
++blockNo; ++blockNo;
} }
......
...@@ -25,15 +25,14 @@ Class ...@@ -25,15 +25,14 @@ Class
Foam::catalyst::faMeshInput Foam::catalyst::faMeshInput
Description Description
A Paraview Catalyst source for OpenFOAM faMesh regions. An input (source) for Paraview Catalyst from faMesh regions.
The source comprises a single internal "input" channel, Produces a multi-block dataset with one block per area mesh with pieces
which is a multi-block dataset (one block per area mesh). from each processor.
On output, the "input" sub-channel receives the name of the source.
Example specification: Example specification:
\verbatim \verbatim
myArea someName
{ {
type area; type area;
fields (U p); fields (U p);
...@@ -42,15 +41,29 @@ Description ...@@ -42,15 +41,29 @@ Description
Usage Usage
\table \table
Property | Description | Required | Default Property | Description | Required | Default
type | area | yes | type | input type: \c area | yes |
region | | no | region0 region | name for a single region | no | region0
regions | wordRe list of regions | no | area | select a single area | no |
fields | wordRe list of fields | yes | areas | wordRe list of multiple areas | no |
fields | wordRe list of fields | yes |
\endtable \endtable
The output block structure:
\verbatim
|-- area0
| |-- piece0
| |-- ...
| \-- pieceN
|-- ...
\-- areaN
\-- ...
\endverbatim
Note
The channel name is that of the defining dictionary.
See also See also
Foam::catalyst::catalystInput
Foam::vtk::faMeshAdaptor Foam::vtk::faMeshAdaptor
SourceFiles SourceFiles
...@@ -75,7 +88,7 @@ namespace catalyst ...@@ -75,7 +88,7 @@ namespace catalyst
{ {
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class catalyst::faMeshInput Declaration Class catalyst::faMeshInput Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
class faMeshInput class faMeshInput
......
...@@ -44,7 +44,7 @@ namespace vtk ...@@ -44,7 +44,7 @@ namespace vtk
{ {
defineTypeNameAndDebug(faMeshAdaptor, 0); defineTypeNameAndDebug(faMeshAdaptor, 0);
} }
} } // End namespace Foam
const Foam::word Foam::vtk::faMeshAdaptor::internalName("internal"); const Foam::word Foam::vtk::faMeshAdaptor::internalName("internal");
......
...@@ -42,9 +42,6 @@ SourceFiles ...@@ -42,9 +42,6 @@ SourceFiles
#define foamVtkFaMeshAdaptor_H #define foamVtkFaMeshAdaptor_H
#include "className.H" #include "className.H"
#include "fileName.H"
#include "stringList.H"
#include "wordList.H"
#include "polyMesh.H" #include "polyMesh.H"
#include "areaFieldsFwd.H" #include "areaFieldsFwd.H"
#include "foamVtkTools.H" #include "foamVtkTools.H"
......
...@@ -34,7 +34,7 @@ License ...@@ -34,7 +34,7 @@ License
// Templates (only needed here) // Templates (only needed here)
#include "foamVtkFaMeshAdaptorFieldTemplates.C" #include "foamVtkFaMeshAdaptorFieldTemplates.C"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam namespace Foam
{ {
...@@ -53,8 +53,10 @@ static wordHashSet supportedTypes() ...@@ -53,8 +53,10 @@ static wordHashSet supportedTypes()
return types; return types;
} }
} // end of Foam } // End namespace Foam
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::wordHashSet Foam::vtk::faMeshAdaptor::knownFields Foam::wordHashSet Foam::vtk::faMeshAdaptor::knownFields
( (
......
...@@ -44,7 +44,7 @@ namespace catalyst ...@@ -44,7 +44,7 @@ namespace catalyst
{ {
defineTypeNameAndDebug(coprocess, 0); defineTypeNameAndDebug(coprocess, 0);
} }
} } // End namespace Foam
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
...@@ -53,7 +53,7 @@ template<class DataType> ...@@ -53,7 +53,7 @@ template<class DataType>
bool Foam::catalyst::coprocess::processImpl bool Foam::catalyst::coprocess::processImpl
( (
const dataQuery& dataq, const dataQuery& dataq,
HashTable<vtkSmartPointer<DataType>, fileName>& outputs HashTable<vtkSmartPointer<DataType>>& outputs
) )
{ {
auto* descrip = dataq.description(); auto* descrip = dataq.description();
...@@ -63,7 +63,7 @@ bool Foam::catalyst::coprocess::processImpl ...@@ -63,7 +63,7 @@ bool Foam::catalyst::coprocess::processImpl
return false; return false;
} }
for (const fileName& channel : dataq.names()) for (const word& channel : dataq.names())
{ {
if (outputs.found(channel)) if (outputs.found(channel))
{ {
......
...@@ -68,7 +68,7 @@ private: ...@@ -68,7 +68,7 @@ private:
bool processImpl bool processImpl
( (
const dataQuery& dataq, const dataQuery& dataq,
HashTable<vtkSmartPointer<DataType>, fileName>& outputs HashTable<vtkSmartPointer<DataType>>& outputs
); );
public: public:
......
...@@ -11,9 +11,12 @@ catalyst ...@@ -11,9 +11,12 @@ catalyst
// ^^^^^ // ^^^^^
// #includeEtc "caseDicts/insitu/catalyst/catalyst.cfg" // #includeEtc "caseDicts/insitu/catalyst/catalyst.cfg"
// Optional directory creation command
// mkdir "<case>/someDir"; // mkdir "<case>/someDir";
// Default output-directory
// outputDir "<case>/insitu";
scripts scripts
( (
// "<etc>/caseDicts/insitu/catalyst/printChannels.py" // "<etc>/caseDicts/insitu/catalyst/printChannels.py"
...@@ -30,6 +33,12 @@ catalyst ...@@ -30,6 +33,12 @@ catalyst
// All regions // All regions
regions (".*"); regions (".*");
// Emit boundary mesh/fields
boundary true;
// Emit internal mesh/fields
internal true;
// Selected fields (words or regex) // Selected fields (words or regex)
fields (T U p); fields (T U p);
} }
......
...@@ -192,7 +192,7 @@ bool Foam::functionObjects::catalystFunctionObject::read(const dictionary& dict) ...@@ -192,7 +192,7 @@ bool Foam::functionObjects::catalystFunctionObject::read(const dictionary& dict)
Foam::mkDir(outputDir_); Foam::mkDir(outputDir_);
} }
dict.lookup("scripts") >> scripts_; // Python scripts dict.read("scripts", scripts_); // Python scripts
expand(scripts_, dict); // Expand and check availability expand(scripts_, dict); // Expand and check availability
...@@ -217,17 +217,18 @@ bool Foam::functionObjects::catalystFunctionObject::read(const dictionary& dict) ...@@ -217,17 +217,18 @@ bool Foam::functionObjects::catalystFunctionObject::read(const dictionary& dict)
continue; continue;
} }
newList.set auto input =
(
nInputs,
catalyst::catalystInput::New catalyst::catalystInput::New
( (
word(iter().keyword()), word(iter().keyword()),
time_, time_,
*subDictPtr *subDictPtr
).ptr() );
);
// We may wish to perform additional validity or sanity checks on
// the input before deciding to add it to the list.
newList.set(nInputs, input);
++nInputs; ++nInputs;
} }
...@@ -250,7 +251,7 @@ bool Foam::functionObjects::catalystFunctionObject::read(const dictionary& dict) ...@@ -250,7 +251,7 @@ bool Foam::functionObjects::catalystFunctionObject::read(const dictionary& dict)
nInputs = 0; nInputs = 0;
for (const auto& inp : inputs_) for (const auto& inp : inputs_)
{ {
if (nInputs++) Info << nl; if (nInputs++) Info<< nl;
inp.print(Info); inp.print(Info);
} }
...@@ -263,8 +264,6 @@ bool Foam::functionObjects::catalystFunctionObject::read(const dictionary& dict) ...@@ -263,8 +264,6 @@ bool Foam::functionObjects::catalystFunctionObject::read(const dictionary& dict)
bool Foam::functionObjects::catalystFunctionObject::execute() bool Foam::functionObjects::catalystFunctionObject::execute()
{ {
// Enforce sanity for backends and adaptor
if (inputs_.empty()) if (inputs_.empty())
{ {
return false; return false;
...@@ -331,7 +330,7 @@ bool Foam::functionObjects::catalystFunctionObject::execute() ...@@ -331,7 +330,7 @@ bool Foam::functionObjects::catalystFunctionObject::execute()
if (catalyst::coprocess::debug > 1) if (catalyst::coprocess::debug > 1)
{ {
Pout<< type() << ": sending data for" << outputs.size() Pout<< type() << ": sending data for " << outputs.size()
<< " outputs" << nl; << " outputs" << nl;
} }
...@@ -349,8 +348,10 @@ bool Foam::functionObjects::catalystFunctionObject::execute() ...@@ -349,8 +348,10 @@ bool Foam::functionObjects::catalystFunctionObject::execute()
} }
// Avoid compiler complaint about unused variable. // Instead of relying on the destructor, manually restore the previous
// - manually restore old SIGFPE state // SIGFPE state.
// This is only to avoid compiler complaints about unused variables.
sigFpeHandling.restore(); sigFpeHandling.restore();
return true; return true;
......
...@@ -28,10 +28,7 @@ Group ...@@ -28,10 +28,7 @@ Group
grpUtilitiesFunctionObjects grpUtilitiesFunctionObjects
Description Description
A Paraview Catalyst adaptor for OpenFOAM fvMesh regions. A Paraview Catalyst adaptor for OpenFOAM.
The output comprises up to three channels ("input", "mesh", "patches"),
each of which is a multi-block dataset.
Example of function object specification: Example of function object specification:
\verbatim \verbatim
...@@ -39,30 +36,42 @@ Description ...@@ -39,30 +36,42 @@ Description
{ {
type catalyst; type catalyst;
libs ("libcatalystFoam.so"); libs ("libcatalystFoam.so");
scripts ( ... );
executeControl timeStep; executeControl timeStep;
executeInterval 1; executeInterval 1;
scripts ( ... );
inputs inputs
{ {
type default; input1
regions ( ".*Solid" ) {
fields (U p); type default;
regions (".*solid" );
fields (U p);
}
input2
{
type cloud;
cloud someCloud;
fields ( T U p rho );
}
} }
} }
\endverbatim \endverbatim
Usage Usage
\table \table
Property | Description | Required | Default Property | Description | Required | Default
type | catalyst | yes | type | catalyst | yes |
log | report extra information | no | false log | report extra information | no | false
mkdir | initial directory to create | no | scripts | Python pipeline scripts | yes |
scripts | Python pipeline scripts | yes | inputs | dictionary of catalyst inputs | yes |
outputDir | the output directory | no | "\<case\>/insitu"
mkdir | optional directory to create | no |
\endtable \endtable
Note Note
The execution frequency can be defined by the functionObject and The execution frequency can be defined by both the functionObject and
by the Catalyst pipeline. by the Catalyst pipeline.
See also See also
...@@ -121,7 +130,7 @@ class catalystFunctionObject ...@@ -121,7 +130,7 @@ class catalystFunctionObject
//- The catalyst coprocess //- The catalyst coprocess
autoPtr<catalyst::coprocess> adaptor_; autoPtr<catalyst::coprocess> adaptor_;
//- Pointers to the requested mesh regions //- Pointers to the requested catalyst inputs
PtrList<catalyst::catalystInput> inputs_; PtrList<catalyst::catalystInput> inputs_;
...@@ -133,6 +142,7 @@ class catalystFunctionObject ...@@ -133,6 +142,7 @@ class catalystFunctionObject
//- No copy assignment //- No copy assignment
void operator=(const catalystFunctionObject&) = delete; void operator=(const catalystFunctionObject&) = delete;
public: public:
// Static Methods // Static Methods
......
...@@ -37,7 +37,7 @@ namespace catalyst ...@@ -37,7 +37,7 @@ namespace catalyst
defineTypeNameAndDebug(catalystInput, 0); defineTypeNameAndDebug(catalystInput, 0);
defineRunTimeSelectionTable(catalystInput, dictionary); defineRunTimeSelectionTable(catalystInput, dictionary);
} }
} } // End namespace Foam
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
...@@ -58,16 +58,15 @@ Foam::catalyst::catalystInput::New ...@@ -58,16 +58,15 @@ Foam::catalyst::catalystInput::New
const dictionary& dict const dictionary& dict
) )
{ {
const word sourceType = dict.lookupOrDefault<word>("type", "default"); const word modelType(dict.lookupOrDefault<word>("type", "default"));