From 1670901942291d87a37b87c7c705ab5c4585fdb1 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Sun, 24 Jun 2018 15:49:34 +0200
Subject: [PATCH] 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')
---
 src/catalyst/areaMesh/catalystFaMesh.C        |  83 +++----
 src/catalyst/areaMesh/catalystFaMesh.H        |  37 ++-
 src/catalyst/areaMesh/foamVtkFaMeshAdaptor.C  |   2 +-
 src/catalyst/areaMesh/foamVtkFaMeshAdaptor.H  |   3 -
 .../areaMesh/foamVtkFaMeshAdaptorFields.C     |   6 +-
 src/catalyst/catalystCoprocess.C              |   6 +-
 src/catalyst/catalystCoprocess.H              |   2 +-
 src/catalyst/catalystDict                     |  11 +-
 src/catalyst/catalystFunctionObject.C         |  25 +-
 src/catalyst/catalystFunctionObject.H         |  40 ++--
 src/catalyst/catalystInput.C                  |  11 +-
 src/catalyst/catalystInput.H                  |  14 +-
 src/catalyst/catalystTools.C                  |  17 +-
 src/catalyst/catalystTools.H                  |  27 +--
 src/catalyst/catalystToolsI.H                 |  15 +-
 src/catalyst/cloud/catalystCloud.C            |  56 ++---
 src/catalyst/cloud/catalystCloud.H            |  44 ++--
 src/catalyst/cloud/foamVtkCloudAdaptor.C      |   2 +-
 src/catalyst/volMesh/catalystFvMesh.C         | 225 +++++++-----------
 src/catalyst/volMesh/catalystFvMesh.H         |  87 ++++---
 src/catalyst/volMesh/foamVtkFvMeshAdaptor.C   |  92 ++++---
 src/catalyst/volMesh/foamVtkFvMeshAdaptor.H   |  74 ++++--
 .../foamVtkFvMeshAdaptorFieldTemplates.C      |  19 +-
 .../volMesh/foamVtkFvMeshAdaptorFields.C      |   6 +-
 .../volMesh/foamVtkFvMeshAdaptorGeom.C        |  24 +-
 .../sphereTransport/showCs.py                 | 217 +++++++++++++++++
 .../sphereTransport/system/catalyst           |   3 +-
 .../system/scripts/writeArea.py               |  70 ------
 .../multiRegionHeater/system/catalyst         |   7 +-
 .../system/scripts/slice1.py                  |  22 +-
 .../system/scripts/writeMesh.py               |  70 ------
 .../system/scripts/writePatches.py            |  70 ------
 .../icoFoam/cavity/system/catalyst            |   6 +-
 .../cavity/system/scripts/writeMesh.py        |  74 ------
 .../simplifiedSiwek/system/catalyst           |  39 ++-
 .../system/scripts/writeCloud.py              |  73 ------
 .../system/scripts/writePatches.py            |  71 ------
 37 files changed, 737 insertions(+), 913 deletions(-)
 create mode 100644 tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/showCs.py
 delete mode 100644 tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/scripts/writeArea.py
 delete mode 100644 tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/scripts/writeMesh.py
 delete mode 100644 tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/scripts/writePatches.py
 delete mode 100644 tutorials/incompressible/icoFoam/cavity/system/scripts/writeMesh.py
 delete mode 100644 tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/scripts/writeCloud.py
 delete mode 100644 tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/scripts/writePatches.py

diff --git a/src/catalyst/areaMesh/catalystFaMesh.C b/src/catalyst/areaMesh/catalystFaMesh.C
index 667c76e..8ff3e11 100644
--- a/src/catalyst/areaMesh/catalystFaMesh.C
+++ b/src/catalyst/areaMesh/catalystFaMesh.C
@@ -47,7 +47,7 @@ namespace catalyst
         area
     );
 }
-}
+} // End namespace Foam
 
 
 // * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
@@ -139,7 +139,7 @@ bool Foam::catalyst::faMeshInput::read(const dictionary& dict)
     // Restrict to specified meshes
     meshes_.filterKeys(selectAreas_);
 
-    dict.lookup("fields") >> selectFields_;
+    dict.read("fields", selectFields_);
 
     return true;
 }
@@ -153,18 +153,18 @@ void Foam::catalyst::faMeshInput::update(polyMesh::readUpdateState state)
         time_.lookupObject<objectRegistry>(regionName_);
 
     // 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
         {
-            backends_.erase(regionName);
-            meshes_.erase(regionName);
+            backends_.erase(areaName);
+            meshes_.erase(areaName);
         }
     }
 }
@@ -186,7 +186,6 @@ Foam::label Foam::catalyst::faMeshInput::addChannels(dataQuery& dataq)
         allFields += iter.object()->knownFields(selectFields_);
     }
 
-
     dataq.set(name(), allFields);
 
     return 1;
@@ -199,61 +198,41 @@ bool Foam::catalyst::faMeshInput::convert
     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;
-
-    if (dataq.found(name()))
-    {
-        ++nChannels;
-    }
+    // A separate block for each area mesh
+    unsigned int blockNo = 0;
 
-    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
-    unsigned int blockNo = 0;
-    for (const word& regionName : regionNames)
-    {
-        auto dataset =
-            backends_[regionName]->output(selectFields_);
+        block->SetBlock(blockNo, dataset);
 
-        {
-            const fileName channel = name();
+        block->GetMetaData(blockNo)->Set
+        (
+            vtkCompositeDataSet::NAME(),
+            areaName                        // block name = area mesh name
+        );
 
-            if (dataq.found(channel))
-            {
-                // 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
-            }
-        }
+        outputs.set(channelName, block);    // overwrites existing
 
         ++blockNo;
     }
diff --git a/src/catalyst/areaMesh/catalystFaMesh.H b/src/catalyst/areaMesh/catalystFaMesh.H
index 275ab60..e3e624a 100644
--- a/src/catalyst/areaMesh/catalystFaMesh.H
+++ b/src/catalyst/areaMesh/catalystFaMesh.H
@@ -25,15 +25,14 @@ Class
     Foam::catalyst::faMeshInput
 
 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,
-    which is a multi-block dataset (one block per area mesh).
-    On output, the "input" sub-channel receives the name of the source.
+    Produces a multi-block dataset with one block per area mesh with pieces
+    from each processor.
 
     Example specification:
     \verbatim
-    myArea
+    someName
     {
         type            area;
         fields          (U p);
@@ -42,15 +41,29 @@ Description
 
 Usage
     \table
-        Property     | Description                 | Required    | Default
-        type         | area                        | yes         |
-        region       |                             | no          | region0
-        regions      | wordRe list of regions      | no          |
-        fields       | wordRe list of fields       | yes         |
+        Property    | Description                           | Required | Default
+        type        | input type: \c area                   | yes   |
+        region      | name for a single region              | no    | region0
+        area        | select a single area                  | no    |
+        areas       | wordRe list of multiple areas         | no    |
+        fields      | wordRe list of fields                 | yes   |
     \endtable
 
+    The output block structure:
+    \verbatim
+    |-- area0
+    |   |-- piece0
+    |   |-- ...
+    |   \-- pieceN
+    |-- ...
+    \-- areaN
+        \-- ...
+    \endverbatim
+
+Note
+    The channel name is that of the defining dictionary.
+
 See also
-    Foam::catalyst::catalystInput
     Foam::vtk::faMeshAdaptor
 
 SourceFiles
@@ -75,7 +88,7 @@ namespace catalyst
 {
 
 /*---------------------------------------------------------------------------*\
-                          Class catalyst::faMeshInput Declaration
+                    Class catalyst::faMeshInput Declaration
 \*---------------------------------------------------------------------------*/
 
 class faMeshInput
diff --git a/src/catalyst/areaMesh/foamVtkFaMeshAdaptor.C b/src/catalyst/areaMesh/foamVtkFaMeshAdaptor.C
index 47a89cf..e09e3d5 100644
--- a/src/catalyst/areaMesh/foamVtkFaMeshAdaptor.C
+++ b/src/catalyst/areaMesh/foamVtkFaMeshAdaptor.C
@@ -44,7 +44,7 @@ namespace vtk
 {
     defineTypeNameAndDebug(faMeshAdaptor, 0);
 }
-}
+} // End namespace Foam
 
 const Foam::word Foam::vtk::faMeshAdaptor::internalName("internal");
 
diff --git a/src/catalyst/areaMesh/foamVtkFaMeshAdaptor.H b/src/catalyst/areaMesh/foamVtkFaMeshAdaptor.H
index 129d780..841d12d 100644
--- a/src/catalyst/areaMesh/foamVtkFaMeshAdaptor.H
+++ b/src/catalyst/areaMesh/foamVtkFaMeshAdaptor.H
@@ -42,9 +42,6 @@ SourceFiles
 #define foamVtkFaMeshAdaptor_H
 
 #include "className.H"
-#include "fileName.H"
-#include "stringList.H"
-#include "wordList.H"
 #include "polyMesh.H"
 #include "areaFieldsFwd.H"
 #include "foamVtkTools.H"
diff --git a/src/catalyst/areaMesh/foamVtkFaMeshAdaptorFields.C b/src/catalyst/areaMesh/foamVtkFaMeshAdaptorFields.C
index c33e204..0184236 100644
--- a/src/catalyst/areaMesh/foamVtkFaMeshAdaptorFields.C
+++ b/src/catalyst/areaMesh/foamVtkFaMeshAdaptorFields.C
@@ -34,7 +34,7 @@ License
 // Templates (only needed here)
 #include "foamVtkFaMeshAdaptorFieldTemplates.C"
 
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
 
 namespace Foam
 {
@@ -53,8 +53,10 @@ static wordHashSet supportedTypes()
     return types;
 }
 
-} // end of Foam
+} // End namespace Foam
+
 
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 Foam::wordHashSet Foam::vtk::faMeshAdaptor::knownFields
 (
diff --git a/src/catalyst/catalystCoprocess.C b/src/catalyst/catalystCoprocess.C
index 12e4d59..f34b892 100644
--- a/src/catalyst/catalystCoprocess.C
+++ b/src/catalyst/catalystCoprocess.C
@@ -44,7 +44,7 @@ namespace catalyst
 {
     defineTypeNameAndDebug(coprocess, 0);
 }
-}
+} // End namespace Foam
 
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
@@ -53,7 +53,7 @@ template<class DataType>
 bool Foam::catalyst::coprocess::processImpl
 (
     const dataQuery& dataq,
-    HashTable<vtkSmartPointer<DataType>, fileName>& outputs
+    HashTable<vtkSmartPointer<DataType>>& outputs
 )
 {
     auto* descrip = dataq.description();
@@ -63,7 +63,7 @@ bool Foam::catalyst::coprocess::processImpl
         return false;
     }
 
-    for (const fileName& channel : dataq.names())
+    for (const word& channel : dataq.names())
     {
         if (outputs.found(channel))
         {
diff --git a/src/catalyst/catalystCoprocess.H b/src/catalyst/catalystCoprocess.H
index bd7b182..c42c83f 100644
--- a/src/catalyst/catalystCoprocess.H
+++ b/src/catalyst/catalystCoprocess.H
@@ -68,7 +68,7 @@ private:
         bool processImpl
         (
             const dataQuery& dataq,
-            HashTable<vtkSmartPointer<DataType>, fileName>& outputs
+            HashTable<vtkSmartPointer<DataType>>& outputs
         );
 
 public:
diff --git a/src/catalyst/catalystDict b/src/catalyst/catalystDict
index e07f0b8..5c35268 100644
--- a/src/catalyst/catalystDict
+++ b/src/catalyst/catalystDict
@@ -11,9 +11,12 @@ catalyst
     // ^^^^^
     // #includeEtc "caseDicts/insitu/catalyst/catalyst.cfg"
 
-
+    // Optional directory creation command
     // mkdir  "<case>/someDir";
 
+    // Default output-directory
+    // outputDir  "<case>/insitu";
+
     scripts
     (
         // "<etc>/caseDicts/insitu/catalyst/printChannels.py"
@@ -30,6 +33,12 @@ catalyst
             // All regions
             regions (".*");
 
+            // Emit boundary mesh/fields
+            boundary true;
+
+            // Emit internal mesh/fields
+            internal true;
+
             // Selected fields (words or regex)
             fields  (T U p);
         }
diff --git a/src/catalyst/catalystFunctionObject.C b/src/catalyst/catalystFunctionObject.C
index cf8feda..c7d31fc 100644
--- a/src/catalyst/catalystFunctionObject.C
+++ b/src/catalyst/catalystFunctionObject.C
@@ -192,7 +192,7 @@ bool Foam::functionObjects::catalystFunctionObject::read(const dictionary& dict)
         Foam::mkDir(outputDir_);
     }
 
-    dict.lookup("scripts") >> scripts_; // Python scripts
+    dict.read("scripts", scripts_);     // Python scripts
     expand(scripts_, dict);             // Expand and check availability
 
 
@@ -217,17 +217,18 @@ bool Foam::functionObjects::catalystFunctionObject::read(const dictionary& dict)
             continue;
         }
 
-        newList.set
-        (
-            nInputs,
+        auto input =
             catalyst::catalystInput::New
             (
                 word(iter().keyword()),
                 time_,
                 *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;
     }
 
@@ -250,7 +251,7 @@ bool Foam::functionObjects::catalystFunctionObject::read(const dictionary& dict)
         nInputs = 0;
         for (const auto& inp : inputs_)
         {
-            if (nInputs++) Info << nl;
+            if (nInputs++) Info<< nl;
             inp.print(Info);
         }
 
@@ -263,8 +264,6 @@ bool Foam::functionObjects::catalystFunctionObject::read(const dictionary& dict)
 
 bool Foam::functionObjects::catalystFunctionObject::execute()
 {
-    // Enforce sanity for backends and adaptor
-
     if (inputs_.empty())
     {
         return false;
@@ -331,7 +330,7 @@ bool Foam::functionObjects::catalystFunctionObject::execute()
 
     if (catalyst::coprocess::debug > 1)
     {
-        Pout<< type() << ": sending data for" << outputs.size()
+        Pout<< type() << ": sending data for " << outputs.size()
             << " outputs" << nl;
     }
 
@@ -349,8 +348,10 @@ bool Foam::functionObjects::catalystFunctionObject::execute()
     }
 
 
-    // Avoid compiler complaint about unused variable.
-    // - manually restore old SIGFPE state
+    // 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;
diff --git a/src/catalyst/catalystFunctionObject.H b/src/catalyst/catalystFunctionObject.H
index 13bd9cf..e829aa9 100644
--- a/src/catalyst/catalystFunctionObject.H
+++ b/src/catalyst/catalystFunctionObject.H
@@ -28,10 +28,7 @@ Group
     grpUtilitiesFunctionObjects
 
 Description
-    A Paraview Catalyst adaptor for OpenFOAM fvMesh regions.
-
-    The output comprises up to three channels ("input", "mesh", "patches"),
-    each of which is a multi-block dataset.
+    A Paraview Catalyst adaptor for OpenFOAM.
 
     Example of function object specification:
     \verbatim
@@ -39,30 +36,42 @@ Description
     {
         type            catalyst;
         libs            ("libcatalystFoam.so");
-        scripts         ( ... );
         executeControl  timeStep;
         executeInterval 1;
 
+        scripts         ( ... );
+
         inputs
         {
-            type        default;
-            regions     ( ".*Solid" )
-            fields      (U p);
+            input1
+            {
+                type    default;
+                regions (".*solid" );
+                fields  (U p);
+            }
+            input2
+            {
+                type    cloud;
+                cloud   someCloud;
+                fields  ( T U p rho );
+            }
         }
     }
     \endverbatim
 
 Usage
     \table
-        Property     | Description                 | Required    | Default
-        type         | catalyst                    | yes         |
-        log          | report extra information    | no          | false
-        mkdir        | initial directory to create | no          |
-        scripts      | Python pipeline scripts     | yes         |
+        Property    | Description                       | Required | Default
+        type        | catalyst                          | yes   |
+        log         | report extra information          | no    | false
+        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
 
 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.
 
 See also
@@ -121,7 +130,7 @@ class catalystFunctionObject
         //- The catalyst coprocess
         autoPtr<catalyst::coprocess> adaptor_;
 
-        //- Pointers to the requested mesh regions
+        //- Pointers to the requested catalyst inputs
         PtrList<catalyst::catalystInput> inputs_;
 
 
@@ -133,6 +142,7 @@ class catalystFunctionObject
         //- No copy assignment
         void operator=(const catalystFunctionObject&) = delete;
 
+
 public:
 
     // Static Methods
diff --git a/src/catalyst/catalystInput.C b/src/catalyst/catalystInput.C
index 4b1645d..1fbcfeb 100644
--- a/src/catalyst/catalystInput.C
+++ b/src/catalyst/catalystInput.C
@@ -37,7 +37,7 @@ namespace catalyst
     defineTypeNameAndDebug(catalystInput, 0);
     defineRunTimeSelectionTable(catalystInput, dictionary);
 }
-}
+} // End namespace Foam
 
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
@@ -58,16 +58,15 @@ Foam::catalyst::catalystInput::New
     const dictionary& dict
 )
 {
-    const word sourceType = dict.lookupOrDefault<word>("type", "default");
+    const word modelType(dict.lookupOrDefault<word>("type", "default"));
 
-    auto cstrIter = dictionaryConstructorTablePtr_->cfind(sourceType);
+    auto cstrIter = dictionaryConstructorTablePtr_->cfind(modelType);
 
     if (!cstrIter.found())
     {
         FatalErrorInFunction
-            << "Unknown catalystInput "
-            << sourceType << nl << nl
-            << "Valid sources : " << endl
+            << "Unknown catalystInput " << modelType << nl << nl
+            << "Valid inputs:" << endl
             << dictionaryConstructorTablePtr_->sortedToc()
             << exit(FatalError);
     }
diff --git a/src/catalyst/catalystInput.H b/src/catalyst/catalystInput.H
index f709f00..0fe3531 100644
--- a/src/catalyst/catalystInput.H
+++ b/src/catalyst/catalystInput.H
@@ -22,10 +22,10 @@ License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
 Class
-    Foam::catalystInput
+    Foam::catalyst::catalystInput
 
 Description
-    An OpenFOAM source for Paraview Catalyst.
+    An abstract input (source) for Paraview Catalyst.
 
 See also
     Foam::catalyst::coprocess
@@ -42,8 +42,8 @@ SourceFiles
 
 #include "className.H"
 #include "polyMesh.H"
-#include "runTimeSelectionTables.H"
 #include "catalystTools.H"
+#include "runTimeSelectionTables.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -66,7 +66,7 @@ class catalystInput
 {
     // Private data
 
-        //- The name of the source
+        //- The Catalyst input channel name
         word name_;
 
 public:
@@ -89,7 +89,7 @@ public:
 
     // Selectors
 
-        //- Return a reference to the selected source
+        //- Return a reference to the selected input
         static autoPtr<catalystInput> New
         (
             const word& name,
@@ -104,7 +104,7 @@ public:
 
     // Constructors
 
-        //- Construct with given channel name
+        //- Construct with given Catalyst input channel name
         explicit catalystInput(const word& channel);
 
 
@@ -114,7 +114,7 @@ public:
 
     // Member Functions
 
-        //- The name of the source (channel)
+        //- The name of the Catalyst input channel
         virtual const word& name() const
         {
             return name_;
diff --git a/src/catalyst/catalystTools.C b/src/catalyst/catalystTools.C
index 815ce81..1c8d377 100644
--- a/src/catalyst/catalystTools.C
+++ b/src/catalyst/catalystTools.C
@@ -93,7 +93,7 @@ Foam::catalyst::dataQuery::~dataQuery()
 
 void Foam::catalyst::dataQuery::set
 (
-    const fileName& channel,
+    const word& channel,
     const wordHashSet& fields
 )
 {
@@ -134,23 +134,23 @@ Foam::label Foam::catalyst::dataQuery::query(vtkCPProcessor* coproc)
     descrip->SetTimeData(dataq.timeValue, dataq.timeIndex);
     descrip->SetForceOutput(dataq.forced);
 
-    const List<fileName> inputNames(dataq.names());
+    const wordList inputNames(dataq.names());
 
     // Sort out which channels already exist, are new, or disappeared
 
     // The currently defined channels
-    HashSet<fileName> currChannels;
+    wordHashSet currChannels;
 
     const unsigned n = descrip->GetNumberOfInputDescriptions();
     for (unsigned i=0; i < n; ++i)
     {
         currChannels.insert
         (
-            fileName::validate(descrip->GetInputDescriptionName(i))
+            word::validate(descrip->GetInputDescriptionName(i))
         );
     }
 
-    HashSet<fileName> oldChannels(currChannels);
+    wordHashSet oldChannels(currChannels);
     oldChannels.erase(inputNames);
 
     if (oldChannels.size())
@@ -165,7 +165,7 @@ Foam::label Foam::catalyst::dataQuery::query(vtkCPProcessor* coproc)
     // Note: this misses updating field information for previously
     // existing inputs.
 
-    for (const fileName& channel : inputNames)
+    for (const word& channel : inputNames)
     {
         if (currChannels.found(channel))
         {
@@ -173,8 +173,7 @@ Foam::label Foam::catalyst::dataQuery::query(vtkCPProcessor* coproc)
         }
 
         descrip->AddInput(channel.c_str());
-        auto* input =
-            descrip->GetInputDescriptionByName(channel.c_str());
+        auto* input = descrip->GetInputDescriptionByName(channel.c_str());
 
         for (const word& fieldName : dataq.fields(channel))
         {
@@ -193,7 +192,7 @@ Foam::label Foam::catalyst::dataQuery::query(vtkCPProcessor* coproc)
         return dataq.size();
     }
 
-    for (const fileName& channel : inputNames)
+    for (const word& channel : inputNames)
     {
         auto* input = descrip->GetInputDescriptionByName(channel.c_str());
 
diff --git a/src/catalyst/catalystTools.H b/src/catalyst/catalystTools.H
index a47fedc..88138bb 100644
--- a/src/catalyst/catalystTools.H
+++ b/src/catalyst/catalystTools.H
@@ -25,7 +25,7 @@ Class
     Foam::catalyst::timeQuery
 
 Description
-    Low-level handling for time queries
+    Low-level handling for Catalyst time queries
 
 SourceFiles
     catalystTools.C
@@ -36,7 +36,6 @@ SourceFiles
 #define functionObjects_catalystTools_H
 
 #include "wordList.H"
-#include "stringList.H"
 #include "DynamicList.H"
 #include "HashSet.H"
 
@@ -61,9 +60,7 @@ namespace catalyst
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 //- Container holding VTK outputs per Catalyst channel name
-typedef
-    HashTable<vtkSmartPointer<vtkMultiBlockDataSet>, fileName>
-    outputChannels;
+typedef HashTable<vtkSmartPointer<vtkMultiBlockDataSet>> outputChannels;
 
 
 //- Print information about data description
@@ -74,7 +71,7 @@ void printInfo(Ostream& os, vtkCPDataDescription* descrip);
                      Class catalyst::timeQuery Declaration
 \*---------------------------------------------------------------------------*/
 
-//- Simple structure for time queries
+//- Simple structure for Catalyst time queries
 struct timeQuery
 {
     double timeValue;
@@ -101,16 +98,16 @@ struct timeQuery
                      Class catalyst::dataQuery Declaration
 \*---------------------------------------------------------------------------*/
 
-//- Simple structure for data description queries
+//- Simple structure for Catalyst data description queries
 class dataQuery
 :
     public timeQuery
 {
     //- Catalyst channel names for query, in the order of addition
-    DynamicList<fileName> names_;
+    DynamicList<word> names_;
 
     //- Fields per channel
-    HashTable<wordHashSet, fileName> fields_;
+    HashTable<wordHashSet> fields_;
 
     //- Indices (into names_) of active channels
     labelHashSet active_;
@@ -156,22 +153,22 @@ public:
         inline label size() const;
 
         //- True if given channel exists (in fields or active)
-        inline bool found(const fileName& channel) const;
+        inline bool found(const word& channel) const;
 
         //- The active channel numbers
         inline List<label> active() const;
 
         //- The channel names
-        inline List<fileName> names() const;
+        inline wordList names() const;
 
         //- Fields for the given channel
-        inline const wordHashSet& fields(const fileName& channel) const;
+        inline const wordHashSet& fields(const word& channel) const;
 
         //- Clear the specified channel
-        inline void clear(const fileName& channel);
+        inline void clear(const word& channel);
 
         //- Set fields for the specified channel and make it active
-        void set(const fileName& channel, const wordHashSet& fields);
+        void set(const word& channel, const wordHashSet& fields);
 
         //- Query coprocess, transform defined input channels to
         //- known requests.
@@ -186,11 +183,9 @@ public:
 
 } // End namespace catalyst
 
-
 // Ostream Operator
 Ostream& operator<<(Ostream& os, const catalyst::timeQuery& when);
 
-
 } // End namespace Foam
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/catalyst/catalystToolsI.H b/src/catalyst/catalystToolsI.H
index 3997b7d..cd9267f 100644
--- a/src/catalyst/catalystToolsI.H
+++ b/src/catalyst/catalystToolsI.H
@@ -51,10 +51,7 @@ inline Foam::label Foam::catalyst::dataQuery::size() const
 }
 
 
-inline bool Foam::catalyst::dataQuery::found
-(
-    const fileName& channel
-) const
+inline bool Foam::catalyst::dataQuery::found(const word& channel) const
 {
     return fields_.found(channel);
 }
@@ -62,18 +59,20 @@ inline bool Foam::catalyst::dataQuery::found
 
 inline Foam::List<Foam::label> Foam::catalyst::dataQuery::active() const
 {
+    // The active indices
     return active_.sortedToc();
 }
 
 
-inline Foam::List<Foam::fileName> Foam::catalyst::dataQuery::names() const
+inline Foam::wordList Foam::catalyst::dataQuery::names() const
 {
-    return List<fileName>(names_, active_.sortedToc());
+    // Subset of known names with the active indices
+    return wordList(names_, active_.sortedToc());
 }
 
 
 inline const Foam::wordHashSet&
-Foam::catalyst::dataQuery::fields(const fileName& channel) const
+Foam::catalyst::dataQuery::fields(const word& channel) const
 {
     const auto iter = fields_.cfind(channel);
     if (iter.found())
@@ -85,7 +84,7 @@ Foam::catalyst::dataQuery::fields(const fileName& channel) const
 }
 
 
-inline void Foam::catalyst::dataQuery::clear(const fileName& channel)
+inline void Foam::catalyst::dataQuery::clear(const word& channel)
 {
     fields_.erase(channel);
     active_.erase(names_.find(channel));
diff --git a/src/catalyst/cloud/catalystCloud.C b/src/catalyst/cloud/catalystCloud.C
index 58e8fae..eeb49be 100644
--- a/src/catalyst/cloud/catalystCloud.C
+++ b/src/catalyst/cloud/catalystCloud.C
@@ -47,7 +47,7 @@ namespace catalyst
         cloud
     );
 }
-}
+} // End namespace Foam
 
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
@@ -120,57 +120,43 @@ bool Foam::catalyst::cloudInput::convert
     outputChannels& outputs
 )
 {
+    const fileName channelName(name());
     const fvMesh& fvm = time_.lookupObject<fvMesh>(regionName_);
     const wordList cloudNames(fvm.sortedNames<cloud>(selectClouds_));
 
-    if (cloudNames.empty())
+    if (cloudNames.empty() || !dataq.found(channelName))
     {
-        return false;  // skip - not available
+        // Not available, or not requested
+        return false;
     }
 
-    // Single channel only
-
-    label nChannels = 0;
 
-    if (dataq.found(name()))
-    {
-        ++nChannels;
-    }
-
-    if (!nChannels)
-    {
-        return false;  // skip - not requested
-    }
-
-    // Each cloud in a separate block.
+    // A separate block for each cloud
     unsigned int blockNo = 0;
+
     for (const word& cloudName : cloudNames)
     {
         auto dataset =
             vtk::cloudAdaptor(fvm).getCloud(cloudName, selectFields_);
 
-        const fileName channel = name();
-
-        if (dataq.found(channel))
-        {
-            // Get existing or new
-            vtkSmartPointer<vtkMultiBlockDataSet> block =
-                outputs.lookup
-                (
-                    channel,
-                    vtkSmartPointer<vtkMultiBlockDataSet>::New()
-                );
 
-            block->SetBlock(blockNo, dataset);
-
-            block->GetMetaData(blockNo)->Set
+        // Existing or new
+        vtkSmartPointer<vtkMultiBlockDataSet> block =
+            outputs.lookup
             (
-                vtkCompositeDataSet::NAME(),
-                cloudName
+                channelName,
+                vtkSmartPointer<vtkMultiBlockDataSet>::New()
             );
 
-            outputs.set(channel, block);  // overwrites existing
-        }
+        block->SetBlock(blockNo, dataset);
+
+        block->GetMetaData(blockNo)->Set
+        (
+            vtkCompositeDataSet::NAME(),
+            cloudName                       // block name = cloud name
+        );
+
+        outputs.set(channelName, block);    // overwrites existing
 
         ++blockNo;
     }
diff --git a/src/catalyst/cloud/catalystCloud.H b/src/catalyst/cloud/catalystCloud.H
index ef18d71..ee25fa5 100644
--- a/src/catalyst/cloud/catalystCloud.H
+++ b/src/catalyst/cloud/catalystCloud.H
@@ -22,37 +22,49 @@ License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
 Class
-    Foam::catalystCloud
+    Foam::catalyst::cloudInput
 
 Description
-    A Paraview Catalyst source for OpenFOAM clouds (lagrangian).
+    An input (source) for Paraview Catalyst from clouds (lagrangian).
 
-    The source comprises a single internal "cloud" channel,
-    which is a multi-block dataset (one block per cloud).
-    On output, the "cloud" sub-channel receives the name of the source.
+    Produces a multi-block dataset with one block per cloud with pieces
+    from each processor.
 
     Example specification:
     \verbatim
-    myCloud
+    someName
     {
-        type            cloud;
-        cloud           NAME;
-        fields          (U T rho);
+        type        cloud;
+        cloud       myCloud;
+        fields      (U T rho);
     }
     \endverbatim
 
 Usage
     \table
-        Property     | Description                 | Required    | Default
-        type         | cloud                       | yes         |
-        region       |                             | no          | region0
-        cloud        |                             | no          | defaultCloud
-        clouds       | wordRe list of clouds       | no          |
-        fields       | wordRe list of fields       | yes         |
+        Property    | Description                           | Required | Default
+        type        | input type: \c cloud                  | yes   |
+        region      | name for a single region              | no    | region0
+        cloud       | name for a single cloud               | no  | defaultCloud
+        clouds      | wordRe list of clouds                 | no    |
+        fields      | wordRe list of fields                 | yes   |
     \endtable
 
+    The output block structure:
+    \verbatim
+    |-- cloud0
+    |   |-- piece0
+    |   |-- ...
+    |   \-- pieceN
+    |-- ...
+    \-- cloudN
+        \-- ...
+    \endverbatim
+
+Note
+    The channel name is that of the defining dictionary.
+
 See also
-    Foam::catalyst::catalystInput
     Foam::vtk::cloudAdaptor
 
 SourceFiles
diff --git a/src/catalyst/cloud/foamVtkCloudAdaptor.C b/src/catalyst/cloud/foamVtkCloudAdaptor.C
index a0877b8..4497adf 100644
--- a/src/catalyst/cloud/foamVtkCloudAdaptor.C
+++ b/src/catalyst/cloud/foamVtkCloudAdaptor.C
@@ -43,7 +43,7 @@ namespace vtk
 {
     defineTypeNameAndDebug(cloudAdaptor, 0);
 }
-}
+} // End namespace Foam
 
 
 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
diff --git a/src/catalyst/volMesh/catalystFvMesh.C b/src/catalyst/volMesh/catalystFvMesh.C
index 4fb1350..deaba5d 100644
--- a/src/catalyst/volMesh/catalystFvMesh.C
+++ b/src/catalyst/volMesh/catalystFvMesh.C
@@ -25,7 +25,6 @@ License
 
 #include "catalystFvMesh.H"
 #include "addToRunTimeSelectionTable.H"
-#include "fileNameList.H"
 
 #include <vtkCPDataDescription.h>
 #include <vtkMultiBlockDataSet.h>
@@ -46,22 +45,11 @@ namespace catalyst
         default
     );
 }
-}
+} // End namespace Foam
 
 
 // * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
 
-Foam::fileName Foam::catalyst::fvMeshInput::channelName(channelEnum chan) const
-{
-    if (chan == channelEnum::INPUT)
-    {
-        return name();
-    }
-
-    return name()/vtk::fvMeshAdaptor::channelNames[chan];
-}
-
-
 void Foam::catalyst::fvMeshInput::update()
 {
     // Backend requires a corresponding mesh
@@ -77,7 +65,7 @@ void Foam::catalyst::fvMeshInput::update()
             backends_.set
             (
                 iter.key(),
-                new Foam::vtk::fvMeshAdaptor(*(iter.object()), decompose_)
+                new Foam::vtk::fvMeshAdaptor(*(iter.object()), decomposeOpt_)
             );
         }
     }
@@ -95,9 +83,10 @@ Foam::catalyst::fvMeshInput::fvMeshInput
 :
     catalystInput(name),
     time_(runTime),
+    channelOpt_(channelType::DEFAULT),
+    decomposeOpt_(false),
     selectRegions_(),
     selectFields_(),
-    decompose_(false),
     meshes_(),
     backends_()
 {
@@ -111,10 +100,34 @@ bool Foam::catalyst::fvMeshInput::read(const dictionary& dict)
 {
     catalystInput::read(dict);
 
+    meshes_.clear();
     backends_.clear();
     selectFields_.clear();
     selectRegions_.clear();
-    decompose_ = dict.lookupOrDefault("decompose", false);
+    decomposeOpt_ = dict.lookupOrDefault("decompose", false);
+
+    unsigned selected(channelType::NONE);
+
+    if (dict.lookupOrDefault("internal", true))
+    {
+        selected |= channelType::INTERNAL;
+    }
+    if (dict.lookupOrDefault("boundary", true))
+    {
+        selected |= channelType::BOUNDARY;
+    }
+
+    channelOpt_ = channelType(selected);
+
+    if (channelType::NONE == channelOpt_)
+    {
+        // Both are disabled - warn, and skip the rest of the input.
+        WarningInFunction
+            << name() << ":" << nl
+            << "    both internal and boundary are disabled" << nl
+            << "    check your input" << nl;
+        return true;
+    }
 
     // All possible meshes
     meshes_ = time_.lookupClass<fvMesh>();
@@ -131,7 +144,7 @@ bool Foam::catalyst::fvMeshInput::read(const dictionary& dict)
     // Restrict to specified meshes
     meshes_.filterKeys(selectRegions_);
 
-    dict.lookup("fields") >> selectFields_;
+    dict.read("fields", selectFields_);
 
     return true;
 }
@@ -161,6 +174,12 @@ void Foam::catalyst::fvMeshInput::update(polyMesh::readUpdateState state)
 
 Foam::label Foam::catalyst::fvMeshInput::addChannels(dataQuery& dataq)
 {
+    if (channelType::NONE == channelOpt_)
+    {
+        // Everything disabled - do nothing
+        return 0;
+    }
+
     update();   // Enforce sanity for backends and adaptor
 
     if (backends_.empty())
@@ -175,14 +194,9 @@ Foam::label Foam::catalyst::fvMeshInput::addChannels(dataQuery& dataq)
         allFields += iter.object()->knownFields(selectFields_);
     }
 
+    dataq.set(name(), allFields);
 
-    // This solution may be a temporary measure...
-
-    dataq.set(name(), allFields);  // channel::INPUT
-    dataq.set(channelName(channelEnum::MESH),    allFields);
-    dataq.set(channelName(channelEnum::PATCHES), allFields);
-
-    return 3;
+    return 1;
 }
 
 
@@ -192,136 +206,49 @@ bool Foam::catalyst::fvMeshInput::convert
     outputChannels& outputs
 )
 {
+    const word channelName(name());
     const wordList regionNames(backends_.sortedToc());
 
-    if (regionNames.empty())
+    if (regionNames.empty() || !dataq.found(channelName))
     {
-        return false;  // skip - not available
+        // Not available, or not requested
+        return false;
     }
-
-    // Multi-channel
-
-    // This solution may be a temporary measure...
-
-    unsigned whichChannels = channelEnum::NONE;
-
-    // channel::INPUT
-    if (dataq.found(name()))
+    if (channelType::NONE == channelOpt_)
     {
-        whichChannels |= channelEnum::INPUT;
+        // Safety: everything disabled (should have been caught before)
+        return false;
     }
 
-    // channel::MESH
-    if (dataq.found(channelName(channelEnum::MESH)))
-    {
-        whichChannels |= channelEnum::MESH;
-    }
 
-    // channel::PATCHES
-    if (dataq.found(channelName(channelEnum::PATCHES)))
-    {
-        whichChannels |= channelEnum::PATCHES;
-    }
+    // A separate block for each region
+    unsigned int blockNo = 0;
 
-    if (channelEnum::NONE == whichChannels)
+    for (const word& regionName : regionNames)
     {
-        return false;  // skip - not requested
-    }
-
+        // Define/redefine output channels (caching)
+        backends_[regionName]->channels(channelOpt_);
 
-    // TODO: currently don't rely on the results from expecting much at all
+        auto dataset = backends_[regionName]->output(selectFields_);
 
-    // Each region goes into a separate block.
-    unsigned int blockNo = 0;
-    for (const word& regionName : regionNames)
-    {
-        // define/redefine output channels
-        backends_[regionName]->channels(whichChannels);
 
-        vtkSmartPointer<vtkMultiBlockDataSet> dataset =
-            backends_[regionName]->output(selectFields_);
+        // Existing or new
+        vtkSmartPointer<vtkMultiBlockDataSet> block =
+            outputs.lookup
+            (
+                channelName,
+                vtkSmartPointer<vtkMultiBlockDataSet>::New()
+            );
 
-        // MESH = block 0
-        {
-            const unsigned int channelNo = 0;
-
-            const fileName channel(channelName(channelEnum::MESH));
-
-            if (dataq.found(channel))
-            {
-                // Get existing or new
-                vtkSmartPointer<vtkMultiBlockDataSet> block =
-                    outputs.lookup
-                    (
-                        channel,
-                        vtkSmartPointer<vtkMultiBlockDataSet>::New()
-                    );
-
-                block->SetBlock(blockNo, dataset->GetBlock(channelNo));
-
-                block->GetMetaData(blockNo)->Set
-                (
-                    vtkCompositeDataSet::NAME(),
-                    regionName
-                );
-
-                outputs.set(channel, block); // overwrites existing
-            }
-        }
+        block->SetBlock(blockNo, dataset);
 
-        // PATCHES = block 1
-        {
-            const unsigned int channelNo = 1;
-
-            const fileName channel(channelName(channelEnum::PATCHES));
-
-            if (dataq.found(channel))
-            {
-                // Get existing or new
-                vtkSmartPointer<vtkMultiBlockDataSet> block =
-                    outputs.lookup
-                    (
-                        channel,
-                        vtkSmartPointer<vtkMultiBlockDataSet>::New()
-                    );
-
-                block->SetBlock(blockNo, dataset->GetBlock(channelNo));
-
-                block->GetMetaData(blockNo)->Set
-                (
-                    vtkCompositeDataSet::NAME(),
-                    regionName
-                );
-
-                outputs.set(channel, block);  // overwrites existing
-            }
-        }
+        block->GetMetaData(blockNo)->Set
+        (
+            vtkCompositeDataSet::NAME(),
+            regionName                      // block name = region name
+        );
 
-        // INPUT
-        {
-            const fileName channel = name();
-
-            if (dataq.found(channel))
-            {
-                // 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
-            }
-        }
+        outputs.set(channelName, block);    // overwrites existing
 
         ++blockNo;
     }
@@ -335,7 +262,27 @@ Foam::Ostream& Foam::catalyst::fvMeshInput::print(Ostream& os) const
     os  << name() << nl
         <<"    regions " << flatOutput(selectRegions_) << nl
         <<"    meshes  " << flatOutput(meshes_.sortedToc()) << nl
-        <<"    fields  " << flatOutput(selectFields_) << nl;
+        <<"    fields  " << flatOutput(selectFields_) << nl
+        <<"    output ";
+
+    const unsigned selected(channelOpt_);
+
+    if (!selected)
+    {
+        os << " none";
+    }
+    else
+    {
+        if (0 != (selected & (channelType::INTERNAL)))
+        {
+            os  <<" internal";
+        }
+        if (0 != (selected & (channelType::BOUNDARY)))
+        {
+            os  <<" boundary";
+        }
+    }
+    os << nl;
 
     return os;
 }
diff --git a/src/catalyst/volMesh/catalystFvMesh.H b/src/catalyst/volMesh/catalystFvMesh.H
index 82d4fcf..b6ab20e 100644
--- a/src/catalyst/volMesh/catalystFvMesh.H
+++ b/src/catalyst/volMesh/catalystFvMesh.H
@@ -25,39 +25,66 @@ Class
     Foam::catalyst::fvMeshInput
 
 Description
-    A Paraview Catalyst source for OpenFOAM fvMesh regions.
+    An input (source) for Paraview Catalyst from fvMesh regions.
 
-    The source comprises up to three internal channels
-    ("input", "mesh", "patches"), each of which is a multi-block dataset.
-    On output, the "input" sub-channel receives the name of the source,
-    while the "mesh" and "patches" sub-channels are prefixed with the
-    name of the source.
+    Produces a multi-block dataset with one block per region.
+    Each region block contains up to two blocks corresponding
+    to the internal (volume) mesh (block 0) and the boundary (block 1),
+    which are further divided into sub-blocks for each patch.
+    The lowest blocks contain pieces from each processor.
 
     Example specification:
     \verbatim
-    myName
+    someName
     {
-        type            default;
-        regions         ( ".*Solid" )
-        fields          (U p);
+        type        default;
+        regions     ( ".*solid" )
+        boundary    false;
+        fields      (U p);
     }
     \endverbatim
 
-    Resulting in three output channels:
-    "myName", "myName/mesh", "myName/patches"
-
 Usage
     \table
-        Property     | Description                      | Required    | Default
-        type         | default                          | no          | default
-        region       |                                  | no          | region0
-        regions      | wordRe list of regions           | no          |
-        fields       | wordRe list of fields            | yes         |
-        decompose    | decompose polyhedra              | no          | false
+        Property    | Description                           | Required | Default
+        type        | input type: \c default                | no    | default
+        region      | name for a single region              | no    | region0
+        regions     | wordRe list of regions                | no    |
+        fields      | wordRe list of fields                 | yes   |
+        boundary    | convert boundary fields               | no    | true
+        internal    | convert internal fields               | no    | true
+        decompose   | decompose polyhedra (experimental)    | no    | false
     \endtable
 
+    The output block structure:
+    \verbatim
+    |-- region0
+    |   |-- internal
+    |   |   |-- piece0
+    |   |   |-- ...
+    |   |   \-- pieceN
+    |   \-- boundary
+    |       |-- patch0
+    |       |   |-- piece0
+    |       |   |-- ...
+    |       |   \-- pieceN
+    |       |-- ...
+    |       \-- patchN
+    |           |-- piece0
+    |           |-- ...
+    |           \-- pieceN
+    |-- ...
+    \-- regionN
+        |-- internal
+        |   \-- ...
+        \-- boundary
+            \-- ...
+    \endverbatim
+
+Note
+    The channel name is that of the defining dictionary.
+
 See also
-    Foam::catalyst::catalystInput
     Foam::vtk::fvMeshAdaptor
 
 SourceFiles
@@ -93,33 +120,33 @@ protected:
 
     // Protected data
 
+        //- Channel enumeration from vtk::fvMeshAdaptor
+        using channelType = vtk::fvMeshAdaptor::channelType;
+
         //- Reference to the time database
         const Time& time_;
 
+        //- Sub-block selection (internal/boundary) mesh and fields
+        channelType channelOpt_;
+
+        //- Decompose polyhedra (experimental, perhaps of questionable use)
+        bool decomposeOpt_;
+
         //- Requested names of regions to process
         wordRes selectRegions_;
 
         //- Names of fields to process
         wordRes selectFields_;
 
-        //- Decompose polyhedra
-        bool decompose_;
-
         //- Pointers to the requested mesh regions
         HashTable<const fvMesh*> meshes_;
 
         //- Backends for OpenFOAM to VTK translation (with internal caching)
         HashPtrTable<vtk::fvMeshAdaptor> backends_;
 
-        //- Use channel enumeration from vtk::fvMeshAdaptor
-        using channelEnum = vtk::fvMeshAdaptor::channel;
-
 
     // Protected Member Functions
 
-        //- Return full channel name
-        fileName channelName(channelEnum chan) const;
-
         //- Update/synchronize internals with catalyst backends
         void update();
 
@@ -159,6 +186,8 @@ public:
         virtual void update(polyMesh::readUpdateState state);
 
         //- Add available channels (with fields) to data query
+        //
+        //  \return the number of channels added
         virtual label addChannels(dataQuery& dataq);
 
         //- Convert channels to vtkMultiBlockDataSet outputs
diff --git a/src/catalyst/volMesh/foamVtkFvMeshAdaptor.C b/src/catalyst/volMesh/foamVtkFvMeshAdaptor.C
index 56f5e1a..1fc8b5a 100644
--- a/src/catalyst/volMesh/foamVtkFvMeshAdaptor.C
+++ b/src/catalyst/volMesh/foamVtkFvMeshAdaptor.C
@@ -43,23 +43,22 @@ namespace vtk
 {
     defineTypeNameAndDebug(fvMeshAdaptor, 0);
 }
-}
+} // End namespace Foam
+
 
 const Foam::Enum
 <
-    Foam::vtk::fvMeshAdaptor::channel
+    Foam::vtk::fvMeshAdaptor::channelType
 >
 Foam::vtk::fvMeshAdaptor::channelNames
 {
-    { channel::MESH,    "mesh" },
-    { channel::PATCHES, "patches" },
-    { channel::INPUT,   "input" },
+    { channelType::NONE,     "none" },
+    { channelType::INTERNAL, "internal" },
+    { channelType::BOUNDARY, "boundary" },
+    { channelType::ALL,      "all" },
 };
 
 
-const Foam::word Foam::vtk::fvMeshAdaptor::internalName("internal");
-
-
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 Foam::vtk::fvMeshAdaptor::fvMeshAdaptor
@@ -69,7 +68,9 @@ Foam::vtk::fvMeshAdaptor::fvMeshAdaptor
 )
 :
     mesh_(mesh),
-    channels_(INPUT),
+    channels_(ALL),
+    interpFields_(true),
+    extrapPatches_(false),
     decomposePoly_(decompose),
     meshState_(polyMesh::TOPO_CHANGE)
 {}
@@ -92,16 +93,32 @@ void Foam::vtk::fvMeshAdaptor::channels(const wordList& chanNames)
 }
 
 
+void Foam::vtk::fvMeshAdaptor::channels(enum channelType chanIds)
+{
+    channels_ = chanIds;
+
+    if (!usingInternal())
+    {
+        cachedVtu_.clear();
+    }
+
+    if (!usingBoundary())
+    {
+        cachedVtp_.clear();
+    }
+}
+
+
 void Foam::vtk::fvMeshAdaptor::channels(unsigned chanIds)
 {
     channels_ = (chanIds & 0x3);
 
-    if (!usingVolume())
+    if (!usingInternal())
     {
         cachedVtu_.clear();
     }
 
-    if (!usingPatches())
+    if (!usingBoundary())
     {
         cachedVtp_.clear();
     }
@@ -114,27 +131,24 @@ Foam::label Foam::vtk::fvMeshAdaptor::channels() const
 }
 
 
-bool Foam::vtk::fvMeshAdaptor::usingVolume() const
+bool Foam::vtk::fvMeshAdaptor::usingInternal() const
 {
-    // MESH = "internal"
-    return (channels_ & (INPUT | MESH));
+    return (channels_ & INTERNAL);
 }
 
 
-bool Foam::vtk::fvMeshAdaptor::usingPatches() const
+bool Foam::vtk::fvMeshAdaptor::usingBoundary() const
 {
-    // PATCHES
-    return (channels_ & (INPUT | PATCHES));
+    return (channels_ & BOUNDARY);
 }
 
 
-
 Foam::label Foam::vtk::fvMeshAdaptor::nPatches() const
 {
     // Restrict to non-processor patches.
     // This value is invariant across all processors.
 
-    if (usingPatches())
+    if (usingBoundary())
     {
         return mesh_.boundaryMesh().nNonProcessor();
     }
@@ -151,13 +165,14 @@ void Foam::vtk::fvMeshAdaptor::updateContent(const wordRes& selectFields)
 
     HashSet<string> nowActive;
 
-    // MESH = "internal"
-    if (usingVolume())
+    // INTERNAL
+    if (usingInternal())
     {
-        nowActive.insert(internalName);
+        nowActive.insert(internalName());
     }
 
-    // PATCHES
+    // BOUNDARY
+
     // Restrict to non-processor patches.
     // This value is invariant across all processors.
 
@@ -203,7 +218,8 @@ void Foam::vtk::fvMeshAdaptor::updateContent(const wordRes& selectFields)
     }
 
     convertGeometryInternal();
-    convertGeometryPatches();
+    convertGeometryBoundary();
+
     applyGhosting();
     convertVolFields(selectFields);
     meshState_ = polyMesh::UNCHANGED;
@@ -230,13 +246,14 @@ Foam::vtk::fvMeshAdaptor::output(const wordRes& select)
 
     auto outputs = vtkSmartPointer<vtkMultiBlockDataSet>::New();
 
-    // MESH
-    {
-        unsigned int blockNo = 0;
+    unsigned int blockNo = 0;
 
+    // INTERNAL
+    if (usingInternal())
+    {
         do
         {
-            const auto& longName = internalName;
+            const auto& longName = internalName();
             auto iter = cachedVtu_.find(longName);
             if (!iter.found() || !iter.object().dataset)
             {
@@ -256,18 +273,18 @@ Foam::vtk::fvMeshAdaptor::output(const wordRes& select)
             outputs->GetMetaData(blockNo)->Set
             (
                 vtkCompositeDataSet::NAME(),
-                internalName
+                internalName()
             );
 
             ++blockNo;
         } while (false);  // do once
     }
 
-    // PATCHES
+    // BOUNDARY
     const label npatches = this->nPatches();
     if (npatches)
     {
-        unsigned int blockNo = 0;
+        unsigned int subBlockNo = 0;
 
         auto output = vtkSmartPointer<vtkMultiBlockDataSet>::New();
 
@@ -292,22 +309,23 @@ Foam::vtk::fvMeshAdaptor::output(const wordRes& select)
             pieces->SetNumberOfPieces(nproc);
             pieces->SetPiece(rank, vtpData.dataset);
 
-            output->SetBlock(blockNo, pieces);
+            output->SetBlock(subBlockNo, pieces);
 
-            output->GetMetaData(blockNo)->Set
+            output->GetMetaData(subBlockNo)->Set
             (
                 vtkCompositeDataSet::NAME(),
                 longName
             );
 
-            ++blockNo;
+            ++subBlockNo;
         }
 
-        outputs->SetBlock(1, output);
-        outputs->GetMetaData(1)->Set
+        outputs->SetBlock(blockNo, output);
+
+        outputs->GetMetaData(blockNo)->Set
         (
             vtkCompositeDataSet::NAME(),
-            channelNames[channel::PATCHES]
+            boundaryName()
         );
     }
 
diff --git a/src/catalyst/volMesh/foamVtkFvMeshAdaptor.H b/src/catalyst/volMesh/foamVtkFvMeshAdaptor.H
index 9ebf492..a5e22db 100644
--- a/src/catalyst/volMesh/foamVtkFvMeshAdaptor.H
+++ b/src/catalyst/volMesh/foamVtkFvMeshAdaptor.H
@@ -28,13 +28,16 @@ Description
     The backend for the catalystFvMesh function object.
 
     The output is a multi-block dataset with two blocks corresponding
-    to the internal (volume) mesh (block 0) and the patches as (block 1).
-    These two blocks correspond simultaneously to the catalyst channels
-    "mesh" and "patches", respectively.
+    to the internal (volume) mesh (block 0) and the boundary (block 1),
+    which are further divided into sub-blocks for each patch.
 
-    The patches are further divided into sub-blocks. The lowest data blocks
-    are multi-piece datasets (UnstructuredGrid and PolyData for internal mesh
-    and patches, respectively) with each piece corresponding to its MPI rank.
+    The lowest data blocks are multi-piece datasets (UnstructuredGrid
+    and PolyData for internal mesh and boundary, respectively) with
+    each piece corresponding to its MPI rank.
+
+Note
+    It is possible to restrict the output of the blocks (eg, patches only)
+    by specifying the appropriate "channels" prior to conversion.
 
 SourceFiles
     foamVtkFvMeshAdaptor.C
@@ -49,13 +52,12 @@ SourceFiles
 #define foamvtk_fvMeshAdaptor_H
 
 #include "className.H"
-#include "fileName.H"
-#include "stringList.H"
 #include "wordList.H"
 #include "Enum.H"
 #include "primitivePatch.H"
 #include "PrimitivePatchInterpolation.H"
 #include "volPointInterpolation.H"
+
 #include "foamVtkTools.H"
 #include "foamVtkMeshMaps.H"
 
@@ -96,19 +98,29 @@ public:
 
         //- Public Data Members
 
-        //- The Catalyst output channels
-        enum channel
+        //- The types of output blocks. Defined as a bitmask.
+        enum channelType : unsigned
         {
-            NONE = 0,
-            MESH = 0x1,
-            PATCHES = 0x2,
-            INPUT = 0x3
+            NONE = 0,           //!< No output (placeholder).
+            INTERNAL = 0x1,     //!< Internal mesh.
+            BOUNDARY = 0x2,     //!< Boundary patches.
+            ALL = 0x3,          //!< Both internal mesh and boundary patches.
+            DEFAULT = ALL       //!< Default is ALL
         };
 
-        static const Enum<channel> channelNames;
+        static const Enum<channelType> channelNames;
 
         //- Name for internal mesh ("internal")
-        static const word internalName;
+        static const word& internalName()
+        {
+            return channelNames[channelType::INTERNAL];
+        }
+
+        //- Name for the boundary ("boundary")
+        static const word& boundaryName()
+        {
+            return channelNames[channelType::BOUNDARY];
+        }
 
 
 private:
@@ -161,7 +173,14 @@ private:
         //- Selected output channels
         unsigned channels_;
 
-        //- Previous/current decomposition request
+        //- Interpolate volume to point fields (default: true)
+        //  Generates PointData in VTK
+        bool interpFields_;
+
+        //- Extrapolate the internal field to the boundaries (default: false)
+        bool extrapPatches_;
+
+        //- Previous/current decomposition request (default: false)
         bool decomposePoly_;
 
         //- Track changes in mesh geometry
@@ -182,13 +201,13 @@ private:
         //- Convert patches
         //  Patches may use additionalIds (cached data) with the patch Ids.
         //  There will be several for groups, but only one for regular patches.
-        void convertGeometryPatches();
+        void convertGeometryBoundary();
 
         //- Ghost cells - internal mesh
         void applyGhostingInternal(const labelUList& types);
 
         //- Ghost cells - patches
-        void applyGhostingPatches(const labelUList& types);
+        void applyGhostingBoundary(const labelUList& types);
 
         //- Ghost cells to affect the visibility of the geometry.
         //  Currently only used for overset.
@@ -286,19 +305,22 @@ public:
         //- Define the output channels by name
         void channels(const wordList& chanNames);
 
+        //- Define the output channels by enum
+        void channels(enum channelType chanIds);
+
         //- Define the output channels by value
         void channels(unsigned chanIds);
 
         //- Return the selected output channel ids
         label channels() const;
 
-        //- True if MESH channel is being used
-        bool usingVolume() const;
+        //- True if INTERNAL channel is being used
+        bool usingInternal() const;
 
-        //- True if PATCHES channel is being used
-        bool usingPatches() const;
+        //- True if BOUNDARY channel is being used
+        bool usingBoundary() const;
 
-        //- Number of non-processor patches, when the PATCHES channel is being
+        //- Number of non-processor patches, when the BOUNDARY channel is being
         //- used - otherwise 0.
         label nPatches() const;
 
@@ -307,8 +329,8 @@ public:
 
         void updateState(polyMesh::readUpdateState state);
 
-        //- The output is a pair (MESH/PATCHES channels) of vtk meshes with
-        //- point/cell data.
+        //- The output is a pair (INTERNAL/BOUNDARY channels) of vtk meshes
+        //- with point/cell data.
         vtkSmartPointer<vtkMultiBlockDataSet> output
         (
             const wordRes& selectFields
diff --git a/src/catalyst/volMesh/foamVtkFvMeshAdaptorFieldTemplates.C b/src/catalyst/volMesh/foamVtkFvMeshAdaptorFieldTemplates.C
index 57717e8..f8e918b 100644
--- a/src/catalyst/volMesh/foamVtkFvMeshAdaptorFieldTemplates.C
+++ b/src/catalyst/volMesh/foamVtkFvMeshAdaptorFieldTemplates.C
@@ -55,12 +55,9 @@ void Foam::vtk::fvMeshAdaptor::convertVolField
     const fvMesh& mesh = fld.mesh();
     const polyBoundaryMesh& patches = mesh.boundaryMesh();
 
-    const bool interpField = !patchInterpList.empty();
-    const bool extrapPatch = false; //reader_->GetExtrapolatePatches(); TODO
-
     // Interpolated field (demand driven)
     autoPtr<GeometricField<Type, pointPatchField, pointMesh>> ptfPtr;
-    if (interpField)
+    if (interpFields_)
     {
         ptfPtr.reset
         (
@@ -68,10 +65,10 @@ void Foam::vtk::fvMeshAdaptor::convertVolField
         );
     }
 
-    // MESH
+    // INTERNAL
     convertVolFieldInternal(fld, ptfPtr);
 
-    // PATCHES
+    // BOUNDARY
     const label npatches = this->nPatches();
 
     for (label patchId=0; patchId < npatches; ++patchId)
@@ -114,7 +111,7 @@ void Foam::vtk::fvMeshAdaptor::convertVolField
             isType<emptyFvPatchField<Type>>(ptf)
          ||
             (
-                extrapPatch
+                extrapPatches_
              && !polyPatch::constraintType(patches[patchId].type())
             )
         )
@@ -128,7 +125,7 @@ void Foam::vtk::fvMeshAdaptor::convertVolField
 
             transcribeFloatData(cdata, tpptf());
 
-            if (interpField && patchId < patchInterpList.size())
+            if (interpFields_ && patchId < patchInterpList.size())
             {
                 pdata = vtk::Tools::convertFieldToVTK
                 (
@@ -141,7 +138,7 @@ void Foam::vtk::fvMeshAdaptor::convertVolField
         {
             transcribeFloatData(cdata, ptf);
 
-            if (interpField && patchId < patchInterpList.size())
+            if (interpFields_ && patchId < patchInterpList.size())
             {
                 pdata = vtk::Tools::convertFieldToVTK
                 (
@@ -193,12 +190,12 @@ void Foam::vtk::fvMeshAdaptor::convertVolFieldInternal
     autoPtr<GeometricField<Type, pointPatchField, pointMesh>>& ptfPtr
 )
 {
-    if (!usingVolume())
+    if (!usingInternal())
     {
         return;
     }
 
-    const auto& longName = internalName;
+    const auto& longName = internalName();
 
     auto iter = cachedVtu_.find(longName);
     if (!iter.found() || !iter.object().dataset)
diff --git a/src/catalyst/volMesh/foamVtkFvMeshAdaptorFields.C b/src/catalyst/volMesh/foamVtkFvMeshAdaptorFields.C
index 1db58fe..facca3c 100644
--- a/src/catalyst/volMesh/foamVtkFvMeshAdaptorFields.C
+++ b/src/catalyst/volMesh/foamVtkFvMeshAdaptorFields.C
@@ -51,7 +51,7 @@ static wordHashSet supportedTypes()
     return types;
 }
 
-} // end of Foam
+} // End namespace Foam
 
 
 Foam::wordHashSet Foam::vtk::fvMeshAdaptor::knownFields
@@ -94,8 +94,6 @@ void Foam::vtk::fvMeshAdaptor::convertVolFields
     const wordRes& selectFields
 )
 {
-    const bool interpFields = true;
-
     // Quick exit if no volume fields can be converted.
     // This could be refined
     HashTable<wordHashSet> objects = mesh_.classes(selectFields);
@@ -107,7 +105,7 @@ void Foam::vtk::fvMeshAdaptor::convertVolFields
 
     PtrList<patchInterpolator> interpLst;
 
-    if (interpFields)
+    if (interpFields_)
     {
         // NOTE: this will be broken with processor patches, but
         // for the catalyst adaptor we explicitly restrict ourselves
diff --git a/src/catalyst/volMesh/foamVtkFvMeshAdaptorGeom.C b/src/catalyst/volMesh/foamVtkFvMeshAdaptorGeom.C
index 7867c12..db8d1a5 100644
--- a/src/catalyst/volMesh/foamVtkFvMeshAdaptorGeom.C
+++ b/src/catalyst/volMesh/foamVtkFvMeshAdaptorGeom.C
@@ -36,14 +36,14 @@ License
 
 void Foam::vtk::fvMeshAdaptor::convertGeometryInternal()
 {
-    // MESH = "internal"
-    if (!usingVolume())
+    // INTERNAL
+    if (!usingInternal())
     {
         cachedVtu_.clear();
         return;
     }
 
-    const auto& longName = internalName;
+    const auto& longName = internalName();
 
     foamVtuData& vtuData = cachedVtu_(longName);
 
@@ -85,9 +85,9 @@ void Foam::vtk::fvMeshAdaptor::convertGeometryInternal()
 }
 
 
-void Foam::vtk::fvMeshAdaptor::convertGeometryPatches()
+void Foam::vtk::fvMeshAdaptor::convertGeometryBoundary()
 {
-    // PATCHES
+    // BOUNDARY
 
     const polyBoundaryMesh& patches = mesh_.boundaryMesh();
     const label npatches = this->nPatches();
@@ -154,14 +154,14 @@ void Foam::vtk::fvMeshAdaptor::convertGeometryPatches()
 
 void Foam::vtk::fvMeshAdaptor::applyGhostingInternal(const labelUList& types)
 {
-    // MESH = "internal"
+    // INTERNAL
 
-    if (types.empty() || !usingVolume())
+    if (types.empty() || !usingInternal())
     {
         return;
     }
 
-    const auto& longName = internalName;
+    const auto& longName = internalName();
 
     auto iter = cachedVtu_.find(longName);
     if (!iter.found() || !iter.object().dataset)
@@ -223,11 +223,11 @@ void Foam::vtk::fvMeshAdaptor::applyGhostingInternal(const labelUList& types)
 }
 
 
-void Foam::vtk::fvMeshAdaptor::applyGhostingPatches(const labelUList& types)
+void Foam::vtk::fvMeshAdaptor::applyGhostingBoundary(const labelUList& types)
 {
-    // PATCHES
+    // BOUNDARY
 
-    if (types.empty())
+    if (types.empty() || !usingBoundary())
     {
         return;
     }
@@ -317,7 +317,7 @@ void Foam::vtk::fvMeshAdaptor::applyGhosting()
         const labelUList& types = stencilPtr->cellTypes();
 
         applyGhostingInternal(types);
-        applyGhostingPatches(types);
+        applyGhostingBoundary(types);
     }
 }
 
diff --git a/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/showCs.py b/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/showCs.py
new file mode 100644
index 0000000..5689709
--- /dev/null
+++ b/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/showCs.py
@@ -0,0 +1,217 @@
+
+from paraview.simple import *
+from paraview import coprocessing
+
+
+#--------------------------------------------------------------
+# Code generated from cpstate.py to create the CoProcessor.
+# paraview version 5.5.2
+
+#--------------------------------------------------------------
+# Global screenshot output options
+imageFileNamePadding=6
+rescale_lookuptable=False
+
+
+# ----------------------- CoProcessor definition -----------------------
+
+def CreateCoProcessor():
+  def _CreatePipeline(coprocessor, datadescription):
+    class Pipeline:
+      # state file generated using paraview version 5.5.2
+
+      # ----------------------------------------------------------------
+      # setup views used in the visualization
+      # ----------------------------------------------------------------
+
+      # trace generated using paraview version 5.5.2
+
+      #### disable automatic camera reset on 'Show'
+      paraview.simple._DisableFirstRenderCameraReset()
+
+      # Create a new 'Render View'
+      renderView1 = CreateView('RenderView')
+      renderView1.ViewSize = [1310, 756]
+      renderView1.AxesGrid = 'GridAxes3DActor'
+      renderView1.StereoType = 0
+      renderView1.CameraPosition = [-2.2544226375406193, 5.894774264129292, 2.2504803852287485]
+      renderView1.CameraFocalPoint = [-0.17575377892067334, 0.05729450607871205, -0.2768849507248347]
+      renderView1.CameraViewUp = [0.24075355565216316, -0.312162886467996, 0.9190168974250745]
+      renderView1.CameraParallelScale = 0.9776975264012226
+      renderView1.CameraParallelProjection = 1
+      renderView1.Background = [0.32, 0.34, 0.43]
+
+      # init the 'GridAxes3DActor' selected for 'AxesGrid'
+      renderView1.AxesGrid.XTitleFontFile = ''
+      renderView1.AxesGrid.YTitleFontFile = ''
+      renderView1.AxesGrid.ZTitleFontFile = ''
+      renderView1.AxesGrid.XLabelFontFile = ''
+      renderView1.AxesGrid.YLabelFontFile = ''
+      renderView1.AxesGrid.ZLabelFontFile = ''
+
+      # register the view with coprocessor
+      # and provide it with information such as the filename to use,
+      # how frequently to write the images, etc.
+      coprocessor.RegisterView(renderView1,
+          filename='image_%t.png', freq=1, fittoscreen=0, magnification=1, width=1310, height=756, cinema={})
+      renderView1.ViewTime = datadescription.GetTime()
+
+      # ----------------------------------------------------------------
+      # restore active view
+      SetActiveView(renderView1)
+      # ----------------------------------------------------------------
+
+      # ----------------------------------------------------------------
+      # setup the data processing pipelines
+      # ----------------------------------------------------------------
+
+      # create a new 'XML MultiBlock Data Reader'
+      # create a producer from a simulation input
+      area = coprocessor.CreateProducer(datadescription, 'area')
+
+      # create a new 'Clip'
+      clip1 = Clip(Input=area)
+      clip1.ClipType = 'Plane'
+      clip1.Scalars = ['CELLS', 'Cs']
+      clip1.Value = 1.020149976015091
+
+      # init the 'Plane' selected for 'ClipType'
+      clip1.ClipType.Normal = [0.0, 0.0, 1.0]
+
+      # ----------------------------------------------------------------
+      # setup the visualization in view 'renderView1'
+      # ----------------------------------------------------------------
+
+      # show data from clip1
+      clip1Display = Show(clip1, renderView1)
+
+      # get color transfer function/color map for 'Cs'
+      csLUT = GetColorTransferFunction('Cs')
+      csLUT.RGBPoints = [0.7730422616004944, 0.231373, 0.298039, 0.752941, 1.020149976015091, 0.865003, 0.865003, 0.865003, 1.2672576904296875, 0.705882, 0.0156863, 0.14902]
+      csLUT.ScalarRangeInitialized = 1.0
+
+      # get opacity transfer function/opacity map for 'Cs'
+      csPWF = GetOpacityTransferFunction('Cs')
+      csPWF.Points = [0.7730422616004944, 0.0, 0.5, 0.0, 1.2672576904296875, 1.0, 0.5, 0.0]
+      csPWF.ScalarRangeInitialized = 1
+
+      # trace defaults for the display properties.
+      clip1Display.Representation = 'Surface'
+      clip1Display.ColorArrayName = ['CELLS', 'Cs']
+      clip1Display.LookupTable = csLUT
+      clip1Display.OSPRayScaleFunction = 'PiecewiseFunction'
+      clip1Display.SelectOrientationVectors = 'None'
+      clip1Display.ScaleFactor = 0.2
+      clip1Display.SelectScaleArray = 'None'
+      clip1Display.GlyphType = 'Arrow'
+      clip1Display.GlyphTableIndexArray = 'None'
+      clip1Display.GaussianRadius = 0.01
+      clip1Display.SetScaleArray = [None, '']
+      clip1Display.ScaleTransferFunction = 'PiecewiseFunction'
+      clip1Display.OpacityArray = [None, '']
+      clip1Display.OpacityTransferFunction = 'PiecewiseFunction'
+      clip1Display.DataAxesGrid = 'GridAxesRepresentation'
+      clip1Display.SelectionCellLabelFontFile = ''
+      clip1Display.SelectionPointLabelFontFile = ''
+      clip1Display.PolarAxes = 'PolarAxesRepresentation'
+      clip1Display.ScalarOpacityFunction = csPWF
+      clip1Display.ScalarOpacityUnitDistance = 0.44814047465571655
+
+      # init the 'GridAxesRepresentation' selected for 'DataAxesGrid'
+      clip1Display.DataAxesGrid.XTitleFontFile = ''
+      clip1Display.DataAxesGrid.YTitleFontFile = ''
+      clip1Display.DataAxesGrid.ZTitleFontFile = ''
+      clip1Display.DataAxesGrid.XLabelFontFile = ''
+      clip1Display.DataAxesGrid.YLabelFontFile = ''
+      clip1Display.DataAxesGrid.ZLabelFontFile = ''
+
+      # init the 'PolarAxesRepresentation' selected for 'PolarAxes'
+      clip1Display.PolarAxes.PolarAxisTitleFontFile = ''
+      clip1Display.PolarAxes.PolarAxisLabelFontFile = ''
+      clip1Display.PolarAxes.LastRadialAxisTextFontFile = ''
+      clip1Display.PolarAxes.SecondaryRadialAxesTextFontFile = ''
+
+      # setup the color legend parameters for each legend in this view
+
+      # get color legend/bar for csLUT in view renderView1
+      csLUTColorBar = GetScalarBar(csLUT, renderView1)
+      csLUTColorBar.Title = 'Cs'
+      csLUTColorBar.ComponentTitle = ''
+      csLUTColorBar.TitleFontFile = ''
+      csLUTColorBar.LabelFontFile = ''
+
+      # set color bar visibility
+      csLUTColorBar.Visibility = 1
+
+      # show color legend
+      clip1Display.SetScalarBarVisibility(renderView1, True)
+
+      # ----------------------------------------------------------------
+      # setup color maps and opacity mapes used in the visualization
+      # note: the Get..() functions create a new object, if needed
+      # ----------------------------------------------------------------
+
+      # ----------------------------------------------------------------
+      # finally, restore active source
+      SetActiveSource(clip1)
+      # ----------------------------------------------------------------
+    return Pipeline()
+
+  class CoProcessor(coprocessing.CoProcessor):
+    def CreatePipeline(self, datadescription):
+      self.Pipeline = _CreatePipeline(self, datadescription)
+
+  coprocessor = CoProcessor()
+  # these are the frequencies at which the coprocessor updates.
+  freqs = {'area': [1, 1]}
+  coprocessor.SetUpdateFrequencies(freqs)
+  return coprocessor
+
+
+#--------------------------------------------------------------
+# Global variable 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 and the update frequency
+coprocessor.EnableLiveVisualization(False, 1)
+
+# ---------------------- 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=rescale_lookuptable,
+        image_quality=0, padding_amount=imageFileNamePadding)
+
+    # Live Visualization, if enabled.
+    coprocessor.DoLiveVisualization(datadescription, "localhost", 22222)
diff --git a/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/catalyst b/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/catalyst
index 67e90c7..6a7cdc3 100644
--- a/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/catalyst
+++ b/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/catalyst
@@ -6,7 +6,8 @@ catalyst
 
     scripts
     (
-        "<system>/scripts/writeArea.py"
+        // "<etc>caseDicts/insitu/catalyst/writeAll.py"
+        "<case>/showCs.py"
     );
 
     inputs
diff --git a/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/scripts/writeArea.py b/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/scripts/writeArea.py
deleted file mode 100644
index 93500d1..0000000
--- a/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/scripts/writeArea.py
+++ /dev/null
@@ -1,70 +0,0 @@
-from paraview.simple import *
-from paraview import coprocessing
-
-# ----------------------- CoProcessor definition -----------------------
-
-def CreateCoProcessor():
-  def _CreatePipeline(coprocessor, datadescription):
-    class Pipeline:
-      input1 = coprocessor.CreateProducer(datadescription, 'area')
-      writer1 = servermanager.writers.XMLMultiBlockDataWriter(Input=input1)
-
-      coprocessor.RegisterWriter(writer1, filename='area_%t.vtm', freq=2)
-
-    return Pipeline()
-
-  class CoProcessor(coprocessing.CoProcessor):
-    def CreatePipeline(self, datadescription):
-      self.Pipeline = _CreatePipeline(self, datadescription)
-
-  coprocessor = CoProcessor()
-  freqs = {'area': [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)
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/catalyst b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/catalyst
index 0823255..a3a707d 100644
--- a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/catalyst
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/catalyst
@@ -7,18 +7,19 @@ catalyst
     scripts
     (
         "<system>/scripts/slice1.py"
-        "<system>/scripts/writePatches.py"
         // "<etc>/caseDicts/insitu/catalyst/printChannels.py"
         // "<etc>/caseDicts/insitu/catalyst/writeAll.py"
     );
 
     inputs
     {
-        // channel = region, region/mesh, region/patches
         region
         {
             // All regions
-            regions (".*");
+            regions     (".*");
+
+            internal    true;
+            boundary    false;
 
             // Selected fields (words or regex)
             fields  (T U p);
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/scripts/slice1.py b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/scripts/slice1.py
index c3c0feb..aa50ce5 100644
--- a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/scripts/slice1.py
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/scripts/slice1.py
@@ -1,31 +1,25 @@
 from paraview.simple import *
 from paraview import coprocessing
 
+fileNamePadding=6
+
 # ----------------------- CoProcessor definition -----------------------
 
 def CreateCoProcessor():
   def _CreatePipeline(coprocessor, datadescription):
     class Pipeline:
-      mesh = coprocessor.CreateProducer(datadescription, 'region/mesh')
+      region = coprocessor.CreateProducer(datadescription, 'region')
 
-      slice1 = Slice(Input=mesh, guiName="Slice1", SliceOffsetValues=[0.0], Triangulatetheslice=1, SliceType="Plane")
+      slice1 = Slice(Input=region, guiName="Slice1", SliceOffsetValues=[0.0], Triangulatetheslice=1, SliceType="Plane")
       slice1.SliceType.Offset = 0.0
       slice1.SliceType.Origin = [0, 0, 0]
       slice1.SliceType.Normal = [0, 0, 1]
 
       sliceWriter = servermanager.writers.XMLMultiBlockDataWriter(Input=slice1)
+      coprocessor.RegisterWriter(sliceWriter, filename='slice_%t.vtm', freq=10, paddingamount=fileNamePadding)
 
-      # register the writer with coprocessor
-      # and provide it with information such as the filename to use,
-      # how frequently to write the data, etc.
-      coprocessor.RegisterWriter(sliceWriter, filename='slice_%t.vtm', freq=10)
-
-      meshWriter = servermanager.writers.XMLMultiBlockDataWriter(Input=mesh)
-
-      # register the writer with coprocessor
-      # and provide it with information such as the filename to use,
-      # how frequently to write the data, etc.
-      coprocessor.RegisterWriter(meshWriter, filename='mesh_%t.vtm', freq=100)
+      meshWriter = servermanager.writers.XMLMultiBlockDataWriter(Input=region)
+      coprocessor.RegisterWriter(meshWriter, filename='region_%t.vtm', freq=100, paddingamount=fileNamePadding)
 
     return Pipeline()
 
@@ -34,7 +28,7 @@ def CreateCoProcessor():
       self.Pipeline = _CreatePipeline(self, datadescription)
 
   coprocessor = CoProcessor()
-  freqs = {'region/mesh': [10, 100]}
+  freqs = {'region': [10, 100]}
   coprocessor.SetUpdateFrequencies(freqs)
   return coprocessor
 
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/scripts/writeMesh.py b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/scripts/writeMesh.py
deleted file mode 100644
index 6b8fdd8..0000000
--- a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/scripts/writeMesh.py
+++ /dev/null
@@ -1,70 +0,0 @@
-from paraview.simple import *
-from paraview import coprocessing
-
-# ----------------------- CoProcessor definition -----------------------
-
-def CreateCoProcessor():
-  def _CreatePipeline(coprocessor, datadescription):
-    class Pipeline:
-      input1 = coprocessor.CreateProducer(datadescription, 'region/mesh')
-      writer1 = servermanager.writers.XMLMultiBlockDataWriter(Input=input1)
-
-      coprocessor.RegisterWriter(writer1, filename='mesh_%t.vtm', freq=2)
-
-    return Pipeline()
-
-  class CoProcessor(coprocessing.CoProcessor):
-    def CreatePipeline(self, datadescription):
-      self.Pipeline = _CreatePipeline(self, datadescription)
-
-  coprocessor = CoProcessor()
-  freqs = {'region/mesh': [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)
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/scripts/writePatches.py b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/scripts/writePatches.py
deleted file mode 100644
index de9def1..0000000
--- a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/scripts/writePatches.py
+++ /dev/null
@@ -1,70 +0,0 @@
-from paraview.simple import *
-from paraview import coprocessing
-
-# ----------------------- CoProcessor definition -----------------------
-
-def CreateCoProcessor():
-  def _CreatePipeline(coprocessor, datadescription):
-    class Pipeline:
-      input1 = coprocessor.CreateProducer(datadescription, 'region/patches')
-      writer1 = servermanager.writers.XMLMultiBlockDataWriter(Input=input1)
-
-      coprocessor.RegisterWriter(writer1, filename='patches_%t.vtm', freq=2)
-
-    return Pipeline()
-
-  class CoProcessor(coprocessing.CoProcessor):
-    def CreatePipeline(self, datadescription):
-      self.Pipeline = _CreatePipeline(self, datadescription)
-
-  coprocessor = CoProcessor()
-  freqs = {'region/patches': [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)
diff --git a/tutorials/incompressible/icoFoam/cavity/system/catalyst b/tutorials/incompressible/icoFoam/cavity/system/catalyst
index 55aa9b2..d01dc7b 100644
--- a/tutorials/incompressible/icoFoam/cavity/system/catalyst
+++ b/tutorials/incompressible/icoFoam/cavity/system/catalyst
@@ -7,7 +7,7 @@ catalyst
     scripts
     (
         "<system>/scripts/slice1.py"
-        "<system>/scripts/writeMesh.py"
+        // "<etc>/caseDicts/insitu/catalyst/writeAll.py"
     );
 
     // Calculate a few iterations before starting processing
@@ -19,9 +19,11 @@ catalyst
 
     inputs
     {
-        // channel = region, region/mesh, region/patches
         region
         {
+            internal    true;
+            boundary    false;
+
             // Selected fields (words or regex)
             fields  (U p);
         }
diff --git a/tutorials/incompressible/icoFoam/cavity/system/scripts/writeMesh.py b/tutorials/incompressible/icoFoam/cavity/system/scripts/writeMesh.py
deleted file mode 100644
index 443bf24..0000000
--- a/tutorials/incompressible/icoFoam/cavity/system/scripts/writeMesh.py
+++ /dev/null
@@ -1,74 +0,0 @@
-from paraview.simple import *
-from paraview import coprocessing
-
-# ----------------------- CoProcessor definition -----------------------
-
-def CreateCoProcessor():
-  def _CreatePipeline(coprocessor, datadescription):
-    class Pipeline:
-      input1 = coprocessor.CreateProducer(datadescription, 'region/mesh')
-      writer1 = servermanager.writers.XMLMultiBlockDataWriter(Input=input1)
-      # Register with filename to use, output frequency
-      coprocessor.RegisterWriter(writer1, filename='mesh_%t.vtm', freq=2)
-
-      # input2 = coprocessor.CreateProducer(datadescription, "patches")
-      # writer2 = servermanager.writers.XMLMultiBlockDataWriter(Input=input2)
-      # coprocessor.RegisterWriter(writer2, filename='patches_%t.vtm', freq=2)
-
-    return Pipeline()
-
-  class CoProcessor(coprocessing.CoProcessor):
-    def CreatePipeline(self, datadescription):
-      self.Pipeline = _CreatePipeline(self, datadescription)
-
-  coprocessor = CoProcessor()
-  freqs = {'region/mesh': [2]}
-  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 pipeline requirements
-    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)
diff --git a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/catalyst b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/catalyst
index 48246a8..e9907dc 100644
--- a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/catalyst
+++ b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/catalyst
@@ -6,23 +6,47 @@ catalyst
 
     scripts
     (
-        "<system>/scripts/writeCloud.py"
-        "<system>/scripts/writePatches.py"
+        "<etc>/caseDicts/insitu/catalyst/writeAll.py"
     );
 
     inputs
     {
-        // channel = region, region/mesh, region/patches
+        // channel = region
         region
         {
-            type    default;
+            type        default;
+
+            internal    false;   // boundary only
+
+            // Selected fields (words or regex)
+            fields  ( T );
+        }
+
+        // channel = coalCloud
+        coalCloud
+        {
+            type    cloud;
+
+            cloud   coalCloud1;
+
+            // Selected fields (words or regex)
+            fields  ( T U );
+        }
+
+        // channel = limestoneCloud
+        limestoneCloud
+        {
+            type    cloud;
+
+            cloud   limestoneCloud1;
 
             // Selected fields (words or regex)
-            fields  ( T U p rho );
+            fields  ( T U );
         }
 
-        // channel = cloud
-        cloud
+        /*
+        // channel = allClouds
+        allClouds
         {
             type    cloud;
 
@@ -32,6 +56,7 @@ catalyst
             // Selected fields (words or regex)
             fields  ( T U p rho "Y.*" );
         }
+        */
     }
 }
 
diff --git a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/scripts/writeCloud.py b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/scripts/writeCloud.py
deleted file mode 100644
index e6a98c6..0000000
--- a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/scripts/writeCloud.py
+++ /dev/null
@@ -1,73 +0,0 @@
-from paraview.simple import *
-from paraview import coprocessing
-
-# ----------------------- CoProcessor definition -----------------------
-
-def CreateCoProcessor():
-  def _CreatePipeline(coprocessor, datadescription):
-    class Pipeline:
-      name1 = 'cloud'
-      input1 = coprocessor.CreateProducer(datadescription, name1)
-      writer1 = servermanager.writers.XMLMultiBlockDataWriter(Input=input1)
-
-      # register writer with coprocessor, with filename + output freq
-      coprocessor.RegisterWriter(writer1, filename=name1+'_%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)
diff --git a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/scripts/writePatches.py b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/scripts/writePatches.py
deleted file mode 100644
index fd5f1ee..0000000
--- a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/scripts/writePatches.py
+++ /dev/null
@@ -1,71 +0,0 @@
-from paraview.simple import *
-from paraview import coprocessing
-
-# ----------------------- CoProcessor definition -----------------------
-
-def CreateCoProcessor():
-  def _CreatePipeline(coprocessor, datadescription):
-    class Pipeline:
-      name1 = 'region/patches'
-      input1 = coprocessor.CreateProducer(datadescription, name1)
-      writer1 = servermanager.writers.XMLMultiBlockDataWriter(Input=input1)
-
-      coprocessor.RegisterWriter(writer1, filename=name1+'_%t.vtm', freq=2)
-
-    return Pipeline()
-
-  class CoProcessor(coprocessing.CoProcessor):
-    def CreatePipeline(self, datadescription):
-      self.Pipeline = _CreatePipeline(self, datadescription)
-
-  coprocessor = CoProcessor()
-  freqs = {'region/patches': [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)
-- 
GitLab