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-2023 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
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 
29 #include "faFieldReconstructor.H"
30 #include "Time.H"
31 #include "PtrList.H"
32 #include "emptyFaPatch.H"
33 #include "faPatchFields.H"
34 #include "faePatchFields.H"
35 
36 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
37 
38 template<class Type>
41 (
42  const IOobject& fieldObject,
44 ) const
45 {
46  // Create the internalField
47  Field<Type> internalField(mesh_.nFaces());
48 
49  // Create the patch fields
50  PtrList<faPatchField<Type>> patchFields(mesh_.boundary().size());
51 
52 
53  // Create global mesh patches starts
54 
55  labelList gStarts(mesh_.boundary().size(), -1);
56 
57  if (mesh_.boundary().size() > 0)
58  {
59  gStarts[0] = mesh_.nInternalEdges();
60  }
61 
62  for(label i=1; i<mesh_.boundary().size(); i++)
63  {
64  gStarts[i] = gStarts[i-1] + mesh_.boundary()[i-1].labelList::size();
65  }
66 
67  forAll(procMeshes_, procI)
68  {
70  procFields[procI];
71 
72  // Set the face values in the reconstructed field
73  internalField.rmap
74  (
75  procField.internalField(),
76  faceProcAddressing_[procI]
77  );
78 
79 
80 
81  // Set the boundary patch values in the reconstructed field
82 
83  labelList starts(procMeshes_[procI].boundary().size(), -1);
84 
85  if(procMeshes_[procI].boundary().size() > 0)
86  {
87  starts[0] = procMeshes_[procI].nInternalEdges();
88  }
89 
90  for(label i=1; i<procMeshes_[procI].boundary().size(); i++)
91  {
92  starts[i] =
93  starts[i-1]
94  + procMeshes_[procI].boundary()[i-1].labelList::size();
95  }
96 
97  forAll(boundaryProcAddressing_[procI], patchI)
98  {
99  // Get patch index of the original patch
100  const label curBPatch = boundaryProcAddressing_[procI][patchI];
101 
102  // Get addressing slice for this patch
103 
104 // const labelList::subList cp =
105 // procMeshes_[procI].boundary()[patchI].patchSlice
106 // (
107 // edgeProcAddressing_[procI]
108 // );
109 
110  const labelList::subList cp =
112  (
113  edgeProcAddressing_[procI],
114  procMeshes_[procI].boundary()[patchI].size(),
115  starts[patchI]
116  );
117 
118  // check if the boundary patch is not a processor patch
119  if (curBPatch >= 0)
120  {
121  // Regular patch. Fast looping
122 
123  if (!patchFields.set(curBPatch))
124  {
125  patchFields.set
126  (
127  curBPatch,
129  (
130  procField.boundaryField()[patchI],
131  mesh_.boundary()[curBPatch],
134  (
135  mesh_.boundary()[curBPatch].size(),
136  procField.boundaryField()[patchI].size()
137  )
138  )
139  );
140  }
141 
142  const label curPatchStart = gStarts[curBPatch];
143 // mesh_.boundary()[curBPatch].start();
144 
145  labelList reverseAddressing(cp.size());
146 
147  forAll(cp, edgeI)
148  {
149  // Subtract one to take into account offsets for
150  // face direction.
151 // reverseAddressing[edgeI] = cp[edgeI] - 1 - curPatchStart;
152  reverseAddressing[edgeI] = cp[edgeI] - curPatchStart;
153  }
154 
155  patchFields[curBPatch].rmap
156  (
157  procField.boundaryField()[patchI],
158  reverseAddressing
159  );
160  }
161  else
162  {
163  const Field<Type>& curProcPatch =
164  procField.boundaryField()[patchI];
165 
166  // In processor patches, there's a mix of internal faces (some
167  // of them turned) and possible cyclics. Slow loop
168  forAll(cp, edgeI)
169  {
170  // Subtract one to take into account offsets for
171  // face direction.
172 // label curE = cp[edgeI] - 1;
173  label curE = cp[edgeI];
174 
175  // Is the face on the boundary?
176  if (curE >= mesh_.nInternalEdges())
177  {
178 // label curBPatch = mesh_.boundary().whichPatch(curE);
179  label curBPatch = -1;
180 
181  forAll(mesh_.boundary(), pI)
182  {
183  if
184  (
185  curE >= gStarts[pI]
186  && curE <
187  (
188  gStarts[pI]
189  + mesh_.boundary()[pI].labelList::size()
190  )
191  )
192  {
193  curBPatch = pI;
194  }
195  }
196 
197  if (!patchFields.set(curBPatch))
198  {
199  patchFields.set
200  (
201  curBPatch,
203  (
204  mesh_.boundary()[curBPatch].type(),
205  mesh_.boundary()[curBPatch],
207  )
208  );
209  }
210 
211  // add the edge
212 // label curPatchEdge =
213 // mesh_.boundary()
214 // [curBPatch].whichEdge(curE);
215 
216  label curPatchEdge = curE - gStarts[curBPatch];
217 
218  patchFields[curBPatch][curPatchEdge] =
219  curProcPatch[edgeI];
220  }
221  }
222  }
223  }
224  }
225 
226  forAll(mesh_.boundary(), patchI)
227  {
228  // add empty patches
229  if
230  (
231  isA<emptyFaPatch>(mesh_.boundary()[patchI])
232  && !patchFields.set(patchI)
233  )
234  {
235  patchFields.set
236  (
237  patchI,
239  (
241  mesh_.boundary()[patchI],
243  )
244  );
245  }
246  }
247 
248 
249  // Now construct and write the field
250  // setting the internalField and patchFields
252  (
253  IOobject
254  (
255  fieldObject.name(),
256  mesh_.thisDb().time().timeName(),
257  mesh_.thisDb(),
260  ),
261  mesh_,
262  procFields[0].dimensions(),
263  internalField,
264  patchFields
265  );
266 }
267 
268 
269 template<class Type>
272 (
273  const IOobject& fieldObject,
275 ) const
276 {
277  // Create the internalField
278  Field<Type> internalField(mesh_.nInternalEdges());
279 
280  // Create the patch fields
281  PtrList<faePatchField<Type>> patchFields(mesh_.boundary().size());
282 
283 
284  labelList gStarts(mesh_.boundary().size(), -1);
285 
286  if(mesh_.boundary().size() > 0)
287  {
288  gStarts[0] = mesh_.nInternalEdges();
289  }
290 
291  for(label i=1; i<mesh_.boundary().size(); i++)
292  {
293  gStarts[i] = gStarts[i-1] + mesh_.boundary()[i-1].labelList::size();
294  }
295 
296 
297  forAll(procMeshes_, procI)
298  {
299  const GeometricField<Type, faePatchField, edgeMesh>& procField =
300  procFields[procI];
301 
302  // Set the face values in the reconstructed field
303 
304  // It is necessary to create a copy of the addressing array to
305  // take care of the face direction offset trick.
306  //
307  {
308  labelList curAddr(edgeProcAddressing_[procI]);
309 
310 // forAll(curAddr, addrI)
311 // {
312 // curAddr[addrI] -= 1;
313 // }
314 
315  internalField.rmap
316  (
317  procField.internalField(),
318  curAddr
319  );
320  }
321 
322  // Set the boundary patch values in the reconstructed field
323 
324  labelList starts(procMeshes_[procI].boundary().size(), -1);
325 
326  if(procMeshes_[procI].boundary().size() > 0)
327  {
328  starts[0] = procMeshes_[procI].nInternalEdges();
329  }
330 
331  for(label i=1; i<procMeshes_[procI].boundary().size(); i++)
332  {
333  starts[i] =
334  starts[i-1]
335  + procMeshes_[procI].boundary()[i-1].labelList::size();
336  }
337 
338  forAll(boundaryProcAddressing_[procI], patchI)
339  {
340  // Get patch index of the original patch
341  const label curBPatch = boundaryProcAddressing_[procI][patchI];
342 
343  // Get addressing slice for this patch
344 
345 // const labelList::subList cp =
346 // procMeshes_[procI].boundary()[patchI].patchSlice
347 // (
348 // faceProcAddressing_[procI]
349 // );
350 
351  const labelList::subList cp =
353  (
354  edgeProcAddressing_[procI],
355  procMeshes_[procI].boundary()[patchI].size(),
356  starts[patchI]
357  );
358 
359  // check if the boundary patch is not a processor patch
360  if (curBPatch >= 0)
361  {
362  // Regular patch. Fast looping
363 
364  if (!patchFields.set(curBPatch))
365  {
366  patchFields.set
367  (
368  curBPatch,
370  (
371  procField.boundaryField()[patchI],
372  mesh_.boundary()[curBPatch],
374  faPatchFieldReconstructor
375  (
376  mesh_.boundary()[curBPatch].size(),
377  procField.boundaryField()[patchI].size()
378  )
379  )
380  );
381  }
382 
383  const label curPatchStart = gStarts[curBPatch];
384 // mesh_.boundary()[curBPatch].start();
385 
386  labelList reverseAddressing(cp.size());
387 
388  forAll(cp, edgeI)
389  {
390  // Subtract one to take into account offsets for
391  // face direction.
392 // reverseAddressing[faceI] = cp[faceI] - 1 - curPatchStart;
393  reverseAddressing[edgeI] = cp[edgeI] - curPatchStart;
394  }
395 
396  patchFields[curBPatch].rmap
397  (
398  procField.boundaryField()[patchI],
399  reverseAddressing
400  );
401  }
402  else
403  {
404  const Field<Type>& curProcPatch =
405  procField.boundaryField()[patchI];
406 
407  // In processor patches, there's a mix of internal faces (some
408  // of them turned) and possible cyclics. Slow loop
409  forAll(cp, edgeI)
410  {
411 // label curF = cp[edgeI] - 1;
412  label curE = cp[edgeI];
413 
414  // Is the face turned the right side round
415  if (curE >= 0)
416  {
417  // Is the face on the boundary?
418  if (curE >= mesh_.nInternalEdges())
419  {
420 // label curBPatch =
421 // mesh_.boundary().whichPatch(curF);
422 
423  label curBPatch = -1;
424 
425  forAll(mesh_.boundary(), pI)
426  {
427  if
428  (
429  curE >= gStarts[pI]
430  && curE <
431  (
432  gStarts[pI]
433  + mesh_.boundary()[pI].labelList::size()
434  )
435  )
436  {
437  curBPatch = pI;
438  }
439  }
440 
441  if (!patchFields.set(curBPatch))
442  {
443  patchFields.set
444  (
445  curBPatch,
447  (
448  mesh_.boundary()[curBPatch].type(),
449  mesh_.boundary()[curBPatch],
451  )
452  );
453  }
454 
455  // add the face
456 // label curPatchFace =
457 // mesh_.boundary()
458 // [curBPatch].whichEdge(curF);
459 
460  label curPatchEdge = curE - gStarts[curBPatch];
461 
462  patchFields[curBPatch][curPatchEdge] =
463  curProcPatch[edgeI];
464  }
465  else
466  {
467  // Internal face
468  internalField[curE] = curProcPatch[edgeI];
469  }
470  }
471  }
472  }
473  }
474  }
475 
476  forAll(mesh_.boundary(), patchI)
477  {
478  // add empty patches
479  if
480  (
481  isA<emptyFaPatch>(mesh_.boundary()[patchI])
482  && !patchFields.set(patchI)
483  )
484  {
485  patchFields.set
486  (
487  patchI,
489  (
491  mesh_.boundary()[patchI],
493  )
494  );
495  }
496  }
497 
498 
499  // Now construct and write the field
500  // setting the internalField and patchFields
501  return tmp<GeometricField<Type, faePatchField, edgeMesh>>::New
502  (
503  IOobject
504  (
505  fieldObject.name(),
506  mesh_.thisDb().time().timeName(),
507  mesh_.thisDb(),
510  ),
511  mesh_,
512  procFields[0].dimensions(),
513  internalField,
514  patchFields
515  );
516 }
517 
518 
519 template<class Type>
522 (
523  const IOobject& fieldObject
524 )
525 {
526  // Read the field for all the processors
528  (
529  procMeshes_.size()
530  );
531 
532  forAll(procMeshes_, proci)
533  {
534  procFields.set
535  (
536  proci,
538  (
539  IOobject
540  (
541  fieldObject.name(),
542  procMeshes_[proci].thisDb().time().timeName(),
543  procMeshes_[proci].thisDb(),
546  ),
547  procMeshes_[proci]
548  )
549  );
550  }
551 
552  return reconstructField
553  (
554  IOobject
555  (
556  fieldObject.name(),
557  mesh_.thisDb().time().timeName(),
558  mesh_.thisDb(),
561  ),
562  procFields
563  );
564 }
565 
566 
567 template<class Type>
570 (
571  const IOobject& fieldObject
572 )
573 {
574  // Read the field for all the processors
576  (
577  procMeshes_.size()
578  );
579 
580  forAll(procMeshes_, proci)
581  {
582  procFields.set
583  (
584  proci,
586  (
587  IOobject
588  (
589  fieldObject.name(),
590  procMeshes_[proci].thisDb().time().timeName(),
591  procMeshes_[proci].thisDb(),
594  ),
595  procMeshes_[proci]
596  )
597  );
598  }
599 
600  return reconstructField
601  (
602  IOobject
603  (
604  fieldObject.name(),
605  mesh_.thisDb().time().timeName(),
606  mesh_.thisDb(),
609  ),
610  procFields
611  );
612 }
613 
614 
615 template<class Type>
617 (
618  const UPtrList<const IOobject>& fieldObjects
619 )
620 {
622 
623  label nFields = 0;
624 
625  for (const IOobject& io : fieldObjects)
626  {
627  if (io.isHeaderClass<fieldType>())
628  {
629  if (verbose_)
630  {
631  if (!nFields)
632  {
633  Info<< " Reconstructing "
634  << fieldType::typeName << "s\n" << nl;
635  }
636  Info<< " " << io.name() << endl;
637  }
638  ++nFields;
639 
640  reconstructAreaField<Type>(io)().write();
641  ++nReconstructed_;
642  }
643  }
644 
645  if (verbose_ && nFields) Info<< endl;
646  return nFields;
647 }
648 
649 
650 template<class Type>
652 (
653  const UPtrList<const IOobject>& fieldObjects
654 )
655 {
657 
658  label nFields = 0;
659 
660  for (const IOobject& io : fieldObjects)
661  {
662  if (io.isHeaderClass<fieldType>())
663  {
664  if (verbose_)
665  {
666  if (!nFields)
667  {
668  Info<< " Reconstructing "
669  << fieldType::typeName << "s\n" << nl;
670  }
671  Info<< " " << io.name() << endl;
672  }
673  ++nFields;
674 
675  reconstructEdgeField<Type>(io)().write();
676  ++nReconstructed_;
677  }
678  }
679 
680  if (verbose_ && nFields) Info<< endl;
681  return nFields;
682 }
683 
684 
685 template<class Type>
687 (
688  const IOobjectList& objects,
689  const wordRes& selectedFields
690 )
691 {
693 
694  return reconstructAreaFields<Type>
695  (
696  (
697  selectedFields.empty()
698  ? objects.csorted<fieldType>()
699  : objects.csorted<fieldType>(selectedFields)
700  )
701  );
702 }
703 
704 
705 template<class Type>
707 (
708  const IOobjectList& objects,
709  const wordRes& selectedFields
710 )
711 {
713 
714  return reconstructEdgeFields<Type>
715  (
716  (
717  selectedFields.empty()
718  ? objects.csorted<fieldType>()
719  : objects.csorted<fieldType>(selectedFields)
720  )
721  );
722 }
723 
724 
725 // ************************************************************************* //
faceListList boundary
List of IOobjects with searching and retrieving facilities. Implemented as a HashTable, so the various sorted methods should be used if traversing in parallel.
Definition: IOobjectList.H:55
static const word & emptyType() noexcept
The type name for empty patch fields.
tmp< GeometricField< Type, faePatchField, edgeMesh > > reconstructEdgeField(const IOobject &fieldObject)
Read and reconstruct edge field.
static const DimensionedField< Type, GeoMesh > & null() noexcept
Return a null DimensionedField (reference to a nullObject).
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:195
const Internal & internalField() const noexcept
Return a const-reference to the dimensioned internal field.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
bool empty() const noexcept
True if List is empty (ie, size() is zero)
Definition: UList.H:675
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
bool cp(const fileName &src, const fileName &dst, const bool followLink=true)
Copy the source to the destination (recursively if necessary).
Definition: POSIX.C:1063
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
label reconstructEdgeFields(const UPtrList< const IOobject > &fieldObjects)
Read, reconstruct and write specified edge fields.
Generic GeometricField class.
SubList< label > subList
Declare type of subList.
Definition: List.H:144
Ignore writing from objectRegistry::writeObject()
faPatchField<Type> abstract base class. This class gives a fat-interface to all derived classes cover...
Definition: areaFieldsFwd.H:46
label nFaces() const noexcept
Number of patch faces.
Definition: faMeshI.H:54
Declarations for faPatchField types.
tmp< GeometricField< Type, faPatchField, areaMesh > > reconstructField(const IOobject &fieldObject, const PtrList< GeometricField< Type, faPatchField, areaMesh >> &) const
Reconstruct area field.
virtual const objectRegistry & thisDb() const
Reference to the mesh database.
Definition: faMesh.H:1203
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
A List obtained as a section of another List.
Definition: SubList.H:50
Declarations for faePatchField types.
Generic templated field type.
Definition: Field.H:62
const Time & time() const noexcept
Return time registry.
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:106
A List of wordRe with additional matching capabilities.
Definition: wordRes.H:53
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
Definition: HashTable.H:106
static word timeName(const scalar t, const int precision=precision_)
Return a time name for the given scalar time value formatted with the given precision.
Definition: Time.C:714
const faBoundaryMesh & boundary() const noexcept
Return constant reference to boundary mesh.
Definition: faMeshI.H:24
tmp< GeometricField< Type, faPatchField, areaMesh > > reconstructAreaField(const IOobject &fieldObject)
Read and reconstruct area field.
static const word & emptyType() noexcept
The type name for empty patch fields.
Definition: faPatchField.H:166
void rmap(const UList< Type > &mapF, const labelUList &mapAddressing)
1 to 1 reverse-map from the given field
Definition: Field.C:529
label nInternalEdges() const noexcept
Number of internal faces.
Definition: faMeshI.H:42
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: List.H:55
label reconstructAreaFields(const UPtrList< const IOobject > &fieldObjects)
Read, reconstruct and write specified area fields.
Nothing to be read.
static tmp< faePatchField< Type > > New(const word &patchFieldType, const faPatch &, const DimensionedField< Type, edgeMesh > &)
Return a pointer to a new patchField created on freestore given.
messageStream Info
Information stream (stdout output on master, null elsewhere)
List< label > labelList
A List of labels.
Definition: List.H:62
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
A class for managing temporary objects.
Definition: HashPtrTable.H:50
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:180
UPtrList< const IOobject > csorted() const
The sorted list of IOobjects with headerClassName == Type::typeName.
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
bool isHeaderClass() const
Check if headerClassName() equals Type::typeName.
Definition: IOobjectI.H:258