From 83db6f793c438cbec2de8de8a9060d4e9bf92cad Mon Sep 17 00:00:00 2001
From: mark <mark@opencfd>
Date: Tue, 25 Oct 2016 18:19:19 +0200
Subject: [PATCH] BUG: resolve some decomposeParDict problems (issues #60,
 #265).

- Cleanup/centralize handling of -decomposeParDict by relocating
  common code into argList. Ensures that all processes receive
  identical information about the -decomposeParDict opton.

- Only use alternative decomposeParDict for simpleFoam/motorBike
  tutorial so that this will be included in the test loop for snappy.

- Added Mattijs' fix for surfaceRedistributePar.
---
 .../mesh/generation/blockMesh/blockMeshApp.C  | 14 +++----
 .../foamyMesh/foamyHexMesh/foamyHexMesh.C     | 11 +----
 .../foamyHexMeshBackgroundMesh.C              | 10 +----
 .../generation/snappyHexMesh/snappyHexMesh.C  | 10 +----
 .../decomposePar/decomposePar.C               | 10 +----
 .../redistributePar/redistributePar.C         | 16 ++------
 .../preProcessing/mapFields/mapFields.C       | 18 ++++----
 .../surfaceMeshConvert/surfaceMeshConvert.C   | 10 ++---
 .../surfaceRedistributePar/Make/options       |  5 ++-
 .../surfaceRedistributePar.C                  | 39 ++++++++++++++++--
 src/OpenFOAM/global/argList/argList.C         | 41 ++++++++++++-------
 .../include/setConstantMeshDictionaryIO.H     |  5 +--
 .../include/setSystemMeshDictionaryIO.H       |  5 +--
 .../include/setSystemRunTimeDictionaryIO.H    |  5 +--
 .../simpleFoam/motorBike/Allrun               | 12 +++---
 .../{decomposeParDict => decomposeParDict.6}  |  2 +-
 16 files changed, 106 insertions(+), 107 deletions(-)
 rename tutorials/incompressible/simpleFoam/motorBike/system/{decomposeParDict => decomposeParDict.6} (97%)

diff --git a/applications/utilities/mesh/generation/blockMesh/blockMeshApp.C b/applications/utilities/mesh/generation/blockMesh/blockMeshApp.C
index 3d0624f7456..ae36aa92715 100644
--- a/applications/utilities/mesh/generation/blockMesh/blockMeshApp.C
+++ b/applications/utilities/mesh/generation/blockMesh/blockMeshApp.C
@@ -107,16 +107,12 @@ int main(int argc, char *argv[])
     fileName dictPath;
 
     // Check if the dictionary is specified on the command-line
-    if (args.optionFound("dict"))
+    if (args.optionReadIfPresent("dict", dictPath))
     {
-        dictPath = args["dict"];
-
-        dictPath =
-        (
-            isDir(dictPath)
-          ? dictPath/dictName
-          : dictPath
-        );
+        if (isDir(dictPath))
+        {
+            dictPath = dictPath / dictName;
+        }
     }
     // Check if dictionary is present in the constant directory
     else if
diff --git a/applications/utilities/mesh/generation/foamyMesh/foamyHexMesh/foamyHexMesh.C b/applications/utilities/mesh/generation/foamyMesh/foamyHexMesh/foamyHexMesh.C
index 3588a9878f6..88c9c82e01d 100644
--- a/applications/utilities/mesh/generation/foamyMesh/foamyHexMesh/foamyHexMesh.C
+++ b/applications/utilities/mesh/generation/foamyMesh/foamyHexMesh/foamyHexMesh.C
@@ -3,7 +3,7 @@
  \\      /   F ield          | OpenFOAM: The Open Source CFD Toolbox
   \\    /    O peration      |
    \\  /     A nd            | Copyright (C) 2011-2016 OpenFOAM Foundation
-    \\/      M anipulation   |
+    \\/      M anipulation   | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -67,14 +67,7 @@ int main(int argc, char *argv[])
 
     // Allow override of decomposeParDict location
     fileName decompDictFile;
-    if (args.optionReadIfPresent("decomposeParDict", decompDictFile))
-    {
-        if (isDir(decompDictFile))
-        {
-            decompDictFile = decompDictFile / "decomposeParDict";
-        }
-    }
-
+    args.optionReadIfPresent("decomposeParDict", decompDictFile);
 
     IOdictionary foamyHexMeshDict
     (
diff --git a/applications/utilities/mesh/generation/foamyMesh/foamyHexMeshBackgroundMesh/foamyHexMeshBackgroundMesh.C b/applications/utilities/mesh/generation/foamyMesh/foamyHexMeshBackgroundMesh/foamyHexMeshBackgroundMesh.C
index 7861ce48618..06d4eb30543 100644
--- a/applications/utilities/mesh/generation/foamyMesh/foamyHexMeshBackgroundMesh/foamyHexMeshBackgroundMesh.C
+++ b/applications/utilities/mesh/generation/foamyMesh/foamyHexMeshBackgroundMesh/foamyHexMeshBackgroundMesh.C
@@ -3,7 +3,7 @@
  \\      /   F ield          | OpenFOAM: The Open Source CFD Toolbox
   \\    /    O peration      |
    \\  /     A nd            | Copyright (C) 2012-2016 OpenFOAM Foundation
-    \\/      M anipulation   |
+    \\/      M anipulation   | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -524,13 +524,7 @@ int main(int argc, char *argv[])
 
         // Allow override of decomposeParDict location
         fileName decompDictFile;
-        if (args.optionReadIfPresent("decomposeParDict", decompDictFile))
-        {
-            if (isDir(decompDictFile))
-            {
-                decompDictFile = decompDictFile / "decomposeParDict";
-            }
-        }
+        args.optionReadIfPresent("decomposeParDict", decompDictFile);
 
         labelList decomp = decompositionModel::New
         (
diff --git a/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C b/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C
index fa856b6fc24..1ee13d46df8 100644
--- a/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C
+++ b/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright 2015-2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2015-2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -837,13 +837,7 @@ int main(int argc, char *argv[])
         if (Pstream::parRun())
         {
             fileName decompDictFile;
-            if (args.optionReadIfPresent("decomposeParDict", decompDictFile))
-            {
-                if (isDir(decompDictFile))
-                {
-                    decompDictFile = decompDictFile/"decomposeParDict";
-                }
-            }
+            args.optionReadIfPresent("decomposeParDict", decompDictFile);
 
             decomposeDict = IOdictionary
             (
diff --git a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
index 07d6c455136..1ba001e2f7a 100644
--- a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
+++ b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
@@ -211,14 +211,7 @@ int main(int argc, char *argv[])
 
     // Allow override of decomposeParDict location
     fileName decompDictFile;
-    if (args.optionReadIfPresent("decomposeParDict", decompDictFile))
-    {
-        if (isDir(decompDictFile))
-        {
-            decompDictFile = decompDictFile/"decomposeParDict";
-        }
-    }
-
+    args.optionReadIfPresent("decomposeParDict", decompDictFile);
 
     wordList regionNames;
     wordList regionDirs;
@@ -301,7 +294,6 @@ int main(int argc, char *argv[])
                     ),
                     decompDictFile
                 )
-
             ).lookup("numberOfSubdomains")
         );
 
diff --git a/applications/utilities/parallelProcessing/redistributePar/redistributePar.C b/applications/utilities/parallelProcessing/redistributePar/redistributePar.C
index dfe03403472..6e8a712045c 100644
--- a/applications/utilities/parallelProcessing/redistributePar/redistributePar.C
+++ b/applications/utilities/parallelProcessing/redistributePar/redistributePar.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2015 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2015-2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -64,6 +64,7 @@ Usage
 #include "fvMeshTools.H"
 #include "fvMeshDistribute.H"
 #include "decompositionMethod.H"
+#include "decompositionModel.H"
 #include "timeSelector.H"
 #include "PstreamReduceOps.H"
 #include "volFields.H"
@@ -74,7 +75,6 @@ Usage
 #include "loadOrCreateMesh.H"
 #include "processorFvPatchField.H"
 #include "zeroGradientFvPatchFields.H"
-#include "decompositionModel.H"
 
 #include "parFvFieldReconstructor.H"
 #include "parLagrangianRedistributor.H"
@@ -2153,7 +2153,6 @@ int main(int argc, char *argv[])
     bool newTimes = args.optionFound("newTimes");
 
 
-
     if (env("FOAM_SIGFPE"))
     {
         WarningInFunction
@@ -2246,8 +2245,6 @@ int main(int argc, char *argv[])
     Pstream::scatter(decompose);
 
 
-
-
     // If running distributed we have problem of new processors not finding
     // a system/controlDict. However if we switch on the master-only reading
     // the problem becomes that the time directories are differing sizes and
@@ -2331,7 +2328,6 @@ int main(int argc, char *argv[])
     // Determine any region
     word regionName = polyMesh::defaultRegion;
     fileName meshSubDir;
-
     if (args.optionReadIfPresent("region", regionName))
     {
         meshSubDir = regionName/polyMesh::meshSubDir;
@@ -2775,13 +2771,7 @@ int main(int argc, char *argv[])
 
         // Allow override of decomposeParDict location
         fileName decompDictFile;
-        if (args.optionReadIfPresent("decomposeParDict", decompDictFile))
-        {
-            if (isDir(decompDictFile))
-            {
-                decompDictFile = decompDictFile / "decomposeParDict";
-            }
-        }
+        args.optionReadIfPresent("decomposeParDict", decompDictFile);
 
 
         // Determine decomposition
diff --git a/applications/utilities/preProcessing/mapFields/mapFields.C b/applications/utilities/preProcessing/mapFields/mapFields.C
index 5eceb0c2b56..1ec2310c53f 100644
--- a/applications/utilities/preProcessing/mapFields/mapFields.C
+++ b/applications/utilities/preProcessing/mapFields/mapFields.C
@@ -51,13 +51,11 @@ int readNumProcs
     const Time& runTime
 )
 {
+    const word dictName = "decomposeParDict";
     fileName dictFile;
-    if (args.optionReadIfPresent(optionName, dictFile))
+    if (args.optionReadIfPresent(optionName, dictFile) && isDir(dictFile))
     {
-        if (isDir(dictFile))
-        {
-            dictFile = dictFile/"decomposeParDict";
-        }
+        dictFile = dictFile / dictName;
     }
 
     return readInt
@@ -68,7 +66,7 @@ int readNumProcs
             (
                 IOobject
                 (
-                    "decomposeParDict",
+                    dictName,
                     runTime.system(),
                     runTime,
                     IOobject::MUST_READ_IF_MODIFIED,
@@ -376,7 +374,7 @@ int main(int argc, char *argv[])
 
     if (parallelSource && !parallelTarget)
     {
-        int nProcs = readNumProcs
+        const int nProcs = readNumProcs
         (
             args,
             "sourceDecomposeParDict",
@@ -448,7 +446,7 @@ int main(int argc, char *argv[])
     }
     else if (!parallelSource && parallelTarget)
     {
-        int nProcs = readNumProcs
+        const int nProcs = readNumProcs
         (
             args,
             "targetDecomposeParDict",
@@ -521,13 +519,13 @@ int main(int argc, char *argv[])
     }
     else if (parallelSource && parallelTarget)
     {
-        int nProcsSource = readNumProcs
+        const int nProcsSource = readNumProcs
         (
             args,
             "sourceDecomposeParDict",
             runTimeSource
         );
-        int nProcsTarget = readNumProcs
+        const int nProcsTarget = readNumProcs
         (
             args,
             "targetDecomposeParDict",
diff --git a/applications/utilities/surface/surfaceMeshConvert/surfaceMeshConvert.C b/applications/utilities/surface/surfaceMeshConvert/surfaceMeshConvert.C
index c35819d0085..94b8ec3978a 100644
--- a/applications/utilities/surface/surfaceMeshConvert/surfaceMeshConvert.C
+++ b/applications/utilities/surface/surfaceMeshConvert/surfaceMeshConvert.C
@@ -156,14 +156,10 @@ int main(int argc, char *argv[])
         // Note: cannot use setSystemRunTimeDictionaryIO.H since dictionary
         //       is in constant
 
-        fileName dictPath = "";
-        if (args.optionFound("dict"))
+        fileName dictPath;
+        if (args.optionReadIfPresent("dict", dictPath) && isDir(dictPath))
         {
-            dictPath = args["dict"];
-            if (isDir(dictPath))
-            {
-                dictPath = dictPath / dictName;
-            }
+            dictPath = dictPath / dictName;
         }
 
         if (dictPath.size())
diff --git a/applications/utilities/surface/surfaceRedistributePar/Make/options b/applications/utilities/surface/surfaceRedistributePar/Make/options
index c46a4c3f38e..d836881301c 100644
--- a/applications/utilities/surface/surfaceRedistributePar/Make/options
+++ b/applications/utilities/surface/surfaceRedistributePar/Make/options
@@ -1,9 +1,12 @@
 EXE_INC = \
     -I$(LIB_SRC)/triSurface/lnInclude \
     -I$(LIB_SRC)/meshTools/lnInclude \
+    -I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude \
+    -I$(LIB_SRC)/parallel/decompose/decompose/lnInclude \
     -I$(LIB_SRC)/parallel/distributed/lnInclude
 
 EXE_LIBS = \
     -ldistributed \
     -lmeshTools \
-    -ltriSurface
+    -ltriSurface \
+    -ldecompose
diff --git a/applications/utilities/surface/surfaceRedistributePar/surfaceRedistributePar.C b/applications/utilities/surface/surfaceRedistributePar/surfaceRedistributePar.C
index d6bb838e1bf..47174d556d6 100644
--- a/applications/utilities/surface/surfaceRedistributePar/surfaceRedistributePar.C
+++ b/applications/utilities/surface/surfaceRedistributePar/surfaceRedistributePar.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2015 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2015-2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -46,6 +46,7 @@ Note
 #include "distributedTriSurfaceMesh.H"
 #include "mapDistribute.H"
 #include "localIOdictionary.H"
+#include "decompositionModel.H"
 
 using namespace Foam;
 
@@ -103,7 +104,8 @@ int main(int argc, char *argv[])
 {
     argList::addNote
     (
-        "redistribute a triSurface"
+        "Redistribute a triSurface. "
+        "The specified surface must be located in the constant/triSurface directory"
     );
 
     argList::validArgs.append("triSurfaceMesh");
@@ -127,7 +129,7 @@ int main(int argc, char *argv[])
         << "Using distribution method "
         << distTypeName << nl << endl;
 
-    const bool keepNonMapped = args.options().found("keepNonMapped");
+    const bool keepNonMapped = args.optionFound("keepNonMapped");
 
     if (keepNonMapped)
     {
@@ -151,6 +153,37 @@ int main(int argc, char *argv[])
 
     Random rndGen(653213);
 
+    // For independent decomposition, ensure that distributedTriSurfaceMesh
+    // can find the alternative decomposeParDict specified via the
+    // -decomposeParDict option.
+    if (distType == distributedTriSurfaceMesh::INDEPENDENT)
+    {
+        fileName decompDictFile;
+        args.optionReadIfPresent("decomposeParDict", decompDictFile);
+
+        IOdictionary* dict = new IOdictionary
+        (
+            decompositionModel::selectIO
+            (
+                IOobject
+                (
+                    "decomposeParDict",
+                    runTime.system(),
+                    runTime,
+                    IOobject::MUST_READ_IF_MODIFIED,
+                    IOobject::NO_WRITE
+                ),
+                decompDictFile
+            )
+        );
+
+        // The object must have the expected "decomposeParDict" name.
+        // This also implies that it cannot be changed during the run.
+        dict->rename("decomposeParDict");
+
+        runTime.store(dict);
+    }
+
     // Determine mesh bounding boxes:
     List<List<treeBoundBox>> meshBb(Pstream::nProcs());
     if (distType == distributedTriSurfaceMesh::FOLLOW)
diff --git a/src/OpenFOAM/global/argList/argList.C b/src/OpenFOAM/global/argList/argList.C
index 8f489589b02..bbd079fa84d 100644
--- a/src/OpenFOAM/global/argList/argList.C
+++ b/src/OpenFOAM/global/argList/argList.C
@@ -2,8 +2,8 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2015 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+     \\/     M anipulation  | Copyright (C) 2015-2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -600,10 +600,29 @@ void Foam::argList::parse
             // establish rootPath_/globalCase_/case_ for master
             getRootCase();
 
-            // See if running distributed (different roots for different procs)
-            label dictNProcs = -1;
-            fileName source;
+            // Establish location of decomposeParDict, allow override with
+            // the -decomposeParDict option.
+            fileName source = rootPath_/globalCase_/"system"/"decomposeParDict";
+            if (options_.found("decomposeParDict"))
+            {
+                bool adjustOpt = false;
 
+                source = options_["decomposeParDict"];
+                if (isDir(source))
+                {
+                    adjustOpt = true;
+                    source = source/"decomposeParDict";
+                }
+                // Could also check for absolute path, but shouldn't be needed
+                if (adjustOpt)
+                {
+                    source.clean();
+                    options_.set("decomposeParDict", source);
+                }
+            }
+
+            // If running distributed (different roots for different procs)
+            label dictNProcs = -1;
             if (options_.found("roots"))
             {
                 source = "-roots";
@@ -617,16 +636,8 @@ void Foam::argList::parse
             }
             else
             {
-                source = rootPath_/globalCase_/"system"/"decomposeParDict";
-                // Override with -decomposeParDict
-                if (options_.found("decomposeParDict"))
-                {
-                    source = options_["decomposeParDict"];
-                    if (isDir(source))
-                    {
-                        source = source/"decomposeParDict";
-                    }
-                }
+                // Use values from decomposeParDict, the location was already
+                // established above.
 
                 IFstream decompDictStream(source);
 
diff --git a/src/OpenFOAM/include/setConstantMeshDictionaryIO.H b/src/OpenFOAM/include/setConstantMeshDictionaryIO.H
index aa5a68004c2..503dff369aa 100644
--- a/src/OpenFOAM/include/setConstantMeshDictionaryIO.H
+++ b/src/OpenFOAM/include/setConstantMeshDictionaryIO.H
@@ -1,7 +1,6 @@
-fileName dictPath = "";
-if (args.optionFound("dict"))
+fileName dictPath;
+if (args.optionReadIfPresent("dict", dictPath))
 {
-    dictPath = args["dict"];
     if (isDir(dictPath))
     {
         dictPath = dictPath / dictName;
diff --git a/src/OpenFOAM/include/setSystemMeshDictionaryIO.H b/src/OpenFOAM/include/setSystemMeshDictionaryIO.H
index 4d5f2e68ec9..c4e5a27ae9d 100644
--- a/src/OpenFOAM/include/setSystemMeshDictionaryIO.H
+++ b/src/OpenFOAM/include/setSystemMeshDictionaryIO.H
@@ -1,7 +1,6 @@
-fileName dictPath = "";
-if (args.optionFound("dict"))
+fileName dictPath;
+if (args.optionReadIfPresent("dict", dictPath))
 {
-    dictPath = args["dict"];
     if (isDir(dictPath))
     {
         dictPath = dictPath / dictName;
diff --git a/src/OpenFOAM/include/setSystemRunTimeDictionaryIO.H b/src/OpenFOAM/include/setSystemRunTimeDictionaryIO.H
index ceebb43815a..510f278c608 100644
--- a/src/OpenFOAM/include/setSystemRunTimeDictionaryIO.H
+++ b/src/OpenFOAM/include/setSystemRunTimeDictionaryIO.H
@@ -1,7 +1,6 @@
-fileName dictPath = "";
-if (args.optionFound("dict"))
+fileName dictPath;
+if (args.optionReadIfPresent("dict", dictPath))
 {
-    dictPath = args["dict"];
     if (isDir(dictPath))
     {
         dictPath = dictPath / dictName;
diff --git a/tutorials/incompressible/simpleFoam/motorBike/Allrun b/tutorials/incompressible/simpleFoam/motorBike/Allrun
index b2bee4f0109..f2d7ed6bb0f 100755
--- a/tutorials/incompressible/simpleFoam/motorBike/Allrun
+++ b/tutorials/incompressible/simpleFoam/motorBike/Allrun
@@ -4,14 +4,16 @@ cd ${0%/*} || exit 1    # Run from this directory
 # Source tutorial run functions
 . $WM_PROJECT_DIR/bin/tools/RunFunctions
 
+decompDict="-decomposeParDict system/decomposeParDict.6"
+
 # copy motorbike surface from resources directory
 \cp $FOAM_TUTORIALS/resources/geometry/motorBike.obj.gz constant/triSurface/
 runApplication surfaceFeatureExtract
 
 runApplication blockMesh
 
-runApplication decomposePar
-runParallel snappyHexMesh -overwrite
+runApplication decomposePar $decompDict
+runParallel $decompDict snappyHexMesh -overwrite
 
 #- For non-parallel running: - set the initial fields
 # restore0Dir
@@ -19,9 +21,9 @@ runParallel snappyHexMesh -overwrite
 #- For parallel running: set the initial fields
 restore0Dir -processor
 
-runParallel patchSummary
-runParallel potentialFoam
-runParallel $(getApplication)
+runParallel $decompDict patchSummary
+runParallel $decompDict potentialFoam
+runParallel $decompDict $(getApplication)
 
 runApplication reconstructParMesh -constant
 runApplication reconstructPar -latestTime
diff --git a/tutorials/incompressible/simpleFoam/motorBike/system/decomposeParDict b/tutorials/incompressible/simpleFoam/motorBike/system/decomposeParDict.6
similarity index 97%
rename from tutorials/incompressible/simpleFoam/motorBike/system/decomposeParDict
rename to tutorials/incompressible/simpleFoam/motorBike/system/decomposeParDict.6
index eb9bb3ad5e9..1f9924aa37b 100644
--- a/tutorials/incompressible/simpleFoam/motorBike/system/decomposeParDict
+++ b/tutorials/incompressible/simpleFoam/motorBike/system/decomposeParDict.6
@@ -28,7 +28,7 @@ simpleCoeffs
 
 hierarchicalCoeffs
 {
-    n               (3 2 1);
+    n               (2 2 1);
     delta           0.001;
     order           xyz;
 }
-- 
GitLab