diff --git a/applications/utilities/mesh/manipulation/topoSet/Make/files b/applications/utilities/mesh/manipulation/topoSet/Make/files
index 872e324100..5514b34344 100644
--- a/applications/utilities/mesh/manipulation/topoSet/Make/files
+++ b/applications/utilities/mesh/manipulation/topoSet/Make/files
@@ -1,3 +1,4 @@
+timeSelector.C
topoSet.C
EXE = $(FOAM_APPBIN)/topoSet
diff --git a/applications/utilities/mesh/manipulation/topoSet/timeSelector.C b/applications/utilities/mesh/manipulation/topoSet/timeSelector.C
new file mode 100644
index 0000000000..a52bd6ebe1
--- /dev/null
+++ b/applications/utilities/mesh/manipulation/topoSet/timeSelector.C
@@ -0,0 +1,289 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd.
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenFOAM. If not, see .
+
+\*---------------------------------------------------------------------------*/
+
+#include "timeSelector.H"
+#include "ListOps.H"
+#include "argList.H"
+#include "Time.H"
+#include "IStringStream.H"
+
+// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+Foam::timeSelector::timeSelector()
+:
+ scalarRanges()
+{}
+
+
+Foam::timeSelector::timeSelector(Istream& is)
+:
+ scalarRanges(is)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+bool Foam::timeSelector::selected(const instant& value) const
+{
+ return scalarRanges::selected(value.value());
+}
+
+
+Foam::List Foam::timeSelector::selected(const instantList& Times) const
+{
+ List lst(Times.size(), false);
+
+ // check ranges, avoid false positive on constant/
+ forAll(Times, timeI)
+ {
+ if (Times[timeI].name() != "constant" && selected(Times[timeI]))
+ {
+ lst[timeI] = true;
+ }
+ }
+
+ // check specific values
+ forAll(*this, rangeI)
+ {
+ if (operator[](rangeI).isExact())
+ {
+ scalar target = operator[](rangeI).value();
+
+ int nearestIndex = -1;
+ scalar nearestDiff = Foam::GREAT;
+
+ forAll(Times, timeI)
+ {
+ if (Times[timeI].name() == "constant") continue;
+
+ scalar diff = fabs(Times[timeI].value() - target);
+ if (diff < nearestDiff)
+ {
+ nearestDiff = diff;
+ nearestIndex = timeI;
+ }
+ }
+
+ if (nearestIndex >= 0)
+ {
+ lst[nearestIndex] = true;
+ }
+ }
+ }
+
+ return lst;
+}
+
+
+Foam::List Foam::timeSelector::select
+(
+ const instantList& Times
+) const
+{
+ return subset(selected(Times), Times);
+}
+
+
+void Foam::timeSelector::inplaceSelect(instantList& Times) const
+{
+ inplaceSubset(selected(Times), Times);
+}
+
+
+void Foam::timeSelector::addOptions
+(
+ const bool constant,
+ const bool zeroTime
+)
+{
+ if (constant)
+ {
+ argList::addBoolOption
+ (
+ "constant",
+ "include the 'constant/' dir in the times list"
+ );
+ }
+ if (zeroTime)
+ {
+ argList::addBoolOption
+ (
+ "zeroTime",
+ "include the '0/' dir in the times list"
+ );
+ }
+ argList::addBoolOption
+ (
+ "noZero",
+ "exclude the '0/' dir from the times list, "
+ "has precedence over the -zeroTime option"
+ );
+ argList::addBoolOption
+ (
+ "latestTime",
+ "select the latest time"
+ );
+ argList::addOption
+ (
+ "time",
+ "ranges",
+ "comma-separated time ranges - eg, ':10,20,40-70,1000:'"
+ );
+}
+
+
+Foam::List Foam::timeSelector::select
+(
+ const instantList& timeDirs,
+ const argList& args
+)
+{
+ if (timeDirs.size())
+ {
+ List selectTimes(timeDirs.size(), true);
+
+ // determine locations of constant/ and 0/ directories
+ label constantIdx = -1;
+ label zeroIdx = -1;
+
+ forAll(timeDirs, timeI)
+ {
+ if (timeDirs[timeI].name() == "constant")
+ {
+ constantIdx = timeI;
+ }
+ else if (timeDirs[timeI].value() == 0)
+ {
+ zeroIdx = timeI;
+ }
+
+ if (constantIdx >= 0 && zeroIdx >= 0)
+ {
+ break;
+ }
+ }
+
+ // determine latestTime selection (if any)
+ // this must appear before the -time option processing
+ label latestIdx = -1;
+ if (args.optionFound("latestTime"))
+ {
+ selectTimes = false;
+ latestIdx = timeDirs.size() - 1;
+
+ // avoid false match on constant/
+ if (latestIdx == constantIdx)
+ {
+ latestIdx = -1;
+ }
+ }
+
+ if (args.optionFound("time"))
+ {
+ // can match 0/, but can never match constant/
+ selectTimes = timeSelector
+ (
+ args.optionLookup("time")()
+ ).selected(timeDirs);
+ }
+
+
+ // add in latestTime (if selected)
+ if (latestIdx >= 0)
+ {
+ selectTimes[latestIdx] = true;
+ }
+
+ if (constantIdx >= 0)
+ {
+ // only add constant/ if specifically requested
+ selectTimes[constantIdx] = args.optionFound("constant");
+ }
+
+ // special treatment for 0/
+ if (zeroIdx >= 0)
+ {
+ if (args.optionFound("noZero"))
+ {
+ // exclude 0/ if specifically requested
+ selectTimes[zeroIdx] = false;
+ }
+ else if (argList::validOptions.found("zeroTime"))
+ {
+ // with -zeroTime enabled, drop 0/ unless specifically requested
+ selectTimes[zeroIdx] = args.optionFound("zeroTime");
+ }
+ }
+
+ return subset(selectTimes, timeDirs);
+ }
+ else
+ {
+ return timeDirs;
+ }
+}
+
+
+Foam::List Foam::timeSelector::select0
+(
+ Time& runTime,
+ const argList& args,
+ const bool useOptionsOnly
+)
+{
+ if
+ (
+ useOptionsOnly
+ || (
+ args.optionFound("latestTime")
+ || args.optionFound("time")
+ || args.optionFound("constant")
+ || args.optionFound("noZero")
+ || args.optionFound("zeroTime")
+ )
+ )
+ {
+ instantList timeDirs = timeSelector::select(runTime.times(), args);
+
+ if (timeDirs.empty())
+ {
+ FatalErrorIn(args.executable())
+ << "No times selected"
+ << exit(FatalError);
+ }
+
+ runTime.setTime(timeDirs[0], 0);
+
+ return timeDirs;
+ }
+ else
+ {
+ // No timeSelector option specified. Do not change runTime.
+ return instantList(1, instant(runTime.value(), runTime.timeName()));
+ }
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/manipulation/topoSet/timeSelector.H b/applications/utilities/mesh/manipulation/topoSet/timeSelector.H
new file mode 100644
index 0000000000..daf821c905
--- /dev/null
+++ b/applications/utilities/mesh/manipulation/topoSet/timeSelector.H
@@ -0,0 +1,163 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2004-2011 OpenCFD Ltd.
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenFOAM. If not, see .
+
+Class
+ Foam::timeSelector
+
+Description
+ A List of scalarRange for selecting times.
+
+ The timeSelector provides a convenient means of selecting multiple
+ times. A typical use would be the following:
+
+ \verbatim
+ timeSelector::addOptions();
+ // add other options
+ #include "setRootCase.H"
+ #include "createTime.H"
+ instantList timeDirs = timeSelector::select0(runTime, args);
+ ...
+ forAll(timeDirs, timeI)
+ {
+ ...
+ }
+ \endverbatim
+
+ The result program would receive \b -time, @b -latestTime, @b -constant
+ and \b -noZero options. The @b -constant option explicitly includes the
+ \c constant/ directory in the time list and the \b -noZero option
+ explicitly excludes the \c 0/ directory from the time list.
+
+ There may however also be many cases in which neither the \c constant/
+ directory nor the \c 0/ directory contain particularly relevant
+ information. This might occur, for example, when post-processing
+ results. In this case, addOptions is called with optional boolean
+ arguments.
+
+ \verbatim
+ timeSelector::addOptions(false, true);
+ \endverbatim
+
+ The first argument avoids adding the \b -constant option. The second
+ argument adds an additional \b -zeroTime option and also prevents the
+ \c 0/ directory from being included in the default time range and in the
+ \b -latestTime selection.
+
+SourceFiles
+ timeSelector.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef timeSelector_H
+#define timeSelector_H
+
+#include "scalarRanges.H"
+#include "instantList.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// Forward declaration of classes
+class argList;
+class Time;
+
+/*---------------------------------------------------------------------------*\
+ Class timeSelector Declaration
+\*---------------------------------------------------------------------------*/
+
+class timeSelector
+:
+ public scalarRanges
+{
+public:
+
+ // Constructors
+
+ //- Construct Null
+ timeSelector();
+
+ //- Construct from Istream
+ timeSelector(Istream&);
+
+
+ // Member Functions
+
+ //- Return true if the given instant is within the ranges
+ bool selected(const instant&) const;
+
+ //- Return the set of selected instants in the given list that are
+ // within the ranges
+ List selected(const List&) const;
+
+ //- Select a list of Time values that are within the ranges
+ instantList select(const List&) const;
+
+ //- Select a list of Time values that are within the ranges
+ void inplaceSelect(List&) const;
+
+ //- Add the options handled by timeSelector to argList::validOptions
+ //
+ // \param constant
+ // Add the \b -constant option to include the \c constant/ directory
+ //
+ // \param zeroTime
+ // Enable the \b -zeroTime option and alter the normal time selection
+ // behaviour (and \b -latestTime behaviour) to exclude the \c 0/
+ // directory. The \c 0/ directory will only be included when
+ // \b -zeroTime is specified.
+ // The \b -noZero option has precedence over the @b -zeroTime option.
+ static void addOptions
+ (
+ const bool constant=true,
+ const bool zeroTime=false
+ );
+
+ //- Return the set of times selected based on the argList options
+ static instantList select
+ (
+ const instantList&,
+ const argList& args
+ );
+
+ //- Return the set of times selected based on the argList options
+ // also set the runTime to the first instance
+ static instantList select0
+ (
+ Time& runTime,
+ const argList& args,
+ const bool useOptionsOnly
+ );
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/manipulation/topoSet/topoSet.C b/applications/utilities/mesh/manipulation/topoSet/topoSet.C
index a377f6133e..0561c887e9 100644
--- a/applications/utilities/mesh/manipulation/topoSet/topoSet.C
+++ b/applications/utilities/mesh/manipulation/topoSet/topoSet.C
@@ -26,6 +26,7 @@ Description
\*---------------------------------------------------------------------------*/
+#include "timeSelector.H"
#include "argList.H"
#include "Time.H"
#include "polyMesh.H"
@@ -33,15 +34,71 @@ Description
#include "cellSet.H"
#include "faceSet.H"
#include "pointSet.H"
+#include "globalMeshData.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+void printMesh(const Time& runTime, const polyMesh& mesh)
+{
+ Info<< "Time:" << runTime.timeName()
+ << " cells:" << mesh.globalData().nTotalCells()
+ << " faces:" << mesh.globalData().nTotalFaces()
+ << " points:" << mesh.globalData().nTotalPoints()
+ << " patches:" << mesh.boundaryMesh().size()
+ << " bb:" << mesh.bounds() << nl;
+}
+
+
+polyMesh::readUpdateState meshReadUpdate(polyMesh& mesh)
+{
+ polyMesh::readUpdateState stat = mesh.readUpdate();
+
+ switch(stat)
+ {
+ case polyMesh::UNCHANGED:
+ {
+ Info<< " mesh not changed." << endl;
+ break;
+ }
+ case polyMesh::POINTS_MOVED:
+ {
+ Info<< " points moved; topology unchanged." << endl;
+ break;
+ }
+ case polyMesh::TOPO_CHANGE:
+ {
+ Info<< " topology changed; patches unchanged." << nl
+ << " ";
+ printMesh(mesh.time(), mesh);
+ break;
+ }
+ case polyMesh::TOPO_PATCH_CHANGE:
+ {
+ Info<< " topology changed and patches changed." << nl
+ << " ";
+ printMesh(mesh.time(), mesh);
+
+ break;
+ }
+ default:
+ {
+ FatalErrorIn("meshReadUpdate(polyMesh&)")
+ << "Illegal mesh update state "
+ << stat << abort(FatalError);
+ break;
+ }
+ }
+ return stat;
+}
+
+
// Main program:
int main(int argc, char *argv[])
{
+ timeSelector::addOptions(true, false);
argList::addOption
(
"dict",
@@ -57,6 +114,14 @@ int main(int argc, char *argv[])
# include "setRootCase.H"
# include "createTime.H"
+ instantList timeDirs = timeSelector::select0
+ (
+ runTime,
+ args,
+ false // not override runTime if no time options
+ );
+
+
# include "createNamedPolyMesh.H"
const bool noSync = args.optionFound("noSync");
@@ -99,128 +164,143 @@ int main(int argc, char *argv[])
// Read set construct info from dictionary
- PtrList patchSources(topoSetDict.lookup("actions"));
+ PtrList actions(topoSetDict.lookup("actions"));
- forAll(patchSources, i)
+
+ forAll(timeDirs, timeI)
{
- const dictionary& dict = patchSources[i];
+ runTime.setTime(timeDirs[timeI], timeI);
+ Info<< "Time = " << runTime.timeName() << endl;
- const word setName(dict.lookup("name"));
- const word actionName(dict.lookup("action"));
- const word setType(dict.lookup("type"));
+ // Optionally re-read mesh
+ meshReadUpdate(mesh);
-
- topoSetSource::setAction action = topoSetSource::toAction(actionName);
-
- autoPtr currentSet;
- if
- (
- (action == topoSetSource::NEW)
- || (action == topoSetSource::CLEAR)
- )
+ // Execute all actions
+ forAll(actions, i)
{
- currentSet = topoSet::New(setType, mesh, setName, 10000);
- Info<< "Created set " << setName << endl;
- }
- else if (action == topoSetSource::REMOVE)
- {
- //?
- }
- else
- {
- currentSet = topoSet::New
+ const dictionary& dict = actions[i];
+
+ const word setName(dict.lookup("name"));
+ const word actionName(dict.lookup("action"));
+ const word setType(dict.lookup("type"));
+
+
+ topoSetSource::setAction action = topoSetSource::toAction
(
- setType,
- mesh,
- setName,
- IOobject::MUST_READ
+ actionName
);
- Info<< "Read set " << setName << " with size "
- << currentSet().size() << endl;
- }
-
-
- // Handle special actions (clear, invert) locally, rest through sources.
- switch (action)
- {
- case topoSetSource::NEW:
- case topoSetSource::ADD:
- case topoSetSource::DELETE:
+ autoPtr currentSet;
+ if
+ (
+ (action == topoSetSource::NEW)
+ || (action == topoSetSource::CLEAR)
+ )
{
- Info<< " Applying source " << word(dict.lookup("source"))
- << endl;
- autoPtr source = topoSetSource::New
- (
- dict.lookup("source"),
- mesh,
- dict.subDict("sourceInfo")
- );
-
- source().applyToSet(action, currentSet());
- // Synchronize for coupled patches.
- if (!noSync) currentSet().sync(mesh);
- currentSet().write();
+ currentSet = topoSet::New(setType, mesh, setName, 10000);
+ Info<< "Created set " << setName << endl;
}
- break;
-
- case topoSetSource::SUBSET:
+ else if (action == topoSetSource::REMOVE)
{
- Info<< " Applying source " << word(dict.lookup("source"))
- << endl;
- autoPtr source = topoSetSource::New
+ //?
+ }
+ else
+ {
+ currentSet = topoSet::New
(
- dict.lookup("source"),
+ setType,
mesh,
- dict.subDict("sourceInfo")
+ setName,
+ IOobject::MUST_READ
);
+ Info<< "Read set " << setName << " with size "
+ << currentSet().size() << endl;
+ }
- // Backup current set.
- autoPtr oldSet
- (
- topoSet::New
+
+
+ // Handle special actions (clear, invert) locally, rest through
+ // sources.
+ switch (action)
+ {
+ case topoSetSource::NEW:
+ case topoSetSource::ADD:
+ case topoSetSource::DELETE:
+ {
+ Info<< " Applying source " << word(dict.lookup("source"))
+ << endl;
+ autoPtr source = topoSetSource::New
(
- setType,
+ dict.lookup("source"),
mesh,
- currentSet().name() + "_old2",
- currentSet()
- )
- );
+ dict.subDict("sourceInfo")
+ );
- currentSet().clear();
- source().applyToSet(topoSetSource::NEW, currentSet());
+ source().applyToSet(action, currentSet());
+ // Synchronize for coupled patches.
+ if (!noSync) currentSet().sync(mesh);
+ currentSet().write();
+ }
+ break;
- // Combine new value of currentSet with old one.
- currentSet().subset(oldSet());
- // Synchronize for coupled patches.
- if (!noSync) currentSet().sync(mesh);
- currentSet().write();
+ case topoSetSource::SUBSET:
+ {
+ Info<< " Applying source " << word(dict.lookup("source"))
+ << endl;
+ autoPtr source = topoSetSource::New
+ (
+ dict.lookup("source"),
+ mesh,
+ dict.subDict("sourceInfo")
+ );
+
+ // Backup current set.
+ autoPtr oldSet
+ (
+ topoSet::New
+ (
+ setType,
+ mesh,
+ currentSet().name() + "_old2",
+ currentSet()
+ )
+ );
+
+ currentSet().clear();
+ source().applyToSet(topoSetSource::NEW, currentSet());
+
+ // Combine new value of currentSet with old one.
+ currentSet().subset(oldSet());
+ // Synchronize for coupled patches.
+ if (!noSync) currentSet().sync(mesh);
+ currentSet().write();
+ }
+ break;
+
+ case topoSetSource::CLEAR:
+ Info<< " Clearing set" << endl;
+ currentSet().clear();
+ currentSet().write();
+ break;
+
+ case topoSetSource::INVERT:
+ Info<< " Inverting set" << endl;
+ currentSet().invert(currentSet().maxSize(mesh));
+ currentSet().write();
+ break;
+
+ default:
+ WarningIn(args.executable())
+ << "Unhandled action " << action << endl;
+ break;
}
- break;
- case topoSetSource::CLEAR:
- Info<< " Clearing set" << endl;
- currentSet().clear();
- currentSet().write();
- break;
-
- case topoSetSource::INVERT:
- Info<< " Inverting set" << endl;
- currentSet().invert(currentSet().maxSize(mesh));
- currentSet().write();
- break;
-
- default:
- WarningIn(args.executable())
- << "Unhandled action " << action << endl;
- break;
- }
-
- if (currentSet.valid())
- {
- Info<< " Set " << currentSet().name()
- << " now size " << currentSet().size()
- << endl;
+ if (currentSet.valid())
+ {
+ Info<< " Set " << currentSet().name()
+ << " now size " << currentSet().size()
+ << endl;
+ }
}
}