1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "PointEdgeWave.H"
28 #include "processorPolyPatch.H"
29 #include "cyclicPolyPatch.H"
32 #include "PstreamCombineReduceOps.H"
35 #include "globalMeshData.H"
36 #include "pointFields.H"
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 template <class Type, class TrackingData>
41 Foam::scalar Foam::PointEdgeWave<Type, TrackingData>::propagationTol_ = 0.01;
43 template <class Type, class TrackingData>
44 Foam::label Foam::PointEdgeWave<Type, TrackingData>::dummyTrackData_ = 12345;
47 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
49 // Handle leaving domain. Implementation referred to Type
50 template <class Type, class TrackingData>
51 void Foam::PointEdgeWave<Type, TrackingData>::leaveDomain
53 const polyPatch& patch,
54 const labelList& patchPointLabels,
58 const labelList& meshPoints = patch.meshPoints();
60 forAll(patchPointLabels, i)
62 label patchPointI = patchPointLabels[i];
64 const point& pt = patch.points()[meshPoints[patchPointI]];
66 pointInfo[i].leaveDomain(patch, patchPointI, pt, td_);
71 // Handle entering domain. Implementation referred to Type
72 template <class Type, class TrackingData>
73 void Foam::PointEdgeWave<Type, TrackingData>::enterDomain
75 const polyPatch& patch,
76 const labelList& patchPointLabels,
80 const labelList& meshPoints = patch.meshPoints();
82 forAll(patchPointLabels, i)
84 label patchPointI = patchPointLabels[i];
86 const point& pt = patch.points()[meshPoints[patchPointI]];
88 pointInfo[i].enterDomain(patch, patchPointI, pt, td_);
93 // Transform. Implementation referred to Type
94 template <class Type, class TrackingData>
95 void Foam::PointEdgeWave<Type, TrackingData>::transform
97 const polyPatch& patch,
98 const tensorField& rotTensor,
102 if (rotTensor.size() == 1)
104 const tensor& T = rotTensor[0];
108 pointInfo[i].transform(T, td_);
115 "PointEdgeWave<Type, TrackingData>::transform"
116 "(const tensorField&, List<Type>&)"
117 ) << "Non-uniform transformation on patch " << patch.name()
118 << " not supported for point fields"
119 << abort(FatalError);
123 pointInfo[i].transform(rotTensor[i], td_);
129 // Update info for pointI, at position pt, with information from
130 // neighbouring edge.
132 // - changedPoint_, changedPoints_, nChangedPoints_,
133 // - statistics: nEvals_, nUnvisitedPoints_
134 template <class Type, class TrackingData>
135 bool Foam::PointEdgeWave<Type, TrackingData>::updatePoint
138 const label neighbourEdgeI,
139 const Type& neighbourInfo,
145 bool wasValid = pointInfo.valid(td_);
148 pointInfo.updatePoint
160 if (!changedPoint_[pointI])
162 changedPoint_[pointI] = true;
163 changedPoints_[nChangedPoints_++] = pointI;
167 if (!wasValid && pointInfo.valid(td_))
176 // Update info for pointI, at position pt, with information from
179 // - changedPoint_, changedPoints_, nChangedPoints_,
180 // - statistics: nEvals_, nUnvisitedPoints_
181 template <class Type, class TrackingData>
182 bool Foam::PointEdgeWave<Type, TrackingData>::updatePoint
185 const Type& neighbourInfo,
191 bool wasValid = pointInfo.valid(td_);
194 pointInfo.updatePoint
205 if (!changedPoint_[pointI])
207 changedPoint_[pointI] = true;
208 changedPoints_[nChangedPoints_++] = pointI;
212 if (!wasValid && pointInfo.valid(td_))
221 // Update info for edgeI, at position pt, with information from
222 // neighbouring point.
224 // - changedEdge_, changedEdges_, nChangedEdges_,
225 // - statistics: nEvals_, nUnvisitedEdge_
226 template <class Type, class TrackingData>
227 bool Foam::PointEdgeWave<Type, TrackingData>::updateEdge
230 const label neighbourPointI,
231 const Type& neighbourInfo,
237 bool wasValid = edgeInfo.valid(td_);
252 if (!changedEdge_[edgeI])
254 changedEdge_[edgeI] = true;
255 changedEdges_[nChangedEdges_++] = edgeI;
259 if (!wasValid && edgeInfo.valid(td_))
268 // Check if patches of given type name are present
269 template <class Type, class TrackingData>
270 template <class PatchType>
271 Foam::label Foam::PointEdgeWave<Type, TrackingData>::countPatchType() const
275 forAll(mesh_.boundaryMesh(), patchI)
277 if (isA<PatchType>(mesh_.boundaryMesh()[patchI]))
286 // Transfer all the information to/from neighbouring processors
287 template <class Type, class TrackingData>
288 void Foam::PointEdgeWave<Type, TrackingData>::handleProcPatches()
290 // 1. Send all point info on processor patches.
292 PstreamBuffers pBufs(Pstream::nonBlocking);
294 DynamicList<Type> patchInfo;
295 DynamicList<label> thisPoints;
296 DynamicList<label> nbrPoints;
298 forAll(mesh_.globalData().processorPatches(), i)
300 label patchI = mesh_.globalData().processorPatches()[i];
301 const processorPolyPatch& procPatch =
302 refCast<const processorPolyPatch>(mesh_.boundaryMesh()[patchI]);
305 patchInfo.reserve(procPatch.nPoints());
307 thisPoints.reserve(procPatch.nPoints());
309 nbrPoints.reserve(procPatch.nPoints());
311 // Get all changed points in reverse order
312 const labelList& neighbPoints = procPatch.neighbPoints();
313 forAll(neighbPoints, thisPointI)
315 label meshPointI = procPatch.meshPoints()[thisPointI];
316 if (changedPoint_[meshPointI])
318 patchInfo.append(allPointInfo_[meshPointI]);
319 thisPoints.append(thisPointI);
320 nbrPoints.append(neighbPoints[thisPointI]);
324 // Adapt for leaving domain
325 leaveDomain(procPatch, thisPoints, patchInfo);
329 Pout<< "Processor patch " << patchI << ' ' << procPatch.name()
330 << " communicating with " << procPatch.neighbProcNo()
331 << " Sending:" << patchInfo.size() << endl;
334 UOPstream toNeighbour(procPatch.neighbProcNo(), pBufs);
335 toNeighbour << nbrPoints << patchInfo;
339 pBufs.finishedSends();
342 // 2. Receive all point info on processor patches.
345 forAll(mesh_.globalData().processorPatches(), i)
347 label patchI = mesh_.globalData().processorPatches()[i];
348 const processorPolyPatch& procPatch =
349 refCast<const processorPolyPatch>(mesh_.boundaryMesh()[patchI]);
351 List<Type> patchInfo;
352 labelList patchPoints;
355 UIPstream fromNeighbour(procPatch.neighbProcNo(), pBufs);
356 fromNeighbour >> patchPoints >> patchInfo;
361 Pout<< "Processor patch " << patchI << ' ' << procPatch.name()
362 << " communicating with " << procPatch.neighbProcNo()
363 << " Received:" << patchInfo.size() << endl;
366 // Apply transform to received data for non-parallel planes
367 if (!procPatch.parallel())
369 transform(procPatch, procPatch.forwardT(), patchInfo);
372 // Adapt for entering domain
373 enterDomain(procPatch, patchPoints, patchInfo);
375 // Merge received info
376 const labelList& meshPoints = procPatch.meshPoints();
379 label meshPointI = meshPoints[patchPoints[i]];
381 if (!allPointInfo_[meshPointI].equal(patchInfo[i], td_))
387 allPointInfo_[meshPointI]
396 // 3. Handle all shared points
397 // (Note:irrespective if changed or not for now)
400 const globalMeshData& pd = mesh_.globalData();
402 List<Type> sharedData(pd.nGlobalPoints());
404 forAll(pd.sharedPointLabels(), i)
406 label meshPointI = pd.sharedPointLabels()[i];
408 // Fill my entries in the shared points
409 sharedData[pd.sharedPointAddr()[i]] = allPointInfo_[meshPointI];
412 // Combine on master. Reduce operator has to handle a list and call
413 // Type.updatePoint for all elements
414 combineReduce(sharedData, listUpdateOp<Type>(propagationTol_, td_));
416 forAll(pd.sharedPointLabels(), i)
418 label meshPointI = pd.sharedPointLabels()[i];
420 // Retrieve my entries from the shared points.
421 const Type& nbrInfo = sharedData[pd.sharedPointAddr()[i]];
423 if (!allPointInfo_[meshPointI].equal(nbrInfo, td_))
429 allPointInfo_[meshPointI]
436 template <class Type, class TrackingData>
437 void Foam::PointEdgeWave<Type, TrackingData>::handleCyclicPatches()
439 // 1. Send all point info on cyclic patches.
441 DynamicList<Type> nbrInfo;
442 DynamicList<label> nbrPoints;
443 DynamicList<label> thisPoints;
445 forAll(mesh_.boundaryMesh(), patchI)
447 const polyPatch& patch = mesh_.boundaryMesh()[patchI];
449 if (isA<cyclicPolyPatch>(patch))
451 const cyclicPolyPatch& cycPatch =
452 refCast<const cyclicPolyPatch>(patch);
455 nbrInfo.reserve(cycPatch.nPoints());
457 nbrPoints.reserve(cycPatch.nPoints());
459 thisPoints.reserve(cycPatch.nPoints());
461 // Collect nbrPatch points that have changed
463 const cyclicPolyPatch& nbrPatch = cycPatch.neighbPatch();
464 const edgeList& pairs = cycPatch.coupledPoints();
465 const labelList& meshPoints = nbrPatch.meshPoints();
469 label thisPointI = pairs[pairI][0];
470 label nbrPointI = pairs[pairI][1];
471 label meshPointI = meshPoints[nbrPointI];
473 if (changedPoint_[meshPointI])
475 nbrInfo.append(allPointInfo_[meshPointI]);
476 nbrPoints.append(nbrPointI);
477 thisPoints.append(thisPointI);
481 // nbr : adapt for leaving domain
482 leaveDomain(nbrPatch, nbrPoints, nbrInfo);
486 // Apply rotation for non-parallel planes
488 if (!cycPatch.parallel())
490 // received data from half1
491 transform(cycPatch, cycPatch.forwardT(), nbrInfo);
496 Pout<< "Cyclic patch " << patchI << ' ' << patch.name()
497 << " Changed : " << nbrInfo.size()
501 // Adapt for entering domain
502 enterDomain(cycPatch, thisPoints, nbrInfo);
504 // Merge received info
505 const labelList& meshPoints = cycPatch.meshPoints();
508 label meshPointI = meshPoints[thisPoints[i]];
510 if (!allPointInfo_[meshPointI].equal(nbrInfo[i], td_))
516 allPointInfo_[meshPointI]
525 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
527 // Iterate, propagating changedPointsInfo across mesh, until no change (or
528 // maxIter reached). Initial point values specified.
529 template <class Type, class TrackingData>
530 Foam::PointEdgeWave<Type, TrackingData>::PointEdgeWave
532 const polyMesh& mesh,
533 const labelList& changedPoints,
534 const List<Type>& changedPointsInfo,
536 UList<Type>& allPointInfo,
537 UList<Type>& allEdgeInfo,
544 allPointInfo_(allPointInfo),
545 allEdgeInfo_(allEdgeInfo),
547 changedPoint_(mesh_.nPoints(), false),
548 changedPoints_(mesh_.nPoints()),
550 changedEdge_(mesh_.nEdges(), false),
551 changedEdges_(mesh_.nEdges()),
553 nCyclicPatches_(countPatchType<cyclicPolyPatch>()),
555 nUnvisitedPoints_(mesh_.nPoints()),
556 nUnvisitedEdges_(mesh_.nEdges())
558 if (allPointInfo_.size() != mesh_.nPoints())
562 "PointEdgeWave<Type, TrackingData>::PointEdgeWave"
563 "(const polyMesh&, const labelList&, const List<Type>,"
564 " List<Type>&, List<Type>&, const label maxIter)"
565 ) << "size of pointInfo work array is not equal to the number"
566 << " of points in the mesh" << endl
567 << " pointInfo :" << allPointInfo_.size() << endl
568 << " mesh.nPoints:" << mesh_.nPoints()
571 if (allEdgeInfo_.size() != mesh_.nEdges())
575 "PointEdgeWave<Type, TrackingData>::PointEdgeWave"
576 "(const polyMesh&, const labelList&, const List<Type>,"
577 " List<Type>&, List<Type>&, const label maxIter)"
578 ) << "size of edgeInfo work array is not equal to the number"
579 << " of edges in the mesh" << endl
580 << " edgeInfo :" << allEdgeInfo_.size() << endl
581 << " mesh.nEdges:" << mesh_.nEdges()
586 // Set from initial changed points data
587 setPointInfo(changedPoints, changedPointsInfo);
591 Pout<< "Seed points : " << nChangedPoints_ << endl;
594 // Iterate until nothing changes
595 label iter = iterate(maxIter);
597 if ((maxIter > 0) && (iter >= maxIter))
601 "PointEdgeWave<Type, TrackingData>::PointEdgeWave"
602 "(const polyMesh&, const labelList&, const List<Type>,"
603 " List<Type>&, List<Type>&, const label maxIter)"
604 ) << "Maximum number of iterations reached. Increase maxIter." << endl
605 << " maxIter:" << maxIter << endl
606 << " nChangedPoints:" << nChangedPoints_ << endl
607 << " nChangedEdges:" << nChangedEdges_ << endl
613 template <class Type, class TrackingData>
614 Foam::PointEdgeWave<Type, TrackingData>::PointEdgeWave
616 const polyMesh& mesh,
617 UList<Type>& allPointInfo,
618 UList<Type>& allEdgeInfo,
623 allPointInfo_(allPointInfo),
624 allEdgeInfo_(allEdgeInfo),
626 changedPoint_(mesh_.nPoints(), false),
627 changedPoints_(mesh_.nPoints()),
629 changedEdge_(mesh_.nEdges(), false),
630 changedEdges_(mesh_.nEdges()),
632 nCyclicPatches_(countPatchType<cyclicPolyPatch>()),
634 nUnvisitedPoints_(mesh_.nPoints()),
635 nUnvisitedEdges_(mesh_.nEdges())
639 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
641 template <class Type, class TrackingData>
642 Foam::PointEdgeWave<Type, TrackingData>::~PointEdgeWave()
646 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
649 template <class Type, class TrackingData>
650 Foam::label Foam::PointEdgeWave<Type, TrackingData>::getUnsetPoints() const
652 return nUnvisitedPoints_;
656 template <class Type, class TrackingData>
657 Foam::label Foam::PointEdgeWave<Type, TrackingData>::getUnsetEdges() const
659 return nUnvisitedEdges_;
663 // Copy point information into member data
664 template <class Type, class TrackingData>
665 void Foam::PointEdgeWave<Type, TrackingData>::setPointInfo
667 const labelList& changedPoints,
668 const List<Type>& changedPointsInfo
671 forAll(changedPoints, changedPointI)
673 label pointI = changedPoints[changedPointI];
675 bool wasValid = allPointInfo_[pointI].valid(td_);
677 // Copy info for pointI
678 allPointInfo_[pointI] = changedPointsInfo[changedPointI];
680 // Maintain count of unset points
681 if (!wasValid && allPointInfo_[pointI].valid(td_))
686 // Mark pointI as changed, both on list and on point itself.
688 if (!changedPoint_[pointI])
690 changedPoint_[pointI] = true;
691 changedPoints_[nChangedPoints_++] = pointI;
697 // Propagate information from edge to point. Return number of points changed.
698 template <class Type, class TrackingData>
699 Foam::label Foam::PointEdgeWave<Type, TrackingData>::edgeToPoint()
703 label changedEdgeI = 0;
704 changedEdgeI < nChangedEdges_;
708 label edgeI = changedEdges_[changedEdgeI];
710 if (!changedEdge_[edgeI])
712 FatalErrorIn("PointEdgeWave<Type, TrackingData>::edgeToPoint()")
714 << " not marked as having been changed" << nl
715 << "This might be caused by multiple occurences of the same"
716 << " seed point." << abort(FatalError);
720 const Type& neighbourWallInfo = allEdgeInfo_[edgeI];
722 // Evaluate all connected points (= edge endpoints)
723 const edge& e = mesh_.edges()[edgeI];
727 Type& currentWallInfo = allPointInfo_[e[eI]];
729 if (!currentWallInfo.equal(neighbourWallInfo, td_))
741 // Reset status of edge
742 changedEdge_[edgeI] = false;
745 // Handled all changed edges by now
748 if (nCyclicPatches_ > 0)
750 // Transfer changed points across cyclic halves
751 handleCyclicPatches();
753 if (Pstream::parRun())
755 // Transfer changed points from neighbouring processors.
761 Pout<< "Changed points : " << nChangedPoints_ << endl;
764 // Sum nChangedPoints over all procs
765 label totNChanged = nChangedPoints_;
767 reduce(totNChanged, sumOp<label>());
773 // Propagate information from point to edge. Return number of edges changed.
774 template <class Type, class TrackingData>
775 Foam::label Foam::PointEdgeWave<Type, TrackingData>::pointToEdge()
777 const labelListList& pointEdges = mesh_.pointEdges();
781 label changedPointI = 0;
782 changedPointI < nChangedPoints_;
786 label pointI = changedPoints_[changedPointI];
788 if (!changedPoint_[pointI])
790 FatalErrorIn("PointEdgeWave<Type, TrackingData>::pointToEdge()")
791 << "Point " << pointI
792 << " not marked as having been changed" << nl
793 << "This might be caused by multiple occurences of the same"
794 << " seed point." << abort(FatalError);
797 const Type& neighbourWallInfo = allPointInfo_[pointI];
799 // Evaluate all connected edges
801 const labelList& edgeLabels = pointEdges[pointI];
802 forAll(edgeLabels, edgeLabelI)
804 label edgeI = edgeLabels[edgeLabelI];
806 Type& currentWallInfo = allEdgeInfo_[edgeI];
808 if (!currentWallInfo.equal(neighbourWallInfo, td_))
820 // Reset status of point
821 changedPoint_[pointI] = false;
824 // Handled all changed points by now
829 Pout<< "Changed edges : " << nChangedEdges_ << endl;
832 // Sum nChangedPoints over all procs
833 label totNChanged = nChangedEdges_;
835 reduce(totNChanged, sumOp<label>());
842 template <class Type, class TrackingData>
843 Foam::label Foam::PointEdgeWave<Type, TrackingData>::iterate
848 if (nCyclicPatches_ > 0)
850 // Transfer changed points across cyclic halves
851 handleCyclicPatches();
853 if (Pstream::parRun())
855 // Transfer changed points from neighbouring processors.
863 while (iter < maxIter)
867 Pout<< "Iteration " << iter << endl;
870 label nEdges = pointToEdge();
874 Pout<< "Total changed edges : " << nEdges << endl;
882 label nPoints = edgeToPoint();
886 Pout<< "Total changed points : " << nPoints << endl;
888 Pout<< "Total evaluations : " << nEvals_ << endl;
890 Pout<< "Remaining unvisited points: " << nUnvisitedPoints_ << endl;
892 Pout<< "Remaining unvisited edges : " << nUnvisitedEdges_ << endl;
909 // ************************************************************************* //