Loading...
Searching...
No Matches
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-2024 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 "OTstream.H"
31#include "Fstream.H"
33// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
34
35namespace Foam
36{
38// Compare time values with tolerance
39static const equalOp<scalar> equalTimes(ROOTSMALL);
40
41// Use ListOps findLower (with tolerance), to find the location of the next
42// time-related index.
43// The returned index is always 0 or larger (no negative values).
44static label findTimeIndex(const UList<scalar>& list, const scalar val)
45{
46 label idx =
48 (
49 list,
50 val,
51 0,
52 [](const scalar a, const scalar b)
53 {
54 return (a < b) && (Foam::mag(b - a) > ROOTSMALL);
55 }
56 );
57
58 if (idx < 0 || !equalTimes(list[idx], val))
59 {
60 ++idx;
61 }
62
63 return idx;
65
66} // End namespace Foam
67
68
69// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
70
73 dictName_(cacheFileName)
74{}
75
76
77// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
78
80{
81 const dictionary* dictptr = cache_.findDict("fields", keyType::LITERAL);
82
83 if (!dictptr)
84 {
85 dictptr = &dictionary::null;
86 }
87
88 return *dictptr;
89}
90
91
92Foam::dictionary& Foam::ensightOutput::writerCaching::fieldDict
93(
94 const word& fieldName
95)
96{
97 return
98 cache_
100 .subDictOrAdd(fieldName, keyType::LITERAL);
101}
102
103
104bool Foam::ensightOutput::writerCaching::remove(const word& fieldName)
105{
106 dictionary* dictptr = cache_.findDict("fields", keyType::LITERAL);
107
108 if (dictptr)
109 {
110 return dictptr->remove(fieldName);
111 }
112
113 return false;
114}
115
116
118{
119 times_.clear();
120 geoms_.clear();
121 cache_.clear();
122}
123
124
125// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
126
127Foam::label Foam::ensightOutput::writerCaching::readPreviousTimes
128(
129 const fileName& dictFile,
130 const scalar timeValue
131)
132{
133 // Track the used geometry intervals as a bitSet
134
135 // Note: only called from master
136 label timeIndex = 0;
137 cache_.clear();
138
139 IFstream is(dictFile);
140
141 if (is.good() && cache_.read(is))
142 {
143 geoms_.clear();
144
145 cache_.readIfPresent("times", times_);
146 timeIndex = findTimeIndex(times_, timeValue);
147
148 labelList geomIndices;
149 scalarList meshTimes;
150
151 if (cache_.readIfPresent("geometry", geomIndices))
152 {
153 // Convert indices to bitSet entries
154 geoms_.set(geomIndices);
155 }
156
157 // Make length consistent with time information.
158 // We read/write the indices instead of simply dumping the bitSet.
159 // This makes the contents more human readable.
160 geoms_.resize(times_.size());
161 }
162
163 return timeIndex;
164}
169 return max(0, times_.size()-1);
170}
171
174 return max(0, geoms_.find_last());
175}
176
177
178// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
179
181{
182 if (geoms_.count() <= 1)
183 {
184 // Static
185 return 0;
186 }
187 if (geoms_.size() == times_.size() && geoms_.all())
188 {
189 // Geometry changing is identical to fields changing
190 return 1;
191 }
192
193 // Geometry changing differently from fields
194 return 2;
195}
196
197
198// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
199
201(
202 const fileName& baseDir,
203 const scalar timeValue,
204 const bool geomChanged,
205 const word& fieldName,
206 const string& fieldType, // May contain spaces (eg, "tensor symm")
207 const word& varName
208)
209{
210 const fileName dictFile(baseDir/dictName_);
211
212 bool stateChanged = false;
213
214 const label timeIndex =
215 (
216 times_.empty()
217 ? readPreviousTimes(dictFile, timeValue)
218 : findTimeIndex(times_, timeValue)
219 );
220
221
222 // Update stored times list and geometry index
223
224 if (timeIndex < geoms_.size()-1)
225 {
226 // Clear old content when shrinking
227 geoms_.unset(timeIndex);
228 }
229
230 // Extend or truncate list
231 geoms_.resize(timeIndex+1);
232 times_.resize(timeIndex+1, VGREAT);
233
234 if (!equalTimes(times_[timeIndex], timeValue))
235 {
236 stateChanged = true;
237 times_[timeIndex] = timeValue;
238 }
239
240 if (geomChanged)
241 {
242 stateChanged = true;
243 geoms_.set(timeIndex);
244 }
245
246 // Update time/geometry information in dictionary
247
248 // Note: to avoid inadvertent loss of precision,
249 // generate output tokens for the list of times directly
250 {
251 // Same as: cache_.set("times", times_);
252 OTstream os;
253 os << times_;
254
255 tokenList toks(std::move(os.tokens()));
256 cache_.set(new primitiveEntry("times", std::move(toks)));
257 }
258 cache_.set("geometry", geoms_.sortedToc());
259
260 // Add field information to dictionary
261 dictionary& dict = fieldDict(fieldName);
262
263 if (dict.empty())
264 {
265 stateChanged = true;
266
267 dict.set("type", fieldType);
268 if (!varName.empty() && varName != fieldName)
269 {
270 // Use variable name, if it differs from fieldName
271 dict.set("name", varName);
272 }
273 }
274
275 if (stateChanged)
276 {
277 OFstream os(dictFile);
278 os.precision(16); // increased precision to avoid rounding
279 os << "// State file for writer output" << nl << nl;
280 cache_.write(os, false);
281
282 os << nl << "// End" << nl;
283 }
284
285 return stateChanged;
286}
287
288
289// ************************************************************************* //
Various functions to operate on Lists.
Input from file stream as an ISstream, normally using std::ifstream for the actual input.
Definition IFstream.H:55
void resize(const label len)
Adjust allocated size of list.
Definition ListI.H:153
Output to file stream as an OSstream, normally using std::ofstream for the actual output.
Definition OFstream.H:75
A simple output token stream that can be used to build token lists. Always UNCOMPRESSED.
Definition OTstream.H:56
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:89
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
const dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary pointer if present (and it is a dictionary) otherwise return nullptr...
dictionary & subDictOrAdd(const word &keyword, enum keyType::option matchOpt=keyType::REGEX)
Find and return a sub-dictionary for manipulation.
Definition dictionary.C:481
bool remove(const word &keyword)
Remove an entry specified by keyword.
void clear()
Clear the dictionary.
Definition dictionary.C:862
static const dictionary null
An empty dictionary, which is also the parent for all dictionaries.
Definition dictionary.H:487
label latestTimeIndex() const
The most current time index.
writerCaching(const word &cacheFileName)
Construct with specified cache name.
bool update(const fileName &baseDir, const scalar timeValue, const bool geomChanged, const word &fieldName, const string &fieldType, const word &varName=word::null)
Update time/geometry information and file cache. This routine should only be called from the master p...
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:75
@ LITERAL
String literal.
Definition keyType.H:82
A keyword and a list of tokens comprise a primitiveEntry. A primitiveEntry can be read,...
A class for handling words, derived from Foam::string.
Definition word.H:66
OBJstream os(runTime.globalPath()/outputName)
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:40
List< label > labelList
A List of labels.
Definition List.H:62
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)
Binary search to find the index of the last element in a sorted list that is less than value.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
List< token > tokenList
List of token, used for dictionary primitive entry (for example).
Definition tokenList.H:32
List< scalar > scalarList
List of scalar.
Definition scalarList.H:32
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
label timeIndex
dictionary dict
volScalarField & b