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-------------------------------------------------------------------------------
10License
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
35template
36<
37 class PrimitivePatchType,
38 class Type,
39 class TrackingData
40>
42propagationTol_ = 0.01;
43
44template
45<
46 class PrimitivePatchType,
47 class Type,
48 class TrackingData
49>
50Foam::label
52dummyTrackData_ = 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_
62template
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_
116template
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
164template
165<
166 class PrimitivePatchType,
167 class Type,
168 class TrackingData
169>
171syncEdges()
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.
283template
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
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
373template
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
405 (
406 patch_,
407 mesh_.globalData().coupledPatch(),
408
409 patchEdges_,
410 coupledEdges_,
411 sameEdgeOrientation_
412 );
413}
414
415
416// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
417
418// Copy edge information into member data
419template
420<
421 class PrimitivePatchType,
422 class Type,
423 class TrackingData
424>
427(
428 const labelList& changedEdges,
429 const List<Type>& changedEdgesInfo
430)
431{
432 forAll(changedEdges, changedEdgeI)
433 {
434 label edgeI = changedEdges[changedEdgeI];
435
436 bool wasValid = allEdgeInfo_[edgeI].valid(td_);
437
438 // Copy info for edgeI
439 allEdgeInfo_[edgeI] = changedEdgesInfo[changedEdgeI];
440
441 // Maintain count of unset edges
442 if (!wasValid && allEdgeInfo_[edgeI].valid(td_))
443 {
444 --nUnvisitedEdges_;
445 }
446
447 // Mark edgeI as changed, both on list and on edge itself.
448
449 if (!changedEdge_[edgeI])
450 {
451 changedEdge_.set(edgeI);
452 changedEdges_.append(edgeI);
453 }
454 }
455}
456
457
458// Propagate information from face to edge. Return number of edges changed.
459template
460<
461 class PrimitivePatchType,
462 class Type,
463 class TrackingData
464>
467{
468 changedEdges_.clear();
469 changedEdge_ = false;
470
471 forAll(changedFaces_, changedFacei)
472 {
473 label facei = changedFaces_[changedFacei];
474
475 if (!changedFace_.test(facei))
476 {
478 << "face " << facei
479 << " not marked as having been changed" << nl
480 << "This might be caused by multiple occurrences of the same"
481 << " seed edge." << abort(FatalError);
482 }
483
484 const Type& neighbourWallInfo = allFaceInfo_[facei];
485
486 // Evaluate all connected edges
487 const labelList& fEdges = patch_.faceEdges()[facei];
488
489 forAll(fEdges, fEdgeI)
490 {
491 label edgeI = fEdges[fEdgeI];
492
493 Type& currentWallInfo = allEdgeInfo_[edgeI];
494
495 if (!currentWallInfo.equal(neighbourWallInfo, td_))
496 {
497 updateEdge
498 (
499 edgeI,
500 facei,
501 neighbourWallInfo,
502 currentWallInfo
503 );
504 }
505 }
506 }
507
508
509 syncEdges();
510
511
512 if (debug)
513 {
514 Pout<< "Changed edges : " << changedEdges_.size() << endl;
515 }
516
517 return returnReduce(changedEdges_.size(), sumOp<label>());
518}
519
520
521// Propagate information from edge to face. Return number of faces changed.
522template
523<
524 class PrimitivePatchType,
525 class Type,
526 class TrackingData
527>
530{
531 changedFaces_.clear();
532 changedFace_ = false;
533
534 const labelListList& edgeFaces = patch_.edgeFaces();
535
536 forAll(changedEdges_, changedEdgeI)
537 {
538 label edgeI = changedEdges_[changedEdgeI];
539
540 if (!changedEdge_[edgeI])
541 {
543 << "edge " << edgeI
544 << " not marked as having been changed" << nl
545 << "This might be caused by multiple occurrences of the same"
546 << " seed edge." << abort(FatalError);
547 }
548
549 const Type& neighbourWallInfo = allEdgeInfo_[edgeI];
550
551 // Evaluate all connected faces
552
553 const labelList& eFaces = edgeFaces[edgeI];
554 forAll(eFaces, eFacei)
555 {
556 label facei = eFaces[eFacei];
557
558 Type& currentWallInfo = allFaceInfo_[facei];
559
560 if (!currentWallInfo.equal(neighbourWallInfo, td_))
561 {
562 updateFace
563 (
564 facei,
565 edgeI,
566 neighbourWallInfo,
567 currentWallInfo
568 );
569 }
570 }
571 }
572
573 if (debug)
574 {
575 Pout<< "Changed faces : " << changedFaces_.size() << endl;
576 }
577
578 return returnReduce(changedFaces_.size(), sumOp<label>());
579}
580
581
582// Iterate
583template
584<
585 class PrimitivePatchType,
586 class Type,
587 class TrackingData
588>
591(
592 const label maxIter
593)
594{
595 // Make sure coupled edges contain same info
596 syncEdges();
597
598 nEvals_ = 0;
599
600 label iter = 0;
601
602 while (iter < maxIter)
603 {
604 if (debug)
605 {
606 Pout<< "Iteration " << iter << endl;
607 }
608
609 label nFaces = edgeToFace();
610
611 if (debug)
612 {
613 Pout<< "Total changed faces : " << nFaces << endl;
614 }
615
616 if (nFaces == 0)
617 {
618 break;
619 }
620
621 label nEdges = faceToEdge();
622
623 if (debug)
624 {
625 Pout<< "Total changed edges : " << nEdges << nl
626 << "Total evaluations : " << nEvals_ << nl
627 << "Remaining unvisited edges : " << nUnvisitedEdges_ << nl
628 << "Remaining unvisited faces : " << nUnvisitedFaces_ << nl
629 << endl;
630 }
631
632 if (nEdges == 0)
633 {
634 break;
635 }
636
637 iter++;
638 }
639
640 return iter;
641}
642
643
644// ************************************************************************* //
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:330
Wave propagation of information along patch. Every iteration information goes through one layer of fa...
label edgeToFace()
Propagate from edge to face.
label iterate(const label maxIter)
Iterate until no changes or maxIter reached.
void setEdgeInfo(const labelList &changedEdges, const List< Type > &changedEdgesInfo)
Copy initial data into allEdgeInfo_.
label faceToEdge()
Propagate from face to edge.
static void matchEdges(const PrimitivePatch< FaceList1, PointField1 > &p1, const PrimitivePatch< FaceList2, PointField2 > &p2, labelList &p1EdgeLabels, labelList &p2EdgeLabels, bitSet &sameOrientation)
Find corresponding edges on patches sharing the same points.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: UList.H:94
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
const indirectPrimitivePatch & coupledPatch() const
Return patch of all coupled faces.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:81
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1310
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
const labelList nFaces(UPstream::listGatherValues< label >(aMesh.nFaces()))
const labelList nEdges(UPstream::listGatherValues< label >(aMesh.nEdges()))
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
errorManip< error > abort(error &err)
Definition: errorManip.H:144
error FatalError
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce (copy) and return value.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333