ensightWriterCaching.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-2022 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
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
29#include "ListOps.H"
30#include "Fstream.H"
31
32// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
33
34namespace Foam
35{
36
37// Compare time values with tolerance
38static 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).
43static label findTimeIndex(const UList<scalar>& list, const scalar val)
44{
45 label idx =
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
91Foam::dictionary& Foam::ensightOutput::writerCaching::fieldDict
92(
93 const word& fieldName
94)
95{
96 return
97 cache_
99 .subDictOrAdd(fieldName, keyType::LITERAL);
100}
101
102
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
126Foam::label Foam::ensightOutput::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
188{
189 return max(0, times_.size()-1);
190}
191
193{
194 return max(0, geoms_.find_last());
195}
196
197
198// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
199
201{
202 if (geoms_.count() <= 1)
203 {
204 // Static
205 return 0;
206 }
207 if (geoms_.size() == times_.size() && geoms_.all())
208 {
209 // Geometry changing is identical to fields changing
210 return 1;
211 }
212
213 // Geometry changing differently from fields
214 return 2;
215}
216
217
218// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
219
221(
222 const fileName& baseDir,
223 const scalar timeValue,
224 const bool geomChanged,
225 const word& fieldName,
226 const word& fieldType,
227 const word& varName
228)
229{
230 const fileName dictFile(baseDir/dictName_);
231
232 bool stateChanged = false;
233
234 const label timeIndex =
235 (
236 times_.empty()
237 ? readPreviousTimes(dictFile, timeValue)
238 : findTimeIndex(times_, timeValue)
239 );
240
241
242 // Update stored times list and geometry index
243
244 if (timeIndex < geoms_.size()-1)
245 {
246 // Clear old content when shrinking
247 geoms_.unset(timeIndex);
248 }
249
250 // Extend or truncate list
251 geoms_.resize(timeIndex+1);
252 times_.resize(timeIndex+1, VGREAT);
253
254 if (!equalTimes(times_[timeIndex], timeValue))
255 {
256 stateChanged = true;
257 times_[timeIndex] = timeValue;
258 }
259
260 if (geomChanged)
261 {
262 stateChanged = true;
263 geoms_.set(timeIndex);
264 }
265
266
267 // Update time/geometry information in dictionary
268 cache_.set("times", times_);
269 cache_.set("geometry", geoms_.sortedToc());
270
271 // Debugging, or if needed for older versions:
277
278 // Add field information to dictionary
279 dictionary& dict = fieldDict(fieldName);
280
281 if (dict.empty())
282 {
283 stateChanged = true;
284
285 dict.set("type", fieldType);
286 if (!varName.empty() && varName != fieldName)
287 {
288 // Use variable name, if it differs from fieldName
289 dict.set("name", varName);
290 }
291 }
292
293 if (stateChanged)
294 {
295 OFstream os(dictFile);
296 os << "// State file for writer output" << nl << nl;
297 cache_.write(os, false);
298
299 os << nl << "// End" << nl;
300 }
301
302 return stateChanged;
303}
304
305
306// ************************************************************************* //
Various functions to operate on Lists.
Input from file stream, using an ISstream.
Definition: IFstream.H:57
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:330
Output to file stream, using an OSstream.
Definition: OFstream.H:57
unsigned int remove()
Remove and return the last element.
Definition: PackedListI.H:709
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: UList.H:94
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX)
Find and return a sub-dictionary pointer if present.
Definition: dictionaryI.H:127
dictionary & subDictOrAdd(const word &keyword, enum keyType::option matchOpt=keyType::REGEX)
Find and return a sub-dictionary for manipulation.
Definition: dictionary.C:500
bool remove(const word &keyword)
Remove an entry specified by keyword.
static const dictionary null
An empty dictionary, which is also the parent for all dictionaries.
Definition: dictionary.H:394
State information for writers with collated times.
label latestTimeIndex() const
The most current time index.
label latestGeomIndex() const
The most current geometry index.
int geometryTimeset() const
Expected timeset for the geometry.
const dictionary & fieldsDict() const
Get or create the 'fields' information dictionary.
A class for handling file names.
Definition: fileName.H:76
virtual bool update()
Update the mesh for both mesh motion and topology change.
@ LITERAL
String literal.
Definition: keyType.H:81
A class for handling words, derived from Foam::string.
Definition: word.H:68
OBJstream os(runTime.globalPath()/outputName)
#define WarningInFunction
Report a warning using Foam::Warning.
Namespace for OpenFOAM.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
static const equalOp< scalar > equalTimes(ROOTSMALL)
static label findTimeIndex(const UList< scalar > &list, const scalar val)
label findLower(const ListType &input, const T &val, const label start, const ComparePredicate &comp)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
label timeIndex
Definition: getTimeIndex.H:30
dictionary dict
volScalarField & b
Definition: createFields.H:27