faFieldReconstructorFields.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 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"
35 #include "emptyFaePatchField.H"
36 
37 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
38 
39 template<class Type>
42 (
43  const IOobject& fieldIoObject
44 )
45 {
46  // Read the field for all the processors
48  (
49  procMeshes_.size()
50  );
51 
52  forAll(procMeshes_, procI)
53  {
54  procFields.set
55  (
56  procI,
58  (
59  IOobject
60  (
61  fieldIoObject.name(),
62  procMeshes_[procI].time().timeName(),
63  procMeshes_[procI](),
64  IOobject::MUST_READ,
65  IOobject::NO_WRITE
66  ),
67  procMeshes_[procI]
68  )
69  );
70  }
71 
72  // Create the internalField
73  Field<Type> internalField(mesh_.nFaces());
74 
75  // Create the patch fields
76  PtrList<faPatchField<Type>> patchFields(mesh_.boundary().size());
77 
78 
79  // Create global mesh patches starts
80 
81  labelList gStarts(mesh_.boundary().size(), -1);
82 
83  if (mesh_.boundary().size() > 0)
84  {
85  gStarts[0] = mesh_.nInternalEdges();
86  }
87 
88  for(label i=1; i<mesh_.boundary().size(); i++)
89  {
90  gStarts[i] = gStarts[i-1] + mesh_.boundary()[i-1].labelList::size();
91  }
92 
93  forAll(procMeshes_, procI)
94  {
96  procFields[procI];
97 
98  // Set the face values in the reconstructed field
99  internalField.rmap
100  (
101  procField.internalField(),
102  faceProcAddressing_[procI]
103  );
104 
105 
106 
107  // Set the boundary patch values in the reconstructed field
108 
109  labelList starts(procMeshes_[procI].boundary().size(), -1);
110 
111  if(procMeshes_[procI].boundary().size() > 0)
112  {
113  starts[0] = procMeshes_[procI].nInternalEdges();
114  }
115 
116  for(label i=1; i<procMeshes_[procI].boundary().size(); i++)
117  {
118  starts[i] =
119  starts[i-1]
120  + procMeshes_[procI].boundary()[i-1].labelList::size();
121  }
122 
123  forAll(boundaryProcAddressing_[procI], patchI)
124  {
125  // Get patch index of the original patch
126  const label curBPatch = boundaryProcAddressing_[procI][patchI];
127 
128  // Get addressing slice for this patch
129 
130 // const labelList::subList cp =
131 // procMeshes_[procI].boundary()[patchI].patchSlice
132 // (
133 // edgeProcAddressing_[procI]
134 // );
135 
136  const labelList::subList cp =
138  (
139  edgeProcAddressing_[procI],
140  procMeshes_[procI].boundary()[patchI].size(),
141  starts[patchI]
142  );
143 
144  // check if the boundary patch is not a processor patch
145  if (curBPatch >= 0)
146  {
147  // Regular patch. Fast looping
148 
149  if (!patchFields(curBPatch))
150  {
151  patchFields.set
152  (
153  curBPatch,
155  (
156  procField.boundaryField()[patchI],
157  mesh_.boundary()[curBPatch],
160  (
161  mesh_.boundary()[curBPatch].size(),
162  procField.boundaryField()[patchI].size()
163  )
164  )
165  );
166  }
167 
168  const label curPatchStart = gStarts[curBPatch];
169 // mesh_.boundary()[curBPatch].start();
170 
171  labelList reverseAddressing(cp.size());
172 
173  forAll(cp, edgeI)
174  {
175  // Subtract one to take into account offsets for
176  // face direction.
177 // reverseAddressing[edgeI] = cp[edgeI] - 1 - curPatchStart;
178  reverseAddressing[edgeI] = cp[edgeI] - curPatchStart;
179  }
180 
181  patchFields[curBPatch].rmap
182  (
183  procField.boundaryField()[patchI],
184  reverseAddressing
185  );
186  }
187  else
188  {
189  const Field<Type>& curProcPatch =
190  procField.boundaryField()[patchI];
191 
192  // In processor patches, there's a mix of internal faces (some
193  // of them turned) and possible cyclics. Slow loop
194  forAll(cp, edgeI)
195  {
196  // Subtract one to take into account offsets for
197  // face direction.
198 // label curE = cp[edgeI] - 1;
199  label curE = cp[edgeI];
200 
201  // Is the face on the boundary?
202  if (curE >= mesh_.nInternalEdges())
203  {
204 // label curBPatch = mesh_.boundary().whichPatch(curE);
205  label curBPatch = -1;
206 
207  forAll(mesh_.boundary(), pI)
208  {
209  if
210  (
211  curE >= gStarts[pI]
212  && curE <
213  (
214  gStarts[pI]
215  + mesh_.boundary()[pI].labelList::size()
216  )
217  )
218  {
219  curBPatch = pI;
220  }
221  }
222 
223  if (!patchFields(curBPatch))
224  {
225  patchFields.set
226  (
227  curBPatch,
229  (
230  mesh_.boundary()[curBPatch].type(),
231  mesh_.boundary()[curBPatch],
233  )
234  );
235  }
236 
237  // add the edge
238 // label curPatchEdge =
239 // mesh_.boundary()
240 // [curBPatch].whichEdge(curE);
241 
242  label curPatchEdge = curE - gStarts[curBPatch];
243 
244  patchFields[curBPatch][curPatchEdge] =
245  curProcPatch[edgeI];
246  }
247  }
248  }
249  }
250  }
251 
252  forAll(mesh_.boundary(), patchI)
253  {
254  // add empty patches
255  if
256  (
257  isA<emptyFaPatch>(mesh_.boundary()[patchI])
258  && !patchFields(patchI)
259  )
260  {
261  patchFields.set
262  (
263  patchI,
265  (
267  mesh_.boundary()[patchI],
269  )
270  );
271  }
272  }
273 
274 
275  // Now construct and write the field
276  // setting the internalField and patchFields
278  (
279  IOobject
280  (
281  fieldIoObject.name(),
282  mesh_.time().timeName(),
283  mesh_(),
284  IOobject::NO_READ,
285  IOobject::NO_WRITE
286  ),
287  mesh_,
288  procFields[0].dimensions(),
289  internalField,
290  patchFields
291  );
292 }
293 
294 
295 template<class Type>
298 (
299  const IOobject& fieldIoObject
300 )
301 {
302  // Read the field for all the processors
304  (
305  procMeshes_.size()
306  );
307 
308  forAll(procMeshes_, procI)
309  {
310  procFields.set
311  (
312  procI,
314  (
315  IOobject
316  (
317  fieldIoObject.name(),
318  procMeshes_[procI].time().timeName(),
319  procMeshes_[procI](),
320  IOobject::MUST_READ,
321  IOobject::NO_WRITE
322  ),
323  procMeshes_[procI]
324  )
325  );
326  }
327 
328 
329  // Create the internalField
330  Field<Type> internalField(mesh_.nInternalEdges());
331 
332  // Create the patch fields
333  PtrList<faePatchField<Type>> patchFields(mesh_.boundary().size());
334 
335 
336  labelList gStarts(mesh_.boundary().size(), -1);
337 
338  if(mesh_.boundary().size() > 0)
339  {
340  gStarts[0] = mesh_.nInternalEdges();
341  }
342 
343  for(label i=1; i<mesh_.boundary().size(); i++)
344  {
345  gStarts[i] = gStarts[i-1] + mesh_.boundary()[i-1].labelList::size();
346  }
347 
348 
349  forAll(procMeshes_, procI)
350  {
352  procFields[procI];
353 
354  // Set the face values in the reconstructed field
355 
356  // It is necessary to create a copy of the addressing array to
357  // take care of the face direction offset trick.
358  //
359  {
360  labelList curAddr(edgeProcAddressing_[procI]);
361 
362 // forAll(curAddr, addrI)
363 // {
364 // curAddr[addrI] -= 1;
365 // }
366 
367  internalField.rmap
368  (
369  procField.internalField(),
370  curAddr
371  );
372  }
373 
374  // Set the boundary patch values in the reconstructed field
375 
376  labelList starts(procMeshes_[procI].boundary().size(), -1);
377 
378  if(procMeshes_[procI].boundary().size() > 0)
379  {
380  starts[0] = procMeshes_[procI].nInternalEdges();
381  }
382 
383  for(label i=1; i<procMeshes_[procI].boundary().size(); i++)
384  {
385  starts[i] =
386  starts[i-1]
387  + procMeshes_[procI].boundary()[i-1].labelList::size();
388  }
389 
390  forAll(boundaryProcAddressing_[procI], patchI)
391  {
392  // Get patch index of the original patch
393  const label curBPatch = boundaryProcAddressing_[procI][patchI];
394 
395  // Get addressing slice for this patch
396 
397 // const labelList::subList cp =
398 // procMeshes_[procI].boundary()[patchI].patchSlice
399 // (
400 // faceProcAddressing_[procI]
401 // );
402 
403  const labelList::subList cp =
405  (
406  edgeProcAddressing_[procI],
407  procMeshes_[procI].boundary()[patchI].size(),
408  starts[patchI]
409  );
410 
411  // check if the boundary patch is not a processor patch
412  if (curBPatch >= 0)
413  {
414  // Regular patch. Fast looping
415 
416  if (!patchFields(curBPatch))
417  {
418  patchFields.set
419  (
420  curBPatch,
422  (
423  procField.boundaryField()[patchI],
424  mesh_.boundary()[curBPatch],
427  (
428  mesh_.boundary()[curBPatch].size(),
429  procField.boundaryField()[patchI].size()
430  )
431  )
432  );
433  }
434 
435  const label curPatchStart = gStarts[curBPatch];
436 // mesh_.boundary()[curBPatch].start();
437 
438  labelList reverseAddressing(cp.size());
439 
440  forAll(cp, edgeI)
441  {
442  // Subtract one to take into account offsets for
443  // face direction.
444 // reverseAddressing[faceI] = cp[faceI] - 1 - curPatchStart;
445  reverseAddressing[edgeI] = cp[edgeI] - curPatchStart;
446  }
447 
448  patchFields[curBPatch].rmap
449  (
450  procField.boundaryField()[patchI],
451  reverseAddressing
452  );
453  }
454  else
455  {
456  const Field<Type>& curProcPatch =
457  procField.boundaryField()[patchI];
458 
459  // In processor patches, there's a mix of internal faces (some
460  // of them turned) and possible cyclics. Slow loop
461  forAll(cp, edgeI)
462  {
463 // label curF = cp[edgeI] - 1;
464  label curE = cp[edgeI];
465 
466  // Is the face turned the right side round
467  if (curE >= 0)
468  {
469  // Is the face on the boundary?
470  if (curE >= mesh_.nInternalEdges())
471  {
472 // label curBPatch =
473 // mesh_.boundary().whichPatch(curF);
474 
475  label curBPatch = -1;
476 
477  forAll(mesh_.boundary(), pI)
478  {
479  if
480  (
481  curE >= gStarts[pI]
482  && curE <
483  (
484  gStarts[pI]
485  + mesh_.boundary()[pI].labelList::size()
486  )
487  )
488  {
489  curBPatch = pI;
490  }
491  }
492 
493  if (!patchFields(curBPatch))
494  {
495  patchFields.set
496  (
497  curBPatch,
499  (
500  mesh_.boundary()[curBPatch].type(),
501  mesh_.boundary()[curBPatch],
503  ::null()
504  )
505  );
506  }
507 
508  // add the face
509 // label curPatchFace =
510 // mesh_.boundary()
511 // [curBPatch].whichEdge(curF);
512 
513  label curPatchEdge = curE - gStarts[curBPatch];
514 
515  patchFields[curBPatch][curPatchEdge] =
516  curProcPatch[edgeI];
517  }
518  else
519  {
520  // Internal face
521  internalField[curE] = curProcPatch[edgeI];
522  }
523  }
524  }
525  }
526  }
527  }
528 
529  forAll(mesh_.boundary(), patchI)
530  {
531  // add empty patches
532  if
533  (
534  isA<emptyFaPatch>(mesh_.boundary()[patchI])
535  && !patchFields(patchI)
536  )
537  {
538  patchFields.set
539  (
540  patchI,
542  (
544  mesh_.boundary()[patchI],
546  )
547  );
548  }
549  }
550 
551 
552  // Now construct and write the field
553  // setting the internalField and patchFields
555  (
556  IOobject
557  (
558  fieldIoObject.name(),
559  mesh_.time().timeName(),
560  mesh_(),
561  IOobject::NO_READ,
562  IOobject::NO_WRITE
563  ),
564  mesh_,
565  procFields[0].dimensions(),
566  internalField,
567  patchFields
568  );
569 }
570 
571 
572 // Reconstruct and write all area fields
573 template<class Type>
575 (
576  const IOobjectList& objects
577 )
578 {
579  const word& clsName =
581 
582  const wordList fieldNames = objects.sortedNames(clsName);
583 
584  if (fieldNames.size())
585  {
586  Info<< " Reconstructing " << clsName << "s\n" << endl;
587  }
588 
589  for (const word& fieldName : fieldNames)
590  {
591  Info << " " << fieldName << endl;
592  reconstructFaAreaField<Type>(*(objects[fieldName]))().write();
593  }
594 
595  if (fieldNames.size()) Info<< endl;
596 }
597 
598 
599 // Reconstruct and write all edge fields
600 template<class Type>
602 (
603  const IOobjectList& objects
604 )
605 {
606  const word& clsName =
608 
609  const wordList fieldNames = objects.sortedNames(clsName);
610 
611  if (fieldNames.size())
612  {
613  Info<< " Reconstructing " << clsName << "s\n" << endl;
614  }
615 
616  for (const word& fieldName : fieldNames)
617  {
618  Info << " " << fieldName << endl;
619 
620  reconstructFaEdgeField<Type>(*(objects[fieldName]))().write();
621  }
622 
623  if (fieldNames.size()) Info<< endl;
624 }
625 
626 
627 // ************************************************************************* //
Foam::faFieldReconstructor::reconstructFaAreaField
tmp< GeometricField< Type, faPatchField, areaMesh > > reconstructFaAreaField(const IOobject &fieldIoObject)
Reconstruct area field.
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:169
Foam::faPatchField
faPatchField<Type> abstract base class. This class gives a fat-interface to all derived classes cover...
Definition: areaFieldsFwd.H:50
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::faePatchField
faePatchField<Type> abstract base class. This class gives a fat-interface to all derived classes cove...
Definition: edgeFieldsFwd.H:49
cp
const volScalarField & cp
Definition: setRegionSolidFields.H:8
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
Foam::emptyFaPatchField
Author Zeljko Tukovic, FMENA Hrvoje Jasak, Wikki Ltd.
Definition: emptyFaPatchField.H:56
Foam::SubList
A List obtained as a section of another List.
Definition: SubList.H:54
Foam::IOobjectList::sortedNames
wordList sortedNames() const
The sorted names of the IOobjects.
Definition: IOobjectList.C:345
Foam::faFieldReconstructor::reconstructFaAreaFields
void reconstructFaAreaFields(const IOobjectList &objects)
Reconstruct and write all area fields.
Definition: faFieldReconstructorFields.C:575
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::GeometricField::internalField
const Internal & internalField() const
Return a const-reference to the dimensioned internal field.
Definition: GeometricFieldI.H:43
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
emptyFaPatchField.H
Foam::faFieldReconstructor::faPatchFieldReconstructor
Definition: faFieldReconstructor.H:90
Foam::Field
Generic templated field type.
Definition: Field.H:63
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
emptyFaePatchField.H
Foam::faFieldReconstructor::reconstructFaEdgeFields
void reconstructFaEdgeFields(const IOobjectList &objects)
Reconstruct and write all area fields.
Definition: faFieldReconstructorFields.C:602
Foam::PtrList
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: List.H:59
fieldNames
const wordRes fieldNames(propsDict.getOrDefault< wordRes >("fields", wordRes()))
Foam::faFieldReconstructor::reconstructFaEdgeField
tmp< GeometricField< Type, faePatchField, edgeMesh > > reconstructFaEdgeField(const IOobject &fieldIoObject)
Reconstruct edge field.
Foam::IOobjectList
List of IOobjects with searching and retrieving facilities.
Definition: IOobjectList.H:55
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
Foam::emptyFaePatchField
Author Zeljko Tukovic, FMENA Hrvoje Jasak, Wikki Ltd.
Definition: emptyFaePatchField.H:56
Foam::List< label >
faFieldReconstructor.H
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
faPatchFields.H
PtrList.H
Foam::GeometricField
Generic GeometricField class.
Definition: areaFieldsFwd.H:53
emptyFaPatch.H
boundary
faceListList boundary
Definition: createBlockMesh.H:4
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