mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: improve/simplify streaming of exprValue
- ensure that operator<< and operator>> behave symmetrically
This commit is contained in:
@ -1,3 +0,0 @@
|
|||||||
Test-exprValue.cxx
|
|
||||||
|
|
||||||
EXE = $(FOAM_USER_APPBIN)/Test-exprValue
|
|
||||||
3
applications/test/exprValue1/Make/files
Normal file
3
applications/test/exprValue1/Make/files
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Test-exprValue1.cxx
|
||||||
|
|
||||||
|
EXE = $(FOAM_USER_APPBIN)/Test-exprValue1
|
||||||
@ -11,7 +11,7 @@ License
|
|||||||
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
||||||
|
|
||||||
Application
|
Application
|
||||||
Test-exprValue
|
Test-exprValue1
|
||||||
|
|
||||||
Description
|
Description
|
||||||
Test low-level polymorphic value container (exprValue)
|
Test low-level polymorphic value container (exprValue)
|
||||||
@ -59,11 +59,11 @@ expressions::exprValue tryParse(const std::string& str)
|
|||||||
Info<< "Direct from string: ";
|
Info<< "Direct from string: ";
|
||||||
if (expressions::exprValue::read(str, val2))
|
if (expressions::exprValue::read(str, val2))
|
||||||
{
|
{
|
||||||
Info<< "good" << nl;
|
Info<< "OK" << nl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Info<< "bad" << nl;
|
Info<< "NOK" << nl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
@ -128,21 +128,22 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
expressions::exprValue oldValue(value);
|
expressions::exprValue oldValue(value);
|
||||||
|
|
||||||
// Since the IO serialization is not symmetric (in ASCII) there
|
|
||||||
// is no 'operator>>' defined and thus the regular Pstream::broadcast
|
|
||||||
// will not compile.
|
|
||||||
// Even although the data are contiguous and that code branch is never
|
|
||||||
// used.
|
|
||||||
|
|
||||||
// Fails to compile: Pstream::broadcast(value);
|
if (true)
|
||||||
|
{
|
||||||
// Broadcast manually
|
// Broadcast with serialization
|
||||||
UPstream::broadcast
|
Pstream::broadcast(value);
|
||||||
(
|
}
|
||||||
value.data_bytes(),
|
else
|
||||||
value.size_bytes(),
|
{
|
||||||
UPstream::worldComm
|
// Broadcast manually
|
||||||
);
|
UPstream::broadcast
|
||||||
|
(
|
||||||
|
value.data_bytes(),
|
||||||
|
value.size_bytes(),
|
||||||
|
UPstream::worldComm
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Pout<< "same values: " << (oldValue == value) << nl;
|
Pout<< "same values: " << (oldValue == value) << nl;
|
||||||
|
|
||||||
5
applications/test/exprValue2/Make/files
Normal file
5
applications/test/exprValue2/Make/files
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
exprValueFieldTag.cxx
|
||||||
|
|
||||||
|
Test-exprValue2.cxx
|
||||||
|
|
||||||
|
EXE = $(FOAM_USER_APPBIN)/Test-exprValue2
|
||||||
1
applications/test/exprValue2/Make/options
Normal file
1
applications/test/exprValue2/Make/options
Normal file
@ -0,0 +1 @@
|
|||||||
|
/* EXE_INC = */
|
||||||
143
applications/test/exprValue2/Test-exprValue2.cxx
Normal file
143
applications/test/exprValue2/Test-exprValue2.cxx
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2023 OpenCFD Ltd.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
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 exprValue uniformity checks
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "argList.H"
|
||||||
|
#include "IOobject.H"
|
||||||
|
#include "IOstreams.H"
|
||||||
|
#include "labelList.H"
|
||||||
|
#include "scalarField.H"
|
||||||
|
#include "vectorField.H"
|
||||||
|
#include "DynamicList.H"
|
||||||
|
#include "Random.H"
|
||||||
|
#include "exprValue.H"
|
||||||
|
#include "exprValueFieldTag.H"
|
||||||
|
|
||||||
|
using namespace Foam;
|
||||||
|
|
||||||
|
Ostream& printInfo(const expressions::exprValueFieldTag& tag)
|
||||||
|
{
|
||||||
|
tag.print(Pout);
|
||||||
|
return Pout;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
// Main program:
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
using fieldTag = expressions::exprValueFieldTag;
|
||||||
|
|
||||||
|
Random rnd(123456);
|
||||||
|
|
||||||
|
argList::noCheckProcessorDirectories();
|
||||||
|
|
||||||
|
#include "setRootCase.H"
|
||||||
|
|
||||||
|
{
|
||||||
|
scalarField fld1(20);
|
||||||
|
scalarField fld2a(20, Zero);
|
||||||
|
scalarField fld2b(10, 3.10);
|
||||||
|
scalarField fld3;
|
||||||
|
|
||||||
|
forAll(fld1, i)
|
||||||
|
{
|
||||||
|
fld1[i] = rnd.position<scalar>(0, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldTag tag1(fld1.begin(), fld1.end());
|
||||||
|
fieldTag tag2a(fld2a.begin(), fld2a.end());
|
||||||
|
fieldTag tag2b(fld2b.begin(), fld2b.end());
|
||||||
|
fieldTag tag3(fld3.begin(), fld3.end());
|
||||||
|
|
||||||
|
printInfo(tag1) << nl;
|
||||||
|
printInfo(tag2a) << nl;
|
||||||
|
printInfo(tag2b) << nl;
|
||||||
|
printInfo(tag3) << nl;
|
||||||
|
|
||||||
|
fieldTag result;
|
||||||
|
|
||||||
|
result = fieldTag::combineOp{}(tag1, tag2a);
|
||||||
|
printInfo(result) << nl;
|
||||||
|
|
||||||
|
Info<< "combine: ";
|
||||||
|
printInfo(tag2a) << " and ";
|
||||||
|
printInfo(tag2b) << nl;
|
||||||
|
|
||||||
|
result = fieldTag::combineOp{}(tag2a, tag2b);
|
||||||
|
printInfo(result) << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
vectorField fld2a(20, Foam::zero{});
|
||||||
|
vectorField fld2b(10, vector::uniform(3.10));
|
||||||
|
|
||||||
|
fieldTag tag2a(fld2a.begin(), fld2a.end());
|
||||||
|
fieldTag tag2b(fld2b.begin(), fld2b.end());
|
||||||
|
|
||||||
|
printInfo(tag2a) << nl;
|
||||||
|
printInfo(tag2b) << nl;
|
||||||
|
|
||||||
|
fieldTag result;
|
||||||
|
|
||||||
|
Info<< "combine: ";
|
||||||
|
printInfo(tag2a) << " and ";
|
||||||
|
printInfo(tag2b) << nl;
|
||||||
|
|
||||||
|
result = fieldTag::combineOp{}(tag2a, tag2b);
|
||||||
|
printInfo(result) << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UPstream::parRun())
|
||||||
|
{
|
||||||
|
scalarField fld;
|
||||||
|
|
||||||
|
if (!UPstream::master())
|
||||||
|
{
|
||||||
|
fld.resize(UPstream::myProcNo(), UPstream::myProcNo());
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldTag oldTag(fld.begin(), fld.end());
|
||||||
|
|
||||||
|
printInfo(oldTag) << " input: " << fld << " <- before reduce" << nl;
|
||||||
|
|
||||||
|
fieldTag newTag = returnReduce(oldTag, fieldTag::combineOp());
|
||||||
|
|
||||||
|
printInfo(newTag) << " <- after reduce" << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Info<< "\nEnd\n" << nl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
170
applications/test/exprValue2/exprValueFieldTag.H
Normal file
170
applications/test/exprValue2/exprValueFieldTag.H
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2023 OpenCFD Ltd.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
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/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::expressions::exprValueFieldTag
|
||||||
|
|
||||||
|
Description
|
||||||
|
A polymorphic single-value container for tracking Field content
|
||||||
|
as uniform etc.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
exprValueFieldTag.cxx
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef Foam_expressions_exprValueFieldTag_H
|
||||||
|
#define Foam_expressions_exprValueFieldTag_H
|
||||||
|
|
||||||
|
#include "exprValue.H"
|
||||||
|
#include "List.H" // For ListPolicy
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
namespace expressions
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class exprValueFieldTag Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class exprValueFieldTag
|
||||||
|
{
|
||||||
|
// Private data
|
||||||
|
|
||||||
|
//- Uniformity of field
|
||||||
|
int uniformity_{};
|
||||||
|
|
||||||
|
//- Representative (uniform) value for the field
|
||||||
|
expressions::exprValue value_{};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Default construct
|
||||||
|
exprValueFieldTag() = default;
|
||||||
|
|
||||||
|
//- Construct from a range of values
|
||||||
|
template<class Type>
|
||||||
|
explicit exprValueFieldTag(const Type* first, const Type* last)
|
||||||
|
{
|
||||||
|
set(first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
//- True if the uniformity is "empty"
|
||||||
|
bool empty() const noexcept;
|
||||||
|
|
||||||
|
//- True if the uniformity is "uniform"
|
||||||
|
bool is_uniform() const noexcept;
|
||||||
|
|
||||||
|
//- True if the uniformity is "non-uniform"
|
||||||
|
bool is_nonuniform() const noexcept;
|
||||||
|
|
||||||
|
//- Test for equality of the values
|
||||||
|
bool equal(const exprValueFieldTag& rhs) const;
|
||||||
|
|
||||||
|
//- Set value and uniformity from range of data
|
||||||
|
template<class Type>
|
||||||
|
void set(const Type* first, const Type* last)
|
||||||
|
{
|
||||||
|
uniformity_ =
|
||||||
|
Foam::Detail::ListPolicy::check_uniformity(first, last);
|
||||||
|
|
||||||
|
if (first != last) // or uniformity_ != EMPTY
|
||||||
|
{
|
||||||
|
value_.set<Type>(*first);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value_.set<Type>(Foam::zero{});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Set uniform type and value
|
||||||
|
template<class Type>
|
||||||
|
void set_uniform(const Type& val)
|
||||||
|
{
|
||||||
|
uniformity_ = Foam::Detail::ListPolicy::uniformity::UNIFORM;
|
||||||
|
value_.set<Type>(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Set as non-uniform
|
||||||
|
void set_nouniform() noexcept;
|
||||||
|
|
||||||
|
|
||||||
|
// Reduction operations
|
||||||
|
|
||||||
|
//- Combine - eg, for global uniformity
|
||||||
|
void combine(const exprValueFieldTag& b);
|
||||||
|
|
||||||
|
//- Binary operator to be used by reduce function for detecting
|
||||||
|
//- global uniformity
|
||||||
|
struct combineOp
|
||||||
|
{
|
||||||
|
exprValueFieldTag operator()
|
||||||
|
(
|
||||||
|
const exprValueFieldTag& a,
|
||||||
|
const exprValueFieldTag& b
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
exprValueFieldTag result(a);
|
||||||
|
result.combine(b);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// IO Operations
|
||||||
|
|
||||||
|
void read(Istream& is);
|
||||||
|
void write(Ostream& os) const;
|
||||||
|
|
||||||
|
//- Print description to Ostream
|
||||||
|
void print(Ostream& os) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace expressions
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// IO
|
||||||
|
Istream& operator>>(Istream&, expressions::exprValueFieldTag&);
|
||||||
|
Ostream& operator<<(Ostream&, const expressions::exprValueFieldTag&);
|
||||||
|
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
160
applications/test/exprValue2/exprValueFieldTag.cxx
Normal file
160
applications/test/exprValue2/exprValueFieldTag.cxx
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2023 OpenCFD Ltd.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
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/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "exprValueFieldTag.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool Foam::expressions::exprValueFieldTag::empty() const noexcept
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(
|
||||||
|
uniformity_ == Foam::Detail::ListPolicy::uniformity::EMPTY
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::expressions::exprValueFieldTag::is_uniform() const noexcept
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(
|
||||||
|
uniformity_ == Foam::Detail::ListPolicy::uniformity::UNIFORM
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::expressions::exprValueFieldTag::is_nonuniform() const noexcept
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(
|
||||||
|
uniformity_ == Foam::Detail::ListPolicy::uniformity::NONUNIFORM
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::expressions::exprValueFieldTag::equal
|
||||||
|
(
|
||||||
|
const exprValueFieldTag& rhs
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
return (value_ == rhs.value_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::expressions::exprValueFieldTag::set_nouniform() noexcept
|
||||||
|
{
|
||||||
|
uniformity_ = Foam::Detail::ListPolicy::uniformity::NONUNIFORM;
|
||||||
|
value_ = Foam::zero{};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::expressions::exprValueFieldTag::combine
|
||||||
|
(
|
||||||
|
const exprValueFieldTag& b
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (b.empty())
|
||||||
|
{
|
||||||
|
// no-op
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
exprValueFieldTag& a = *this;
|
||||||
|
|
||||||
|
if (a.empty())
|
||||||
|
{
|
||||||
|
a = b;
|
||||||
|
}
|
||||||
|
else if (a.is_nonuniform())
|
||||||
|
{
|
||||||
|
// Already non-uniform/mixed
|
||||||
|
// a.uniformity_ |= b.uniformity_;
|
||||||
|
|
||||||
|
a.value_ = Foam::zero{};
|
||||||
|
}
|
||||||
|
else if (a.is_uniform() && b.is_uniform())
|
||||||
|
{
|
||||||
|
// Both are uniform, but are they the same value?
|
||||||
|
if (!a.equal(b))
|
||||||
|
{
|
||||||
|
a.set_nouniform();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::expressions::exprValueFieldTag::read(Istream& is)
|
||||||
|
{
|
||||||
|
label uniformTag;
|
||||||
|
|
||||||
|
is >> uniformTag;
|
||||||
|
uniformity_ = int(uniformTag);
|
||||||
|
value_.read(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::expressions::exprValueFieldTag::write(Ostream& os) const
|
||||||
|
{
|
||||||
|
os << label(uniformity_);
|
||||||
|
value_.write(os, false); // No pruning
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::expressions::exprValueFieldTag::print(Ostream& os) const
|
||||||
|
{
|
||||||
|
os << "{ uniform:"
|
||||||
|
<< label(uniformity_)
|
||||||
|
<< " type:" << label(value_.typeCode())
|
||||||
|
<< " value: " << value_ << " }";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::Istream& Foam::operator>>
|
||||||
|
(
|
||||||
|
Istream& is,
|
||||||
|
expressions::exprValueFieldTag& tag
|
||||||
|
)
|
||||||
|
{
|
||||||
|
tag.read(is);
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::Ostream& Foam::operator<<
|
||||||
|
(
|
||||||
|
Ostream& os,
|
||||||
|
const expressions::exprValueFieldTag& tag
|
||||||
|
)
|
||||||
|
{
|
||||||
|
tag.write(os);
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2021 OpenCFD Ltd.
|
Copyright (C) 2021-2023 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -61,7 +61,37 @@ Foam::expressions::Detail::nComponents
|
|||||||
\
|
\
|
||||||
case expressions::valueTypeCode::type_##Type : \
|
case expressions::valueTypeCode::type_##Type : \
|
||||||
{ \
|
{ \
|
||||||
return pTraits<Type>::nComponents; \
|
return exprTypeTraits<Type>::nComponents; \
|
||||||
|
}
|
||||||
|
|
||||||
|
FOR_ALL_EXPR_TYPE_CODES(doLocalCode);
|
||||||
|
#undef doLocalCode
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::direction
|
||||||
|
Foam::expressions::Detail::rank
|
||||||
|
(
|
||||||
|
const expressions::valueTypeCode typeCode
|
||||||
|
) noexcept
|
||||||
|
{
|
||||||
|
switch (typeCode)
|
||||||
|
{
|
||||||
|
case expressions::valueTypeCode::NONE :
|
||||||
|
case expressions::valueTypeCode::INVALID :
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef doLocalCode
|
||||||
|
#define doLocalCode(Type, UnusedParam) \
|
||||||
|
\
|
||||||
|
case expressions::valueTypeCode::type_##Type : \
|
||||||
|
{ \
|
||||||
|
return exprTypeTraits<Type>::rank; \
|
||||||
}
|
}
|
||||||
|
|
||||||
FOR_ALL_EXPR_TYPE_CODES(doLocalCode);
|
FOR_ALL_EXPR_TYPE_CODES(doLocalCode);
|
||||||
@ -112,7 +142,7 @@ Foam::word Foam::name(const expressions::valueTypeCode typeCode)
|
|||||||
|
|
||||||
case expressions::valueTypeCode::INVALID :
|
case expressions::valueTypeCode::INVALID :
|
||||||
{
|
{
|
||||||
// returns ""
|
// returns "", could also return "bad"
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -117,6 +117,9 @@ namespace Detail
|
|||||||
//- The number of components associated with given valueTypeCode
|
//- The number of components associated with given valueTypeCode
|
||||||
::Foam::direction nComponents(const expressions::valueTypeCode) noexcept;
|
::Foam::direction nComponents(const expressions::valueTypeCode) noexcept;
|
||||||
|
|
||||||
|
//- The vector-space rank associated with given valueTypeCode
|
||||||
|
::Foam::direction rank(const expressions::valueTypeCode) noexcept;
|
||||||
|
|
||||||
} // End namespace Detail
|
} // End namespace Detail
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -129,6 +129,10 @@ Foam::expressions::exprValue::peekType(const ITstream& is)
|
|||||||
|
|
||||||
switch (endCmpti - firstCmpti)
|
switch (endCmpti - firstCmpti)
|
||||||
{
|
{
|
||||||
|
case 0: // Explicitly provided '()' - ie, none
|
||||||
|
whichCode = expressions::valueTypeCode::NONE;
|
||||||
|
break;
|
||||||
|
|
||||||
case 1: // pTraits<sphericalTensor>::nComponents
|
case 1: // pTraits<sphericalTensor>::nComponents
|
||||||
whichCode = exprTypeTraits<sphericalTensor>::value;
|
whichCode = exprTypeTraits<sphericalTensor>::value;
|
||||||
break;
|
break;
|
||||||
@ -177,6 +181,13 @@ Foam::expressions::exprValue::peekType(const ITstream& is)
|
|||||||
{
|
{
|
||||||
whichCode = exprTypeTraits<bool>::value;
|
whichCode = exprTypeTraits<bool>::value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Treat anything else as 'invalid', which also implicitly
|
||||||
|
// includes the token "bad"
|
||||||
|
// else if (tok0.isWord("bad"))
|
||||||
|
// {
|
||||||
|
// whichCode = expressions::valueTypeCode::INVALID;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
return whichCode;
|
return whichCode;
|
||||||
@ -192,7 +203,7 @@ bool Foam::expressions::exprValue::read
|
|||||||
ITstream is(str);
|
ITstream is(str);
|
||||||
|
|
||||||
// No trailing non-whitespace!
|
// No trailing non-whitespace!
|
||||||
return (val.read(is) && !is.nRemainingTokens());
|
return (val.readTokens(is) && !is.nRemainingTokens());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -215,10 +226,33 @@ void Foam::expressions::exprValue::deepCopy(const exprValue& rhs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::tokenList Foam::expressions::exprValue::tokens() const
|
Foam::tokenList Foam::expressions::exprValue::tokens(bool prune) const
|
||||||
{
|
{
|
||||||
|
// Handling for NONE, INVALID:
|
||||||
|
// - NONE => pair of ( ) brackets
|
||||||
|
// - INVALID => "bad" as a word
|
||||||
|
//
|
||||||
|
// With prune:
|
||||||
|
// - no output for either
|
||||||
|
|
||||||
tokenList toks;
|
tokenList toks;
|
||||||
|
|
||||||
|
if (!prune)
|
||||||
|
{
|
||||||
|
if (typeCode_ == expressions::valueTypeCode::NONE)
|
||||||
|
{
|
||||||
|
toks.resize(2);
|
||||||
|
toks.front() = token::BEGIN_LIST;
|
||||||
|
toks.back() = token::END_LIST;
|
||||||
|
return toks;
|
||||||
|
}
|
||||||
|
else if (typeCode_ == expressions::valueTypeCode::INVALID)
|
||||||
|
{
|
||||||
|
toks.emplace_back(word("bad"));
|
||||||
|
return toks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (typeCode_)
|
switch (typeCode_)
|
||||||
{
|
{
|
||||||
#undef doLocalCode
|
#undef doLocalCode
|
||||||
@ -245,8 +279,29 @@ Foam::tokenList Foam::expressions::exprValue::tokens() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::expressions::exprValue::print(Ostream& os) const
|
void Foam::expressions::exprValue::write(Ostream& os, bool prune) const
|
||||||
{
|
{
|
||||||
|
// Handling for NONE, INVALID:
|
||||||
|
// - NONE => pair of ( ) brackets
|
||||||
|
// - INVALID => "bad" as a word
|
||||||
|
//
|
||||||
|
// With prune:
|
||||||
|
// - no output for either
|
||||||
|
|
||||||
|
if (!prune)
|
||||||
|
{
|
||||||
|
if (typeCode_ == expressions::valueTypeCode::NONE)
|
||||||
|
{
|
||||||
|
os << token::BEGIN_LIST << token::END_LIST;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (typeCode_ == expressions::valueTypeCode::INVALID)
|
||||||
|
{
|
||||||
|
os << word("bad");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (typeCode_)
|
switch (typeCode_)
|
||||||
{
|
{
|
||||||
#undef doLocalCode
|
#undef doLocalCode
|
||||||
@ -271,12 +326,87 @@ void Foam::expressions::exprValue::print(Ostream& os) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Foam::expressions::exprValue::read(ITstream& is)
|
bool Foam::expressions::exprValue::read(Istream& is)
|
||||||
|
{
|
||||||
|
ITstream* stream = dynamic_cast<ITstream*>(&is);
|
||||||
|
|
||||||
|
// Reading via tokens - simple for now
|
||||||
|
// Expect either a single token (scalar, label, word etc)
|
||||||
|
// or ( ... ) content
|
||||||
|
|
||||||
|
ITstream toks;
|
||||||
|
|
||||||
|
if (!stream)
|
||||||
|
{
|
||||||
|
token tok(is);
|
||||||
|
|
||||||
|
is.fatalCheck(FUNCTION_NAME);
|
||||||
|
|
||||||
|
if (tok.isPunctuation(token::BEGIN_LIST))
|
||||||
|
{
|
||||||
|
// Expecting "( content )" - eg, (x y z), (xx xy ...)
|
||||||
|
do
|
||||||
|
{
|
||||||
|
toks.add_tokens(tok);
|
||||||
|
|
||||||
|
is >> tok;
|
||||||
|
is.fatalCheck(FUNCTION_NAME);
|
||||||
|
}
|
||||||
|
while (!tok.isPunctuation(token::END_LIST));
|
||||||
|
|
||||||
|
if (tok.isPunctuation(token::END_LIST))
|
||||||
|
{
|
||||||
|
toks.add_tokens(tok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tok.good())
|
||||||
|
{
|
||||||
|
toks.add_tokens(tok);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Truncate to number tokens read
|
||||||
|
toks.resize(toks.tokenIndex());
|
||||||
|
toks.seek(0);
|
||||||
|
|
||||||
|
stream = &toks;
|
||||||
|
}
|
||||||
|
|
||||||
|
return readTokens(*stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::expressions::exprValue::readTokens(ITstream& is)
|
||||||
{
|
{
|
||||||
clear(); // type: none, value: zero
|
clear(); // type: none, value: zero
|
||||||
|
|
||||||
const valueTypeCode whichCode(exprValue::peekType(is));
|
const valueTypeCode whichCode(exprValue::peekType(is));
|
||||||
|
|
||||||
|
if (whichCode == expressions::valueTypeCode::NONE)
|
||||||
|
{
|
||||||
|
typeCode_ = whichCode;
|
||||||
|
is.skip(2); // Skip tokens: '( )'
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This one should be rare or even impossible
|
||||||
|
if (whichCode == expressions::valueTypeCode::INVALID)
|
||||||
|
{
|
||||||
|
typeCode_ = whichCode;
|
||||||
|
|
||||||
|
if (is.bad())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const token& tok0 = is.peek();
|
||||||
|
|
||||||
|
if (tok0.isWord("bad"))
|
||||||
|
{
|
||||||
|
is.skip(1); // Skip token: "bad"
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (whichCode)
|
switch (whichCode)
|
||||||
{
|
{
|
||||||
#undef doLocalCode
|
#undef doLocalCode
|
||||||
@ -347,13 +477,24 @@ bool Foam::expressions::exprValue::operator<(const exprValue& rhs) const
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::Istream& Foam::operator>>
|
||||||
|
(
|
||||||
|
Istream& is,
|
||||||
|
expressions::exprValue& val
|
||||||
|
)
|
||||||
|
{
|
||||||
|
val.read(is);
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::Ostream& Foam::operator<<
|
Foam::Ostream& Foam::operator<<
|
||||||
(
|
(
|
||||||
Ostream& os,
|
Ostream& os,
|
||||||
const expressions::exprValue& val
|
const expressions::exprValue& val
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
val.print(os);
|
val.write(os, false); // no pruning
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,16 +508,18 @@ Foam::Ostream& Foam::operator<<
|
|||||||
{
|
{
|
||||||
const auto& val = *iproxy;
|
const auto& val = *iproxy;
|
||||||
|
|
||||||
if (val.good())
|
if (val.typeCode() == expressions::valueTypeCode::NONE)
|
||||||
{
|
{
|
||||||
os << val.valueTypeName() << ": ";
|
os << "none";
|
||||||
val.print(os);
|
}
|
||||||
|
else if (val.typeCode() == expressions::valueTypeCode::INVALID)
|
||||||
|
{
|
||||||
|
os << "bad";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// typeCode_ is *never* set to INVALID,
|
os << val.valueTypeName() << ": ";
|
||||||
// so NONE is the only remaining non-good type
|
val.write(os); // pruning is immaterial - !good() already handled
|
||||||
os << "none";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return os;
|
return os;
|
||||||
|
|||||||
@ -169,7 +169,7 @@ class exprValue
|
|||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Assign zero, preserving the data type
|
//- Fill the data with zero, preserving the data type
|
||||||
inline void fill_zero();
|
inline void fill_zero();
|
||||||
|
|
||||||
//- Copy assignment
|
//- Copy assignment
|
||||||
@ -215,6 +215,12 @@ public:
|
|||||||
const expressions::valueTypeCode
|
const expressions::valueTypeCode
|
||||||
) noexcept;
|
) noexcept;
|
||||||
|
|
||||||
|
//- The vector-space rank associated with the valueTypeCode
|
||||||
|
inline static direction rank
|
||||||
|
(
|
||||||
|
const expressions::valueTypeCode
|
||||||
|
) noexcept;
|
||||||
|
|
||||||
//- True if the specified type is supported
|
//- True if the specified type is supported
|
||||||
template<class Type>
|
template<class Type>
|
||||||
inline static bool supportedType();
|
inline static bool supportedType();
|
||||||
@ -250,6 +256,9 @@ public:
|
|||||||
//- The number of components associated with the value type
|
//- The number of components associated with the value type
|
||||||
inline direction nComponents() const noexcept;
|
inline direction nComponents() const noexcept;
|
||||||
|
|
||||||
|
//- The vector-space rank associated with the value type
|
||||||
|
inline direction rank() const noexcept;
|
||||||
|
|
||||||
//- The name for the value type. Similar to pTraits typeName
|
//- The name for the value type. Similar to pTraits typeName
|
||||||
inline word valueTypeName() const;
|
inline word valueTypeName() const;
|
||||||
|
|
||||||
@ -260,9 +269,13 @@ public:
|
|||||||
//- Reset to 'none'
|
//- Reset to 'none'
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
//- Read read tokens (if possible)
|
||||||
|
// \return True on success
|
||||||
|
bool read(Istream& is);
|
||||||
|
|
||||||
//- Guess type and read tokens (if possible)
|
//- Guess type and read tokens (if possible)
|
||||||
// \return True on success
|
// \return True on success
|
||||||
bool read(ITstream& is);
|
bool readTokens(ITstream& is);
|
||||||
|
|
||||||
|
|
||||||
// Typed Access
|
// Typed Access
|
||||||
@ -346,11 +359,19 @@ public:
|
|||||||
//- Return info proxy for printing information to a stream
|
//- Return info proxy for printing information to a stream
|
||||||
InfoProxy<exprValue> info() const { return *this; }
|
InfoProxy<exprValue> info() const { return *this; }
|
||||||
|
|
||||||
//- The value as tokens. An empty list is returned for NONE.
|
//- The exprValue as tokens.
|
||||||
tokenList tokens() const;
|
// For none : emits pair of brackets.
|
||||||
|
// For invalid : emits "bad".
|
||||||
|
//
|
||||||
|
// \param prune suppress the output for none/invalid
|
||||||
|
tokenList tokens(bool prune = false) const;
|
||||||
|
|
||||||
//- Print the (type-specific) content
|
//- Write the (type-specific) content.
|
||||||
void print(Ostream& os) const;
|
// For none : emits pair of brackets.
|
||||||
|
// For invalid : emits "bad".
|
||||||
|
//
|
||||||
|
// \param prune suppress the output for none/invalid
|
||||||
|
void write(Ostream& os, bool prune = false) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -364,7 +385,11 @@ template<> struct is_contiguous<expressions::exprValue> : std::true_type {};
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
|
||||||
|
|
||||||
//- Write value to output stream in ASCII format. No output for !good().
|
//- Read/parse value from input stream (uses ASCII format).
|
||||||
|
Istream& operator>>(Istream& is, expressions::exprValue& val);
|
||||||
|
|
||||||
|
//- Write value to output stream (uses ASCII format).
|
||||||
|
//- Writes 'none' or 'bad' for unknown/unsupported types.
|
||||||
Ostream& operator<<(Ostream& os, const expressions::exprValue& val);
|
Ostream& operator<<(Ostream& os, const expressions::exprValue& val);
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|||||||
@ -64,6 +64,15 @@ inline Foam::direction Foam::expressions::exprValue::nComponents
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Foam::direction Foam::expressions::exprValue::rank
|
||||||
|
(
|
||||||
|
const expressions::valueTypeCode valTypeCode
|
||||||
|
) noexcept
|
||||||
|
{
|
||||||
|
return expressions::Detail::rank(valTypeCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
inline bool Foam::expressions::exprValue::supportedType()
|
inline bool Foam::expressions::exprValue::supportedType()
|
||||||
{
|
{
|
||||||
@ -110,7 +119,7 @@ inline Foam::expressions::exprValue::exprValue(const Type& val)
|
|||||||
{
|
{
|
||||||
FatalErrorInFunction
|
FatalErrorInFunction
|
||||||
<< "Cannot construct for unsupported type: "
|
<< "Cannot construct for unsupported type: "
|
||||||
<< typeid(Type).name() << endl
|
<< typeid(Type).name() << nl
|
||||||
<< abort(FatalError);
|
<< abort(FatalError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,6 +146,13 @@ Foam::expressions::exprValue::nComponents() const noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Foam::direction
|
||||||
|
Foam::expressions::exprValue::rank() const noexcept
|
||||||
|
{
|
||||||
|
return expressions::Detail::rank(typeCode_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline Foam::word
|
inline Foam::word
|
||||||
Foam::expressions::exprValue::valueTypeName() const
|
Foam::expressions::exprValue::valueTypeName() const
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user