Loading...
Searching...
No Matches
ccmReaderSolution.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-2021 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
28#include "ccmReader.H"
29#include "ccmInternal.H" // include last to avoid any strange interactions
30
31
32// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
33
34// Get information about available fields.
35// - assume that all fields are available for all solution intervals
36// eg,
37// /FieldSets/FieldSet-1/Phase-1/Fields/Velocity
38// /FieldSets/FieldSet-1/Phase-1/Fields/Pressure
39// ...
40void Foam::ccm::reader::determineFieldInfo
41(
42 const ccmID& fieldSetNode,
43 fieldTable& table
44)
45{
46 char fullName[kCCMIOMaxStringLength + 1];
47 char shortName[kCCMIOProstarShortNameLength+1];
48
49 // Loop through all phases
50 ccmID phaseNode;
51 int phaseI = 0;
52
53 while
54 (
55 CCMIONextEntity
56 (
57 nullptr,
58 fieldSetNode,
59 kCCMIOFieldPhase,
60 &phaseI,
61 &phaseNode
62 )
63 == kCCMIONoErr
64 )
65 {
66 CCMIODimensionality dims;
67
68 // Examine each field in this fieldSet
69 ccmID fieldNode;
70 int fieldI = 0;
71
72 // Get full/short names and dimension (scalar/vector/tensor).
73 // Use short name as unique identifier.
74
75 while
76 (
77 CCMIONextEntity
78 (
79 nullptr,
80 phaseNode,
81 kCCMIOField,
82 &fieldI,
83 &fieldNode
84 )
85 == kCCMIONoErr
86
87 && CCMIOReadField
88 (
89 nullptr,
90 fieldNode,
91 fullName,
92 shortName,
93 &dims,
94 nullptr
95 )
96 == kCCMIONoErr
97 )
98 {
99 // The shortName *should* be a word, but some fields seem
100 // to have blanks!
101 {
102 char *ptr = shortName;
103 while (*ptr)
104 {
105 if (!word::valid(*ptr))
106 {
107 *ptr = '_';
108 }
109 ptr++;
110 }
111 }
112
113 word fieldName(shortName);
114
115 if (dims == kCCMIOScalar)
116 {
117 auto tableIter = table.find(fieldName);
118
119 if (!tableIter.good())
120 {
121 // Add to table as required
122 fieldEntry entry(fieldName, fullName);
123
124 entry.units
125 (
126 ccmReadOptstr("Units", fieldNode)
127 );
128
129 table.push_back(entry);
130
131 tableIter = table.find(fieldName);
132 }
133 fieldEntry& entry = *tableIter;
134
135 // Obtain sizes of data field
136 // - only process cell/face data
137 ccmID dataNode;
138 int dataI = 0;
139
140 CCMIODataLocation dataLocation;
141 CCMIOIndex maxId;
142
143 while
144 (
145 CCMIONextEntity
146 (
147 nullptr,
148 fieldNode,
149 kCCMIOFieldData,
150 &dataI,
151 &dataNode
152 )
153 == kCCMIONoErr
154
155 && CCMIOEntitySize
156 (
157 nullptr,
158 dataNode,
159 nullptr,
160 &maxId
161 )
162 == kCCMIONoErr
163
164 && CCMIOReadFieldDatad
165 (
166 nullptr,
167 dataNode,
168 nullptr,
169 &dataLocation,
170 nullptr,
171 kCCMIOStart,
172 kCCMIOEnd
173 )
174 == kCCMIONoErr
175 )
176 {
177 if (dataLocation == kCCMIOCell)
178 {
179 entry.maxCellId(maxId);
180 }
181 else if (dataLocation == kCCMIOFace)
182 {
183 entry.maxFaceId(maxId);
184 }
185 }
186 }
187 }
188 }
189}
190
191
192// Get information about all available solutions.
193// - it is sufficient to examine the first processor
194//
195// The "States":
196// Restart_1/Processor-1
197// -OR-
198// Transient_1/Processor-1
199// ...
200// Transient_N/Processor-1
201//
202// point to the "FieldSets":
203// FieldSet-1/RestartInfo
204//
205bool Foam::ccm::reader::detectSolution()
206{
207 // call once
208 if (solutionStatus_ != UNKNOWN)
209 {
210 return (solutionStatus_ == OKAY || solutionStatus_ == READ);
211 }
212
213 // loop through all States
214 ccmID stateNode;
215 int stateI = 0;
216 while
217 (
218 CCMIONextEntity
219 (
220 nullptr,
221 (globalState_->root),
222 kCCMIOState,
223 &stateI,
224 &stateNode
225 )
226 == kCCMIONoErr
227 )
228 {
229 // Loop through all processors/solutions
230 ccmID processorNode;
231 ccmID solutionNode;
232 int procI = 0;
233
234 while
235 (
236 CCMIONextEntity
237 (
238 nullptr,
239 stateNode,
240 kCCMIOProcessor,
241 &procI,
242 &processorNode
243 )
244 == kCCMIONoErr
245
246 && CCMIOReadProcessor
247 (
248 nullptr,
249 processorNode,
250 nullptr, // Ignore verticesNode
251 nullptr, // Ignore topologyNode
252 nullptr, // Ignore initialField
253 &solutionNode
254 )
255 == kCCMIONoErr
256 )
257 {
258 // Restrict to solutions with RestartInfo on the first cpu
259 // (there is normally only one set of restart data)
260 ccmID restartNode;
261 int restartI = 0;
262
263 char solutionName[kCCMIOMaxStringLength + 1];
264 int iteration = 0;
265 float timeValue = 0;
266
267 if
268 (
269 CCMIONextEntity
270 (
271 nullptr,
272 solutionNode,
273 kCCMIORestart,
274 &restartI,
275 &restartNode
276 )
277 == kCCMIONoErr
278
279 && CCMIOEntityName
280 (
281 nullptr,
282 stateNode,
283 solutionName
284 )
285 == kCCMIONoErr
286
287 && CCMIOReadRestartInfo
288 (
289 nullptr,
290 restartNode,
291 nullptr, // Ignore solverName
292 &iteration,
293 &timeValue,
294 nullptr, // Ignore timeUnits
295 nullptr // Ignore startAngle
296 )
297 == kCCMIONoErr
298 )
299 {
300 solutionTable_.append
301 (
302 solutionEntry(solutionName, iteration, timeValue)
303 );
304 }
305
306 // Determine field information
307 determineFieldInfo(solutionNode, fieldTable_);
308
309 // check Lagrangian data
310 ccmID lagrangianNode;
311 ccmID lagrangianSolutions;
312 int lagrangianI = 0;
313
314 if
315 (
316 CCMIONextEntity
317 (
318 nullptr,
319 processorNode,
320 kCCMIOLagrangianData,
321 &lagrangianI,
322 &lagrangianNode
323 )
324 == kCCMIONoErr
325
326 && CCMIOReadLagrangianData
327 (
328 nullptr,
329 lagrangianNode,
330 nullptr,
331 &lagrangianSolutions
332 )
333 == kCCMIONoErr
334 )
335 {
336 determineFieldInfo(lagrangianSolutions, lagrangianTable_);
337 }
338 }
339 }
340
341 if (solutionTable_.size() && fieldTable_.size())
342 {
343 solutionStatus_ = OKAY;
344 }
345 else
347 solutionStatus_ = BAD;
348 }
349
350 return (solutionStatus_ == OKAY || solutionStatus_ == READ);
351}
353#define SOLID_STRESS_HACK
354
355//
356// Read solution and field combination
357//
360(
361 const word& solutionName,
362 const word& fieldName,
363 const bool wallData
364)
365{
366 // get State by name
367 ccmID stateNode;
368 ccmID solutionNode;
369
370 if
371 (
372 CCMIOGetState
373 (
374 nullptr,
375 (globalState_->root),
376 solutionName.c_str(),
377 nullptr,
378 &stateNode
379 )
380 != kCCMIONoErr
381 )
382 {
383 return tmp<scalarField>::New();
384 }
385
386 label maxId = 0;
387 CCMIODataLocation requestedLocation = kCCMIOCell;
388
389 const auto tableIter = fieldTable_.find(fieldName);
390
391 if (tableIter.good())
392 {
393 const fieldEntry& entry = *tableIter;
394
395 maxId = entry.maxCellId();
396
397 if (wallData)
398 {
399 maxId = entry.maxFaceId();
400 requestedLocation = kCCMIOFace;
401 }
402 }
403
404 // Can skip empty/unknown fields immediately
405 if (!maxId)
406 {
407 return tmp<scalarField>::New();
408 }
409
410 char shortName[kCCMIOProstarShortNameLength+1];
411
412 List<label> mapData;
413 List<scalar> rawData;
414
415 auto tscalarData = tmp<scalarField>::New(maxId + 1, option().undefScalar());
416 auto& scalarData = tscalarData.ref();
417
418
419 CCMIODimensionality dims;
420
421 // Loop across all processors
422 ccmID processorNode;
423 int procI = 0;
424
425 while
426 (
427 CCMIONextEntity
428 (
429 nullptr,
430 stateNode,
431 kCCMIOProcessor,
432 &procI,
433 &processorNode
434 )
435 == kCCMIONoErr
436
437 && CCMIOReadProcessor
438 (
439 nullptr,
440 processorNode,
441 nullptr, // Ignore verticesNode
442 nullptr, // Ignore topologyNode
443 nullptr, // Ignore initialField
444 &solutionNode
445 )
446 == kCCMIONoErr
447 )
448 {
449 // loop through all phases
450 int phaseI = 0;
451 ccmID phaseNode;
452
453 while
454 (
455 CCMIONextEntity
456 (
457 nullptr,
458 solutionNode,
459 kCCMIOFieldPhase,
460 &phaseI,
461 &phaseNode
462 )
463 == kCCMIONoErr
464 )
465 {
466 // Get Field that matches the name
467 ccmID fieldNode;
468 int fieldI = 0;
469
470 while
471 (
472 CCMIONextEntity
473 (
474 nullptr,
475 phaseNode,
476 kCCMIOField,
477 &fieldI,
478 &fieldNode
479 )
480 == kCCMIONoErr
481 )
482 {
483 // Get full/short names and dimension (scalar/vector/tensor)
484 // use short name as unique identifier
485 CCMIOReadField
486 (
487 &(globalState_->error),
488 fieldNode,
489 nullptr,
490 shortName,
491 &dims,
492 nullptr
493 );
495 (
496 "reading post data field: "
497 + string(shortName)
498 );
499
500 if (fieldName == shortName && dims == kCCMIOScalar)
501 {
502 // Obtain sizes of data field
503 ccmID dataNode;
504 ccmID mapId;
505 int dataI = 0;
506 while
507 (
508 CCMIONextEntity
509 (
510 nullptr,
511 fieldNode,
512 kCCMIOFieldData,
513 &dataI,
514 &dataNode
515 )
516 == kCCMIONoErr
517 )
518 {
519 CCMIODataLocation dataLocation;
520 CCMIOSize n;
521
522 // Only process cell/face data
523 if
524 (
525 CCMIOEntitySize
526 (
527 nullptr,
528 dataNode,
529 &n,
530 nullptr
531 )
532 == kCCMIONoErr
533
534 && CCMIOReadFieldDatad
535 (
536 nullptr,
537 dataNode,
538 &mapId,
539 &dataLocation,
540 nullptr,
541 kCCMIOStart,
542 kCCMIOEnd
543 )
544 == kCCMIONoErr
545
546 && dataLocation == requestedLocation
547 )
548 {
549#ifdef SOLID_STRESS_HACK
550 bool okayCombination = true;
551
552 CCMIOSize len;
553 if
554 (
555 CCMIOEntityDescription
556 (
557 nullptr,
558 dataNode,
559 &len,
560 nullptr
561 )
562 == kCCMIONoErr
563 )
564 {
565 char* dataLabel = new char[len + 1];
566
567 if
568 (
569 CCMIOEntityDescription
570 (
571 nullptr,
572 dataNode,
573 &len,
574 dataLabel
575 )
576 == kCCMIONoErr
577 )
578 {
579 if
580 (
581 (
582 strstr(fieldName.c_str(), "SIG")
583 || strstr(fieldName.c_str(), "EPS")
584 )
585 && strstr(dataLabel, "So") == nullptr
586 )
587 {
588 okayCombination = false;
589 // skip non-solid
590 }
591 }
592
593 delete[] dataLabel;
594 }
595
596 if (!okayCombination)
597 {
598 continue;
599 }
600#endif
601
602 mapData.setSize(n);
603 rawData.setSize(n);
604
605 readMap
606 (
607 mapId,
608 mapData
609 );
610
611 CCMIOReadFieldDatad
612 (
613 &(globalState_->error),
614 dataNode,
615 nullptr,
616 nullptr,
617 rawData.data(),
618 kCCMIOStart,
619 kCCMIOEnd
620 );
622 (
623 "reading post data field: "
624 + string(shortName)
625 );
626
627 // transcribe to output list
628 forAll(mapData, i)
629 {
630 const label cellId = mapData[i];
631 scalarData[cellId] = rawData[i];
632 }
633 }
634 }
635 }
636 }
637 }
638 }
639
640 // Overwrite possible junk in cell 0 (often used as /dev/null)
641 scalarData[0] = option().undefScalar();
642
643 return tscalarData;
644}
645
646
647// ************************************************************************* //
label n
Internal bits for wrapping libccmio - do not use directly.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
void setSize(label n)
Alias for resize().
Definition List.H:536
T * data() noexcept
Return pointer to the underlying array serving as data storage.
Definition UListI.H:274
std::unique_ptr< ccmGlobalState > globalState_
Maintain overall global states (error, root-node).
Definition ccmBase.H:79
static bool assertNoError(int err, const char *msg)
Die with msg if there is an error.
Definition ccmBase.C:28
A ccm field entry with short name, name, maxId and type.
FOAM_DLL_EXPORT const reader::options & option() const
Reference to the reader options.
Definition ccmReader.C:693
FOAM_DLL_EXPORT tmp< scalarField > readField(const word &solutionName, const word &fieldName, const bool wallData=false)
Read solution and field combination.
A ccm solution entry with name, iteration and time.
A keyword and a list of tokens is an 'entry'.
Definition entry.H:66
A class for managing temporary objects.
Definition tmp.H:75
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
Definition tmp.H:215
A class for handling words, derived from Foam::string.
Definition word.H:66
static bool valid(char c)
Is this character valid for a word?
Definition wordI.H:52
label cellId
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299