faFieldReconstructorTemplates.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-2017 Wikki Ltd
9 Copyright (C) 2018-2022 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
30#include "Time.H"
31#include "PtrList.H"
32#include "faPatchFields.H"
33#include "emptyFaPatch.H"
34#include "emptyFaPatchField.H"
35#include "emptyFaePatchField.H"
36
37// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
38
39template<class Type>
42(
43 const IOobject& fieldObject,
45) const
46{
47 // Create the internalField
48 Field<Type> internalField(mesh_.nFaces());
49
50 // Create the patch fields
51 PtrList<faPatchField<Type>> patchFields(mesh_.boundary().size());
52
53
54 // Create global mesh patches starts
55
56 labelList gStarts(mesh_.boundary().size(), -1);
57
58 if (mesh_.boundary().size() > 0)
59 {
60 gStarts[0] = mesh_.nInternalEdges();
61 }
62
63 for(label i=1; i<mesh_.boundary().size(); i++)
64 {
65 gStarts[i] = gStarts[i-1] + mesh_.boundary()[i-1].labelList::size();
66 }
67
68 forAll(procMeshes_, procI)
69 {
71 procFields[procI];
72
73 // Set the face values in the reconstructed field
74 internalField.rmap
75 (
76 procField.internalField(),
77 faceProcAddressing_[procI]
78 );
79
80
81
82 // Set the boundary patch values in the reconstructed field
83
84 labelList starts(procMeshes_[procI].boundary().size(), -1);
85
86 if(procMeshes_[procI].boundary().size() > 0)
87 {
88 starts[0] = procMeshes_[procI].nInternalEdges();
89 }
90
91 for(label i=1; i<procMeshes_[procI].boundary().size(); i++)
92 {
93 starts[i] =
94 starts[i-1]
95 + procMeshes_[procI].boundary()[i-1].labelList::size();
96 }
97
98 forAll(boundaryProcAddressing_[procI], patchI)
99 {
100 // Get patch index of the original patch
101 const label curBPatch = boundaryProcAddressing_[procI][patchI];
102
103 // Get addressing slice for this patch
104
105// const labelList::subList cp =
106// procMeshes_[procI].boundary()[patchI].patchSlice
107// (
108// edgeProcAddressing_[procI]
109// );
110
111 const labelList::subList cp =
113 (
114 edgeProcAddressing_[procI],
115 procMeshes_[procI].boundary()[patchI].size(),
116 starts[patchI]
117 );
118
119 // check if the boundary patch is not a processor patch
120 if (curBPatch >= 0)
121 {
122 // Regular patch. Fast looping
123
124 if (!patchFields(curBPatch))
125 {
126 patchFields.set
127 (
128 curBPatch,
130 (
131 procField.boundaryField()[patchI],
132 mesh_.boundary()[curBPatch],
135 (
136 mesh_.boundary()[curBPatch].size(),
137 procField.boundaryField()[patchI].size()
138 )
139 )
140 );
141 }
142
143 const label curPatchStart = gStarts[curBPatch];
144// mesh_.boundary()[curBPatch].start();
145
146 labelList reverseAddressing(cp.size());
147
148 forAll(cp, edgeI)
149 {
150 // Subtract one to take into account offsets for
151 // face direction.
152// reverseAddressing[edgeI] = cp[edgeI] - 1 - curPatchStart;
153 reverseAddressing[edgeI] = cp[edgeI] - curPatchStart;
154 }
155
156 patchFields[curBPatch].rmap
157 (
158 procField.boundaryField()[patchI],
159 reverseAddressing
160 );
161 }
162 else
163 {
164 const Field<Type>& curProcPatch =
165 procField.boundaryField()[patchI];
166
167 // In processor patches, there's a mix of internal faces (some
168 // of them turned) and possible cyclics. Slow loop
169 forAll(cp, edgeI)
170 {
171 // Subtract one to take into account offsets for
172 // face direction.
173// label curE = cp[edgeI] - 1;
174 label curE = cp[edgeI];
175
176 // Is the face on the boundary?
177 if (curE >= mesh_.nInternalEdges())
178 {
179// label curBPatch = mesh_.boundary().whichPatch(curE);
180 label curBPatch = -1;
181
182 forAll(mesh_.boundary(), pI)
183 {
184 if
185 (
186 curE >= gStarts[pI]
187 && curE <
188 (
189 gStarts[pI]
190 + mesh_.boundary()[pI].labelList::size()
191 )
192 )
193 {
194 curBPatch = pI;
195 }
196 }
197
198 if (!patchFields(curBPatch))
199 {
200 patchFields.set
201 (
202 curBPatch,
204 (
205 mesh_.boundary()[curBPatch].type(),
206 mesh_.boundary()[curBPatch],
208 )
209 );
210 }
211
212 // add the edge
213// label curPatchEdge =
214// mesh_.boundary()
215// [curBPatch].whichEdge(curE);
216
217 label curPatchEdge = curE - gStarts[curBPatch];
218
219 patchFields[curBPatch][curPatchEdge] =
220 curProcPatch[edgeI];
221 }
222 }
223 }
224 }
225 }
226
227 forAll(mesh_.boundary(), patchI)
228 {
229 // add empty patches
230 if
231 (
232 isA<emptyFaPatch>(mesh_.boundary()[patchI])
233 && !patchFields(patchI)
234 )
235 {
236 patchFields.set
237 (
238 patchI,
240 (
242 mesh_.boundary()[patchI],
244 )
245 );
246 }
247 }
248
249
250 // Now construct and write the field
251 // setting the internalField and patchFields
253 (
255 (
256 fieldObject.name(),
257 mesh_.thisDb().time().timeName(),
258 mesh_.thisDb(),
261 ),
262 mesh_,
263 procFields[0].dimensions(),
264 internalField,
265 patchFields
266 );
267}
268
269
270template<class Type>
273(
274 const IOobject& fieldObject,
276) const
277{
278 // Create the internalField
279 Field<Type> internalField(mesh_.nInternalEdges());
280
281 // Create the patch fields
282 PtrList<faePatchField<Type>> patchFields(mesh_.boundary().size());
283
284
285 labelList gStarts(mesh_.boundary().size(), -1);
286
287 if(mesh_.boundary().size() > 0)
288 {
289 gStarts[0] = mesh_.nInternalEdges();
290 }
291
292 for(label i=1; i<mesh_.boundary().size(); i++)
293 {
294 gStarts[i] = gStarts[i-1] + mesh_.boundary()[i-1].labelList::size();
295 }
296
297
298 forAll(procMeshes_, procI)
299 {
301 procFields[procI];
302
303 // Set the face values in the reconstructed field
304
305 // It is necessary to create a copy of the addressing array to
306 // take care of the face direction offset trick.
307 //
308 {
309 labelList curAddr(edgeProcAddressing_[procI]);
310
311// forAll(curAddr, addrI)
312// {
313// curAddr[addrI] -= 1;
314// }
315
316 internalField.rmap
317 (
318 procField.internalField(),
319 curAddr
320 );
321 }
322
323 // Set the boundary patch values in the reconstructed field
324
325 labelList starts(procMeshes_[procI].boundary().size(), -1);
326
327 if(procMeshes_[procI].boundary().size() > 0)
328 {
329 starts[0] = procMeshes_[procI].nInternalEdges();
330 }
331
332 for(label i=1; i<procMeshes_[procI].boundary().size(); i++)
333 {
334 starts[i] =
335 starts[i-1]
336 + procMeshes_[procI].boundary()[i-1].labelList::size();
337 }
338
339 forAll(boundaryProcAddressing_[procI], patchI)
340 {
341 // Get patch index of the original patch
342 const label curBPatch = boundaryProcAddressing_[procI][patchI];
343
344 // Get addressing slice for this patch
345
346// const labelList::subList cp =
347// procMeshes_[procI].boundary()[patchI].patchSlice
348// (
349// faceProcAddressing_[procI]
350// );
351
352 const labelList::subList cp =
354 (
355 edgeProcAddressing_[procI],
356 procMeshes_[procI].boundary()[patchI].size(),
357 starts[patchI]
358 );
359
360 // check if the boundary patch is not a processor patch
361 if (curBPatch >= 0)
362 {
363 // Regular patch. Fast looping
364
365 if (!patchFields(curBPatch))
366 {
367 patchFields.set
368 (
369 curBPatch,
371 (
372 procField.boundaryField()[patchI],
373 mesh_.boundary()[curBPatch],
376 (
377 mesh_.boundary()[curBPatch].size(),
378 procField.boundaryField()[patchI].size()
379 )
380 )
381 );
382 }
383
384 const label curPatchStart = gStarts[curBPatch];
385// mesh_.boundary()[curBPatch].start();
386
387 labelList reverseAddressing(cp.size());
388
389 forAll(cp, edgeI)
390 {
391 // Subtract one to take into account offsets for
392 // face direction.
393// reverseAddressing[faceI] = cp[faceI] - 1 - curPatchStart;
394 reverseAddressing[edgeI] = cp[edgeI] - curPatchStart;
395 }
396
397 patchFields[curBPatch].rmap
398 (
399 procField.boundaryField()[patchI],
400 reverseAddressing
401 );
402 }
403 else
404 {
405 const Field<Type>& curProcPatch =
406 procField.boundaryField()[patchI];
407
408 // In processor patches, there's a mix of internal faces (some
409 // of them turned) and possible cyclics. Slow loop
410 forAll(cp, edgeI)
411 {
412// label curF = cp[edgeI] - 1;
413 label curE = cp[edgeI];
414
415 // Is the face turned the right side round
416 if (curE >= 0)
417 {
418 // Is the face on the boundary?
419 if (curE >= mesh_.nInternalEdges())
420 {
421// label curBPatch =
422// mesh_.boundary().whichPatch(curF);
423
424 label curBPatch = -1;
425
426 forAll(mesh_.boundary(), pI)
427 {
428 if
429 (
430 curE >= gStarts[pI]
431 && curE <
432 (
433 gStarts[pI]
434 + mesh_.boundary()[pI].labelList::size()
435 )
436 )
437 {
438 curBPatch = pI;
439 }
440 }
441
442 if (!patchFields(curBPatch))
443 {
444 patchFields.set
445 (
446 curBPatch,
448 (
449 mesh_.boundary()[curBPatch].type(),
450 mesh_.boundary()[curBPatch],
452 ::null()
453 )
454 );
455 }
456
457 // add the face
458// label curPatchFace =
459// mesh_.boundary()
460// [curBPatch].whichEdge(curF);
461
462 label curPatchEdge = curE - gStarts[curBPatch];
463
464 patchFields[curBPatch][curPatchEdge] =
465 curProcPatch[edgeI];
466 }
467 else
468 {
469 // Internal face
470 internalField[curE] = curProcPatch[edgeI];
471 }
472 }
473 }
474 }
475 }
476 }
477
478 forAll(mesh_.boundary(), patchI)
479 {
480 // add empty patches
481 if
482 (
483 isA<emptyFaPatch>(mesh_.boundary()[patchI])
484 && !patchFields(patchI)
485 )
486 {
487 patchFields.set
488 (
489 patchI,
491 (
493 mesh_.boundary()[patchI],
495 )
496 );
497 }
498 }
499
500
501 // Now construct and write the field
502 // setting the internalField and patchFields
504 (
506 (
507 fieldObject.name(),
508 mesh_.thisDb().time().timeName(),
509 mesh_.thisDb(),
512 ),
513 mesh_,
514 procFields[0].dimensions(),
515 internalField,
516 patchFields
517 );
518}
519
520
521template<class Type>
524(
525 const IOobject& fieldObject
526)
527{
528 // Read the field for all the processors
530 (
531 procMeshes_.size()
532 );
533
534 forAll(procMeshes_, proci)
535 {
536 procFields.set
537 (
538 proci,
540 (
542 (
543 fieldObject.name(),
544 procMeshes_[proci].thisDb().time().timeName(),
545 procMeshes_[proci].thisDb(),
548 ),
549 procMeshes_[proci]
550 )
551 );
552 }
553
554 return reconstructField
555 (
557 (
558 fieldObject.name(),
559 mesh_.thisDb().time().timeName(),
560 mesh_.thisDb(),
563 ),
564 procFields
565 );
566}
567
568
569template<class Type>
572(
573 const IOobject& fieldObject
574)
575{
576 // Read the field for all the processors
578 (
579 procMeshes_.size()
580 );
581
582 forAll(procMeshes_, proci)
583 {
584 procFields.set
585 (
586 proci,
588 (
590 (
591 fieldObject.name(),
592 procMeshes_[proci].thisDb().time().timeName(),
593 procMeshes_[proci].thisDb(),
596 ),
597 procMeshes_[proci]
598 )
599 );
600 }
601
602 return reconstructField
603 (
605 (
606 fieldObject.name(),
607 mesh_.thisDb().time().timeName(),
608 mesh_.thisDb(),
611 ),
612 procFields
613 );
614}
615
616
617template<class Type>
619(
620 const UPtrList<const IOobject>& fieldObjects
621)
622{
624
625 label nFields = 0;
626
627 for (const IOobject& io : fieldObjects)
628 {
629 if (io.isHeaderClass<fieldType>())
630 {
631 if (verbose_)
632 {
633 if (!nFields)
634 {
635 Info<< " Reconstructing "
636 << fieldType::typeName << "s\n" << nl;
637 }
638 Info<< " " << io.name() << endl;
639 }
640 ++nFields;
641
642 reconstructAreaField<Type>(io)().write();
643 ++nReconstructed_;
644 }
645 }
646
647 if (verbose_ && nFields) Info<< endl;
648 return nFields;
649}
650
651
652template<class Type>
654(
655 const UPtrList<const IOobject>& fieldObjects
656)
657{
659
660 label nFields = 0;
661
662 for (const IOobject& io : fieldObjects)
663 {
664 if (io.isHeaderClass<fieldType>())
665 {
666 if (verbose_)
667 {
668 if (!nFields)
669 {
670 Info<< " Reconstructing "
671 << fieldType::typeName << "s\n" << nl;
672 }
673 Info<< " " << io.name() << endl;
674 }
675 ++nFields;
676
677 reconstructEdgeField<Type>(io)().write();
678 ++nReconstructed_;
679 }
680 }
681
682 if (verbose_ && nFields) Info<< endl;
683 return nFields;
684}
685
686
687template<class Type>
689(
690 const IOobjectList& objects,
691 const wordRes& selectedFields
692)
693{
695
696 return reconstructAreaFields<Type>
697 (
698 (
699 selectedFields.empty()
700 ? objects.sorted<fieldType>()
701 : objects.sorted<fieldType>(selectedFields)
702 )
703 );
704}
705
706
707template<class Type>
709(
710 const IOobjectList& objects,
711 const wordRes& selectedFields
712)
713{
715
716 return reconstructEdgeFields<Type>
717 (
718 (
719 selectedFields.empty()
720 ? objects.sorted<fieldType>()
721 : objects.sorted<fieldType>(selectedFields)
722 )
723 );
724}
725
726
727// ************************************************************************* //
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Generic templated field type.
Definition: Field.H:82
void rmap(const UList< Type > &mapF, const labelUList &mapAddressing)
1 to 1 reverse-map from the given field
Definition: Field.C:466
Generic GeometricField class.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
const Internal & internalField() const
Return a const-reference to the dimensioned internal field.
List of IOobjects with searching and retrieving facilities.
Definition: IOobjectList.H:59
UPtrList< const IOobject > sorted() const
The sorted list of IOobjects.
Definition: IOobjectList.C:336
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
bool isHeaderClass() const
Check if headerClassName() equals Type::typeName.
Definition: IOobjectI.H:156
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:65
SubList< label > subList
Declare type of subList.
Definition: List.H:111
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: PtrList.H:73
const T * set(const label i) const
Definition: PtrList.H:138
A List obtained as a section of another List.
Definition: SubList.H:70
static word timeName(const scalar t, const int precision=precision_)
Definition: Time.C:780
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
Definition: UListI.H:427
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
Definition: UPtrList.H:71
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:106
Author Zeljko Tukovic, FMENA Hrvoje Jasak, Wikki Ltd.
Author Zeljko Tukovic, FMENA Hrvoje Jasak, Wikki Ltd.
tmp< GeometricField< Type, faPatchField, areaMesh > > reconstructAreaField(const IOobject &fieldObject)
Read and reconstruct area field.
tmp< GeometricField< Type, faPatchField, areaMesh > > reconstructField(const IOobject &fieldObject, const PtrList< GeometricField< Type, faPatchField, areaMesh > > &) const
Reconstruct area field.
tmp< GeometricField< Type, faePatchField, edgeMesh > > reconstructEdgeField(const IOobject &fieldObject)
Read and reconstruct edge field.
label reconstructEdgeFields(const UPtrList< const IOobject > &fieldObjects)
Read, reconstruct and write specified edge fields.
label reconstructAreaFields(const UPtrList< const IOobject > &fieldObjects)
Read, reconstruct and write specified area fields.
const faBoundaryMesh & boundary() const noexcept
Return constant reference to boundary mesh.
Definition: faMeshI.H:38
virtual const objectRegistry & thisDb() const
Return reference to the mesh database.
Definition: faMesh.C:697
label nInternalEdges() const noexcept
Number of internal faces.
Definition: faMeshI.H:68
label nFaces() const noexcept
Number of patch faces.
Definition: faMeshI.H:80
faPatchField<Type> abstract base class. This class gives a fat-interface to all derived classes cover...
Definition: faPatchField.H:82
faePatchField<Type> abstract base class. This class gives a fat-interface to all derived classes cove...
Definition: faePatchField.H:83
const Time & time() const noexcept
Return time registry.
A class for managing temporary objects.
Definition: tmp.H:65
A List of wordRe with additional matching capabilities.
Definition: wordRes.H:54
faceListList boundary
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, false)
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh > > &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
runTime write()
const volScalarField & cp
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333