fvFieldReconstructorFields.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) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2018 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 "fvFieldReconstructor.H"
30 #include "Time.H"
31 #include "PtrList.H"
32 #include "fvPatchFields.H"
33 #include "emptyFvPatch.H"
34 #include "emptyFvPatchField.H"
35 #include "emptyFvsPatchField.H"
36 
37 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
38 
39 template<class Type>
42 (
43  const IOobject& fieldIoObject,
44  const PtrList<DimensionedField<Type, volMesh>>& procFields
45 ) const
46 {
47  // Create the internalField
48  Field<Type> internalField(mesh_.nCells());
49 
50  forAll(procMeshes_, proci)
51  {
52  const DimensionedField<Type, volMesh>& procField = procFields[proci];
53 
54  // Set the cell values in the reconstructed field
55  internalField.rmap
56  (
57  procField.field(),
58  cellProcAddressing_[proci]
59  );
60  }
61 
63  (
64  fieldIoObject,
65  mesh_,
66  procFields[0].dimensions(),
67  internalField
68  );
69 
70  tfield.ref().oriented() = procFields[0].oriented();
71 
72  return tfield;
73 }
74 
75 
76 template<class Type>
79 (
80  const IOobject& fieldIoObject
81 ) const
82 {
83  // Read the field for all the processors
85  (
86  procMeshes_.size()
87  );
88 
89  forAll(procMeshes_, proci)
90  {
91  procFields.set
92  (
93  proci,
95  (
96  IOobject
97  (
98  fieldIoObject.name(),
99  procMeshes_[proci].time().timeName(),
100  procMeshes_[proci],
101  IOobject::MUST_READ,
102  IOobject::NO_WRITE
103  ),
104  procMeshes_[proci]
105  )
106  );
107  }
108 
109  return reconstructFvVolumeInternalField
110  (
111  IOobject
112  (
113  fieldIoObject.name(),
114  mesh_.time().timeName(),
115  mesh_,
116  IOobject::NO_READ,
117  IOobject::NO_WRITE
118  ),
119  procFields
120  );
121 }
122 
123 
124 template<class Type>
127 (
128  const IOobject& fieldIoObject,
130 ) const
131 {
132  // Create the internalField
133  Field<Type> internalField(mesh_.nCells());
134 
135  // Create the patch fields
136  PtrList<fvPatchField<Type>> patchFields(mesh_.boundary().size());
137 
138  forAll(procFields, proci)
139  {
141  procFields[proci];
142 
143  // Set the cell values in the reconstructed field
144  internalField.rmap
145  (
146  procField.primitiveField(),
147  cellProcAddressing_[proci]
148  );
149 
150  // Set the boundary patch values in the reconstructed field
151  forAll(boundaryProcAddressing_[proci], patchi)
152  {
153  // Get patch index of the original patch
154  const label curBPatch = boundaryProcAddressing_[proci][patchi];
155 
156  // Get addressing slice for this patch
157  const labelList::subList cp =
158  procField.mesh().boundary()[patchi].patchSlice
159  (
160  faceProcAddressing_[proci]
161  );
162 
163  // check if the boundary patch is not a processor patch
164  if (curBPatch >= 0)
165  {
166  // Regular patch. Fast looping
167 
168  if (!patchFields(curBPatch))
169  {
170  patchFields.set
171  (
172  curBPatch,
174  (
175  procField.boundaryField()[patchi],
176  mesh_.boundary()[curBPatch],
179  (
180  mesh_.boundary()[curBPatch].size()
181  )
182  )
183  );
184  }
185 
186  const label curPatchStart =
187  mesh_.boundaryMesh()[curBPatch].start();
188 
189  labelList reverseAddressing(cp.size());
190 
191  forAll(cp, facei)
192  {
193  // Check
194  if (cp[facei] <= 0)
195  {
197  << "Processor " << proci
198  << " patch "
199  << procField.mesh().boundary()[patchi].name()
200  << " face " << facei
201  << " originates from reversed face since "
202  << cp[facei]
203  << exit(FatalError);
204  }
205 
206  // Subtract one to take into account offsets for
207  // face direction.
208  reverseAddressing[facei] = cp[facei] - 1 - curPatchStart;
209  }
210 
211 
212  patchFields[curBPatch].rmap
213  (
214  procField.boundaryField()[patchi],
215  reverseAddressing
216  );
217  }
218  else
219  {
220  const Field<Type>& curProcPatch =
221  procField.boundaryField()[patchi];
222 
223  // In processor patches, there's a mix of internal faces (some
224  // of them turned) and possible cyclics. Slow loop
225  forAll(cp, facei)
226  {
227  // Subtract one to take into account offsets for
228  // face direction.
229  label curF = cp[facei] - 1;
230 
231  // Is the face on the boundary?
232  if (curF >= mesh_.nInternalFaces())
233  {
234  label curBPatch = mesh_.boundaryMesh().whichPatch(curF);
235 
236  if (!patchFields(curBPatch))
237  {
238  patchFields.set
239  (
240  curBPatch,
242  (
243  mesh_.boundary()[curBPatch].type(),
244  mesh_.boundary()[curBPatch],
246  )
247  );
248  }
249 
250  // add the face
251  label curPatchFace =
252  mesh_.boundaryMesh()
253  [curBPatch].whichFace(curF);
254 
255  patchFields[curBPatch][curPatchFace] =
256  curProcPatch[facei];
257  }
258  }
259  }
260  }
261  }
262 
263  forAll(mesh_.boundary(), patchi)
264  {
265  // add empty patches
266  if
267  (
268  isType<emptyFvPatch>(mesh_.boundary()[patchi])
269  && !patchFields(patchi)
270  )
271  {
272  patchFields.set
273  (
274  patchi,
276  (
278  mesh_.boundary()[patchi],
280  )
281  );
282  }
283  }
284 
285 
286  // Now construct and write the field
287  // setting the internalField and patchFields
289  (
290  fieldIoObject,
291  mesh_,
292  procFields[0].dimensions(),
293  internalField,
294  patchFields
295  );
296 
297  tfield.ref().oriented() = procFields[0].oriented();
298 
299  return tfield;
300 }
301 
302 
303 template<class Type>
306 (
307  const IOobject& fieldIoObject
308 ) const
309 {
310  // Read the field for all the processors
312  (
313  procMeshes_.size()
314  );
315 
316  forAll(procMeshes_, proci)
317  {
318  procFields.set
319  (
320  proci,
322  (
323  IOobject
324  (
325  fieldIoObject.name(),
326  procMeshes_[proci].time().timeName(),
327  procMeshes_[proci],
328  IOobject::MUST_READ,
329  IOobject::NO_WRITE
330  ),
331  procMeshes_[proci]
332  )
333  );
334  }
335 
336  return reconstructFvVolumeField
337  (
338  IOobject
339  (
340  fieldIoObject.name(),
341  mesh_.time().timeName(),
342  mesh_,
343  IOobject::NO_READ,
344  IOobject::NO_WRITE
345  ),
346  procFields
347  );
348 }
349 
350 
351 template<class Type>
354 (
355  const IOobject& fieldIoObject,
357 ) const
358 {
359  // Create the internalField
360  Field<Type> internalField(mesh_.nInternalFaces());
361 
362  // Create the patch fields
363  PtrList<fvsPatchField<Type>> patchFields(mesh_.boundary().size());
364 
365 
366  forAll(procMeshes_, proci)
367  {
369  procFields[proci];
370 
371  // Set the face values in the reconstructed field
372 
373  // It is necessary to create a copy of the addressing array to
374  // take care of the face direction offset trick.
375  //
376  {
377  const labelList& faceMap = faceProcAddressing_[proci];
378 
379  // Correctly oriented copy of internal field
380  Field<Type> procInternalField(procField.primitiveField());
381  // Addressing into original field
382  labelList curAddr(procInternalField.size());
383 
384  forAll(procInternalField, addrI)
385  {
386  curAddr[addrI] = mag(faceMap[addrI])-1;
387  if (faceMap[addrI] < 0)
388  {
389  procInternalField[addrI] = -procInternalField[addrI];
390  }
391  }
392 
393  // Map
394  internalField.rmap(procInternalField, curAddr);
395  }
396 
397  // Set the boundary patch values in the reconstructed field
398  forAll(boundaryProcAddressing_[proci], patchi)
399  {
400  // Get patch index of the original patch
401  const label curBPatch = boundaryProcAddressing_[proci][patchi];
402 
403  // Get addressing slice for this patch
404  const labelList::subList cp =
405  procMeshes_[proci].boundary()[patchi].patchSlice
406  (
407  faceProcAddressing_[proci]
408  );
409 
410  // check if the boundary patch is not a processor patch
411  if (curBPatch >= 0)
412  {
413  // Regular patch. Fast looping
414 
415  if (!patchFields(curBPatch))
416  {
417  patchFields.set
418  (
419  curBPatch,
421  (
422  procField.boundaryField()[patchi],
423  mesh_.boundary()[curBPatch],
426  (
427  mesh_.boundary()[curBPatch].size()
428  )
429  )
430  );
431  }
432 
433  const label curPatchStart =
434  mesh_.boundaryMesh()[curBPatch].start();
435 
436  labelList reverseAddressing(cp.size());
437 
438  forAll(cp, facei)
439  {
440  // Subtract one to take into account offsets for
441  // face direction.
442  reverseAddressing[facei] = cp[facei] - 1 - curPatchStart;
443  }
444 
445  patchFields[curBPatch].rmap
446  (
447  procField.boundaryField()[patchi],
448  reverseAddressing
449  );
450  }
451  else
452  {
453  const Field<Type>& curProcPatch =
454  procField.boundaryField()[patchi];
455 
456  // In processor patches, there's a mix of internal faces (some
457  // of them turned) and possible cyclics. Slow loop
458  forAll(cp, facei)
459  {
460  label curF = cp[facei] - 1;
461 
462  // Is the face turned the right side round
463  if (curF >= 0)
464  {
465  // Is the face on the boundary?
466  if (curF >= mesh_.nInternalFaces())
467  {
468  label curBPatch =
469  mesh_.boundaryMesh().whichPatch(curF);
470 
471  if (!patchFields(curBPatch))
472  {
473  patchFields.set
474  (
475  curBPatch,
477  (
478  mesh_.boundary()[curBPatch].type(),
479  mesh_.boundary()[curBPatch],
481  ::null()
482  )
483  );
484  }
485 
486  // add the face
487  label curPatchFace =
488  mesh_.boundaryMesh()
489  [curBPatch].whichFace(curF);
490 
491  patchFields[curBPatch][curPatchFace] =
492  curProcPatch[facei];
493  }
494  else
495  {
496  // Internal face
497  internalField[curF] = curProcPatch[facei];
498  }
499  }
500  }
501  }
502  }
503  }
504 
505  forAll(mesh_.boundary(), patchi)
506  {
507  // add empty patches
508  if
509  (
510  isType<emptyFvPatch>(mesh_.boundary()[patchi])
511  && !patchFields(patchi)
512  )
513  {
514  patchFields.set
515  (
516  patchi,
518  (
520  mesh_.boundary()[patchi],
522  )
523  );
524  }
525  }
526 
527 
528  // Now construct and write the field
529  // setting the internalField and patchFields
531  (
532  fieldIoObject,
533  mesh_,
534  procFields[0].dimensions(),
535  internalField,
536  patchFields
537  );
538 
539  tfield.ref().oriented() = procFields[0].oriented();
540 
541  return tfield;
542 }
543 
544 
545 template<class Type>
548 (
549  const IOobject& fieldIoObject
550 ) const
551 {
552  // Read the field for all the processors
554  (
555  procMeshes_.size()
556  );
557 
558  forAll(procMeshes_, proci)
559  {
560  procFields.set
561  (
562  proci,
564  (
565  IOobject
566  (
567  fieldIoObject.name(),
568  procMeshes_[proci].time().timeName(),
569  procMeshes_[proci],
570  IOobject::MUST_READ,
571  IOobject::NO_WRITE
572  ),
573  procMeshes_[proci]
574  )
575  );
576  }
577 
578  return reconstructFvSurfaceField
579  (
580  IOobject
581  (
582  fieldIoObject.name(),
583  mesh_.time().timeName(),
584  mesh_,
585  IOobject::NO_READ,
586  IOobject::NO_WRITE
587  ),
588  procFields
589  );
590 }
591 
592 
593 template<class Type>
595 (
596  const IOobjectList& objects,
597  const UList<word>& fieldNames
598 )
599 {
600  typedef DimensionedField<Type, volMesh> fieldType;
601 
602  label nFields = 0;
603  for (const word& fieldName : fieldNames)
604  {
605  const IOobject* io = objects.cfindObject<fieldType>(fieldName);
606  if (io)
607  {
608  if (!nFields++)
609  {
610  Info<< " Reconstructing "
611  << fieldType::typeName << "s\n" << nl;
612  }
613  Info<< " " << fieldName << endl;
614 
615  reconstructFvVolumeInternalField<Type>(*io)().write();
616  ++nReconstructed_;
617  }
618  }
619 
620  if (nFields) Info<< endl;
621  return nFields;
622 }
623 
624 
625 template<class Type>
627 (
628  const IOobjectList& objects,
629  const UList<word>& fieldNames
630 )
631 {
633 
634  label nFields = 0;
635  for (const word& fieldName : fieldNames)
636  {
637  const IOobject* io = objects.cfindObject<fieldType>(fieldName);
638  if (io)
639  {
640  if (!nFields++)
641  {
642  Info<< " Reconstructing "
643  << fieldType::typeName << "s\n" << nl;
644  }
645  Info<< " " << fieldName << endl;
646 
647  reconstructFvVolumeField<Type>(*io)().write();
648  ++nReconstructed_;
649  }
650  }
651 
652  if (nFields) Info<< endl;
653  return nFields;
654 }
655 
656 
657 template<class Type>
659 (
660  const IOobjectList& objects,
661  const UList<word>& fieldNames
662 )
663 {
665 
666  label nFields = 0;
667  for (const word& fieldName : fieldNames)
668  {
669  const IOobject* io = objects.cfindObject<fieldType>(fieldName);
670  if (io)
671  {
672  if (!nFields++)
673  {
674  Info<< " Reconstructing "
675  << fieldType::typeName << "s\n" << nl;
676  }
677  Info<< " " << fieldName << endl;
678 
679  reconstructFvSurfaceField<Type>(*io)().write();
680  ++nReconstructed_;
681  }
682  }
683 
684  if (nFields) Info<< endl;
685  return nFields;
686 }
687 
688 
689 template<class Type>
691 (
692  const IOobjectList& objects,
693  const wordRes& selectedFields
694 )
695 {
696  typedef DimensionedField<Type, volMesh> fieldType;
697 
698  const wordList fieldNames =
699  (
700  selectedFields.empty()
701  ? objects.sortedNames<fieldType>()
702  : objects.sortedNames<fieldType>(selectedFields)
703  );
704 
705  return reconstructFvVolumeInternalFields<Type>(objects, fieldNames);
706 }
707 
708 
709 template<class Type>
711 (
712  const IOobjectList& objects,
713  const wordRes& selectedFields
714 )
715 {
717 
718  const wordList fieldNames =
719  (
720  selectedFields.empty()
721  ? objects.sortedNames<fieldType>()
722  : objects.sortedNames<fieldType>(selectedFields)
723  );
724 
725  return reconstructFvVolumeFields<Type>(objects, fieldNames);
726 }
727 
728 
729 template<class Type>
731 (
732  const IOobjectList& objects,
733  const wordRes& selectedFields
734 )
735 {
737 
738  const wordList fieldNames =
739  (
740  selectedFields.empty()
741  ? objects.sortedNames<fieldType>()
742  : objects.sortedNames<fieldType>(selectedFields)
743  );
744 
745  return reconstructFvSurfaceFields<Type>(objects, fieldNames);
746 }
747 
748 
749 template<class Type>
751 (
752  const IOobjectList& objects,
753  const wordHashSet& selectedFields
754 )
755 {
756  typedef DimensionedField<Type, volMesh> fieldType;
757 
758  const wordList fieldNames =
759  (
760  selectedFields.empty()
761  ? objects.sortedNames<fieldType>()
762  : objects.sortedNames<fieldType>(selectedFields)
763  );
764 
765  return reconstructFvVolumeInternalFields<Type>(objects, fieldNames);
766 }
767 
768 
769 template<class Type>
771 (
772  const IOobjectList& objects,
773  const wordHashSet& selectedFields
774 )
775 {
777 
778  const wordList fieldNames =
779  (
780  selectedFields.empty()
781  ? objects.sortedNames<fieldType>()
782  : objects.sortedNames<fieldType>(selectedFields)
783  );
784 
785  return reconstructFvVolumeField<Type>(objects, fieldNames);
786 }
787 
788 
789 template<class Type>
791 (
792  const IOobjectList& objects,
793  const wordHashSet& selectedFields
794 )
795 {
797 
798  const wordList fieldNames =
799  (
800  selectedFields.empty()
801  ? objects.sortedNames<fieldType>()
802  : objects.sortedNames<fieldType>(selectedFields)
803  );
804 
805  return reconstructFvSurfaceFields<Type>(objects, fieldNames);
806 }
807 
808 
809 // ************************************************************************* //
Foam::fvPatchField
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Definition: volSurfaceMapping.H:51
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:169
Foam::fvFieldReconstructor::reconstructFvVolumeField
tmp< GeometricField< Type, fvPatchField, volMesh > > reconstructFvVolumeField(const IOobject &fieldIoObject, const PtrList< GeometricField< Type, fvPatchField, volMesh >> &) const
Reconstruct volume field.
Foam::fvFieldReconstructor::reconstructFvVolumeInternalFields
label reconstructFvVolumeInternalFields(const IOobjectList &objects, const UList< word > &fieldNames)
Read, reconstruct and write specified volume internal fields.
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeTopological.C:94
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
cp
const volScalarField & cp
Definition: setRegionSolidFields.H:8
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
Foam::DimensionedField::field
const Field< Type > & field() const
Return field.
Definition: DimensionedFieldI.H:90
fvFieldReconstructor.H
Foam::SubList
A List obtained as a section of another List.
Definition: SubList.H:54
Foam::GeometricField::primitiveField
const Internal::FieldType & primitiveField() const
Return a const-reference to the internal field.
Definition: GeometricFieldI.H:53
Foam::emptyFvsPatchField
Foam::emptyFvsPatchField.
Definition: emptyFvsPatchField.H:52
Foam::fvsPatchField
An abstract base class with a fat-interface to all derived classes covering all possible ways in whic...
Definition: fvsPatchField.H:68
Foam::IOobjectList::sortedNames
wordList sortedNames() const
The sorted names of the IOobjects.
Definition: IOobjectList.C:345
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
emptyFvsPatchField.H
Foam::HashSet< word, Hash< word > >
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::fvFieldReconstructor::reconstructFvSurfaceField
tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > reconstructFvSurfaceField(const IOobject &fieldIoObject, const PtrList< GeometricField< Type, fvsPatchField, surfaceMesh >> &) const
Reconstruct surface field.
Foam::fvFieldReconstructor::fvPatchFieldReconstructor
Mapper for sizing only - does not do any actual mapping.
Definition: fvFieldReconstructor.H:91
Foam::Field
Generic templated field type.
Definition: Field.H:63
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::IOobjectList::cfindObject
const IOobject * cfindObject(const word &objName) const
Return const pointer to the object found by name.
Definition: IOobjectList.C:245
Foam::PtrList
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: List.H:59
Foam::emptyFvPatchField
This boundary condition provides an 'empty' condition for reduced dimensions cases,...
Definition: emptyFvPatchField.H:67
Foam::FatalError
error FatalError
fieldNames
const wordRes fieldNames(propsDict.getOrDefault< wordRes >("fields", wordRes()))
emptyFvPatch.H
Foam::IOobjectList
List of IOobjects with searching and retrieving facilities.
Definition: IOobjectList.H:55
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::New
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
Definition: DimensionedFieldReuseFunctions.H:105
Foam::IOobject::name
const word & name() const noexcept
Return name.
Definition: IOobjectI.H:65
Time.H
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
emptyFvPatchField.H
Foam::nl
constexpr char nl
Definition: Ostream.H:404
fvPatchFields.H
Foam::List< label >
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::UList
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:103
Foam::wordRes
A List of wordRe with additional matching capabilities.
Definition: wordRes.H:51
Foam::vtk::write
void write(vtk::formatter &fmt, const Type &val, const label n=1)
Component-wise write of a value (N times)
Definition: foamVtkOutputTemplates.C:36
PtrList.H
Foam::fvFieldReconstructor::reconstructFvVolumeInternalField
tmp< DimensionedField< Type, volMesh > > reconstructFvVolumeInternalField(const IOobject &fieldIoObject, const PtrList< DimensionedField< Type, volMesh >> &procFields) const
Reconstruct volume internal field.
Foam::GeometricField< Type, fvPatchField, volMesh >
Foam::fvFieldReconstructor::reconstructFvSurfaceFields
label reconstructFvSurfaceFields(const IOobjectList &objects, const UList< word > &fieldNames)
Read, reconstruct and write specified surface fields.
Foam::fvFieldReconstructor::reconstructFvVolumeFields
label reconstructFvVolumeFields(const IOobjectList &objects, const UList< word > &fieldNames)
Read, reconstruct and write specified volume fields.
Foam::GeometricField::boundaryField
const Boundary & boundaryField() const
Return const-reference to the boundary field.
Definition: GeometricFieldI.H:62
Foam::DimensionedField
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Definition: DimensionedField.H:54