PatchEdgeFaceWave.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 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "PatchEdgeFaceWave.H"
29 #include "polyMesh.H"
30 #include "globalMeshData.H"
31 #include "PatchTools.H"
32 
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 
35 template
36 <
37  class PrimitivePatchType,
38  class Type,
39  class TrackingData
40 >
42 propagationTol_ = 0.01;
43 
44 template
45 <
46  class PrimitivePatchType,
47  class Type,
48  class TrackingData
49 >
52 dummyTrackData_ = 12345;
53 
54 
55 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
56 
57 // Update info for edgeI, at position pt, with information from
58 // neighbouring face.
59 // Updates:
60 // - changedEdge_, changedEdges_,
61 // - statistics: nEvals_, nUnvisitedEdges_
62 template
63 <
64  class PrimitivePatchType,
65  class Type,
66  class TrackingData
67 >
70 (
71  const label edgeI,
72  const label neighbourFacei,
73  const Type& neighbourInfo,
74  Type& edgeInfo
75 )
76 {
77  nEvals_++;
78 
79  bool wasValid = edgeInfo.valid(td_);
80 
81  bool propagate =
82  edgeInfo.updateEdge
83  (
84  mesh_,
85  patch_,
86  edgeI,
87  neighbourFacei,
88  neighbourInfo,
89  propagationTol_,
90  td_
91  );
92 
93  if (propagate)
94  {
95  if (!changedEdge_[edgeI])
96  {
97  changedEdge_.set(edgeI);
98  changedEdges_.append(edgeI);
99  }
100  }
101 
102  if (!wasValid && edgeInfo.valid(td_))
103  {
104  --nUnvisitedEdges_;
105  }
106 
107  return propagate;
108 }
109 
110 
111 // Update info for facei, at position pt, with information from
112 // neighbouring edge.
113 // Updates:
114 // - changedFace_, changedFaces_,
115 // - statistics: nEvals_, nUnvisitedFace_
116 template
117 <
118  class PrimitivePatchType,
119  class Type,
120  class TrackingData
121 >
124 (
125  const label facei,
126  const label neighbourEdgeI,
127  const Type& neighbourInfo,
128  Type& faceInfo
129 )
130 {
131  nEvals_++;
132 
133  bool wasValid = faceInfo.valid(td_);
134 
135  bool propagate =
136  faceInfo.updateFace
137  (
138  mesh_,
139  patch_,
140  facei,
141  neighbourEdgeI,
142  neighbourInfo,
143  propagationTol_,
144  td_
145  );
146 
147  if (propagate)
148  {
149  if (changedFace_.set(facei))
150  {
151  changedFaces_.append(facei);
152  }
153  }
154 
155  if (!wasValid && faceInfo.valid(td_))
156  {
157  --nUnvisitedFaces_;
158  }
159 
160  return propagate;
161 }
162 
163 
164 template
165 <
166  class PrimitivePatchType,
167  class Type,
168  class TrackingData
169 >
171 syncEdges()
172 {
173  const globalMeshData& globalData = mesh_.globalData();
174  const mapDistribute& map = globalData.globalEdgeSlavesMap();
175  const bitSet& cppOrientation = globalData.globalEdgeOrientation();
176 
177  // Convert patch-edge data into cpp-edge data
178  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
179 
180  //- Construct with all data in consistent orientation
181  List<Type> cppEdgeData(map.constructSize());
182 
183  forAll(patchEdges_, i)
184  {
185  label patchEdgeI = patchEdges_[i];
186  label coupledEdgeI = coupledEdges_[i];
187 
188  if (changedEdge_[patchEdgeI])
189  {
190  const Type& data = allEdgeInfo_[patchEdgeI];
191 
192  // Patch-edge data needs to be converted into coupled-edge data
193  // (optionally flipped) and consistent in orientation with
194  // master of coupled edge (optionally flipped)
195  bool sameOrientation =
196  (
197  sameEdgeOrientation_[i]
198  == cppOrientation[coupledEdgeI]
199  );
200 
201  cppEdgeData[coupledEdgeI].updateEdge
202  (
203  mesh_,
204  patch_,
205  data,
206  sameOrientation,
207  propagationTol_,
208  td_
209  );
210  }
211  }
212 
213 
214  // Synchronise
215  // ~~~~~~~~~~~
216 
217  globalData.syncData
218  (
219  cppEdgeData,
220  globalData.globalEdgeSlaves(),
221  globalData.globalEdgeTransformedSlaves(),
222  map,
223  globalData.globalTransforms(),
224  updateOp<PrimitivePatchType, Type, TrackingData>
225  (
226  mesh_,
227  patch_,
228  propagationTol_,
229  td_
230  ),
231  transformOp<PrimitivePatchType, Type, TrackingData>
232  (
233  mesh_,
234  patch_,
235  propagationTol_,
236  td_
237  )
238  );
239 
240 
241  // Back from cpp-edge to patch-edge data
242  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
243 
244  forAll(patchEdges_, i)
245  {
246  label patchEdgeI = patchEdges_[i];
247  label coupledEdgeI = coupledEdges_[i];
248 
249  const Type& data = cppEdgeData[coupledEdgeI];
250 
251  if (data.valid(td_))
252  {
253  bool sameOrientation =
254  (
255  sameEdgeOrientation_[i]
256  == cppOrientation[coupledEdgeI]
257  );
258 
259  allEdgeInfo_[patchEdgeI].updateEdge
260  (
261  mesh_,
262  patch_,
263  data,
264  sameOrientation,
265  propagationTol_,
266  td_
267  );
268 
269  if (!changedEdge_[patchEdgeI])
270  {
271  changedEdge_.set(patchEdgeI);
272  changedEdges_.append(patchEdgeI);
273  }
274  }
275  }
276 }
277 
278 
279 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
280 
281 // Iterate, propagating changedEdgesInfo across patch, until no change (or
282 // maxIter reached). Initial edge values specified.
283 template
284 <
285  class PrimitivePatchType,
286  class Type,
287  class TrackingData
288 >
291 (
292  const polyMesh& mesh,
293  const PrimitivePatchType& patch,
294  const labelList& changedEdges,
295  const List<Type>& changedEdgesInfo,
296 
297  UList<Type>& allEdgeInfo,
298  UList<Type>& allFaceInfo,
299 
300  const label maxIter,
301  TrackingData& td
302 )
303 :
304  mesh_(mesh),
305  patch_(patch),
306  allEdgeInfo_(allEdgeInfo),
307  allFaceInfo_(allFaceInfo),
308  td_(td),
309  changedEdge_(patch_.nEdges()),
310  changedEdges_(patch_.size()),
311  changedFace_(patch_.size()),
312  changedFaces_(patch_.size()),
313  nEvals_(0),
314  nUnvisitedEdges_(patch_.nEdges()),
315  nUnvisitedFaces_(patch_.size())
316 {
317  // Calculate addressing between patch_ and mesh.globalData().coupledPatch()
318  // for ease of synchronisation
319  PatchTools::matchEdges
320  (
321  patch_,
322  mesh_.globalData().coupledPatch(),
323 
324  patchEdges_,
325  coupledEdges_,
326  sameEdgeOrientation_
327  );
328 
329 
330  if (allEdgeInfo_.size() != patch_.nEdges())
331  {
333  << "size of edgeInfo work array is not equal to the number"
334  << " of edges in the patch" << endl
335  << " edgeInfo :" << allEdgeInfo_.size() << endl
336  << " patch.nEdges:" << patch_.nEdges()
337  << exit(FatalError);
338  }
339  if (allFaceInfo_.size() != patch_.size())
340  {
342  << "size of edgeInfo work array is not equal to the number"
343  << " of faces in the patch" << endl
344  << " faceInfo :" << allFaceInfo_.size() << endl
345  << " patch.size:" << patch_.size()
346  << exit(FatalError);
347  }
348 
349 
350  // Set from initial changed edges data
351  setEdgeInfo(changedEdges, changedEdgesInfo);
352 
353  if (debug)
354  {
355  Pout<< "Seed edges : " << changedEdges_.size() << endl;
356  }
357 
358  // Iterate until nothing changes
359  label iter = iterate(maxIter);
360 
361  if ((maxIter > 0) && (iter >= maxIter))
362  {
364  << "Maximum number of iterations reached. Increase maxIter." << endl
365  << " maxIter:" << maxIter << endl
366  << " changedEdges:" << changedEdges_.size() << endl
367  << " changedFaces:" << changedFaces_.size() << endl
368  << exit(FatalError);
369  }
370 }
371 
372 
373 template
374 <
375  class PrimitivePatchType,
376  class Type,
377  class TrackingData
378 >
381 (
382  const polyMesh& mesh,
383  const PrimitivePatchType& patch,
384  UList<Type>& allEdgeInfo,
385  UList<Type>& allFaceInfo,
386  TrackingData& td
387 )
388 :
389  mesh_(mesh),
390  patch_(patch),
391  allEdgeInfo_(allEdgeInfo),
392  allFaceInfo_(allFaceInfo),
393  td_(td),
394  changedEdge_(patch_.nEdges()),
395  changedEdges_(patch_.nEdges()),
396  changedFace_(patch_.size()),
397  changedFaces_(patch_.size()),
398  nEvals_(0),
399  nUnvisitedEdges_(patch_.nEdges()),
400  nUnvisitedFaces_(patch_.size())
401 {
402  // Calculate addressing between patch_ and mesh.globalData().coupledPatch()
403  // for ease of synchronisation
404  PatchTools::matchEdges
405  (
406  patch_,
407  mesh_.globalData().coupledPatch(),
408 
409  patchEdges_,
410  coupledEdges_,
411  sameEdgeOrientation_
412  );
413 }
414 
415 
416 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
417 
418 template
419 <
420  class PrimitivePatchType,
421  class Type,
422  class TrackingData
423 >
426 {
427  return nUnvisitedEdges_;
428 }
429 
430 
431 template
432 <
433  class PrimitivePatchType,
434  class Type,
435  class TrackingData
436 >
439 {
440  return nUnvisitedFaces_;
441 }
442 
443 
444 // Copy edge information into member data
445 template
446 <
447  class PrimitivePatchType,
448  class Type,
449  class TrackingData
450 >
453 (
454  const labelList& changedEdges,
455  const List<Type>& changedEdgesInfo
456 )
457 {
458  forAll(changedEdges, changedEdgeI)
459  {
460  label edgeI = changedEdges[changedEdgeI];
461 
462  bool wasValid = allEdgeInfo_[edgeI].valid(td_);
463 
464  // Copy info for edgeI
465  allEdgeInfo_[edgeI] = changedEdgesInfo[changedEdgeI];
466 
467  // Maintain count of unset edges
468  if (!wasValid && allEdgeInfo_[edgeI].valid(td_))
469  {
470  --nUnvisitedEdges_;
471  }
472 
473  // Mark edgeI as changed, both on list and on edge itself.
474 
475  if (!changedEdge_[edgeI])
476  {
477  changedEdge_.set(edgeI);
478  changedEdges_.append(edgeI);
479  }
480  }
481 }
482 
483 
484 // Propagate information from face to edge. Return number of edges changed.
485 template
486 <
487  class PrimitivePatchType,
488  class Type,
489  class TrackingData
490 >
493 {
494  changedEdges_.clear();
495  changedEdge_ = false;
496 
497  forAll(changedFaces_, changedFacei)
498  {
499  label facei = changedFaces_[changedFacei];
500 
501  if (!changedFace_.test(facei))
502  {
504  << "face " << facei
505  << " not marked as having been changed" << nl
506  << "This might be caused by multiple occurences of the same"
507  << " seed edge." << abort(FatalError);
508  }
509 
510  const Type& neighbourWallInfo = allFaceInfo_[facei];
511 
512  // Evaluate all connected edges
513  const labelList& fEdges = patch_.faceEdges()[facei];
514 
515  forAll(fEdges, fEdgeI)
516  {
517  label edgeI = fEdges[fEdgeI];
518 
519  Type& currentWallInfo = allEdgeInfo_[edgeI];
520 
521  if (!currentWallInfo.equal(neighbourWallInfo, td_))
522  {
523  updateEdge
524  (
525  edgeI,
526  facei,
527  neighbourWallInfo,
528  currentWallInfo
529  );
530  }
531  }
532  }
533 
534 
535  syncEdges();
536 
537 
538  if (debug)
539  {
540  Pout<< "Changed edges : " << changedEdges_.size() << endl;
541  }
542 
543  return returnReduce(changedEdges_.size(), sumOp<label>());
544 }
545 
546 
547 // Propagate information from edge to face. Return number of faces changed.
548 template
549 <
550  class PrimitivePatchType,
551  class Type,
552  class TrackingData
553 >
556 {
557  changedFaces_.clear();
558  changedFace_ = false;
559 
560  const labelListList& edgeFaces = patch_.edgeFaces();
561 
562  forAll(changedEdges_, changedEdgeI)
563  {
564  label edgeI = changedEdges_[changedEdgeI];
565 
566  if (!changedEdge_[edgeI])
567  {
569  << "edge " << edgeI
570  << " not marked as having been changed" << nl
571  << "This might be caused by multiple occurences of the same"
572  << " seed edge." << abort(FatalError);
573  }
574 
575  const Type& neighbourWallInfo = allEdgeInfo_[edgeI];
576 
577  // Evaluate all connected faces
578 
579  const labelList& eFaces = edgeFaces[edgeI];
580  forAll(eFaces, eFacei)
581  {
582  label facei = eFaces[eFacei];
583 
584  Type& currentWallInfo = allFaceInfo_[facei];
585 
586  if (!currentWallInfo.equal(neighbourWallInfo, td_))
587  {
588  updateFace
589  (
590  facei,
591  edgeI,
592  neighbourWallInfo,
593  currentWallInfo
594  );
595  }
596  }
597  }
598 
599  if (debug)
600  {
601  Pout<< "Changed faces : " << changedFaces_.size() << endl;
602  }
603 
604  return returnReduce(changedFaces_.size(), sumOp<label>());
605 }
606 
607 
608 // Iterate
609 template
610 <
611  class PrimitivePatchType,
612  class Type,
613  class TrackingData
614 >
616 iterate
617 (
618  const label maxIter
619 )
620 {
621  // Make sure coupled edges contain same info
622  syncEdges();
623 
624  nEvals_ = 0;
625 
626  label iter = 0;
627 
628  while (iter < maxIter)
629  {
630  if (debug)
631  {
632  Pout<< "Iteration " << iter << endl;
633  }
634 
635  label nFaces = edgeToFace();
636 
637  if (debug)
638  {
639  Pout<< "Total changed faces : " << nFaces << endl;
640  }
641 
642  if (nFaces == 0)
643  {
644  break;
645  }
646 
647  label nEdges = faceToEdge();
648 
649  if (debug)
650  {
651  Pout<< "Total changed edges : " << nEdges << nl
652  << "Total evaluations : " << nEvals_ << nl
653  << "Remaining unvisited edges : " << nUnvisitedEdges_ << nl
654  << "Remaining unvisited faces : " << nUnvisitedFaces_ << nl
655  << endl;
656  }
657 
658  if (nEdges == 0)
659  {
660  break;
661  }
662 
663  iter++;
664  }
665 
666  return iter;
667 }
668 
669 
670 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
PatchTools.H
globalMeshData.H
Foam::PatchEdgeFaceWave
Wave propagation of information along patch. Every iteration information goes through one layer of fa...
Definition: PatchEdgeFaceWave.H:71
Foam::PatchEdgeFaceWave::faceToEdge
label faceToEdge()
Propagate from face to edge. Returns total number of edges.
Definition: PatchEdgeFaceWave.C:492
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::PatchEdgeFaceWave::nUnvisitedEdges
label nUnvisitedEdges() const
Definition: PatchEdgeFaceWave.C:425
Foam::Pout
prefixOSstream Pout
An Ostream wrapper for parallel output to std::cout.
polyMesh.H
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
Foam::sumOp
Definition: ops.H:213
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
PatchEdgeFaceWave.H
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:62
Foam::PatchEdgeFaceWave::nUnvisitedFaces
label nUnvisitedFaces() const
Number of unvisited faces, i.e. faces that were not (yet)
Definition: PatchEdgeFaceWave.C:438
Foam::PatchEdgeFaceWave::edgeToFace
label edgeToFace()
Propagate from edge to face. Returns total number of faces.
Definition: PatchEdgeFaceWave.C:555
Foam::FatalError
error FatalError
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:137
Foam::PatchEdgeFaceWave::setEdgeInfo
void setEdgeInfo(const labelList &changedEdges, const List< Type > &changedEdgesInfo)
Copy initial data into allEdgeInfo_.
Definition: PatchEdgeFaceWave.C:453
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
Foam::nl
constexpr char nl
Definition: Ostream.H:372
Foam::foamVersion::patch
const std::string patch
OpenFOAM patch number as a std::string.
Foam::List< label >
Foam::UList< Type >
Foam::List::set
std::enable_if< std::is_same< bool, TypeT >::value, bool >::type set(const label i, bool val=true)
A bitSet::set() method for a list of bool.
Definition: List.H:320
Foam::PatchEdgeFaceWave::iterate
label iterate(const label maxIter)
Iterate until no changes or maxIter reached. Returns actual.
Definition: PatchEdgeFaceWave.C:617