From 3c0a2e7959755a84f48e25bbe3436ec6437f7cf6 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Thu, 12 Apr 2018 15:36:18 +0200
Subject: [PATCH] ENH: support mkdir as dictionary keyword

- this is a convenient means of creating an output directory from within
  the function object without corresponding python or shell script.

  Some pipelines (image generation) balk if the output directory does
  not exist. Others (vtm writer etc) will create their own.

STYLE: use OpenFOAM caseDicts config files, newer string expansion.

- Eg, "<system>/scripts" instead of "$FOAM_CASE/system/scripts"

- OpenFOAM CleanFunctions now include removal of the 'insitu' directory
---
 etc/writeArea.py                              | 70 ++++++++++++++++++
 etc/writeCloud.py                             | 72 +++++++++++++++++++
 etc/writePatches.py                           | 70 ++++++++++++++++++
 src/catalyst/Allwclean                        |  2 +
 src/catalyst/areaMesh/catalystFaMesh.C        | 33 ++++++---
 src/catalyst/areaMesh/catalystFaMesh.H        |  6 ++
 src/catalyst/catalystCoprocess.C              |  1 +
 src/catalyst/cloud/catalystCloud.C            | 36 +++++++---
 src/catalyst/cloud/catalystCloud.H            |  7 +-
 src/catalyst/volMesh/catalystFvMesh.C         | 40 ++++++++++-
 src/catalyst/volMesh/catalystFvMesh.H         |  6 ++
 .../sphereTransport/Allclean                  |  1 -
 .../sphereTransport/system/area.cfg           | 16 -----
 .../sphereTransport/system/catalystArea       |  8 ++-
 .../multiRegionHeater/Allclean                |  8 ---
 .../multiRegionHeater/system/catalyst         |  7 +-
 .../multiRegionHeater/system/catalyst.cfg     | 16 -----
 .../system/scripts/writeMesh.py               | 70 ++++++++++++++++++
 .../system/scripts/writePatches.py            | 70 ++++++++++++++++++
 .../incompressible/icoFoam/cavity/Allclean    |  2 -
 .../icoFoam/cavity/system/catalyst            |  7 +-
 .../icoFoam/cavity/system/catalyst.cfg        | 16 -----
 .../icoFoam/cavity/system/decomposeParDict    | 24 +------
 .../scripts/{writeVtm.py => writeMesh.py}     |  9 +--
 .../simplifiedSiwek/Allclean                  |  8 +++
 .../coalChemistryFoam/simplifiedSiwek/Allrun  | 12 ++++
 .../simplifiedSiwek/Allrun-parallel           | 14 ++++
 .../constant/thermophysicalProperties         |  4 +-
 .../simplifiedSiwek/system/catalystCloud      |  5 +-
 .../simplifiedSiwek/system/cloud.cfg          | 16 -----
 30 files changed, 519 insertions(+), 137 deletions(-)
 create mode 100644 etc/writeArea.py
 create mode 100644 etc/writeCloud.py
 create mode 100644 etc/writePatches.py
 delete mode 100644 tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/area.cfg
 delete mode 100644 tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/catalyst.cfg
 create mode 100644 tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/scripts/writeMesh.py
 create mode 100644 tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/scripts/writePatches.py
 delete mode 100644 tutorials/incompressible/icoFoam/cavity/system/catalyst.cfg
 rename tutorials/incompressible/icoFoam/cavity/system/scripts/{writeVtm.py => writeMesh.py} (90%)
 create mode 100755 tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/Allclean
 create mode 100755 tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/Allrun
 create mode 100755 tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/Allrun-parallel
 delete mode 100644 tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/cloud.cfg

diff --git a/etc/writeArea.py b/etc/writeArea.py
new file mode 100644
index 0000000..b94085c
--- /dev/null
+++ b/etc/writeArea.py
@@ -0,0 +1,70 @@
+from paraview.simple import *
+from paraview import coprocessing
+
+# ----------------------- CoProcessor definition -----------------------
+
+def CreateCoProcessor():
+  def _CreatePipeline(coprocessor, datadescription):
+    class Pipeline:
+      input1 = coprocessor.CreateProducer(datadescription, 'input')
+      writer1 = servermanager.writers.XMLMultiBlockDataWriter(Input=input1)
+
+      coprocessor.RegisterWriter(writer1, filename='insitu/area_%t.vtm', freq=2)
+
+    return Pipeline()
+
+  class CoProcessor(coprocessing.CoProcessor):
+    def CreatePipeline(self, datadescription):
+      self.Pipeline = _CreatePipeline(self, datadescription)
+
+  coprocessor = CoProcessor()
+  freqs = {'input': [10]}
+  coprocessor.SetUpdateFrequencies(freqs)
+  return coprocessor
+
+#--------------------------------------------------------------
+# Global variables that will hold the pipeline for each timestep
+# Creating the CoProcessor object, doesn't actually create the ParaView pipeline.
+# It will be automatically setup when coprocessor.UpdateProducers() is called the
+# first time.
+coprocessor = CreateCoProcessor()
+
+#--------------------------------------------------------------
+# Enable Live-Visualizaton with ParaView
+coprocessor.EnableLiveVisualization(True)
+
+# ---------------------- Data Selection method ----------------------
+
+def RequestDataDescription(datadescription):
+    'Callback to populate the request for current timestep'
+    global coprocessor
+    if datadescription.GetForceOutput() == True:
+        # We are just going to request all fields and meshes from the simulation
+        # code/adaptor.
+        for i in range(datadescription.GetNumberOfInputDescriptions()):
+            datadescription.GetInputDescription(i).AllFieldsOn()
+            datadescription.GetInputDescription(i).GenerateMeshOn()
+        return
+
+    # setup requests for all inputs based on the requirements of the
+    # pipeline.
+    coprocessor.LoadRequestedData(datadescription)
+
+# ------------------------ Processing method ------------------------
+
+def DoCoProcessing(datadescription):
+    'Callback to do co-processing for current timestep'
+    global coprocessor
+
+    # Update the coprocessor by providing it the newly generated simulation data.
+    # If the pipeline hasn't been setup yet, this will setup the pipeline.
+    coprocessor.UpdateProducers(datadescription)
+
+    # Write output data, if appropriate.
+    coprocessor.WriteData(datadescription);
+
+    # Write image capture (Last arg: rescale lookup table), if appropriate.
+    coprocessor.WriteImages(datadescription, rescale_lookuptable=False)
+
+    # Live Visualization, if enabled.
+    coprocessor.DoLiveVisualization(datadescription, 'localhost', 22222)
diff --git a/etc/writeCloud.py b/etc/writeCloud.py
new file mode 100644
index 0000000..73512ec
--- /dev/null
+++ b/etc/writeCloud.py
@@ -0,0 +1,72 @@
+from paraview.simple import *
+from paraview import coprocessing
+
+# ----------------------- CoProcessor definition -----------------------
+
+def CreateCoProcessor():
+  def _CreatePipeline(coprocessor, datadescription):
+    class Pipeline:
+      input1 = coprocessor.CreateProducer(datadescription, 'cloud')
+      writer1 = servermanager.writers.XMLMultiBlockDataWriter(Input=input1)
+
+      # register writer with coprocessor, with filename + output freq
+      coprocessor.RegisterWriter(writer1, filename='insitu/cloud_%t.vtm', freq=10)
+
+    return Pipeline()
+
+  class CoProcessor(coprocessing.CoProcessor):
+    def CreatePipeline(self, datadescription):
+      self.Pipeline = _CreatePipeline(self, datadescription)
+
+  coprocessor = CoProcessor()
+  freqs = {'cloud': [10]}
+  coprocessor.SetUpdateFrequencies(freqs)
+  return coprocessor
+
+#--------------------------------------------------------------
+# Global variables that will hold the pipeline for each timestep
+# Creating the CoProcessor object, doesn't actually create the ParaView pipeline.
+# It will be automatically setup when coprocessor.UpdateProducers() is called the
+# first time.
+coprocessor = CreateCoProcessor()
+
+#--------------------------------------------------------------
+# Enable Live-Visualizaton with ParaView
+coprocessor.EnableLiveVisualization(True)
+
+
+# ---------------------- Data Selection method ----------------------
+
+def RequestDataDescription(datadescription):
+    'Callback to populate the request for current timestep'
+    global coprocessor
+    if datadescription.GetForceOutput() == True:
+        # We are just going to request all fields and meshes from the simulation
+        # code/adaptor.
+        for i in range(datadescription.GetNumberOfInputDescriptions()):
+            datadescription.GetInputDescription(i).AllFieldsOn()
+            datadescription.GetInputDescription(i).GenerateMeshOn()
+        return
+
+    # setup requests for all inputs based on the requirements of the
+    # pipeline.
+    coprocessor.LoadRequestedData(datadescription)
+
+# ------------------------ Processing method ------------------------
+
+def DoCoProcessing(datadescription):
+    'Callback to do co-processing for current timestep'
+    global coprocessor
+
+    # Update the coprocessor by providing it the newly generated simulation data.
+    # If the pipeline hasn't been setup yet, this will setup the pipeline.
+    coprocessor.UpdateProducers(datadescription)
+
+    # Write output data, if appropriate.
+    coprocessor.WriteData(datadescription);
+
+    # Write image capture (Last arg: rescale lookup table), if appropriate.
+    coprocessor.WriteImages(datadescription, rescale_lookuptable=False)
+
+    # Live Visualization, if enabled.
+    coprocessor.DoLiveVisualization(datadescription, 'localhost', 22222)
diff --git a/etc/writePatches.py b/etc/writePatches.py
new file mode 100644
index 0000000..92b8c9f
--- /dev/null
+++ b/etc/writePatches.py
@@ -0,0 +1,70 @@
+from paraview.simple import *
+from paraview import coprocessing
+
+# ----------------------- CoProcessor definition -----------------------
+
+def CreateCoProcessor():
+  def _CreatePipeline(coprocessor, datadescription):
+    class Pipeline:
+      input1 = coprocessor.CreateProducer(datadescription, 'patches')
+      writer1 = servermanager.writers.XMLMultiBlockDataWriter(Input=input1)
+
+      coprocessor.RegisterWriter(writer1, filename='insitu/patches_%t.vtm', freq=2)
+
+    return Pipeline()
+
+  class CoProcessor(coprocessing.CoProcessor):
+    def CreatePipeline(self, datadescription):
+      self.Pipeline = _CreatePipeline(self, datadescription)
+
+  coprocessor = CoProcessor()
+  freqs = {'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/src/catalyst/Allwclean b/src/catalyst/Allwclean
index c65d7b4..e19c764 100755
--- a/src/catalyst/Allwclean
+++ b/src/catalyst/Allwclean
@@ -3,6 +3,8 @@ cd ${0%/*} || exit 1                            # Run from this directory
 . $WM_PROJECT_DIR/wmake/scripts/wmakeFunctions  # The wmake functions
 
 rm -f $FOAM_LIBBIN/libcatalystFoam* 2>/dev/null # Cleanup library
+rm -f $FOAM_SITE_LIBBIN/libcatalystFoam* 2>/dev/null # ... extra safety
+rm -f $FOAM_USER_LIBBIN/libcatalystFoam* 2>/dev/null # ... extra safety
 
 # Cleanup generated files - remove entire top-level
 removeObjectDir $PWD
diff --git a/src/catalyst/areaMesh/catalystFaMesh.C b/src/catalyst/areaMesh/catalystFaMesh.C
index 2db6b2c..9988e8f 100644
--- a/src/catalyst/areaMesh/catalystFaMesh.C
+++ b/src/catalyst/areaMesh/catalystFaMesh.C
@@ -48,6 +48,29 @@ namespace functionObjects
 
 // * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
 
+bool Foam::functionObjects::catalystFaMesh::readBasics(const dictionary& dict)
+{
+    int debugLevel = 0;
+    if (dict.readIfPresent("debug", debugLevel))
+    {
+        catalystCoprocess::debug = debugLevel;
+    }
+
+    fileName outputDir;
+    if (dict.readIfPresent("mkdir", outputDir))
+    {
+        outputDir.expand();
+        outputDir.clean();
+        Foam::mkDir(outputDir);
+    }
+
+    dict.lookup("scripts") >> scripts_;         // Python scripts
+    catalystCoprocess::expand(scripts_, dict);  // Expand and check availability
+
+    return true;
+}
+
+
 void Foam::functionObjects::catalystFaMesh::updateState
 (
     polyMesh::readUpdateState state
@@ -106,11 +129,7 @@ bool Foam::functionObjects::catalystFaMesh::read(const dictionary& dict)
 {
     fvMeshFunctionObject::read(dict);
 
-    int debugLevel = 0;
-    if (dict.readIfPresent("debug", debugLevel))
-    {
-        catalystCoprocess::debug = debugLevel;
-    }
+    readBasics(dict);
 
     // All possible meshes
     meshes_ = mesh_.lookupClass<faMesh>();
@@ -143,9 +162,7 @@ bool Foam::functionObjects::catalystFaMesh::read(const dictionary& dict)
     meshes_.filterKeys(wordRes(selectAreas_));
 
     dict.lookup("fields") >> selectFields_;
-    dict.lookup("scripts") >> scripts_;         // Python scripts
 
-    catalystCoprocess::expand(scripts_, dict);  // Expand and check availability
 
     Info<< type() << " " << name() << ":" << nl
         <<"    areas   " << flatOutput(selectAreas_) << nl
@@ -153,9 +170,9 @@ bool Foam::functionObjects::catalystFaMesh::read(const dictionary& dict)
         <<"    fields  " << flatOutput(selectFields_) << nl
         <<"    scripts " << scripts_ << nl;
 
-    // Run-time modification of pipeline
     if (adaptor_.valid())
     {
+        // Run-time modification of pipeline
         adaptor_().reset(scripts_);
     }
 
diff --git a/src/catalyst/areaMesh/catalystFaMesh.H b/src/catalyst/areaMesh/catalystFaMesh.H
index 6786184..07b5b72 100644
--- a/src/catalyst/areaMesh/catalystFaMesh.H
+++ b/src/catalyst/areaMesh/catalystFaMesh.H
@@ -51,6 +51,7 @@ Usage
         Property     | Description                 | Required    | Default
         type         | catalyst::area              | yes         |
         log          | report extra information    | no          | false
+        mkdir        | initial directory to create | no          |
         region       |                             | no          | region0
         regions      | wordRe list of regions      | no          |
         fields       | wordRe list of fields       | yes         |
@@ -127,8 +128,13 @@ protected:
 
     // Protected Member Functions
 
+        //- Common boilerplate settings
+        bool readBasics(const dictionary& dict);
+
+        //- On movement
         void updateState(polyMesh::readUpdateState state);
 
+
         //- No copy construct
         catalystFaMesh(const catalystFaMesh&) = delete;
 
diff --git a/src/catalyst/catalystCoprocess.C b/src/catalyst/catalystCoprocess.C
index 5f137ac..120859f 100644
--- a/src/catalyst/catalystCoprocess.C
+++ b/src/catalyst/catalystCoprocess.C
@@ -99,6 +99,7 @@ Foam::label Foam::catalystCoprocess::expand
         string& s = scripts[scripti];
 
         stringOps::inplaceExpand(s, dict, true, true);
+        fileName::clean(s);  // Remove trailing, repeated slashes etc.
 
         if (isFile(s))
         {
diff --git a/src/catalyst/cloud/catalystCloud.C b/src/catalyst/cloud/catalystCloud.C
index 2bbcaed..5ac05a6 100644
--- a/src/catalyst/cloud/catalystCloud.C
+++ b/src/catalyst/cloud/catalystCloud.C
@@ -46,6 +46,31 @@ namespace functionObjects
 }
 
 
+// * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
+
+bool Foam::functionObjects::catalystCloud::readBasics(const dictionary& dict)
+{
+    int debugLevel = 0;
+    if (dict.readIfPresent("debug", debugLevel))
+    {
+        catalystCoprocess::debug = debugLevel;
+    }
+
+    fileName outputDir;
+    if (dict.readIfPresent("mkdir", outputDir))
+    {
+        outputDir.expand();
+        outputDir.clean();
+        Foam::mkDir(outputDir);
+    }
+
+    dict.lookup("scripts") >> scripts_;         // Python scripts
+    catalystCoprocess::expand(scripts_, dict);  // Expand and check availability
+
+    return true;
+}
+
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 Foam::functionObjects::catalystCloud::catalystCloud
@@ -76,11 +101,7 @@ bool Foam::functionObjects::catalystCloud::read(const dictionary& dict)
 {
     fvMeshFunctionObject::read(dict);
 
-    int debugLevel = 0;
-    if (dict.readIfPresent("debug", debugLevel))
-    {
-        catalystCoprocess::debug = debugLevel;
-    }
+    readBasics(dict);
 
     selectClouds_.clear();
     dict.readIfPresent("clouds", selectClouds_);
@@ -95,18 +116,15 @@ bool Foam::functionObjects::catalystCloud::read(const dictionary& dict)
     selectFields_.clear();
     dict.readIfPresent("fields", selectFields_);
 
-    dict.lookup("scripts") >> scripts_;         // Python scripts
-
-    catalystCoprocess::expand(scripts_, dict);  // Expand and check availability
 
     Info<< type() << " " << name() << ":" << nl
         <<"    clouds  " << flatOutput(selectClouds_) << nl
         <<"    fields  " << flatOutput(selectFields_) << nl
         <<"    scripts " << scripts_ << nl;
 
-    // Run-time modification of pipeline
     if (adaptor_.valid())
     {
+        // Run-time modification of pipeline
         adaptor_().reset(scripts_);
     }
 
diff --git a/src/catalyst/cloud/catalystCloud.H b/src/catalyst/cloud/catalystCloud.H
index 27f4622..fb31f28 100644
--- a/src/catalyst/cloud/catalystCloud.H
+++ b/src/catalyst/cloud/catalystCloud.H
@@ -52,6 +52,7 @@ Usage
         Property     | Description                 | Required    | Default value
         type         | catalyst::cloud             | yes         |
         log          | report extra information    | no          | false
+        mkdir        | initial directory to create | no          |
         cloud        |                             | no          | defaultCloud
         clouds       | wordRe list of clouds       | no          |
         region       |                             | no          | region0
@@ -120,7 +121,11 @@ protected:
         autoPtr<catalystCoprocess> adaptor_;
 
 
-    // Private Member Functions
+    // Protected Member Functions
+
+        //- Common boilerplate settings
+        bool readBasics(const dictionary& dict);
+
 
         //- No copy construct
         catalystCloud(const catalystCloud&) = delete;
diff --git a/src/catalyst/volMesh/catalystFvMesh.C b/src/catalyst/volMesh/catalystFvMesh.C
index e1344a2..fa33f54 100644
--- a/src/catalyst/volMesh/catalystFvMesh.C
+++ b/src/catalyst/volMesh/catalystFvMesh.C
@@ -46,6 +46,29 @@ namespace functionObjects
 
 // * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
 
+bool Foam::functionObjects::catalystFvMesh::readBasics(const dictionary& dict)
+{
+    int debugLevel = 0;
+    if (dict.readIfPresent("debug", debugLevel))
+    {
+        catalystCoprocess::debug = debugLevel;
+    }
+
+    fileName outputDir;
+    if (dict.readIfPresent("mkdir", outputDir))
+    {
+        outputDir.expand();
+        outputDir.clean();
+        Foam::mkDir(outputDir);
+    }
+
+    dict.lookup("scripts") >> scripts_;         // Python scripts
+    catalystCoprocess::expand(scripts_, dict);  // Expand and check availability
+
+    return true;
+}
+
+
 void Foam::functionObjects::catalystFvMesh::updateState
 (
     polyMesh::readUpdateState state
@@ -105,12 +128,25 @@ bool Foam::functionObjects::catalystFvMesh::read(const dictionary& dict)
 {
     functionObject::read(dict);
 
+    // Common settings
     int debugLevel = 0;
     if (dict.readIfPresent("debug", debugLevel))
     {
         catalystCoprocess::debug = debugLevel;
     }
 
+    fileName outputDir;
+    if (dict.readIfPresent("mkdir", outputDir))
+    {
+        outputDir.expand();
+        outputDir.clean();
+        Foam::mkDir(outputDir);
+    }
+
+    dict.lookup("scripts") >> scripts_;         // Python scripts
+    catalystCoprocess::expand(scripts_, dict);  // Expand and check availability
+
+
     // All possible meshes
     meshes_ = time_.lookupClass<fvMesh>();
 
@@ -128,9 +164,7 @@ bool Foam::functionObjects::catalystFvMesh::read(const dictionary& dict)
     meshes_.filterKeys(wordRes(selectRegions_));
 
     dict.lookup("fields") >> selectFields_;
-    dict.lookup("scripts") >> scripts_;         // Python scripts
 
-    catalystCoprocess::expand(scripts_, dict);  // Expand and check availability
 
     Info<< type() << " " << name() << ":" << nl
         <<"    regions " << flatOutput(selectRegions_) << nl
@@ -138,9 +172,9 @@ bool Foam::functionObjects::catalystFvMesh::read(const dictionary& dict)
         <<"    fields  " << flatOutput(selectFields_) << nl
         <<"    scripts " << scripts_ << nl;
 
-    // Run-time modification of pipeline
     if (adaptor_.valid())
     {
+        // Run-time modification of pipeline
         adaptor_().reset(scripts_);
     }
 
diff --git a/src/catalyst/volMesh/catalystFvMesh.H b/src/catalyst/volMesh/catalystFvMesh.H
index 0606cb4..a5a264b 100644
--- a/src/catalyst/volMesh/catalystFvMesh.H
+++ b/src/catalyst/volMesh/catalystFvMesh.H
@@ -52,6 +52,7 @@ Usage
         Property     | Description                 | Required    | Default
         type         | catalyst                    | yes         |
         log          | report extra information    | no          | false
+        mkdir        | initial directory to create | no          |
         region       |                             | no          | region0
         regions      | wordRe list of regions      | no          |
         fields       | wordRe list of fields       | yes         |
@@ -131,8 +132,13 @@ protected:
 
     // Protected Member Functions
 
+        //- Common boilerplate settings
+        bool readBasics(const dictionary& dict);
+
+        //- On movement
         void updateState(polyMesh::readUpdateState state);
 
+
         //- No copy construct
         catalystFvMesh(const catalystFvMesh&) = delete;
 
diff --git a/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/Allclean b/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/Allclean
index 49abfb9..ecc502a 100755
--- a/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/Allclean
+++ b/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/Allclean
@@ -7,7 +7,6 @@ cleanTimeDirectories
 cleanFaMesh
 
 rm -rf processor*
-
 rm -rf insitu
 
 #------------------------------------------------------------------------------
diff --git a/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/area.cfg b/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/area.cfg
deleted file mode 100644
index 2f6850f..0000000
--- a/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/area.cfg
+++ /dev/null
@@ -1,16 +0,0 @@
-/*--------------------------------*- C++ -*----------------------------------*\
-| =========                 |                                                 |
-| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
-|  \\    /   O peration     | Version:  plus                                  |
-|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
-|    \\/     M anipulation  |                                                 |
-\*---------------------------------------------------------------------------*/
-// Insitu processing of finiteArea fields with ParaView Catalyst
-
-type            catalyst::area;
-libs            ("libcatalystFoam.so");
-
-executeControl  timeStep;
-writeControl    none;
-
-// ************************************************************************* //
diff --git a/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/catalystArea b/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/catalystArea
index 1572d92..ead19c9 100644
--- a/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/catalystArea
+++ b/tutorials/finiteArea/sphereSurfactantFoam/sphereTransport/system/catalystArea
@@ -4,15 +4,17 @@ functions
 {
     catalystArea
     {
-        #include "area.cfg";
-        // FUTURE: #includeEtc "caseDicts/postProcessing/catalyst/area.cfg"
+        #includeEtc "caseDicts/postProcessing/catalyst/area.cfg"
 
         // Selected fields (words or regex)
         fields  ( ".*" );
 
+        // Output directory
+        //mkdir   "<case>/images";
+
         scripts
         (
-            "$FOAM_CASE/system/scripts/writeArea.py"
+            "<system>/scripts/writeArea.py"
         );
     }
 }
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/Allclean b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/Allclean
index 8643b2f..2830e42 100755
--- a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/Allclean
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/Allclean
@@ -3,14 +3,6 @@ cd ${0%/*} || exit 1                        # Run from this directory
 . $WM_PROJECT_DIR/bin/tools/CleanFunctions  # Tutorial clean functions
 
 cleanCase0
-rm -rf VTK
-rm -rf constant/cellToRegion
 rm -rf constant/*/polyMesh
 
-# Remove ParaView Catalyst output
-rm -rf insitu
-
-# Remove ADIOS output
-rm -rf adiosData
-
 # -----------------------------------------------------------------------------
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/catalyst b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/catalyst
index 4f9bc04..ab49f45 100644
--- a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/catalyst
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/catalyst
@@ -4,8 +4,7 @@ functions
 {
     catalyst
     {
-        #include "catalyst.cfg";
-        // FUTURE: #includeEtc "caseDicts/postProcessing/catalyst/default.cfg"
+        #includeEtc "caseDicts/postProcessing/catalyst/default.cfg"
 
         // All regions
         regions  (".*");
@@ -15,8 +14,8 @@ functions
 
         scripts
         (
-            "$FOAM_CASE/system/scripts/slice1.py"
-            "$FOAM_CASE/system/scripts/writePatches.py"
+            "<system>/scripts/slice1.py"
+            "<system>/scripts/writePatches.py"
         );
     }
 }
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/catalyst.cfg b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/catalyst.cfg
deleted file mode 100644
index e9ace6b..0000000
--- a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/catalyst.cfg
+++ /dev/null
@@ -1,16 +0,0 @@
-/*--------------------------------*- C++ -*----------------------------------*\
-| =========                 |                                                 |
-| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
-|  \\    /   O peration     | Version:  plus                                  |
-|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
-|    \\/     M anipulation  |                                                 |
-\*---------------------------------------------------------------------------*/
-// Insitu processing of finiteVolume fields with ParaView Catalyst
-
-type            catalyst;
-libs            ("libcatalystFoam.so");
-
-executeControl  timeStep;
-writeControl    none;
-
-// ************************************************************************* //
diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/scripts/writeMesh.py b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/scripts/writeMesh.py
new file mode 100644
index 0000000..43533a9
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/scripts/writeMesh.py
@@ -0,0 +1,70 @@
+from paraview.simple import *
+from paraview import coprocessing
+
+# ----------------------- CoProcessor definition -----------------------
+
+def CreateCoProcessor():
+  def _CreatePipeline(coprocessor, datadescription):
+    class Pipeline:
+      input1 = coprocessor.CreateProducer(datadescription, 'mesh')
+      writer1 = servermanager.writers.XMLMultiBlockDataWriter(Input=input1)
+
+      coprocessor.RegisterWriter(writer1, filename='insitu/mesh_%t.vtm', freq=2)
+
+    return Pipeline()
+
+  class CoProcessor(coprocessing.CoProcessor):
+    def CreatePipeline(self, datadescription):
+      self.Pipeline = _CreatePipeline(self, datadescription)
+
+  coprocessor = CoProcessor()
+  freqs = {'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
new file mode 100644
index 0000000..92b8c9f
--- /dev/null
+++ b/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/scripts/writePatches.py
@@ -0,0 +1,70 @@
+from paraview.simple import *
+from paraview import coprocessing
+
+# ----------------------- CoProcessor definition -----------------------
+
+def CreateCoProcessor():
+  def _CreatePipeline(coprocessor, datadescription):
+    class Pipeline:
+      input1 = coprocessor.CreateProducer(datadescription, 'patches')
+      writer1 = servermanager.writers.XMLMultiBlockDataWriter(Input=input1)
+
+      coprocessor.RegisterWriter(writer1, filename='insitu/patches_%t.vtm', freq=2)
+
+    return Pipeline()
+
+  class CoProcessor(coprocessing.CoProcessor):
+    def CreatePipeline(self, datadescription):
+      self.Pipeline = _CreatePipeline(self, datadescription)
+
+  coprocessor = CoProcessor()
+  freqs = {'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/Allclean b/tutorials/incompressible/icoFoam/cavity/Allclean
index 5a23af9..be7ddb0 100755
--- a/tutorials/incompressible/icoFoam/cavity/Allclean
+++ b/tutorials/incompressible/icoFoam/cavity/Allclean
@@ -4,6 +4,4 @@ cd ${0%/*} || exit 1                        # Run from this directory
 
 cleanCase
 
-rm -rf insitu
-
 #------------------------------------------------------------------------------
diff --git a/tutorials/incompressible/icoFoam/cavity/system/catalyst b/tutorials/incompressible/icoFoam/cavity/system/catalyst
index dc137ea..4d40d14 100644
--- a/tutorials/incompressible/icoFoam/cavity/system/catalyst
+++ b/tutorials/incompressible/icoFoam/cavity/system/catalyst
@@ -4,8 +4,7 @@ functions
 {
     catalyst
     {
-        #include "catalyst.cfg";
-        // FUTURE: #includeEtc "caseDicts/postProcessing/catalyst/default.cfg"
+        #includeEtc "caseDicts/postProcessing/catalyst/default.cfg"
 
         // Regions
         // regions ( );
@@ -15,8 +14,8 @@ functions
 
         scripts
         (
-            "$FOAM_CASE/system/scripts/slice1.py"
-            "$FOAM_CASE/system/scripts/writeVtm.py"
+            "<system>/scripts/slice1.py"
+            "<system>/scripts/writeMesh.py"
         );
 
         // Calculate a few iterations before starting processing
diff --git a/tutorials/incompressible/icoFoam/cavity/system/catalyst.cfg b/tutorials/incompressible/icoFoam/cavity/system/catalyst.cfg
deleted file mode 100644
index e9ace6b..0000000
--- a/tutorials/incompressible/icoFoam/cavity/system/catalyst.cfg
+++ /dev/null
@@ -1,16 +0,0 @@
-/*--------------------------------*- C++ -*----------------------------------*\
-| =========                 |                                                 |
-| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
-|  \\    /   O peration     | Version:  plus                                  |
-|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
-|    \\/     M anipulation  |                                                 |
-\*---------------------------------------------------------------------------*/
-// Insitu processing of finiteVolume fields with ParaView Catalyst
-
-type            catalyst;
-libs            ("libcatalystFoam.so");
-
-executeControl  timeStep;
-writeControl    none;
-
-// ************************************************************************* //
diff --git a/tutorials/incompressible/icoFoam/cavity/system/decomposeParDict b/tutorials/incompressible/icoFoam/cavity/system/decomposeParDict
index 4162d19..e1431eb 100644
--- a/tutorials/incompressible/icoFoam/cavity/system/decomposeParDict
+++ b/tutorials/incompressible/icoFoam/cavity/system/decomposeParDict
@@ -15,31 +15,13 @@ FoamFile
 }
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-numberOfSubdomains 2;
+numberOfSubdomains 3;
 
 method          simple;
 
-simpleCoeffs
+coeffs
 {
-    n               (2 1 1);
-    delta           0.001;
+    n           (3 1 1);
 }
 
-hierarchicalCoeffs
-{
-    n               (1 1 1);
-    delta           0.001;
-    order           xyz;
-}
-
-manualCoeffs
-{
-    dataFile        "";
-}
-
-distributed     no;
-
-roots           ( );
-
-
 // ************************************************************************* //
diff --git a/tutorials/incompressible/icoFoam/cavity/system/scripts/writeVtm.py b/tutorials/incompressible/icoFoam/cavity/system/scripts/writeMesh.py
similarity index 90%
rename from tutorials/incompressible/icoFoam/cavity/system/scripts/writeVtm.py
rename to tutorials/incompressible/icoFoam/cavity/system/scripts/writeMesh.py
index eb112de..a9c04d2 100644
--- a/tutorials/incompressible/icoFoam/cavity/system/scripts/writeVtm.py
+++ b/tutorials/incompressible/icoFoam/cavity/system/scripts/writeMesh.py
@@ -7,13 +7,14 @@ def CreateCoProcessor():
   def _CreatePipeline(coprocessor, datadescription):
     class Pipeline:
       input1 = coprocessor.CreateProducer(datadescription, "mesh")
-      ## input2 = coprocessor.CreateProducer(datadescription, "patches")
-
       writer1 = servermanager.writers.XMLMultiBlockDataWriter(Input=input1)
-
-      # register writer with coprocessor, with filename to use, output frequency
+      # Register with filename to use, output frequency
       coprocessor.RegisterWriter(writer1, filename='insitu/mesh_%t.vtm', freq=2)
 
+      # input2 = coprocessor.CreateProducer(datadescription, "patches")
+      # writer2 = servermanager.writers.XMLMultiBlockDataWriter(Input=input2)
+      # coprocessor.RegisterWriter(writer2, filename='insitu/patches_%t.vtm', freq=2)
+
     return Pipeline()
 
   class CoProcessor(coprocessing.CoProcessor):
diff --git a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/Allclean b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/Allclean
new file mode 100755
index 0000000..0151d5e
--- /dev/null
+++ b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/Allclean
@@ -0,0 +1,8 @@
+#!/bin/sh
+cd ${0%/*} || exit 1                        # Run from this directory
+. $WM_PROJECT_DIR/bin/tools/CleanFunctions  # Tutorial clean functions
+
+cleanCase
+rm -rf constant/*/polyMesh
+
+# -----------------------------------------------------------------------------
diff --git a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/Allrun b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/Allrun
new file mode 100755
index 0000000..61c2efb
--- /dev/null
+++ b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/Allrun
@@ -0,0 +1,12 @@
+#!/bin/sh
+cd ${0%/*} || exit 1                        # Run from this directory
+. $WM_PROJECT_DIR/bin/tools/RunFunctions    # Tutorial run functions
+
+runApplication blockMesh
+
+# Create ignition cells cellSet
+runApplication topoSet
+
+runApplication $(getApplication)
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/Allrun-parallel b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/Allrun-parallel
new file mode 100755
index 0000000..da47afd
--- /dev/null
+++ b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/Allrun-parallel
@@ -0,0 +1,14 @@
+#!/bin/sh
+cd ${0%/*} || exit 1                        # Run from this directory
+. $WM_PROJECT_DIR/bin/tools/RunFunctions    # Tutorial run functions
+
+runApplication blockMesh
+
+# Create ignition cells cellSet
+runApplication topoSet
+
+runApplication decomposePar
+
+runParallel $(getApplication)
+
+#------------------------------------------------------------------------------
diff --git a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/constant/thermophysicalProperties b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/constant/thermophysicalProperties
index 22fca74..603743f 100644
--- a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/constant/thermophysicalProperties
+++ b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/constant/thermophysicalProperties
@@ -28,9 +28,9 @@ thermoType
 
 chemistryReader foamChemistryReader;
 
-foamChemistryThermoFile "$FOAM_CASE/constant/foam.dat";
+foamChemistryFile "<constant>/foam.inp";
 
-foamChemistryFile "$FOAM_CASE/constant/foam.inp";
+foamChemistryThermoFile "<constant>/foam.dat";
 
 inertSpecie     N2;
 
diff --git a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/catalystCloud b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/catalystCloud
index 20db93f..e9b7336 100644
--- a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/catalystCloud
+++ b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/catalystCloud
@@ -4,8 +4,7 @@ functions
 {
     catalystCloud1
     {
-        #includeEtc "cloud.cfg";
-        // FUTURE: #includeEtc "caseDicts/postProcessing/catalyst/cloud.cfg"
+        #includeEtc "caseDicts/postProcessing/catalyst/cloud.cfg"
 
         // Selected clouds (words or regex)
         clouds  ( coalCloud1 limestoneCloud1 );
@@ -15,7 +14,7 @@ functions
 
         scripts
         (
-            "$FOAM_CASE/system/scripts/writeCloud.py"
+            "<system>/scripts/writeCloud.py"
         );
     }
 }
diff --git a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/cloud.cfg b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/cloud.cfg
deleted file mode 100644
index d860e90..0000000
--- a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/cloud.cfg
+++ /dev/null
@@ -1,16 +0,0 @@
-/*--------------------------------*- C++ -*----------------------------------*\
-| =========                 |                                                 |
-| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
-|  \\    /   O peration     | Version:  plus                                  |
-|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
-|    \\/     M anipulation  |                                                 |
-\*---------------------------------------------------------------------------*/
-// Insitu processing of lagrangian clouds with ParaView Catalyst
-
-type            catalyst::cloud;
-libs            ("libcatalystFoam.so");
-
-executeControl  timeStep;
-writeControl    none;
-
-// ************************************************************************* //
-- 
GitLab