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; + } } }