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 "faPatchFields.H"
33 #include "emptyFaPatch.H"
34 #include "emptyFaPatchField.H"
36 
37 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
38 
39 template<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.set(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.set(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.set(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  (
254  IOobject
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 
270 template<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  {
300  const GeometricField<Type, faePatchField, edgeMesh>& procField =
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.set(curBPatch))
366  {
367  patchFields.set
368  (
369  curBPatch,
371  (
372  procField.boundaryField()[patchI],
373  mesh_.boundary()[curBPatch],
375  faPatchFieldReconstructor
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.set(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.set(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
503  return tmp<GeometricField<Type, faePatchField, edgeMesh>>::New
504  (
505  IOobject
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 
521 template<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  (
541  IOobject
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  (
556  IOobject
557  (
558  fieldObject.name(),
559  mesh_.thisDb().time().timeName(),
560  mesh_.thisDb(),
563  ),
564  procFields
565  );
566 }
567 
568 
569 template<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  (
589  IOobject
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  (
604  IOobject
605  (
606  fieldObject.name(),
607  mesh_.thisDb().time().timeName(),
608  mesh_.thisDb(),
611  ),
612  procFields
613  );
614 }
615 
616 
617 template<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 
652 template<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 
687 template<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.csorted<fieldType>()
701  : objects.csorted<fieldType>(selectedFields)
702  )
703  );
704 }
705 
706 
707 template<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.csorted<fieldType>()
721  : objects.csorted<fieldType>(selectedFields)
722  )
723  );
724 }
725 
726 
727 // ************************************************************************* //
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
tmp< GeometricField< Type, faePatchField, edgeMesh > > reconstructEdgeField(const IOobject &fieldObject)
Read and reconstruct edge field.
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:666
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.
Definition: areaFieldsFwd.H:50
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:56
virtual const objectRegistry & thisDb() const
Return reference to the mesh database.
Definition: faMesh.C:815
label nFaces() const noexcept
Number of patch faces.
Definition: faMeshI.H:61
Declarations for faPatchField types.
tmp< GeometricField< Type, faPatchField, areaMesh > > reconstructField(const IOobject &fieldObject, const PtrList< GeometricField< Type, faPatchField, areaMesh >> &) const
Reconstruct area field.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
static const char *const typeName
Typename for Field.
Definition: Field.H:86
A List obtained as a section of another List.
Definition: SubList.H:50
static const DimensionedField< Type, GeoMesh > & null()
Return a NullObjectRef DimensionedField.
Generic templated field type.
Definition: Field.H:62
Author Zeljko Tukovic, FMENA Hrvoje Jasak, Wikki Ltd.
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:31
tmp< GeometricField< Type, faPatchField, areaMesh > > reconstructAreaField(const IOobject &fieldObject)
Read and reconstruct area field.
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:49
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:172
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