From 66b72c97457a11aaaa95d8d263ebe0add2bddf67 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Thu, 12 Oct 2017 18:43:12 +0200
Subject: [PATCH] ENH: make creation of streamline seeds demand-driven

---
 .../field/streamLine/streamLine.C             |   2 +-
 .../field/streamLine/streamLineBase.C         | 113 +++++++++++-------
 .../field/streamLine/streamLineBase.H         |  44 ++++---
 .../wallBoundedStreamLine.C                   |   5 +-
 4 files changed, 98 insertions(+), 66 deletions(-)

diff --git a/src/functionObjects/field/streamLine/streamLine.C b/src/functionObjects/field/streamLine/streamLine.C
index 131d3ba025..46406489c7 100644
--- a/src/functionObjects/field/streamLine/streamLine.C
+++ b/src/functionObjects/field/streamLine/streamLine.C
@@ -52,7 +52,7 @@ void Foam::functionObjects::streamLine::track()
         initialParticles
     );
 
-    const sampledSet& seedPoints = sampledSetPtr_();
+    const sampledSet& seedPoints = sampledSetPoints();
 
     forAll(seedPoints, i)
     {
diff --git a/src/functionObjects/field/streamLine/streamLineBase.C b/src/functionObjects/field/streamLine/streamLineBase.C
index 9eaae07a82..ac4153db68 100644
--- a/src/functionObjects/field/streamLine/streamLineBase.C
+++ b/src/functionObjects/field/streamLine/streamLineBase.C
@@ -47,6 +47,38 @@ namespace functionObjects
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
+const Foam::word&
+Foam::functionObjects::streamLineBase::sampledSetAxis() const
+{
+    if (sampledSetPtr_.empty())
+    {
+        sampledSetPoints();
+    }
+
+    return sampledSetAxis_;
+}
+
+
+const Foam::sampledSet&
+Foam::functionObjects::streamLineBase::sampledSetPoints() const
+{
+    if (sampledSetPtr_.empty())
+    {
+        sampledSetPtr_ = sampledSet::New
+        (
+            "seedSampleSet",
+            mesh_,
+            meshSearchMeshObject::New(mesh_),
+            dict_.subDict("seedSampleSet")
+        );
+
+        sampledSetAxis_ = sampledSetPtr_->axis();
+    }
+
+    return sampledSetPtr_();
+}
+
+
 Foam::autoPtr<Foam::indirectPrimitivePatch>
 Foam::functionObjects::streamLineBase::wallPatch() const
 {
@@ -54,12 +86,12 @@ Foam::functionObjects::streamLineBase::wallPatch() const
 
     label nFaces = 0;
 
-    forAll(patches, patchi)
+    for (const polyPatch& pp : patches)
     {
-        //if (!polyPatch::constraintType(patches[patchi].type()))
-        if (isA<wallPolyPatch>(patches[patchi]))
+        //if (!polyPatch::constraintType(pp.type()))
+        if (isA<wallPolyPatch>(pp))
         {
-            nFaces += patches[patchi].size();
+            nFaces += pp.size();
         }
     }
 
@@ -67,13 +99,11 @@ Foam::functionObjects::streamLineBase::wallPatch() const
 
     nFaces = 0;
 
-    forAll(patches, patchi)
+    for (const polyPatch& pp : patches)
     {
-        //if (!polyPatch::constraintType(patches[patchi].type()))
-        if (isA<wallPolyPatch>(patches[patchi]))
+        //if (!polyPatch::constraintType(pp.type()))
+        if (isA<wallPolyPatch>(pp))
         {
-            const polyPatch& pp = patches[patchi];
-
             forAll(pp, i)
             {
                 addressing[nFaces++] = pp.start()+i;
@@ -110,24 +140,24 @@ void Foam::functionObjects::streamLineBase::initInterpolations
     label nScalar = 0;
     label nVector = 0;
 
-    forAll(fields_, i)
+    for (const word& fieldName : fields_)
     {
-        if (foundObject<volScalarField>(fields_[i]))
+        if (foundObject<volScalarField>(fieldName))
         {
             nScalar++;
         }
-        else if (foundObject<volVectorField>(fields_[i]))
+        else if (foundObject<volVectorField>(fieldName))
         {
             nVector++;
         }
         else
         {
             FatalErrorInFunction
-                << "Cannot find field " << fields_[i] << nl
+                << "Cannot find field " << fieldName << nl
                 << "Valid scalar fields are:"
-                << mesh_.names(volScalarField::typeName) << nl
+                << flatOutput(mesh_.names(volScalarField::typeName)) << nl
                 << "Valid vector fields are:"
-                << mesh_.names(volVectorField::typeName)
+                << flatOutput(mesh_.names(volVectorField::typeName))
                 << exit(FatalError);
         }
     }
@@ -136,12 +166,11 @@ void Foam::functionObjects::streamLineBase::initInterpolations
     vvInterp.setSize(nVector);
     nVector = 0;
 
-    forAll(fields_, i)
+    for (const word& fieldName : fields_)
     {
-        if (foundObject<volScalarField>(fields_[i]))
+        if (foundObject<volScalarField>(fieldName))
         {
-            const volScalarField& f =
-                lookupObject<volScalarField>(fields_[i]);
+            const volScalarField& f = lookupObject<volScalarField>(fieldName);
             vsInterp.set
             (
                 nScalar++,
@@ -152,10 +181,9 @@ void Foam::functionObjects::streamLineBase::initInterpolations
                 )
             );
         }
-        else if (foundObject<volVectorField>(fields_[i]))
+        else if (foundObject<volVectorField>(fieldName))
         {
-            const volVectorField& f =
-                lookupObject<volVectorField>(fields_[i]);
+            const volVectorField& f = lookupObject<volVectorField>(fieldName);
 
             if (f.name() == UName_)
             {
@@ -231,7 +259,7 @@ void Foam::functionObjects::streamLineBase::storePoint
     DynamicList<vectorList>& newVectors
 ) const
 {
-    label sz = newTrack.size();
+    const label sz = newTrack.size();
 
     const List<point>& track = allTracks_[tracki];
 
@@ -274,6 +302,7 @@ void Foam::functionObjects::streamLineBase::trimToBox
 ) const
 {
     const List<point>& track = allTracks_[tracki];
+
     if (track.size())
     {
         for
@@ -287,7 +316,7 @@ void Foam::functionObjects::streamLineBase::trimToBox
             const point& endPt = track[segmenti];
 
             const vector d(endPt-startPt);
-            scalar magD = mag(d);
+            const scalar magD = mag(d);
             if (magD > ROOTVSMALL)
             {
                 if (bb.contains(startPt))
@@ -507,6 +536,12 @@ Foam::functionObjects::streamLineBase::~streamLineBase()
 
 bool Foam::functionObjects::streamLineBase::read(const dictionary& dict)
 {
+    if (&dict_ != &dict)
+    {
+        // Update local copy of dictionary:
+        dict_ = dict;
+    }
+
     fvMeshFunctionObject::read(dict);
 
     Info<< type() << " " << name() << ":" << nl;
@@ -536,10 +571,8 @@ bool Foam::functionObjects::streamLineBase::read(const dictionary& dict)
 
 
     trackLength_ = VGREAT;
-    if (dict.found("trackLength"))
+    if (dict.readIfPresent("trackLength", trackLength_))
     {
-        dict.lookup("trackLength") >> trackLength_;
-
         Info<< type() << " : fixed track length specified : "
             << trackLength_ << nl << endl;
     }
@@ -562,14 +595,8 @@ bool Foam::functionObjects::streamLineBase::read(const dictionary& dict)
 
     cloudName_ = dict.lookupOrDefault<word>("cloud", type());
 
-    sampledSetPtr_ = sampledSet::New
-    (
-        "seedSampleSet",
-        mesh_,
-        meshSearchMeshObject::New(mesh_),
-        dict.subDict("seedSampleSet")
-    );
-    sampledSetAxis_ = sampledSetPtr_->axis();
+    sampledSetPtr_.clear();
+    sampledSetAxis_.clear();
 
     scalarFormatterPtr_ = writer<scalar>::New(dict.lookup("setFormat"));
     vectorFormatterPtr_ = writer<vector>::New(dict.lookup("setFormat"));
@@ -756,7 +783,7 @@ bool Foam::functionObjects::streamLineBase::write()
                     new coordSet
                     (
                         "track" + Foam::name(nTracks),
-                        sampledSetAxis_                 //"xyz"
+                        sampledSetAxis()  // "xyz"
                     )
                 );
                 oldToNewTrack[tracki] = nTracks;
@@ -767,7 +794,7 @@ bool Foam::functionObjects::streamLineBase::write()
 
         // Convert scalar values
 
-        if (allScalars_.size() > 0 && tracks.size() > 0)
+        if (!allScalars_.empty() && !tracks.empty())
         {
             List<List<scalarField>> scalarValues(allScalars_.size());
 
@@ -781,7 +808,7 @@ bool Foam::functionObjects::streamLineBase::write()
                     scalarList& vals = allTrackVals[tracki];
                     if (vals.size())
                     {
-                        label newTracki = oldToNewTrack[tracki];
+                        const label newTracki = oldToNewTrack[tracki];
                         scalarValues[scalari][newTracki].transfer(vals);
                     }
                 }
@@ -811,7 +838,7 @@ bool Foam::functionObjects::streamLineBase::write()
 
         // Convert vector values
 
-        if (allVectors_.size() > 0 && tracks.size() > 0)
+        if (!allVectors_.empty() && !tracks.empty())
         {
             List<List<vectorField>> vectorValues(allVectors_.size());
 
@@ -825,7 +852,7 @@ bool Foam::functionObjects::streamLineBase::write()
                     vectorList& vals = allTrackVals[tracki];
                     if (vals.size())
                     {
-                        label newTracki = oldToNewTrack[tracki];
+                        const label newTracki = oldToNewTrack[tracki];
                         vectorValues[vectori][newTracki].transfer(vals);
                     }
                 }
@@ -854,20 +881,18 @@ bool Foam::functionObjects::streamLineBase::write()
     // File names are generated on the master but setProperty needs to
     // be across all procs
     Pstream::scatter(scalarVtkFile);
-    forAll(scalarNames_, namei)
+    for (const word& fieldName : scalarNames_)
     {
         dictionary propsDict;
         propsDict.add("file", scalarVtkFile);
-        const word& fieldName = scalarNames_[namei];
         setProperty(fieldName, propsDict);
     }
 
     Pstream::scatter(vectorVtkFile);
-    forAll(vectorNames_, namei)
+    for (const word& fieldName : vectorNames_)
     {
         dictionary propsDict;
         propsDict.add("file", vectorVtkFile);
-        const word& fieldName = vectorNames_[namei];
         setProperty(fieldName, propsDict);
     }
 
diff --git a/src/functionObjects/field/streamLine/streamLineBase.H b/src/functionObjects/field/streamLine/streamLineBase.H
index a87e3fd210..881ef4d140 100644
--- a/src/functionObjects/field/streamLine/streamLineBase.H
+++ b/src/functionObjects/field/streamLine/streamLineBase.H
@@ -63,6 +63,14 @@ class streamLineBase
 :
     public fvMeshFunctionObject
 {
+    // Private data
+
+        //- Seed set engine
+        mutable autoPtr<sampledSet> sampledSetPtr_;
+
+        //- Axis of the sampled points to output
+        mutable word sampledSetAxis_;
+
 protected:
 
         //- Input dictionary
@@ -102,35 +110,35 @@ protected:
         wordList vectorNames_;
 
 
-        // Demand driven
+      // Demand driven
 
-            //- Mesh searching enigne
-            autoPtr<meshSearch> meshSearchPtr_;
+        //- File writer for scalar data
+        autoPtr<writer<scalar>> scalarFormatterPtr_;
 
-            //- Seed set engine
-            autoPtr<sampledSet> sampledSetPtr_;
+        //- File writer for vector data
+        autoPtr<writer<vector>> vectorFormatterPtr_;
 
-            //- Axis of the sampled points to output
-            word sampledSetAxis_;
 
-            //- File writer for scalar data
-            autoPtr<writer<scalar>> scalarFormatterPtr_;
+      // Generated data
 
-            //- File writer for vector data
-            autoPtr<writer<vector>> vectorFormatterPtr_;
+        //- All tracks. Per track the points it passed through
+        DynamicList<List<point>> allTracks_;
 
+        //- Per scalarField, per track, the sampled values
+        List<DynamicList<scalarList>> allScalars_;
 
-        // Generated data
+        //- Per vectorField, per track, the sampled values
+        List<DynamicList<vectorList>> allVectors_;
 
-            //- All tracks. Per track the points it passed through
-            DynamicList<List<point>> allTracks_;
 
-            //- Per scalarField, per track, the sampled values
-            List<DynamicList<scalarList>> allScalars_;
+    // Protected Member Functions
 
-            //- Per vectorField, per track, the sampled values
-            List<DynamicList<vectorList>> allVectors_;
+        //- The axis of the sampledSet. Creates sampledSet if required.
+        const word& sampledSetAxis() const;
 
+        //- Demand driven construction of the sampledSet.
+        //  Also updates sampledSetAxis_
+        const sampledSet& sampledSetPoints() const;
 
         //- Construct patch out of all wall patch faces
         autoPtr<indirectPrimitivePatch> wallPatch() const;
diff --git a/src/functionObjects/field/wallBoundedStreamLine/wallBoundedStreamLine.C b/src/functionObjects/field/wallBoundedStreamLine/wallBoundedStreamLine.C
index ce96d78714..d5b2560329 100644
--- a/src/functionObjects/field/wallBoundedStreamLine/wallBoundedStreamLine.C
+++ b/src/functionObjects/field/wallBoundedStreamLine/wallBoundedStreamLine.C
@@ -131,12 +131,11 @@ void Foam::functionObjects::wallBoundedStreamLine::track()
         // Get the seed points
         // ~~~~~~~~~~~~~~~~~~~
 
-        const sampledSet& seedPoints = sampledSetPtr_();
-
+        const sampledSet& seedPoints = sampledSetPoints();
 
         forAll(seedPoints, i)
         {
-            label celli = seedPoints.cells()[i];
+            const label celli = seedPoints.cells()[i];
 
             if (celli != -1)
             {
-- 
GitLab