surfaceWriterCaching.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) 2016-2020 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "surfaceWriterCaching.H"
29 #include "ListOps.H"
30 #include "Fstream.H"
31 
32 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
33 
34 namespace Foam
35 {
36 
37 // Compare time values with tolerance
38 static const equalOp<scalar> equalTimes(ROOTSMALL);
39 
40 // Use ListOps findLower (with tolerance), to find the location of the next
41 // time-related index.
42 // The returned index is always 0 or larger (no negative values).
43 static label findTimeIndex(const UList<scalar>& list, const scalar val)
44 {
45  label idx =
46  findLower
47  (
48  list,
49  val,
50  0,
51  [](const scalar a, const scalar b)
52  {
53  return (a < b) && (Foam::mag(b - a) > ROOTSMALL);
54  }
55  );
56 
57  if (idx < 0 || !equalTimes(list[idx], val))
58  {
59  ++idx;
60  }
61 
62  return idx;
63 }
64 
65 } // End namespace Foam
66 
67 
68 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
69 
71 :
72  dictName_(cacheFileName)
73 {}
74 
75 
76 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
77 
79 {
80  const dictionary* dictptr = cache_.findDict("fields", keyType::LITERAL);
81 
82  if (!dictptr)
83  {
84  dictptr = &dictionary::null;
85  }
86 
87  return *dictptr;
88 }
89 
90 
91 Foam::dictionary& Foam::surfaceWriters::writerCaching::fieldDict
92 (
93  const word& fieldName
94 )
95 {
96  return
97  cache_
98  .subDictOrAdd("fields", keyType::LITERAL)
99  .subDictOrAdd(fieldName, keyType::LITERAL);
100 }
101 
102 
103 bool Foam::surfaceWriters::writerCaching::remove(const word& fieldName)
104 {
105  dictionary* dictptr = cache_.findDict("fields", keyType::LITERAL);
106 
107  if (dictptr)
108  {
109  return dictptr->remove(fieldName);
110  }
111 
112  return false;
113 }
114 
115 
117 {
118  times_.clear();
119  geoms_.clear();
120  cache_.clear();
121 }
122 
123 
124 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
125 
126 Foam::label Foam::surfaceWriters::writerCaching::readPreviousTimes
127 (
128  const fileName& dictFile,
129  const scalar timeValue
130 )
131 {
132  // In 1906 and earlier, the fieldsDict contained "meshes" and "times"
133  // entries, each with their own time values.
134  // This makes it more difficult to define the exact correspondence
135  // between geometry intervals and times.
136  //
137  // Now track the used geometry intervals as a bitSet.
138 
139 
140  // Only called from master
141  label timeIndex = 0;
142  cache_.clear();
143 
144  IFstream is(dictFile);
145 
146  if (is.good() && cache_.read(is))
147  {
148  geoms_.clear();
149 
150  cache_.readIfPresent("times", times_);
151  timeIndex = findTimeIndex(times_, timeValue);
152 
153  labelList geomIndices;
154  scalarList meshTimes;
155 
156  if (cache_.readIfPresent("geometry", geomIndices))
157  {
158  // Convert indices to bitSet entries
159  geoms_.set(geomIndices);
160  }
161  else if (cache_.readIfPresent("meshes", meshTimes))
162  {
164  << nl
165  << "Setting geometry timeset information from time values"
166  << " (cache from an older OpenFOAM version)." << nl
167  << "This may not be fully reliable." << nl
168  << nl;
169 
170  for (const scalar meshTime : meshTimes)
171  {
172  const label geomIndex = findTimeIndex(times_, meshTime);
173  geoms_.set(geomIndex);
174  }
175  }
176 
177  // Make length consistent with time information.
178  // We read/write the indices instead of simply dumping the bitSet.
179  // This makes the contents more human readable.
180  geoms_.resize(times_.size());
181  }
182 
183  return timeIndex;
184 }
185 
186 
187 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
188 
190 (
191  const fileName& baseDir,
192  const scalar timeValue,
193  const bool geomChanged,
194  const word& fieldName,
195  const word& fieldType,
196  const word& varName
197 )
198 {
199  const fileName dictFile(baseDir/dictName_);
200 
201  bool stateChanged = false;
202 
203  const label timeIndex =
204  (
205  times_.empty()
206  ? readPreviousTimes(dictFile, timeValue)
207  : findTimeIndex(times_, timeValue)
208  );
209 
210 
211  // Update stored times list and geometry index
212 
213  if (timeIndex < geoms_.size()-1)
214  {
215  // Clear old content when shrinking
216  geoms_.unset(timeIndex);
217  }
218 
219  // Extend or truncate list
220  geoms_.resize(timeIndex+1);
221  times_.resize(timeIndex+1, VGREAT);
222 
223  if (!equalTimes(times_[timeIndex], timeValue))
224  {
225  stateChanged = true;
226  times_[timeIndex] = timeValue;
227  }
228 
229  if (geomChanged)
230  {
231  stateChanged = true;
232  geoms_.set(timeIndex);
233  }
234 
235 
236  // Update time/geometry information in dictionary
237  cache_.set("times", times_);
238  cache_.set("geometry", geoms_.sortedToc());
239 
240  // Debugging, or if needed for older versions:
246 
247  // Add field information to dictionary
248  dictionary& dict = fieldDict(fieldName);
249 
250  if (dict.empty())
251  {
252  stateChanged = true;
253 
254  dict.set("type", fieldType);
255  if (!varName.empty() && varName != fieldName)
256  {
257  // Use variable name, if it differs from fieldName
258  dict.set("name", varName);
259  }
260  }
261 
262  if (stateChanged)
263  {
264  OFstream os(dictFile);
265  os << "// State file for surface writer output" << nl << nl;
266  cache_.write(os, false);
267 
268  os << nl << "// End" << nl;
269  }
270 
271  return stateChanged;
272 }
273 
274 
275 // ************************************************************************* //
Foam::dictionary::findDict
dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX)
Find and return a sub-dictionary pointer if present.
Definition: dictionaryI.H:127
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::fileName
A class for handling file names.
Definition: fileName.H:73
Foam::IFstream
Input from file stream, using an ISstream.
Definition: IFstream.H:53
Foam::surfaceWriters::writerCaching::fieldsDict
const dictionary & fieldsDict() const
Get or create the 'fields' information dictionary.
Definition: surfaceWriterCaching.C:78
Foam::dictionary::subDictOrAdd
dictionary & subDictOrAdd(const word &keyword, enum keyType::option matchOpt=keyType::REGEX)
Find and return a sub-dictionary for manipulation.
Definition: dictionary.C:500
Foam::dictionary::null
static const dictionary null
An empty dictionary, which is also the parent for all dictionaries.
Definition: dictionary.H:392
Foam::constant::physicoChemical::b
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:27
Foam::findLower
label findLower(const ListType &input, const T &val, const label start, const ComparePredicate &comp)
Foam::equalTimes
static const equalOp< scalar > equalTimes(ROOTSMALL)
Foam::surfaceWriters::writerCaching::clear
void clear()
Clear all values.
Definition: surfaceWriterCaching.C:116
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::surfaceWriters::writerCaching::update
bool update(const fileName &baseDir, const scalar timeValue, const bool geomChanged, const word &fieldName, const word &fieldType, const word &varName=word::null)
Definition: surfaceWriterCaching.C:190
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
os
OBJstream os(runTime.globalPath()/outputName)
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::OFstream
Output to file stream, using an OSstream.
Definition: OFstream.H:53
Foam::findTimeIndex
static label findTimeIndex(const UList< scalar > &list, const scalar val)
Definition: surfaceWriterCaching.C:43
surfaceWriterCaching.H
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Fstream.H
Foam::dictionary::remove
bool remove(const word &keyword)
Remove an entry specified by keyword.
Definition: dictionarySearch.C:582
Foam::List< label >
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::UList
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:103
Foam::List::set
std::enable_if< std::is_same< bool, TypeT >::value, bool >::type set(const label i, bool val=true)
A bitSet::set() method for a list of bool.
Definition: List.H:341
timeIndex
label timeIndex
Definition: getTimeIndex.H:30
ListOps.H
Various functions to operate on Lists.
Foam::keyType::LITERAL
String literal.
Definition: keyType.H:81
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
Foam::surfaceWriters::writerCaching::writerCaching
writerCaching(const word &cacheFileName)
Construct with specified cache name.
Definition: surfaceWriterCaching.C:70