Loading...
Searching...
No Matches
exprResult.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2012-2018 Bernhard Gschaider
9 Copyright (C) 2019-2022 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
29#include "exprResult.H"
30#include "vector.H"
31#include "tensor.H"
32#include "symmTensor.H"
33#include "sphericalTensor.H"
34#include "Switch.H"
37// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39namespace Foam
40{
41namespace expressions
44
47
50
51} // End namespace expressions
52} // End namespace Foam
53
54
56
57
58// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
59
60bool Foam::expressions::exprResult::setAverageValueCheckedBool
61(
62 const bool parRun
63)
64{
65 typedef bool Type;
66
67 if (!isType<Type>())
68 {
69 return false;
70 }
71
72 const Field<Type>& fld = *static_cast<const Field<Type>*>(fieldPtr_);
73 label len = fld.size();
74
75 // The average of a bool is slightly dodgy
76
77 label nTrue = 0;
78 for (const Type val : fld)
79 {
80 if (val)
81 {
82 ++nTrue;
83 }
84 }
85
86 if (parRun)
87 {
88 reduce(nTrue, sumOp<label>());
89 }
90
91 if (!nTrue)
92 {
93 // All false
94 value_.set(false);
95 return true;
96 }
97
98 if (parRun)
99 {
100 reduce(len, sumOp<label>());
101 }
102
103 if (nTrue == len)
104 {
105 // All true
106 value_.set(true);
107 }
108 if (nTrue*10 < len)
109 {
110 // 90% are false => False
111 value_.set(false);
112 }
113 else if (nTrue*10 >= len*9)
114 {
115 // 90% are true => True
116 value_.set(true);
117 }
118 else
119 {
120 // Mixed - no single value representation
121 value_.clear();
122 }
123
124 return true;
125}
126
127
128bool Foam::expressions::exprResult::getUniformCheckedBool
129(
130 exprResult& result,
131 const label size,
132 const bool noWarn,
133 const bool parRun
134) const
135{
136 typedef bool Type;
137
138 if (!isType<Type>())
139 {
140 return false;
141 }
142
143 result.clear();
144
145 const Field<Type>& fld = *static_cast<const Field<Type>*>(fieldPtr_);
146 label len = fld.size();
147
148 // The average of a bool is slightly dodgy
149
150 label nTrue = 0;
151 for (const Type val : fld)
152 {
153 if (val)
154 {
155 ++nTrue;
156 }
157 }
158
159 if (parRun)
160 {
161 reduce(nTrue, sumOp<label>());
162 reduce(len, sumOp<label>());
163 }
164
165 const Type avg = (nTrue > len/2);
166
167 if (!noWarn)
168 {
169 // TODO?
170 }
171
172 result.setResult<Type>(avg, size);
174 return true;
175}
176
177
178// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
179
181:
182 valType_(),
183 isPointData_(false),
184 noReset_(false),
185 needsReset_(false),
186 size_(0),
187 value_(),
188 fieldPtr_(nullptr)
189{}
190
191
194 exprResult()
195{
196 this->operator=(rhs);
197}
198
199
202 exprResult()
203{
204 this->operator=(std::move(rhs));
205}
206
207
209(
210 const dictionary& dict,
211 bool singleValueOnly,
212 bool valueReqd
213)
214:
215 exprResult()
216{
217 dict.readIfPresent("valueType", valType_);
218 dict.readIfPresent("isPointValue", isPointData_);
219 dict.readIfPresent("noReset", noReset_);
220 dict.readIfPresent("isSingleValue", singleValueOnly);
221
223
224 const auto* hasValue = dict.findEntry("value", keyType::LITERAL);
225
226 if (hasValue)
227 {
228 const auto& valueEntry = *hasValue;
229
230 const label len =
231 (
232 singleValueOnly
233 ? dict.getOrDefault<label>("fieldSize", 1)
234 : dict.get<label>("fieldSize")
235 );
236
237 const bool ok =
238 (
239 // Just use <scalar> for <label>?
240 readChecked<scalar>(valueEntry, len, singleValueOnly)
241 || readChecked<vector>(valueEntry, len, singleValueOnly)
242 || readChecked<tensor>(valueEntry, len, singleValueOnly)
243 || readChecked<symmTensor>(valueEntry, len, singleValueOnly)
244 || readChecked<sphericalTensor>(valueEntry, len, singleValueOnly)
245 || readChecked<bool>(valueEntry, len, singleValueOnly)
246 );
247
248 if (!ok)
249 {
250 if (valType_.empty())
251 {
252 // For error message only
253 valType_ = "none";
254 }
255
257 << "Do not know how to read data type " << valueType()
258 << (singleValueOnly ? " as a single value." : ".") << nl
259 << exit(FatalIOError);
260 }
261 }
262 else if (valueReqd)
263 {
264 if (valType_.empty())
265 {
266 // For error message only
267 valType_ = "none";
268 }
269
271 << "No entry 'value' defined for data type " << valueType() << nl
272 << exit(FatalIOError);
273 }
274}
275
276
279(
280 const dictionary& dict
281)
282{
283 const word resultType
284 (
285 dict.getOrDefault<word>("resultType", "exprResult")
286 );
287
288 if (dict.getOrDefault("unsetValue", false))
289 {
290 auto* ctorPtr = emptyConstructorTable(resultType);
291
292 if (!ctorPtr)
293 {
295 (
296 dict,
297 "resultType",
298 resultType,
299 *emptyConstructorTablePtr_
300 ) << exit(FatalIOError);
301 }
302
304 << "Creating unset result of type " << resultType << nl;
305
306 return autoPtr<exprResult>(ctorPtr());
307 }
308
309
310 auto* ctorPtr = dictionaryConstructorTable(resultType);
311
312 if (!ctorPtr)
313 {
315 (
316 dict,
317 "resultType",
318 resultType,
319 *dictionaryConstructorTablePtr_
320 ) << exit(FatalIOError);
321 }
322
324 << "Creating result of type " << resultType << nl;
325
326 return autoPtr<exprResult>(ctorPtr(dict));
327}
328
329
332(
333 Istream& is
334)
335{
337 return New(dict);
338}
339
340
341// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
342
344{
347 destroy();
348}
349
350
351// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
354{
355 clear();
356}
357
358
360{
361 if (force || !noReset_ || needsReset_)
362 {
363 this->resetImpl();
364 return true;
365 }
366
367 return false;
368}
369
370
372{
373 destroy();
374 valType_.clear();
375 size_ = 0;
376}
377
378
379// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
380
381void Foam::expressions::exprResult::destroy()
382{
383 if (fieldPtr_)
384 {
385 const bool ok =
386 (
387 deleteChecked<scalar>()
388 || deleteChecked<vector>()
389 || deleteChecked<tensor>()
390 || deleteChecked<symmTensor>()
391 || deleteChecked<sphericalTensor>()
392 || deleteChecked<bool>()
393 );
394
395 if (!ok)
396 {
398 << "Unknown type " << valueType()
399 << " probable memory loss" << nl
400 << exit(FatalError);
401 }
402
403 fieldPtr_ = nullptr;
404 size_ = 0;
405 }
406}
407
408
411(
412 const label size,
413 const bool noWarn,
414 const bool parRun
415) const
416{
417 if (fieldPtr_ == nullptr)
418 {
420 << "Not set. Cannot construct uniform value" << nl
421 << exit(FatalError);
422 }
423
424 exprResult ret;
425
426 const bool ok =
427 (
428 getUniformChecked<scalar>(ret, size, noWarn, parRun)
429 || getUniformChecked<vector>(ret, size, noWarn, parRun)
430 || getUniformChecked<tensor>(ret, size, noWarn, parRun)
431 || getUniformChecked<symmTensor>(ret, size, noWarn, parRun)
432 || getUniformChecked<sphericalTensor>(ret, size, noWarn, parRun)
433 );
434
435 if (!ok)
436 {
438 << "Cannot get uniform value for type "
439 << valueType() << nl
441 }
442
443 return ret;
444}
445
446
448{
449 if (fieldPtr_ == nullptr)
450 {
452 << "Not set - cannot determine if uniform" << nl << endl;
453 return;
454 }
455
456 const bool ok =
457 (
458 setAverageValueChecked<scalar>(parRun)
459 || setAverageValueChecked<vector>(parRun)
460 || setAverageValueChecked<tensor>(parRun)
461 || setAverageValueChecked<symmTensor>(parRun)
462 || setAverageValueChecked<sphericalTensor>(parRun)
463 || setAverageValueCheckedBool(parRun)
464 );
465
466 if (!ok)
469 << "Type " << valueType() << " was not handled" << nl << endl;
470 }
471}
472
473
474void Foam::expressions::exprResult::operator=(const exprResult& rhs)
475{
476 if (this == &rhs)
477 {
478 return; // Self-assignment is a no-op
479 }
480
481 DebugInFunction << "rhs:" << rhs << nl;
482
483 clear();
484
485 valType_ = rhs.valType_;
486 isPointData_ = rhs.isPointData_;
487 value_ = rhs.value_;
488
489 if (rhs.fieldPtr_)
490 {
491 const bool ok =
492 (
493 duplicateFieldChecked<scalar>(rhs.fieldPtr_)
494 || duplicateFieldChecked<vector>(rhs.fieldPtr_)
495 || duplicateFieldChecked<tensor>(rhs.fieldPtr_)
496 || duplicateFieldChecked<symmTensor>(rhs.fieldPtr_)
497 || duplicateFieldChecked<sphericalTensor>(rhs.fieldPtr_)
498 || duplicateFieldChecked<bool>(rhs.fieldPtr_)
499 );
500
501 if (!ok)
502 {
504 << "Type " << valueType() << " could not be copied" << nl
505 << exit(FatalError);
506 }
507 }
508}
509
510
512{
513 if (this == &rhs)
514 {
515 return; // Self-assignment is a no-op
516 }
517
518 clear();
519
520 valType_ = rhs.valType_;
521 isPointData_ = rhs.isPointData_;
522 noReset_ = rhs.noReset_;
523 needsReset_ = rhs.needsReset_;
524 size_ = rhs.size_;
525
526 value_ = rhs.value_;
527 fieldPtr_ = rhs.fieldPtr_;
528
529 rhs.fieldPtr_ = nullptr; // Took ownership of field pointer
530 rhs.clear();
531}
532
533
535(
536 const word& keyword,
537 Ostream& os
538) const
539{
540 const bool ok =
541 (
542 writeEntryChecked<scalar>(keyword, os)
543 || writeEntryChecked<vector>(keyword, os)
544 || writeEntryChecked<tensor>(keyword, os)
545 || writeEntryChecked<symmTensor>(keyword, os)
546 || writeEntryChecked<sphericalTensor>(keyword, os)
547 || writeEntryChecked<bool>(keyword, os)
548 );
549
550 if (!ok)
553 << "Data type " << valueType() << " was not written" << endl;
554 }
555}
556
557
559(
560 Ostream& os,
561 const bool subDict
562) const
563{
564 // const auto oldFmt = os.format(IOstreamOption::ASCII);
565
567 << Foam::name(this) << nl
568 << "Format: "
569 << IOstreamOption::formatNames[os.format()] << nl;
570
571 if (subDict)
572 {
573 os.beginBlock();
574 }
575
576 os.writeEntry("resultType", valueType());
577 os.writeEntryIfDifferent<Switch>("noReset", false, noReset_);
578
579 if (fieldPtr_ == nullptr)
580 {
581 os.writeEntry<Switch>("unsetValue", true);
582 }
583 else
584 {
585 os.writeEntry("valueType", valueType());
586
587 os.writeEntryIfDifferent<Switch>("isPointValue", false, isPointData_);
588 os.writeEntry<Switch>("isSingleValue", value_.good());
589
590 this->writeField(os, "value");
591 }
592
593 if (subDict)
594 {
595 os.endBlock();
596 }
597
598 // os.format(oldFmt);
599}
600
601
603(
604 Ostream& os,
605 const word& keyword
606) const
607{
608 // const auto oldFmt = os.format(IOstreamOption::ASCII);
609
611 << Foam::name(this) << nl
612 << "Format: "
613 << IOstreamOption::formatNames[os.format()] << nl;
614
615 const bool ok =
616 (
617 writeFieldChecked<scalar>(keyword, os)
618 || writeFieldChecked<vector>(keyword, os)
619 || writeFieldChecked<tensor>(keyword, os)
620 || writeFieldChecked<symmTensor>(keyword, os)
621 || writeFieldChecked<sphericalTensor>(keyword, os)
622 || writeFieldChecked<label>(keyword, os)
623 || writeFieldChecked<bool>(keyword, os)
624 );
625
626 if (!ok)
629 << "Data type " << valueType() << " was not written" << endl;
630 }
631}
632
633
635(
636 Ostream& os
637) const
638{
639 // const auto oldFmt = os.format(IOstreamOption::ASCII);
640
642 << Foam::name(this) << nl
643 << "Format: "
644 << IOstreamOption::formatNames[os.format()] << nl;
645
646 const bool ok =
647 (
648 writeSingleValueChecked<scalar>(os)
649 || writeSingleValueChecked<vector>(os)
650 || writeSingleValueChecked<tensor>(os)
651 || writeSingleValueChecked<symmTensor>(os)
652 || writeSingleValueChecked<sphericalTensor>(os)
653 || writeSingleValueChecked<label>(os)
654 || writeSingleValueChecked<bool>(os)
655 );
656
657 if (!ok)
658 {
660 << "Data type " << valueType() << " was not written" << endl;
662}
663
664
665// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
666
668Foam::expressions::exprResult::operator*=
669(
670 const scalar& b
671)
672{
673 if (!fieldPtr_)
674 {
676 << "Can not multiply. Unallocated field of type "
677 << valueType() << nl
678 << exit(FatalError);
679 }
680
681 const bool ok =
682 (
683 multiplyEqChecked<scalar>(b)
684 || multiplyEqChecked<vector>(b)
685 || multiplyEqChecked<tensor>(b)
686 || multiplyEqChecked<symmTensor>(b)
687 || multiplyEqChecked<sphericalTensor>(b)
688 );
689
690 if (!ok)
691 {
693 << "Can not multiply field of type "
694 << valueType() << nl
695 << exit(FatalError);
697
698 return *this;
699}
700
701
703Foam::expressions::exprResult::operator+=
704(
705 const exprResult& b
706)
707{
708 if (!fieldPtr_)
709 {
711 << "Can not add. Unallocated field of type "
712 << valueType() << nl
713 << exit(FatalError);
714 }
715
716 if (this->size() != b.size())
717 {
719 << "Different sizes " << this->size() << " and " << b.size() << nl
720 << exit(FatalError);
721 }
722
723 if (this->valueType() != b.valueType())
724 {
726 << "Different types: "
727 << this->valueType() << " and " << b.valueType() << nl
728 << exit(FatalError);
729 }
730
731 const bool ok =
732 (
733 plusEqChecked<scalar>(b)
734 || plusEqChecked<vector>(b)
735 || plusEqChecked<tensor>(b)
736 || plusEqChecked<symmTensor>(b)
737 || plusEqChecked<sphericalTensor>(b)
738 );
739
740 if (!ok)
741 {
743 << "Can not add Field-type exprResult of type "
744 << valueType() << nl
745 << exit(FatalError);
746 }
748 return *this;
749}
750
751
752// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
753
754Foam::Istream& Foam::operator>>
755(
756 Istream& is,
757 expressions::exprResult& data
758)
759{
760 dictionary dict(is);
763
764 return is;
765}
766
767
768Foam::Ostream& Foam::operator<<
769(
770 Ostream& os,
771 const expressions::exprResult& data
772)
774 data.writeDict(os);
775
776 return os;
777}
778
779
780Foam::expressions::exprResult Foam::operator*
781(
782 const scalar& a,
783 const expressions::exprResult& b
785{
787 return result *= a;
788}
789
790
791Foam::expressions::exprResult Foam::operator*
792(
793 const expressions::exprResult& a,
794 const scalar& b
795)
796{
798 result *= b;
799
800 return result;
801}
802
803
804Foam::expressions::exprResult Foam::operator+
805(
806 const expressions::exprResult& a,
807 const expressions::exprResult& b
808)
809{
811 result += b;
812
813 return result;
814}
815
816
818{
819 #undef defineExpressionMethod
820 #define defineExpressionMethod(Type) \
821 if (isType<Type>()) \
822 { \
823 return static_cast<Field<Type>*>(fieldPtr_)->cdata(); \
824 }
825
831
832 #undef defineExpressionMethod
833
835 << "Unsupported type:" << valueType() << nl
836 << exit(FatalError);
837
838 return nullptr;
839}
840
841
842// ************************************************************************* //
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
Info<< nl;Info<< "Write faMesh in vtk format:"<< nl;{ vtk::uindirectPatchWriter writer(aMesh.patch(), fileName(aMesh.time().globalPath()/vtkBaseFileName));writer.writeGeometry();globalIndex procAddr(aMesh.nFaces());labelList cellIDs;if(UPstream::master()) { cellIDs.resize(procAddr.totalSize());for(const labelRange &range :procAddr.ranges()) { auto slice=cellIDs.slice(range);slice=identity(range);} } writer.beginCellData(4);writer.writeProcIDs();writer.write("cellID", cellIDs);writer.write("area", aMesh.S().field());writer.write("normal", aMesh.faceAreaNormals());writer.beginPointData(1);writer.write("normal", aMesh.pointAreaNormals());Info<< " "<< writer.output().name()<< nl;}{ vtk::lineWriter writer(aMesh.points(), aMesh.edges(), fileName(aMesh.time().globalPath()/(vtkBaseFileName+"-edges")));writer.writeGeometry();writer.beginCellData(4);writer.writeProcIDs();{ Field< scalar > fld(faMeshTools::flattenEdgeField(aMesh.magLe(), true))
static const Enum< streamFormat > formatNames
Stream format names (ascii, binary).
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition Istream.H:60
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition Ostream.H:59
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
Definition Switch.H:81
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
A polymorphic field/result from evaluating an expression.
Definition exprResult.H:122
const word & valueType() const noexcept
Basic type for the field or single value.
void testIfSingleValue(const bool parRun=UPstream::parRun())
Test if field corresponds to a single-value and thus uniform.
Definition exprResult.C:440
void writeDict(Ostream &os, const bool subDict=true) const
Write entry as dictionary contents.
Definition exprResult.C:552
static const exprResult null
An empty result.
Definition exprResult.H:332
virtual void resetImpl()
Reset at new timestep according to the derived class type.
Definition exprResult.C:346
label size() const
The field or object size.
bool isType() const
True if valueType corresponds to the given Type.
exprResult getUniform(const label size, const bool noWarn, const bool parRun=UPstream::parRun()) const
Construct a uniform field from the current results.
Definition exprResult.C:404
void writeValue(Ostream &os) const
Write the single value, or the first value from field.
Definition exprResult.C:628
void writeEntry(const word &keyword, Ostream &os) const
Forwarding to Field::writeEntry.
Definition exprResult.C:528
virtual void operator=(const exprResult &rhs)
Copy assignment.
Definition exprResult.C:467
exprResult()
Default construct.
Definition exprResult.C:173
static autoPtr< exprResult > New(const dictionary &dict)
Return a reference to the selected value driver.
Definition exprResult.C:272
void clear()
Clear (zero) the result.
Definition exprResult.C:364
virtual ~exprResult()
Destructor.
Definition exprResult.C:336
const void * dataAddress() const
The address of the field data content.
Definition exprResult.C:810
bool reset(bool force=false)
Reset at new timestep according to type.
Definition exprResult.C:352
bool hasValue() const
Has a value?
void writeField(Ostream &os, const word &keyword="") const
Write the field, optionally as an entry.
Definition exprResult.C:596
@ LITERAL
String literal.
Definition keyType.H:82
A class for handling words, derived from Foam::string.
Definition word.H:66
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
#define FatalIOErrorInLookup(ios, lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalIOError.
Definition error.H:637
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition error.H:629
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
#define defineExpressionMethod(Type)
OBJstream os(runTime.globalPath()/outputName)
surface1 clear()
#define DebugInfo
Report an information message using Foam::Info.
#define WarningInFunction
Report a warning using Foam::Warning.
#define DebugInFunction
Report an information message using Foam::Info.
bool writeField(ensightOutput::floatBufferType &scratch, ensightFile &os, const Field< Type > &fld, const ensightCells &part, bool parallel)
Write a field of cell values as an indirect list, using the cell ids from ensightCells.
A namespace for expression-related classes/traits etc.
Namespace for OpenFOAM.
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh > > &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
Tensor< scalar > tensor
Definition symmTensor.H:57
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
void reduce(T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce).
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
void rhs(fvMatrix< typename Expr::value_type > &m, const Expr &expression)
bool isType(const U &obj)
Check if typeid of the object and Type are identical.
Definition typeInfo.H:112
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition exprTraits.C:127
Vector< scalar > vector
Definition vector.H:57
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
SphericalTensor< scalar > sphericalTensor
SphericalTensor of scalars, i.e. SphericalTensor<scalar>.
SymmTensor< scalar > symmTensor
SymmTensor of scalars, i.e. SymmTensor<scalar>.
Definition symmTensor.H:55
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
#define defineRunTimeSelectionTable(baseType, argNames)
Define run-time selection table.
dictionary dict
volScalarField & b