ENH: improve robustness of scalarRanges from string (fixes #673)
- now avoid Istream and token mechanism in favour of a simpler string parser. This makes the code clearer, smaller, robuster. - provide convenience ge/gt/le/lt static constructors for scalarRange for using bounds directly with specifying via a string parameter. - scalarRange, scalarRanges now follow the unary predicate pattern (using an operator() for testing). This allows their reuse in other contexts. Eg, for filtering operations: myHash.filterValues(scalarRange::ge(100)); - remove unused scalarRanges methods that were specific to handling lists of time values. These were superseded by timeSelector methods several versions ago.
This commit is contained in:
parent
85eb441bea
commit
f55a42a835
3
applications/test/scalarRanges/Make/files
Normal file
3
applications/test/scalarRanges/Make/files
Normal file
@ -0,0 +1,3 @@
|
||||
Test-scalarRanges.C
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-scalarRanges
|
0
applications/test/scalarRanges/Make/options
Normal file
0
applications/test/scalarRanges/Make/options
Normal file
112
applications/test/scalarRanges/Test-scalarRanges.C
Normal file
112
applications/test/scalarRanges/Test-scalarRanges.C
Normal file
@ -0,0 +1,112 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Description
|
||||
Test scalar ranges
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "argList.H"
|
||||
#include "scalarRanges.H"
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
|
||||
template<class HTable>
|
||||
Ostream& printHash(const HTable& h)
|
||||
{
|
||||
const auto keys = h.sortedToc();
|
||||
|
||||
Info<<"keys: " << keys.size() << "(";
|
||||
for (const auto& k : keys)
|
||||
{
|
||||
Info<<" " << k;
|
||||
}
|
||||
Info<< " )" << nl;
|
||||
|
||||
Info<<"vals: " << keys.size() << "(";
|
||||
for (const auto& k : keys)
|
||||
{
|
||||
Info<<" " << h[k];
|
||||
}
|
||||
Info<< " )" << nl;
|
||||
|
||||
return Info;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
// Main program:
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
argList::noParallel();
|
||||
argList::noFunctionObjects();
|
||||
argList::addArgument("range,range range,range");
|
||||
argList::addNote
|
||||
(
|
||||
"Test parsing of comma-separated ranges\n\n"
|
||||
"Eg, ':10,20,40:70,1000:'"
|
||||
);
|
||||
|
||||
argList args(argc, argv, false, true);
|
||||
|
||||
HashTable<scalar> testHash;
|
||||
for (label i = 0; i < 26; ++i)
|
||||
{
|
||||
word key("X");
|
||||
key[0] = 'a' + i;
|
||||
testHash.insert(key, i);
|
||||
|
||||
key[0] = 'A' + i;
|
||||
testHash.insert(key, 100 + i);
|
||||
}
|
||||
|
||||
printHash(testHash)
|
||||
<< nl;
|
||||
|
||||
for (int argi = 1; argi < argc; ++argi)
|
||||
{
|
||||
Info<<"tokenize " << args[argi] << nl;
|
||||
|
||||
scalarRanges ranges(args[argi]);
|
||||
Info<<"=> " << ranges << endl;
|
||||
|
||||
HashTable<scalar> subHash(testHash);
|
||||
subHash.filterValues(ranges);
|
||||
|
||||
Info<<"filtered:" << nl;
|
||||
|
||||
printHash(subHash)
|
||||
<< nl;
|
||||
|
||||
subHash.filterValues(scalarRange::le(8));
|
||||
Info<<"filtered <= 8:" << nl;
|
||||
|
||||
printHash(subHash)
|
||||
<< nl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
@ -813,7 +813,6 @@ DebugSwitches
|
||||
saturateEvaporationModel 0;
|
||||
scalarAverageField 0;
|
||||
scalarField 0;
|
||||
scalarRange 0;
|
||||
scaleSimilarity 0;
|
||||
scatterModel 0;
|
||||
searchableBox 0;
|
||||
|
@ -3,7 +3,7 @@
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
\\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -27,7 +27,6 @@ License
|
||||
#include "ListOps.H"
|
||||
#include "argList.H"
|
||||
#include "Time.H"
|
||||
#include "StringStream.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
@ -37,9 +36,9 @@ Foam::timeSelector::timeSelector()
|
||||
{}
|
||||
|
||||
|
||||
Foam::timeSelector::timeSelector(Istream& is)
|
||||
Foam::timeSelector::timeSelector(const std::string& str)
|
||||
:
|
||||
scalarRanges(is)
|
||||
scalarRanges(str)
|
||||
{}
|
||||
|
||||
|
||||
@ -47,7 +46,7 @@ Foam::timeSelector::timeSelector(Istream& is)
|
||||
|
||||
bool Foam::timeSelector::selected(const instant& value) const
|
||||
{
|
||||
return scalarRanges::selected(value.value());
|
||||
return scalarRanges::operator()(value.value());
|
||||
}
|
||||
|
||||
|
||||
@ -67,7 +66,7 @@ Foam::List<bool> Foam::timeSelector::selected(const instantList& times) const
|
||||
// Check specific values
|
||||
for (const scalarRange& range : *this)
|
||||
{
|
||||
if (range.isExact())
|
||||
if (range.single())
|
||||
{
|
||||
const scalar target = range.value();
|
||||
|
||||
@ -97,8 +96,7 @@ Foam::List<bool> Foam::timeSelector::selected(const instantList& times) const
|
||||
}
|
||||
|
||||
|
||||
Foam::instantList Foam::timeSelector::select(const instantList& times)
|
||||
const
|
||||
Foam::instantList Foam::timeSelector::select(const instantList& times) const
|
||||
{
|
||||
return subset(selected(times), times);
|
||||
}
|
||||
@ -211,10 +209,7 @@ Foam::instantList Foam::timeSelector::select
|
||||
if (args.optionFound("time"))
|
||||
{
|
||||
// Can match 0/, but can never match constant/
|
||||
selectTimes = timeSelector
|
||||
(
|
||||
args.optionLookup("time")()
|
||||
).selected(times);
|
||||
selectTimes = timeSelector(args["time"]).selected(times);
|
||||
}
|
||||
|
||||
// Add in latestTime (if selected)
|
||||
@ -301,7 +296,7 @@ Foam::instantList Foam::timeSelector::selectIfPresent
|
||||
}
|
||||
|
||||
// No timeSelector option specified. Do not change runTime.
|
||||
return instantList(1, instant(runTime.value(), runTime.timeName()));
|
||||
return instantList{ instant(runTime.value(), runTime.timeName()) };
|
||||
}
|
||||
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
\\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -89,17 +89,17 @@ class Time;
|
||||
|
||||
class timeSelector
|
||||
:
|
||||
public scalarRanges
|
||||
private scalarRanges
|
||||
{
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct Null
|
||||
//- Construct null
|
||||
timeSelector();
|
||||
|
||||
//- Construct from Istream
|
||||
timeSelector(Istream& is);
|
||||
//- Construct by parsing string for time ranges
|
||||
timeSelector(const std::string& str);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -24,334 +24,106 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "scalarRange.H"
|
||||
#include "token.H"
|
||||
#include "string.H"
|
||||
#include "error.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
bool Foam::scalarRange::parse(const std::string& str, scalarRange& range)
|
||||
{
|
||||
int scalarRange::debug(debug::debugSwitch("scalarRange", 0));
|
||||
}
|
||||
range.clear();
|
||||
|
||||
const auto colon = str.find(':');
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::scalarRange::scalarRange()
|
||||
:
|
||||
type_(EMPTY),
|
||||
value_(0),
|
||||
value2_(0)
|
||||
{}
|
||||
|
||||
|
||||
Foam::scalarRange::scalarRange(const scalar lower, const scalar upper)
|
||||
:
|
||||
type_(RANGE),
|
||||
value_(lower),
|
||||
value2_(upper)
|
||||
{
|
||||
if (lower > upper)
|
||||
if (colon == std::string::npos)
|
||||
{
|
||||
clear(); // Mark invalid range as empty
|
||||
// "VALUE"
|
||||
scalar val;
|
||||
if (readScalar(str, val))
|
||||
{
|
||||
range = scalarRange(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::scalarRange::scalarRange(Istream& is)
|
||||
:
|
||||
type_(EXACT),
|
||||
value_(0),
|
||||
value2_(0)
|
||||
{
|
||||
is >> *this;
|
||||
|
||||
if (scalarRange::debug)
|
||||
else if (str.find(':', colon+1) != std::string::npos)
|
||||
{
|
||||
Info<<"constructed scalarRange: " << *this << endl;
|
||||
// A second colon is a syntax error
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::scalarRange::clear()
|
||||
{
|
||||
type_ = scalarRange::EMPTY;
|
||||
value_ = 0;
|
||||
value2_ = 0;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::scalarRange::empty() const
|
||||
{
|
||||
return type_ == EMPTY;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::scalarRange::valid() const
|
||||
{
|
||||
return type_ != EMPTY;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::scalarRange::isExact() const
|
||||
{
|
||||
return type_ == EXACT;
|
||||
}
|
||||
|
||||
|
||||
Foam::scalar Foam::scalarRange::value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
|
||||
Foam::scalar Foam::scalarRange::lower() const
|
||||
{
|
||||
if (type_ == UPPER)
|
||||
else if (colon == 0)
|
||||
{
|
||||
return -Foam::GREAT;
|
||||
// ":MAX"
|
||||
scalar val;
|
||||
if (readScalar(str.substr(1), val))
|
||||
{
|
||||
range = scalarRange::le(val);
|
||||
}
|
||||
}
|
||||
else if (colon == str.size()-1)
|
||||
{
|
||||
// "MIN:"
|
||||
scalar val;
|
||||
if (readScalar(str.substr(0, colon), val))
|
||||
{
|
||||
range = scalarRange::ge(val);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return value_;
|
||||
// "MIN:MAX"
|
||||
scalar minVal, maxVal;
|
||||
if
|
||||
(
|
||||
readScalar(str.substr(0, colon), minVal)
|
||||
&& readScalar(str.substr(colon+1), maxVal)
|
||||
)
|
||||
{
|
||||
range = scalarRange(minVal, maxVal);
|
||||
}
|
||||
}
|
||||
|
||||
return range.valid();
|
||||
}
|
||||
|
||||
Foam::scalar Foam::scalarRange::upper() const
|
||||
|
||||
Foam::scalarRange Foam::scalarRange::parse(const std::string& str)
|
||||
{
|
||||
switch (type_)
|
||||
scalarRange range;
|
||||
|
||||
if (!parse(str, range))
|
||||
{
|
||||
case LOWER:
|
||||
return Foam::GREAT;
|
||||
break;
|
||||
|
||||
case RANGE:
|
||||
return value2_;
|
||||
break;
|
||||
|
||||
default:
|
||||
return value_;
|
||||
break;
|
||||
Info<< "Bad scalar-range while parsing: " << str << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::scalarRange::selected(const scalar value) const
|
||||
{
|
||||
switch (type_)
|
||||
{
|
||||
case LOWER:
|
||||
return value >= value_;
|
||||
|
||||
case UPPER:
|
||||
return value <= value_;
|
||||
|
||||
case RANGE:
|
||||
return value >= value_ && value <= value2_;
|
||||
|
||||
case EXACT:
|
||||
return value == value_;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::scalarRange::operator==(const scalarRange& range) const
|
||||
{
|
||||
return
|
||||
(
|
||||
type_ == range.type_
|
||||
&& value_ == range.value_
|
||||
&& value2_ == range.value2_
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::scalarRange::operator!=(const scalarRange& range) const
|
||||
{
|
||||
return !(operator==(range));
|
||||
return range;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
||||
|
||||
Foam::Istream& Foam::operator>>(Istream& is, scalarRange& range)
|
||||
{
|
||||
range.type_ = scalarRange::EXACT;
|
||||
range.value_ = 0;
|
||||
range.value2_ = 0;
|
||||
|
||||
List<token> toks(4);
|
||||
label nTok = 0;
|
||||
|
||||
// skip leading ','
|
||||
do
|
||||
{
|
||||
is.read(toks[nTok]);
|
||||
is.check("scalarRange token read");
|
||||
}
|
||||
while
|
||||
(
|
||||
toks[nTok].isPunctuation()
|
||||
&& toks[nTok].pToken() == token::COMMA
|
||||
);
|
||||
|
||||
++nTok;
|
||||
|
||||
// looks like ':VALUE'
|
||||
if
|
||||
(
|
||||
toks[nTok-1].isPunctuation()
|
||||
&& toks[nTok-1].pToken() == token::COLON
|
||||
)
|
||||
{
|
||||
range.type_ = scalarRange::UPPER;
|
||||
is.read(toks[nTok++]);
|
||||
is.check("scalarRange token read");
|
||||
}
|
||||
|
||||
// a number is now required
|
||||
if (!toks[nTok-1].isNumber())
|
||||
{
|
||||
range.clear(); // Mark invalid range as empty
|
||||
Info<< "rejected ill-formed or empty range:";
|
||||
for (label i=0; i<nTok; ++i)
|
||||
{
|
||||
Info<< " " << toks[i];
|
||||
}
|
||||
Info<< endl;
|
||||
is.setBad();
|
||||
return is;
|
||||
}
|
||||
|
||||
range.value_ = toks[nTok-1].number();
|
||||
is.read(toks[nTok++]);
|
||||
is.check("scalarRange token read");
|
||||
|
||||
if (scalarRange::debug)
|
||||
{
|
||||
Info<<"tokens:";
|
||||
for (label i=0; i<nTok; ++i)
|
||||
{
|
||||
Info<< " " << toks[i];
|
||||
}
|
||||
Info<< endl;
|
||||
}
|
||||
|
||||
// could be 'VALUE:' or 'VALUE:VALUE'
|
||||
if
|
||||
(
|
||||
toks[nTok-1].isPunctuation()
|
||||
&& toks[nTok-1].pToken() == token::COLON
|
||||
)
|
||||
{
|
||||
if (range.type_ == scalarRange::UPPER)
|
||||
{
|
||||
range.clear(); // Mark invalid range as empty
|
||||
Info<< "rejected ill-formed range:";
|
||||
for (label i=0; i<nTok; ++i)
|
||||
{
|
||||
Info<< " " << toks[i];
|
||||
}
|
||||
Info<< endl;
|
||||
is.setBad();
|
||||
return is;
|
||||
}
|
||||
|
||||
is.read(toks[nTok++]);
|
||||
is.check("scalarRange token read");
|
||||
|
||||
if (scalarRange::debug)
|
||||
{
|
||||
Info<<"tokens:";
|
||||
for (label i=0; i<nTok; ++i)
|
||||
{
|
||||
Info<< " " << toks[i];
|
||||
}
|
||||
Info<< endl;
|
||||
}
|
||||
|
||||
|
||||
// if there is a number, we have 'VALUE:VALUE' and not simply 'VALUE:'
|
||||
if (toks[nTok-1].isNumber())
|
||||
{
|
||||
range.type_ = scalarRange::RANGE;
|
||||
range.value2_ = toks[nTok-1].number();
|
||||
is.read(toks[nTok++]);
|
||||
is.check("scalarRange token read");
|
||||
}
|
||||
else
|
||||
{
|
||||
range.type_ = scalarRange::LOWER;
|
||||
}
|
||||
}
|
||||
|
||||
if (scalarRange::debug)
|
||||
{
|
||||
Info<<"tokens:";
|
||||
for (label i=0; i<nTok; ++i)
|
||||
{
|
||||
Info<< " " << toks[i];
|
||||
}
|
||||
Info<< endl;
|
||||
}
|
||||
|
||||
|
||||
// some remaining tokens, but they are not the next comma
|
||||
// - this is a problem!
|
||||
if
|
||||
(
|
||||
toks[nTok-1].good()
|
||||
&&
|
||||
(
|
||||
!toks[nTok-1].isPunctuation()
|
||||
|| toks[nTok-1].pToken() != token::COMMA
|
||||
)
|
||||
)
|
||||
{
|
||||
range.clear(); // Mark invalid range as empty
|
||||
Info<< "rejected ill-formed range:";
|
||||
for (label i=0; i<nTok; ++i)
|
||||
{
|
||||
Info<< " " << toks[i];
|
||||
}
|
||||
Info<< endl;
|
||||
is.setBad();
|
||||
return is;
|
||||
}
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
Foam::Ostream& Foam::operator<<(Ostream& os, const scalarRange& range)
|
||||
{
|
||||
switch (range.type_)
|
||||
{
|
||||
case scalarRange::LOWER:
|
||||
os << range.value_ << " <=> Inf";
|
||||
case scalarRange::EQ:
|
||||
os << range.min_;
|
||||
break;
|
||||
|
||||
case scalarRange::UPPER:
|
||||
os << "-Inf <=> " << range.value_;
|
||||
case scalarRange::GE:
|
||||
case scalarRange::GT:
|
||||
os << range.min_ << ":Inf";
|
||||
break;
|
||||
|
||||
case scalarRange::RANGE:
|
||||
os << range.value_ << " <=> " << range.value2_;
|
||||
case scalarRange::LE:
|
||||
case scalarRange::LT:
|
||||
os << "-Inf:" << range.max_;
|
||||
break;
|
||||
|
||||
case scalarRange::EXACT:
|
||||
os << range.value_;
|
||||
case scalarRange::GE_LE:
|
||||
os << range.min_ << ":" << range.max_;
|
||||
break;
|
||||
|
||||
default:
|
||||
os << "empty";
|
||||
os << "false";
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -25,12 +25,10 @@ Class
|
||||
Foam::scalarRange
|
||||
|
||||
Description
|
||||
A scalar range specifier.
|
||||
Scalar bounds to be used as a unary predicate.
|
||||
|
||||
The range selector can be specified as an "LOWER:UPPER" range, as a
|
||||
"LOWER:" bound, as an ":UPPER" bound or simply as an "EXACT" value.
|
||||
The read constructor uses a colon (:) as a range marker and a comma (,)
|
||||
to delimit the next possible range selector.
|
||||
The bound can be specified as an "MIN:MAX" range, as a "MIN:" or ":MAX"
|
||||
bound or simply as a single "VALUE".
|
||||
|
||||
SourceFiles
|
||||
scalarRange.C
|
||||
@ -46,96 +44,125 @@ SourceFiles
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
class Istream;
|
||||
class Ostream;
|
||||
|
||||
// Forward declaration of friend functions and operators
|
||||
// Forward declarations
|
||||
class scalarRange;
|
||||
Istream& operator>>(Istream& is, scalarRange& range);
|
||||
class Ostream;
|
||||
Ostream& operator<<(Ostream& os, const scalarRange& range);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class scalarRange Declaration
|
||||
Class scalarRange Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class scalarRange
|
||||
{
|
||||
//- Enumeration defining the types of token
|
||||
enum rangeType
|
||||
//- Enumeration defining type of range test to use
|
||||
enum testType
|
||||
{
|
||||
EMPTY = 0,
|
||||
EXACT,
|
||||
LOWER,
|
||||
UPPER,
|
||||
RANGE
|
||||
NONE = 0, //!< An empty, invalid (inverse) range. Never matches.
|
||||
EQ, //!< A single value test.
|
||||
GE, //!< Greater-than-equal.
|
||||
GT, //!< Greater-than.
|
||||
LE, //!< Less-than-equal.
|
||||
LT, //!< Less-than.
|
||||
GE_LE //!< An inclusive range.
|
||||
};
|
||||
|
||||
|
||||
// Private Member Data
|
||||
|
||||
enum rangeType type_;
|
||||
scalar value_;
|
||||
scalar value2_;
|
||||
//- The type of range test
|
||||
enum testType type_;
|
||||
|
||||
//- The min value of the range
|
||||
scalar min_;
|
||||
|
||||
//- The max value of the range
|
||||
scalar max_;
|
||||
|
||||
//- Construct from components without sanity checking
|
||||
inline scalarRange(const testType type, scalar minVal, scalar maxVal);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
static int debug;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct an empty range
|
||||
scalarRange();
|
||||
//- Construct an empty (inverse) range
|
||||
inline scalarRange();
|
||||
|
||||
//- Construct a range from lower to upper
|
||||
scalarRange(const scalar lower, const scalar upper);
|
||||
//- Construct an exact value matcher
|
||||
explicit inline scalarRange(const scalar value);
|
||||
|
||||
//- Construct from Istream.
|
||||
// Since commas can be used as list delimiters,
|
||||
// leading and trailing commas are ignored.
|
||||
scalarRange(Istream& is);
|
||||
//- Construct a range from min-value to max-value
|
||||
inline scalarRange(const scalar minVal, const scalar maxVal);
|
||||
|
||||
|
||||
// Static Constructors
|
||||
|
||||
//- Construct by parsing string content.
|
||||
// A colon (:) is used as a range marker or when specifying
|
||||
// greater-than or less-than bounds.
|
||||
// \return True if no parse problems were encountered.
|
||||
static bool parse(const std::string& str, scalarRange& range);
|
||||
|
||||
//- Construct by parsing string content.
|
||||
// Any parse problems are emitted as information and the returned
|
||||
// range is of type empty().
|
||||
// \return The parsed range, which is empty() on any problems
|
||||
static scalarRange parse(const std::string& str);
|
||||
|
||||
|
||||
//- Construct a greater-than-equals bound
|
||||
inline static scalarRange ge(const scalar minVal);
|
||||
|
||||
//- Construct a greater-than bound
|
||||
inline static scalarRange gt(const scalar minVal);
|
||||
|
||||
//- Construct a less-than-equals bound
|
||||
inline static scalarRange le(const scalar maxVal);
|
||||
|
||||
//- Construct a less-than bound
|
||||
inline static scalarRange lt(const scalar maxVal);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Reset to an empty range.
|
||||
void clear();
|
||||
//- Reset to an empty (inverse) range.
|
||||
inline void clear();
|
||||
|
||||
//- Is the range empty?
|
||||
bool empty() const;
|
||||
//- True if bounds are empty (eg, inverted)
|
||||
inline bool empty() const;
|
||||
|
||||
//- Is the range non-empty?
|
||||
bool valid() const;
|
||||
//- True if bounds are non-empty.
|
||||
inline bool valid() const;
|
||||
|
||||
//- Is the range 'EXACT'?
|
||||
bool isExact() const;
|
||||
//- True if the bounds represents a single value.
|
||||
inline bool single() const;
|
||||
|
||||
//- The value constituting an 'EXACT' match
|
||||
// or the values for 'UPPER' or 'LOWER' limits
|
||||
scalar value() const;
|
||||
//- The min value of the range.
|
||||
inline scalar min() const;
|
||||
|
||||
//- The lower limit
|
||||
scalar lower() const;
|
||||
//- The max value of the range.
|
||||
inline scalar max() const;
|
||||
|
||||
//- The upper limit
|
||||
scalar upper() const;
|
||||
|
||||
//- Return true if the value is within the range
|
||||
bool selected(const scalar value) const;
|
||||
//- A representative (average) value for the range.
|
||||
// For GE, LE bounds it is the min/max value, respectively.
|
||||
inline scalar value() const;
|
||||
|
||||
|
||||
// Member Operators
|
||||
|
||||
bool operator==(const scalarRange& range) const;
|
||||
bool operator!=(const scalarRange& range) const;
|
||||
//- Unary predicate to test if the value is within the bounds
|
||||
inline bool operator()(const scalar& value) const;
|
||||
|
||||
inline bool operator==(const scalarRange& rhs) const;
|
||||
inline bool operator!=(const scalarRange& rhs) const;
|
||||
|
||||
|
||||
// IOstream Operators
|
||||
|
||||
friend Istream& operator>>(Istream& is, scalarRange& range);
|
||||
//- Print information about the bounds.
|
||||
friend Ostream& operator<<(Ostream& os, const scalarRange& range);
|
||||
};
|
||||
|
||||
@ -146,6 +173,8 @@ public:
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "scalarRangeI.H"
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
|
184
src/OpenFOAM/primitives/ranges/scalarRange/scalarRangeI.H
Normal file
184
src/OpenFOAM/primitives/ranges/scalarRange/scalarRangeI.H
Normal file
@ -0,0 +1,184 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
inline Foam::scalarRange::scalarRange
|
||||
(
|
||||
const scalarRange::testType type,
|
||||
const scalar minVal,
|
||||
const scalar maxVal
|
||||
)
|
||||
:
|
||||
type_(type),
|
||||
min_(minVal),
|
||||
max_(maxVal)
|
||||
{}
|
||||
|
||||
|
||||
inline Foam::scalarRange::scalarRange()
|
||||
:
|
||||
scalarRange(NONE, Foam::VGREAT, -Foam::VGREAT)
|
||||
{}
|
||||
|
||||
|
||||
inline Foam::scalarRange::scalarRange(const scalar value)
|
||||
:
|
||||
scalarRange(EQ, value, value)
|
||||
{}
|
||||
|
||||
|
||||
inline Foam::scalarRange::scalarRange(const scalar minVal, const scalar maxVal)
|
||||
:
|
||||
scalarRange(GE_LE, minVal, maxVal)
|
||||
{
|
||||
if (minVal > maxVal)
|
||||
{
|
||||
clear(); // Inverted - explicitly mark as such
|
||||
}
|
||||
else if (minVal == maxVal)
|
||||
{
|
||||
type_ = EQ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline Foam::scalarRange Foam::scalarRange::ge(const scalar minVal)
|
||||
{
|
||||
return scalarRange(GE, minVal, Foam::VGREAT);
|
||||
}
|
||||
|
||||
|
||||
inline Foam::scalarRange Foam::scalarRange::gt(const scalar minVal)
|
||||
{
|
||||
return scalarRange(GT, minVal, Foam::VGREAT);
|
||||
}
|
||||
|
||||
|
||||
inline Foam::scalarRange Foam::scalarRange::le(const scalar maxVal)
|
||||
{
|
||||
return scalarRange(LE, -Foam::VGREAT, maxVal);
|
||||
}
|
||||
|
||||
inline Foam::scalarRange Foam::scalarRange::lt(const scalar maxVal)
|
||||
{
|
||||
return scalarRange(LT, -Foam::VGREAT, maxVal);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
inline void Foam::scalarRange::clear()
|
||||
{
|
||||
type_ = scalarRange::NONE;
|
||||
min_ = Foam::VGREAT;
|
||||
max_ = -Foam::VGREAT;
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::scalarRange::empty() const
|
||||
{
|
||||
return type_ == NONE;
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::scalarRange::valid() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::scalarRange::single() const
|
||||
{
|
||||
return type_ == EQ;
|
||||
}
|
||||
|
||||
|
||||
inline Foam::scalar Foam::scalarRange::min() const
|
||||
{
|
||||
return min_;
|
||||
}
|
||||
|
||||
|
||||
inline Foam::scalar Foam::scalarRange::max() const
|
||||
{
|
||||
return max_;
|
||||
}
|
||||
|
||||
|
||||
inline Foam::scalar Foam::scalarRange::value() const
|
||||
{
|
||||
switch (type_)
|
||||
{
|
||||
case EQ:
|
||||
return min_; // For equals, min and max are identical
|
||||
|
||||
case GE:
|
||||
case GT:
|
||||
return min_;
|
||||
|
||||
case LE:
|
||||
case LT:
|
||||
return max_;
|
||||
|
||||
case GE_LE:
|
||||
return 0.5*(min_ + max_);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
inline bool Foam::scalarRange::operator()(const scalar& value) const
|
||||
{
|
||||
switch (type_)
|
||||
{
|
||||
case EQ: return equal(value, min_);
|
||||
case GE: return value >= min_;
|
||||
case GT: return value > min_;
|
||||
case LE: return value <= max_;
|
||||
case LT: return value < max_;
|
||||
case GE_LE: return value >= min_ && value <= max_;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::scalarRange::operator==(const scalarRange& rhs) const
|
||||
{
|
||||
return (type_ == rhs.type_ && min_ == rhs.min_ && max_ == rhs.max_);
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::scalarRange::operator!=(const scalarRange& rhs) const
|
||||
{
|
||||
return !(operator==(rhs));
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -24,114 +24,35 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "scalarRanges.H"
|
||||
#include "DynamicList.H"
|
||||
#include "ListOps.H"
|
||||
#include "stringOps.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::scalarRanges::scalarRanges()
|
||||
Foam::scalarRanges::scalarRanges(const std::string& str)
|
||||
:
|
||||
List<scalarRange>(0)
|
||||
{}
|
||||
|
||||
|
||||
Foam::scalarRanges::scalarRanges(Istream& is)
|
||||
:
|
||||
List<scalarRange>(0)
|
||||
List<scalarRange>()
|
||||
{
|
||||
DynamicList<scalarRange> lst;
|
||||
const SubStrings<std::string> items = stringOps::splitAny(str, " ,;");
|
||||
|
||||
while (is.good())
|
||||
setSize(items.size());
|
||||
|
||||
label nItems = 0;
|
||||
|
||||
for (const auto& item : items)
|
||||
{
|
||||
scalarRange sr(is);
|
||||
if (sr.valid())
|
||||
const std::string s = item.str();
|
||||
|
||||
if (scalarRange::parse(s, operator[](nItems)))
|
||||
{
|
||||
lst.append(sr);
|
||||
++nItems;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "Bad scalar-range while parsing: " << s << endl;
|
||||
}
|
||||
}
|
||||
|
||||
transfer(lst);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::scalarRanges::selected(const scalar value) const
|
||||
{
|
||||
forAll(*this, i)
|
||||
{
|
||||
if (operator[](i).selected(value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Foam::List<bool> Foam::scalarRanges::selected
|
||||
(
|
||||
const UList<scalar>& values
|
||||
) const
|
||||
{
|
||||
List<bool> lst(values.size(), false);
|
||||
|
||||
// check ranges
|
||||
forAll(values, i)
|
||||
{
|
||||
if (selected(values[i]))
|
||||
{
|
||||
lst[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// check specific values
|
||||
forAll(*this, rangeI)
|
||||
{
|
||||
if (operator[](rangeI).isExact())
|
||||
{
|
||||
scalar target = operator[](rangeI).value();
|
||||
|
||||
int nearestIndex = -1;
|
||||
scalar nearestDiff = Foam::GREAT;
|
||||
|
||||
forAll(values, timeIndex)
|
||||
{
|
||||
scalar diff = fabs(values[timeIndex] - target);
|
||||
if (diff < nearestDiff)
|
||||
{
|
||||
nearestDiff = diff;
|
||||
nearestIndex = timeIndex;
|
||||
}
|
||||
}
|
||||
|
||||
if (nearestIndex >= 0)
|
||||
{
|
||||
lst[nearestIndex] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lst;
|
||||
}
|
||||
|
||||
|
||||
Foam::List<Foam::scalar> Foam::scalarRanges::select
|
||||
(
|
||||
const List<scalar>& values
|
||||
) const
|
||||
{
|
||||
return subset(selected(values), values);
|
||||
}
|
||||
|
||||
|
||||
void Foam::scalarRanges::inplaceSelect
|
||||
(
|
||||
List<scalar>& values
|
||||
) const
|
||||
{
|
||||
inplaceSubset(selected(values), values);
|
||||
setSize(nItems);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
@ -25,7 +25,7 @@ Class
|
||||
Foam::scalarRanges
|
||||
|
||||
Description
|
||||
A List of scalarRange.
|
||||
A collection of scalar bounds to be used as a unary predicate.
|
||||
|
||||
SourceFiles
|
||||
scalarRanges.C
|
||||
@ -44,7 +44,7 @@ namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class scalarRanges Declaration
|
||||
Class scalarRanges Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class scalarRanges
|
||||
@ -56,27 +56,18 @@ public:
|
||||
// Constructors
|
||||
|
||||
//- Construct null
|
||||
scalarRanges();
|
||||
inline scalarRanges();
|
||||
|
||||
//- Construct from Istream.
|
||||
// The list items are comma-delimited.
|
||||
scalarRanges(Istream& is);
|
||||
//- Construct by parsing a string for scalar ranges
|
||||
// The individual items are space, comma or semicolon delimited.
|
||||
scalarRanges(const std::string& str);
|
||||
|
||||
|
||||
// Member Functions
|
||||
// Member Operators
|
||||
|
||||
//- Return true if the given value is within the ranges
|
||||
bool selected(const scalar value) const;
|
||||
//- Unary predicate to test if the value is within any of the ranges
|
||||
inline bool operator()(const scalar& value) const;
|
||||
|
||||
//- Return the set of selected entries in the given list
|
||||
// that are within the ranges
|
||||
List<bool> selected(const UList<scalar>& values) const;
|
||||
|
||||
//- Select a list of values that are within the ranges
|
||||
List<scalar> select(const List<scalar>& values) const;
|
||||
|
||||
//- Select a list of values that are within the ranges
|
||||
void inplaceSelect(List<scalar>& values) const;
|
||||
};
|
||||
|
||||
|
||||
@ -86,6 +77,8 @@ public:
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "scalarRangesI.H"
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
|
50
src/OpenFOAM/primitives/ranges/scalarRange/scalarRangesI.H
Normal file
50
src/OpenFOAM/primitives/ranges/scalarRange/scalarRangesI.H
Normal file
@ -0,0 +1,50 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
inline Foam::scalarRanges::scalarRanges()
|
||||
:
|
||||
List<scalarRange>()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
inline bool Foam::scalarRanges::operator()(const scalar& value) const
|
||||
{
|
||||
for (const scalarRange& range : *this)
|
||||
{
|
||||
if (range(value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
Loading…
Reference in New Issue
Block a user