unitConversionIO.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2024 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "unitConversion.H"
27 #include "dictionary.H"
28 #include "symbols.H"
29 
30 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
31 
33 :
34  dimensions_(dimless),
35  multiplier_(NaN)
36 {
37  is >> *this;
38 }
39 
40 
41 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
42 
43 void Foam::unitConversion::read(const word& keyword, const dictionary& dict)
44 {
45  const unitConversion units(dict.lookup(keyword));
46 
47  if (!compare(*this, units, false))
48  {
50  << "The units " << units.info() << " provided do not match "
51  << "the required units " << info()
52  << abort(FatalIOError);
53  }
54 
55  reset(units);
56 }
57 
58 
60 (
61  const word& keyword,
62  const dictionary& dict
63 )
64 {
65  const entry* entryPtr = dict.lookupEntryPtr(keyword, false, true);
66 
67  if (entryPtr)
68  {
69  const unitConversion units(entryPtr->stream());
70 
71  if (!compare(*this, units, false))
72  {
74  << "The units " << units.info() << " provided do not match "
75  << "the required units " << info()
76  << abort(FatalIOError);
77  }
78 
79  reset(units);
80 
81  return true;
82  }
83  else
84  {
86  {
88  << "Optional entry '" << keyword << "' is not present,"
89  << " the default value '" << info() << "' will be used."
90  << endl;
91  }
92 
93  return false;
94  }
95 }
96 
97 
99 {
100  token nextToken(is);
101  is.putBack(nextToken);
102 
103  if (nextToken != token::BEGIN_SQR) return false;
104 
105  unitConversion u(is);
106 
107  if (!unitConversion::compare(u, *this, false))
108  {
110  << "The units " << u.info() << " provided do not match "
111  << "the required units " << info()
112  << abort(FatalIOError);
113  }
114 
115  if (debug && (any() || !unitConversion::compare(u, *this, true)))
116  {
117  Info<< "Unit conversion at line " << is.lineNumber()
118  << " of file " << is.name()
119  << " with factor " << u.multiplier_ << endl;
120  }
121 
122  reset(u);
123 
124  return true;
125 }
126 
127 
129 (
130  const word& keyword,
131  const dictionary& dict,
132  Istream& is
133 )
134 {
135  token nextToken(is);
136  is.putBack(nextToken);
137 
138  if (nextToken != token::BEGIN_SQR) return false;
139 
140  unitConversion u(is);
141 
142  if (!unitConversion::compare(u, *this, false))
143  {
145  << "The units " << u.info() << " of " << keyword
146  << " in dictionary " << dict.name() << " do not match "
147  << "the required units " << info()
148  << abort(FatalIOError);
149  }
150 
151  if (debug && (any() || !unitConversion::compare(u, *this, true)))
152  {
153  Info<< "Unit conversion of " << keyword
154  << " in dictionary " << dict.name()
155  << " with factor " << u.multiplier_ << endl;
156  }
157 
158  reset(u);
159 
160  return true;
161 }
162 
163 
164 // * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * * //
165 
167 {
168  // Read beginning of unitConversion
169  token startToken(is);
170 
171  if (startToken != token::BEGIN_SQR)
172  {
174  << "expected a " << token::BEGIN_SQR << " in unitConversion"
175  << endl << "in stream " << is.info()
176  << exit(FatalIOError);
177  }
178 
179  // Peek at the next token
180  token nextToken(is);
181  is.putBack(nextToken);
182 
183  if (!nextToken.isNumber())
184  {
185  // Named units. Parse.
187  }
188  else
189  {
190  // Read the dimensions
191  units.dimensions_.readNoBegin(is);
192 
193  // Read the dimensionless units if present, or set to zero
194  token nextToken;
195  if (!is.eof())
196  {
197  is >> nextToken;
198  }
199  if (nextToken == token::BEGIN_SQR)
200  {
201  for (int i = 0; i < unitConversion::nDimlessUnits; ++ i)
202  {
203  is >> units.exponents_[i];
204  }
205 
206  // Check end of dimensionless units
207  token endToken(is);
208  if (endToken != token::END_SQR)
209  {
211  << "expected a " << token::END_SQR
212  << " in unitConversion " << endl << "in stream "
213  << is.info() << exit(FatalIOError);
214  }
215 
216  // Read the multiplier if present, or set to unity
217  token nextToken;
218  if (!is.eof())
219  {
220  is >> nextToken;
221  }
222  if (nextToken == token::BEGIN_SQR)
223  {
224  is >> units.multiplier_;
225 
226  // Check end of multiplier
227  token endToken(is);
228  if (endToken != token::END_SQR)
229  {
231  << "expected a " << token::END_SQR
232  << " in unitConversion " << endl << "in stream "
233  << is.info() << exit(FatalIOError);
234  }
235  }
236  else
237  {
238  units.multiplier_ = 1;
239  if (!nextToken.undefined())
240  {
241  is.putBack(nextToken);
242  }
243  }
244  }
245  else
246  {
247  for (int i = 0; i < unitConversion::nDimlessUnits; ++ i)
248  {
249  units.exponents_[i] = 0;
250  }
251  units.multiplier_ = 1;
252  if (!nextToken.undefined())
253  {
254  is.putBack(nextToken);
255  }
256  }
257  }
258 
259  // Check state of Istream
260  is.check("Istream& operator>>(Istream&, unitConversion&)");
261 
262  return is;
263 }
264 
265 
267 {
268  // Write the dimensions
269  os << units.dimensions_;
270 
271  // Determine if any dimensionless units are non-zero
272  bool nonZeroDimlessUnits = false;
273  for (int i = 0; i < unitConversion::nDimlessUnits; ++ i)
274  {
275  nonZeroDimlessUnits =
276  nonZeroDimlessUnits
277  || mag(units.exponents_[i]) > unitConversion::smallExponent;
278  }
279 
280  // Determine if the multiplier is non-unity
281  bool nonUnityMultiplier = units.multiplier_ != 1;
282 
283  // Write the dimensionless units if any are non-zero or we have a
284  // multiplier to write out afterwards
285  if (nonZeroDimlessUnits || nonUnityMultiplier)
286  {
287  os << token::BEGIN_SQR;
288  for (int i = 0; i < unitConversion::nDimlessUnits; ++ i)
289  {
290  if (i) os << token::SPACE;
291  os << units.exponents_[i];
292  }
293  os << token::END_SQR;
294  }
295 
296  // Write the multiplier if it is non-unity
297  if (nonUnityMultiplier)
298  {
299  os << token::BEGIN_SQR << units.multiplier_ << token::END_SQR;
300  }
301 
302  // Check state of Ostream
303  os.check("Ostream& operator<<(Ostream&, const unitConversion&)");
304 
305  return os;
306 }
307 
308 
309 Foam::Ostream& Foam::operator<<
310 (
311  Ostream& os,
312  const InfoProxy<unitConversion>& ip
313 )
314 {
315  const unitConversion& units = ip.t_;
316 
317  // Filter out special cases
318  if (units.any())
319  {
320  return os << token::BEGIN_SQR << "<any>" << token::END_SQR;
321  }
322  if (units.none())
323  {
324  return os << token::BEGIN_SQR << "<none>" << token::END_SQR;
325  }
326 
327  // Write the dimensions
328  os << units.dimensions_.info();
329 
330  // Determine if any dimensionless units are non-zero
331  bool nonZeroDimlessUnits = false;
332  for (int i = 0; i < unitConversion::nDimlessUnits; ++ i)
333  {
334  nonZeroDimlessUnits =
335  nonZeroDimlessUnits
336  || mag(units.exponents_[i]) > unitConversion::smallExponent;
337  }
338 
339  // Determine if the multiplier is non-unity
340  bool nonUnityMultiplier = units.multiplier_ != 1;
341 
342  // Write the dimensionless units if any are non-zero or we have a
343  // multiplier to write out afterwards
344  if (nonZeroDimlessUnits || nonUnityMultiplier)
345  {
346  // Write the dimensionless units
347  os << token::BEGIN_SQR;
348 
349  for (int first=true, i=0; i<unitConversion::nDimlessUnits; i++)
350  {
351  if (mag(units.exponents_[i]) > unitConversion::smallExponent)
352  {
353  if (!first)
354  {
355  os << token::SPACE;
356  }
357 
359  [static_cast<unitConversion::dimlessUnitType>(i)];
360 
361  if (units.exponents_[i] != 1)
362  {
363  os << '^' << units.exponents_[i];
364  }
365 
366  first = false;
367  }
368  }
369 
370  os << token::END_SQR;
371  }
372 
373  // Write the multiplier if it is non-unity
374  if (nonUnityMultiplier)
375  {
376  os << token::BEGIN_SQR << units.multiplier_ << token::END_SQR;
377  }
378 
379  // Check state of Ostream
380  os.check("Ostream& operator<<(Ostream&, const InfoProxy<unitConversion>&)");
381 
382  return os;
383 }
384 
385 
386 // ************************************************************************* //
label lineNumber() const
Return current stream line number.
Definition: IOstream.H:435
virtual bool check(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:92
virtual const fileName & name() const
Return the name of the stream.
Definition: IOstream.H:294
InfoProxy< IOstream > info() const
Return info proxy.
Definition: IOstream.H:528
bool eof() const
Return true if end of input seen.
Definition: IOstream.H:336
A helper class for outputting values to Ostream.
Definition: InfoProxy.H:50
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:60
void putBack(const token &)
Put back token.
Definition: Istream.C:30
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
const fileName & name() const
Return the dictionary name.
Definition: dictionary.H:111
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:162
static bool writeOptionalEntries
If true write optional keywords and values.
Definition: dictionary.H:262
const entry * lookupEntryPtr(const word &, bool recursive, bool patternMatch) const
Find and return an entry data stream pointer if present.
Definition: dictionary.C:548
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:710
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:68
virtual ITstream & stream() const =0
Return token stream if this entry is a primitive entry.
A token holds items read from Istream.
Definition: token.H:73
bool isNumber() const
Definition: tokenI.H:745
@ BEGIN_SQR
Definition: token.H:111
@ END_SQR
Definition: token.H:112
bool undefined() const
Definition: tokenI.H:270
Unit conversion structure. Contains the associated dimensions and the multiplier with which to conver...
bool readIfPresent(const word &keyword, const dictionary &)
Update if found in the dictionary.
static const NamedEnum< dimlessUnitType, 2 > dimlessUnitTypeNames_
Names of the dimensionless units.
static const scalar smallExponent
A small exponent with which to perform inexact comparisons.
unitConversion(const dimensionSet &, const scalar fraction, const scalar angle, const scalar multiplier)
Construct from components.
InfoProxy< unitConversion > info() const
Return info proxy.
void read(const word &keyword, const dictionary &)
Update.
dimlessUnitType
Define an enumeration for the names of the dimensionless unit.
A class for handling words, derived from string.
Definition: word.H:62
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
#define IOInfoInFunction(ios)
Report an IO information message using Foam::Info.
Type parseNoBegin(const label lastPrior, tokeniser &tis, const Type &identity, const HashTable< Type > &table)
Parse tokens into a dimension set or unit conversion, assuming that the '['.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:257
errorManip< error > abort(error &err)
Definition: errorManip.H:131
const dimensionSet dimless
messageStream Info
labelList first(const UList< labelPair > &p)
Definition: patchToPatch.C:39
const HashTable< unitConversion > & units()
Get the table of unit conversions.
Istream & operator>>(Istream &, pistonPointEdgeData &)
dimensioned< scalar > mag(const dimensioned< Type > &)
IOerror FatalIOError
bool any(const boolList &l)
Ostream & operator<<(Ostream &os, const fvConstraints &constraints)
const unitConversion unitless
dictionary dict