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-2021 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"
36
37// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38
39namespace Foam
40{
41namespace expressions
42{
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 isUniform_ = true;
94 single_.set(false);
95 return true;
96 }
97
98 if (parRun)
99 {
100 reduce(len, sumOp<label>());
101 }
102
103 if (nTrue == len)
104 {
105 isUniform_ = true;
106 single_.set(true);
107 }
108 else
109 {
110 isUniform_ = false;
111
112 if (nTrue > len/2)
113 {
114 single_.set(true);
115 }
116 else
117 {
118 single_.set(false);
119 }
120 }
121
122 return true;
123}
124
125
126bool Foam::expressions::exprResult::getUniformCheckedBool
127(
128 exprResult& result,
129 const label size,
130 const bool noWarn,
131 const bool parRun
132) const
133{
134 typedef bool Type;
135
136 if (!isType<Type>())
137 {
138 return false;
139 }
140
141 result.clear();
142
143 const Field<Type>& fld = *static_cast<const Field<Type>*>(fieldPtr_);
144 label len = fld.size();
145
146 // The average of a bool is slightly dodgy
147
148 label nTrue = 0;
149 for (const Type val : fld)
150 {
151 if (val)
152 {
153 ++nTrue;
154 }
155 }
156
157 if (parRun)
158 {
159 reduce(nTrue, sumOp<label>());
160 reduce(len, sumOp<label>());
161 }
162
163 const Type avg = (nTrue > len/2);
164
165 if (!noWarn)
166 {
167 // TODO?
168 }
169
170 result.setResult<Type>(avg, size);
171
172 return true;
173}
174
175
176// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
177
178Foam::expressions::exprResult::singleValue::singleValue()
179{
180 std::memset(static_cast<void*>(this), '\0', sizeof(*this));
181}
182
183
184Foam::expressions::exprResult::singleValue::singleValue
185(
186 const singleValue& val
187)
188{
189 std::memcpy(static_cast<void*>(this), &val, sizeof(*this));
190}
191
192
194(
195 const singleValue& val
196)
197{
198 if (this != &val)
199 {
200 // Self-assignment is a no-op
201 std::memcpy(static_cast<void*>(this), &val, sizeof(*this));
202 }
203}
204
205
207:
208 refCount(),
209 valType_(),
210 isUniform_(false),
211 isPointData_(false),
212 noReset_(false),
213 needsReset_(false),
214 size_(0),
215 single_(),
216 fieldPtr_(nullptr)
217{
218 clear();
219}
220
221
223:
224 exprResult()
225{
226 this->operator=(rhs);
227}
228
229
231:
232 exprResult()
233{
234 this->operator=(std::move(rhs));
235}
236
237
239(
240 const dictionary& dict,
241 bool uniform,
242 bool needsValue
243)
244:
245 refCount(),
246 valType_(dict.getOrDefault<word>("valueType", "")),
247 isUniform_(dict.getOrDefault("isSingleValue", uniform)),
248 isPointData_(dict.getOrDefault("isPointValue", false)),
249 noReset_(dict.getOrDefault("noReset", false)),
250 needsReset_(false),
251 size_(0),
252 single_(),
253 fieldPtr_(nullptr)
254{
256
257 if (dict.found("value"))
258 {
259 const bool uniform = isUniform_;
260
261 const label len =
262 (
263 uniform
264 ? dict.getOrDefault<label>("fieldSize", 1)
265 : dict.get<label>("fieldSize")
266 );
267
268 const bool ok =
269 (
270 // Just use <scalar> for <label>?
271 readChecked<scalar>("value", dict, len, uniform)
272 || readChecked<vector>("value", dict, len, uniform)
273 || readChecked<tensor>("value", dict, len, uniform)
274 || readChecked<symmTensor>("value", dict, len, uniform)
275 || readChecked<sphericalTensor>("value", dict, len, uniform)
276 || readChecked<bool>("value", dict, len, uniform)
277 );
278
279 if (!ok)
280 {
281 if (valType_.empty())
282 {
283 // For error message only
284 valType_ = "none";
285 }
286
288 << "Do not know how to read data type " << valType_
289 << (uniform ? " as a single value." : ".") << nl
290 << exit(FatalIOError);
291 }
292 }
293 else if (needsValue)
294 {
296 << "No entry 'value' defined" << nl
297 << exit(FatalIOError);
298 }
299}
300
301
304(
305 const dictionary& dict
306)
307{
308 const word resultType
309 (
310 dict.getOrDefault<word>("resultType", "exprResult")
311 );
312
313 if (dict.getOrDefault("unsetValue", false))
314 {
315 auto* ctorPtr = emptyConstructorTable(resultType);
316
317 if (!ctorPtr)
318 {
320 (
321 dict,
322 "resultType",
323 resultType,
324 *emptyConstructorTablePtr_
325 ) << exit(FatalIOError);
326 }
327
329 << "Creating unset result of type " << resultType << nl;
330
331 return autoPtr<exprResult>(ctorPtr());
332 }
333
334
335 auto* ctorPtr = dictionaryConstructorTable(resultType);
336
337 if (!ctorPtr)
338 {
340 (
341 dict,
342 "resultType",
343 resultType,
344 *dictionaryConstructorTablePtr_
345 ) << exit(FatalIOError);
346 }
347
349 << "Creating result of type " << resultType << nl;
350
351 return autoPtr<exprResult>(ctorPtr(dict));
352}
353
354
357(
358 Istream& is
359)
360{
361 dictionary dict(is);
362 return New(dict);
363}
364
365
366// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
367
369{
371
372 uglyDelete();
373}
374
375
376// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
377
379{
380 clear();
381}
382
383
385{
386 if (force || !noReset_ || needsReset_)
387 {
388 this->resetImpl();
389 return true;
390 }
391
392 return false;
393}
394
395
397{
398 uglyDelete();
399 valType_.clear();
400 size_ = 0;
401}
402
403
404// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
405
406void Foam::expressions::exprResult::uglyDelete()
407{
408 if (fieldPtr_)
409 {
410 const bool ok =
411 (
412 deleteChecked<scalar>()
413 || deleteChecked<vector>()
414 || deleteChecked<tensor>()
415 || deleteChecked<symmTensor>()
416 || deleteChecked<sphericalTensor>()
417 || deleteChecked<bool>()
418 );
419
420 if (!ok)
421 {
423 << "Unknown type " << valType_
424 << " probable memory loss" << nl
425 << exit(FatalError);
426 }
427
428 fieldPtr_ = nullptr;
429 size_ = 0;
430 }
431}
432
433
436(
437 const label size,
438 const bool noWarn,
439 const bool parRun
440) const
441{
442 if (fieldPtr_ == nullptr)
443 {
445 << "Not set. Cannot construct uniform value" << nl
446 << exit(FatalError);
447 }
448
449 exprResult ret;
450
451 const bool ok =
452 (
453 getUniformChecked<scalar>(ret, size, noWarn, parRun)
454 || getUniformChecked<vector>(ret, size, noWarn, parRun)
455 || getUniformChecked<tensor>(ret, size, noWarn, parRun)
456 || getUniformChecked<symmTensor>(ret, size, noWarn, parRun)
457 || getUniformChecked<sphericalTensor>(ret, size, noWarn, parRun)
458 );
459
460 if (!ok)
461 {
463 << "Cannot get uniform value for type " << valType_ << nl
464 << exit(FatalError);
465 }
466
467 return ret;
468}
469
470
472{
473 if (fieldPtr_ == nullptr)
474 {
476 << "Not set - cannot determine if uniform" << nl << endl;
477 return;
478 }
479
480 const bool ok =
481 (
482 setAverageValueChecked<scalar>(parRun)
483 || setAverageValueChecked<vector>(parRun)
484 || setAverageValueChecked<tensor>(parRun)
485 || setAverageValueChecked<symmTensor>(parRun)
486 || setAverageValueChecked<sphericalTensor>(parRun)
487 || setAverageValueCheckedBool(parRun)
488 );
489
490 if (!ok)
491 {
493 << "Unknown type " << valType_ << nl << endl;
494 }
495}
496
497
499{
500 if (this == &rhs)
501 {
502 return; // Self-assignment is a no-op
503 }
504
505 DebugInFunction << "rhs:" << rhs << nl;
506
507 clear();
508
509 valType_ = rhs.valType_;
510 isUniform_ = rhs.isUniform_;
511 isPointData_ = rhs.isPointData_;
512 single_ = rhs.single_;
513
514 if (rhs.fieldPtr_)
515 {
516 const bool ok =
517 (
518 duplicateFieldChecked<scalar>(rhs.fieldPtr_)
519 || duplicateFieldChecked<vector>(rhs.fieldPtr_)
520 || duplicateFieldChecked<tensor>(rhs.fieldPtr_)
521 || duplicateFieldChecked<symmTensor>(rhs.fieldPtr_)
522 || duplicateFieldChecked<sphericalTensor>(rhs.fieldPtr_)
523 || duplicateFieldChecked<bool>(rhs.fieldPtr_)
524 );
525
526 if (!ok)
527 {
529 << " Type " << valType_ << " can not be copied" << nl
530 << exit(FatalError);
531 }
532 }
533}
534
535
537{
538 if (this == &rhs)
539 {
540 return; // Self-assignment is a no-op
541 }
542
543 clear();
544
545 valType_ = rhs.valType_;
546 isUniform_ = rhs.isUniform_;
547 isPointData_ = rhs.isPointData_;
548 noReset_ = rhs.noReset_;
549 needsReset_ = rhs.needsReset_;
550 size_ = rhs.size_;
551
552 single_ = rhs.single_;
553 fieldPtr_ = rhs.fieldPtr_;
554
555 rhs.fieldPtr_ = nullptr; // Took ownership of field pointer
556 rhs.clear();
557}
558
559
561(
562 const word& keyword,
563 Ostream& os
564) const
565{
566 const bool ok =
567 (
568 writeEntryChecked<scalar>(keyword, os)
569 || writeEntryChecked<vector>(keyword, os)
570 || writeEntryChecked<tensor>(keyword, os)
571 || writeEntryChecked<symmTensor>(keyword, os)
572 || writeEntryChecked<sphericalTensor>(keyword, os)
573 || writeEntryChecked<bool>(keyword, os)
574 );
575
576 if (!ok)
577 {
579 << "Unknown data type " << valType_ << endl;
580 }
581}
582
583
585(
586 Ostream& os,
587 const bool subDict
588) const
589{
590 // const auto oldFmt = os.format(IOstream::ASCII);
591
593 << Foam::name(this) << nl
594 << "Format: "
595 << IOstreamOption::formatNames[os.format()] << nl;
596
597 if (subDict)
598 {
599 os.beginBlock();
600 }
601
602 os.writeEntry("resultType", valueType());
603 os.writeEntryIfDifferent<Switch>("noReset", false, noReset_);
604
605 if (fieldPtr_ == nullptr)
606 {
607 os.writeEntry<Switch>("unsetValue", true);
608 }
609 else
610 {
611 os.writeEntry("valueType", valType_);
612
613 os.writeEntryIfDifferent<Switch>("isPointValue", false, isPointData_);
614 os.writeEntry<Switch>("isSingleValue", isUniform_);
615
616 this->writeField(os, "value");
617 }
618
619 if (subDict)
620 {
621 os.endBlock();
622 }
623
624 // os.format(oldFmt);
625}
626
627
629(
630 Ostream& os,
631 const word& keyword
632) const
633{
634 // const auto oldFmt = os.format(IOstream::ASCII);
635
637 << Foam::name(this) << nl
638 << "Format: "
639 << IOstreamOption::formatNames[os.format()] << nl;
640
641 const bool ok =
642 (
643 writeFieldChecked<scalar>(keyword, os)
644 || writeFieldChecked<vector>(keyword, os)
645 || writeFieldChecked<tensor>(keyword, os)
646 || writeFieldChecked<symmTensor>(keyword, os)
647 || writeFieldChecked<sphericalTensor>(keyword, os)
648 || writeFieldChecked<label>(keyword, os)
649 || writeFieldChecked<bool>(keyword, os)
650 );
651
652 if (!ok)
653 {
655 << "Unknown data type " << valType_ << endl;
656 }
657}
658
659
661(
662 Ostream& os
663) const
664{
665 // const auto oldFmt = os.format(IOstream::ASCII);
666
668 << Foam::name(this) << nl
669 << "Format: "
670 << IOstreamOption::formatNames[os.format()] << nl;
671
672 const bool ok =
673 (
674 writeSingleValueChecked<scalar>(os)
675 || writeSingleValueChecked<vector>(os)
676 || writeSingleValueChecked<tensor>(os)
677 || writeSingleValueChecked<symmTensor>(os)
678 || writeSingleValueChecked<sphericalTensor>(os)
679 || writeSingleValueChecked<label>(os)
680 || writeSingleValueChecked<bool>(os)
681 );
682
683 if (!ok)
684 {
686 << "Unknown data type " << valType_ << endl;
687 }
688}
689
690
691// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
692
695(
696 const scalar& b
697)
698{
699 if (!fieldPtr_)
700 {
702 << "Can not multiply. Unallocated field of type" << valType_ << nl
703 << exit(FatalError);
704 }
705
706 const bool ok =
707 (
708 multiplyEqChecked<scalar>(b)
709 || multiplyEqChecked<vector>(b)
710 || multiplyEqChecked<tensor>(b)
711 || multiplyEqChecked<symmTensor>(b)
712 || multiplyEqChecked<sphericalTensor>(b)
713 );
714
715 if (!ok)
716 {
718 << "Can not multiply field of type "
719 << valType_ << nl
720 << exit(FatalError);
721 }
722
723 return *this;
724}
725
726
729(
730 const exprResult& b
731)
732{
733 if (!fieldPtr_)
734 {
736 << "Can not add. Unallocated field of type " << valType_ << nl
737 << exit(FatalError);
738 }
739
740 if (this->size() != b.size())
741 {
743 << "Different sizes " << this->size() << " and " << b.size() << nl
744 << exit(FatalError);
745 }
746
747 const bool ok =
748 (
749 plusEqChecked<scalar>(b)
750 || plusEqChecked<vector>(b)
751 || plusEqChecked<tensor>(b)
752 || plusEqChecked<symmTensor>(b)
753 || plusEqChecked<sphericalTensor>(b)
754 );
755
756 if (!ok)
757 {
759 << "Can not add Field-type exprResult of type"
760 << valType_ << nl
761 << exit(FatalError);
762 }
763
764 return *this;
765}
766
767
768// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
769
770Foam::Istream& Foam::operator>>
771(
772 Istream& is,
774)
775{
776 dictionary dict(is);
777
779
780 return is;
781}
782
783
784Foam::Ostream& Foam::operator<<
785(
786 Ostream& os,
788)
789{
790 data.writeDict(os);
791
792 return os;
793}
794
795
797(
798 const scalar& a,
800)
801{
803 return result *= a;
804}
805
806
808(
810 const scalar& b
811)
812{
813 expressions::exprResult result(a);
814 result *= b;
815
816 return result;
817}
818
819
821(
824)
825{
826 expressions::exprResult result(a);
827 result += b;
828
829 return result;
830}
831
832
834{
835 #undef defineExpressionMethod
836 #define defineExpressionMethod(Type) \
837 if (isType<Type>()) \
838 { \
839 return static_cast<Field<Type>*>(fieldPtr_)->cdata(); \
840 }
841
847
848 #undef defineExpressionMethod
849
851 << "Unsupported type" << valType_ << nl
852 << exit(FatalError);
853
854 return nullptr;
855}
856
857
858// ************************************************************************* //
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<< "Wrote faMesh in vtk format: "<< writer.output().name()<< nl;}{ vtk::lineWriter writer(aMesh.points(), aMesh.edges(), fileName(aMesh.mesh().time().globalPath()/"finiteArea-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:64
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:62
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
Definition: Switch.H:78
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
Definition: Time.C:717
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
Database for solution data, solver performance and other reduced data.
Definition: data.H:58
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Search for an entry (const access) with the given keyword.
Definition: dictionaryI.H:87
void reset()
Reset to defaults.
A polymorphic field/result from evaluating an expression.
Definition: exprResult.H:127
exprResult getUniform(const label size, const bool noWarn, const bool parRun=Pstream::parRun()) const
Construct a uniform field from the current results.
Definition: exprResult.C:436
static const exprResult null
An empty result.
Definition: exprResult.H:318
virtual void resetImpl()
Reset at new timestep according to the derived class type.
Definition: exprResult.C:378
void testIfSingleValue(const bool parRun=Pstream::parRun())
Test if field corresponds to a single-value and thus uniform.
Definition: exprResult.C:471
void writeValue(Ostream &os) const
Write the single value, or the first value from field.
Definition: exprResult.C:661
void writeEntry(const word &keyword, Ostream &os) const
Forwarding to Field::writeEntry.
Definition: exprResult.C:561
virtual void operator=(const exprResult &rhs)
Copy assignment.
Definition: exprResult.C:498
exprResult()
Default construct.
Definition: exprResult.C:206
void clear()
Clear (zero) the result.
Definition: exprResult.C:396
virtual ~exprResult()
Destructor.
Definition: exprResult.C:368
const void * dataAddress() const
The address of the field data content.
Definition: exprResult.C:833
void writeField(Ostream &os, const word &keyword="") const
Write the field, optionally as an entry.
Definition: exprResult.C:629
friend Ostream & operator(Ostream &, const faMatrix< Type > &)
Foam::dictionary writeDict() const
Write to dictionary.
Reference counter for various OpenFOAM components.
Definition: refCount.H:51
A class for handling words, derived from Foam::string.
Definition: word.H:68
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
patchWriters clear()
#define FatalIOErrorInLookup(ios, lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalIOError.
Definition: error.H:478
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
#define defineExpressionMethod(Type)
OBJstream os(runTime.globalPath()/outputName)
#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.
Namespace for OpenFOAM.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
IOerror FatalIOError
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh > > &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
error FatalError
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
#define defineRunTimeSelectionTable(baseType, argNames)
Define run-time selection table.
dictionary dict
volScalarField & b
Definition: createFields.H:27