coupleSlidingInterface.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) 2017-2020 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
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 "slidingInterface.H"
30#include "polyTopoChange.H"
31#include "polyMesh.H"
32#include "primitiveMesh.H"
33#include "enrichedPatch.H"
34#include "DynamicList.H"
35#include "pointHit.H"
36#include "triPointRef.H"
37#include "plane.H"
38#include "polyTopoChanger.H"
39#include "polyAddPoint.H"
40#include "polyRemovePoint.H"
41#include "polyAddFace.H"
42#include "polyModifyPoint.H"
43#include "polyModifyFace.H"
44#include "polyRemoveFace.H"
45
46// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
47
48const Foam::scalar Foam::slidingInterface::edgeCoPlanarTolDefault_ = 0.8;
49
50
51// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
52
53// Index of debug signs:
54// Index of debug signs:
55// . - loop of the edge-to-face interaction detection
56// x - reversal of direction in edge-to-face interaction detection
57// + - complete edge-to-face interaction detection
58// z - incomplete edge-to-face interaction detection. This may be OK for edges
59// crossing from one to the other side of multiply connected master patch
60
61// e - adding a point on edge
62// f - adding a point on face
63// . - collecting edges off another face for edge-to-edge cut
64// + - finished collection of edges
65// * - cut both master and slave
66// n - cutting new edge
67// t - intersection exists but it is outside of tolerance
68// x - missed slave edge in cut
69// - - missed master edge in cut
70// u - edge already used in cutting
71
72void Foam::slidingInterface::coupleInterface(polyTopoChange& ref) const
73{
74 if (debug)
75 {
77 << ": Coupling sliding interface " << name() << endl;
78 }
79
80 const polyMesh& mesh = topoChanger().mesh();
81 const pointField& points = mesh.points();
82 const faceList& faces = mesh.faces();
83 const labelList& own = mesh.faceOwner();
84 const labelList& nei = mesh.faceNeighbour();
85 const faceZoneMesh& faceZones = mesh.faceZones();
86
87 const primitiveFacePatch& masterPatch =
88 faceZones[masterFaceZoneID_.index()]();
89
90 const labelList& masterPatchAddr = faceZones[masterFaceZoneID_.index()];
91
92 const boolList& masterPatchFlip =
93 faceZones[masterFaceZoneID_.index()].flipMap();
94
95 const primitiveFacePatch& slavePatch =
96 faceZones[slaveFaceZoneID_.index()]();
97
98 const labelList& slavePatchAddr = faceZones[slaveFaceZoneID_.index()];
99
100 const boolList& slavePatchFlip =
101 faceZones[slaveFaceZoneID_.index()].flipMap();
102
103 const edgeList& masterEdges = masterPatch.edges();
104 const labelListList& masterPointEdges = masterPatch.pointEdges();
105 const labelList& masterMeshPoints = masterPatch.meshPoints();
106 const pointField& masterLocalPoints = masterPatch.localPoints();
107 const labelListList& masterFaceFaces = masterPatch.faceFaces();
108 const labelListList& masterFaceEdges = masterPatch.faceEdges();
109 const Map<label>& masterMeshPointMap = masterPatch.meshPointMap();
110
111 const edgeList& slaveEdges = slavePatch.edges();
112 const labelListList& slavePointEdges = slavePatch.pointEdges();
113 const labelList& slaveMeshPoints = slavePatch.meshPoints();
114 const pointField& slaveLocalPoints = slavePatch.localPoints();
115 const Map<label>& slaveMeshPointMap = slavePatch.meshPointMap();
116 const vectorField& slavePointNormals = slavePatch.pointNormals();
117
118 // Collect projection addressing
119 if
120 (
121 !(
122 slavePointPointHitsPtr_
123 && slavePointEdgeHitsPtr_
124 && slavePointFaceHitsPtr_
125 && masterPointEdgeHitsPtr_
126 )
127 )
128 {
130 << "Point projection addressing not available."
131 << abort(FatalError);
132 }
133
134 const labelList& slavePointPointHits = *slavePointPointHitsPtr_;
135 const labelList& slavePointEdgeHits = *slavePointEdgeHitsPtr_;
136 const List<objectHit>& slavePointFaceHits = *slavePointFaceHitsPtr_;
137 const labelList& masterPointEdgeHits = *masterPointEdgeHitsPtr_;
138 const pointField& projectedSlavePoints = *projectedSlavePointsPtr_;
139
140 // Create enriched patch
141 enrichedPatch cutPatch
142 (
143 masterPatch,
144 slavePatch,
145 slavePointPointHits,
146 slavePointEdgeHits,
147 slavePointFaceHits
148 );
149
150 // Get reference to list of added point for the enriched patch.
151 // This will be used for point addition
152 Map<point>& pointMap = cutPatch.pointMap();
153
154 // Get reference to the list of merged points
155 Map<label>& pointMergeMap = cutPatch.pointMergeMap();
156
157 // Create mapping for every merged point of the slave patch
158 forAll(slavePointPointHits, pointi)
159 {
160 const label slaveHitPti = slavePointPointHits[pointi];
161
162 if (slaveHitPti >= 0)
163 {
164 pointMergeMap.insert
165 (
166 slaveMeshPoints[pointi],
167 masterMeshPoints[slaveHitPti]
168 );
169 }
170 }
171
172
173 // Collect the list of used edges for every slave edge
174
175 List<labelHashSet> usedMasterEdges(slaveEdges.size());
176
177 // Collect of slave point hits
178 forAll(slavePointPointHits, pointi)
179 {
180 // For point hits, add all point-edges from master side to all point
181 const labelList& curSlaveEdges = slavePointEdges[pointi];
182
183 if (slavePointPointHits[pointi] > -1)
184 {
185 const labelList& curMasterEdges =
186 masterPointEdges[slavePointPointHits[pointi]];
187
188 // Mark all current master edges as used for all the current slave
189 // edges
190 for (const label slaveEdgei : curSlaveEdges)
191 {
192 usedMasterEdges[slaveEdgei].insert(curMasterEdges);
193 }
194 }
195 else if (slavePointEdgeHits[pointi] > -1)
196 {
197 // For edge hits, add the master edge
198 for (const label slaveEdgei : curSlaveEdges)
199 {
200 usedMasterEdges[slaveEdgei].insert
201 (
202 slavePointEdgeHits[pointi]
203 );
204 }
205 }
206 }
207
208 // Collect off master point hits
209 // For every master point that has hit an edge, add all edges coming from
210 // that point to the slave edge that has been hit
211 forAll(masterPointEdgeHits, masterPointi)
212 {
213 if (masterPointEdgeHits[masterPointi] > -1)
214 {
215 const labelList& curMasterEdges = masterPointEdges[masterPointi];
216
217 usedMasterEdges[masterPointEdgeHits[masterPointi]].insert
218 (
219 curMasterEdges
220 );
221 }
222 }
223
224 // Pout<< "used edges: " << endl;
225 // forAll(usedMasterEdges, edgei)
226 // {
227 // Pout<< "edge: " << edgei
228 // << " used: " << usedMasterEdges[edgei].toc()
229 // << endl;
230 // }
231
232 // For every master and slave edge make a list of points to be added into
233 // that edge.
234 List<DynamicList<label>> pointsIntoMasterEdges(masterEdges.size());
235 List<DynamicList<label>> pointsIntoSlaveEdges(slaveEdges.size());
236
237 // Add all points from the slave patch that have hit the edge
238 forAll(slavePointEdgeHits, pointi)
239 {
240 if (slavePointEdgeHits[pointi] > -1)
241 {
242 // Create a new point on the master edge
243
244 const point edgeCutPoint =
245 masterEdges[slavePointEdgeHits[pointi]].line
246 (
247 masterLocalPoints
248 ).nearestDist(projectedSlavePoints[pointi]).hitPoint();
249
250 const label newPointi =
251 ref.setAction
252 (
253 polyAddPoint
254 (
255 edgeCutPoint, // point
256 slaveMeshPoints[pointi], // master point
257 cutPointZoneID_.index(), // zone for point
258 true // supports a cell
259 )
260 );
261
262 // Add the new edge point into the merge map
263 pointMergeMap.insert
264 (
265 slaveMeshPoints[pointi],
267 );
268
269 pointsIntoMasterEdges[slavePointEdgeHits[pointi]].append
270 (
272 );
273
274 // Add the point into the enriched patch map
275 pointMap.insert
276 (
277 newPointi,
278 edgeCutPoint
279 );
280
281 if (debug)
282 {
283 Pout<< "e";
284
285 // Pout<< "Inserting merge pair off edge: "
286 // << slaveMeshPoints[pointi] << " " << newPointi
287 // << " cut point: " << edgeCutPoint
288 // << " orig: " << slaveLocalPoints[pointi]
289 // << " proj: " << projectedSlavePoints[pointi]
290 // << endl;
291
292 // Pout<< newPointi << " = " << edgeCutPoint << endl;
293 }
294 }
295 }
296
297 if (debug)
298 {
299 Pout<< endl;
300 }
301
302 // Add all points from the slave patch that have hit a face
303 forAll(slavePointFaceHits, pointi)
304 {
305 if
306 (
307 slavePointPointHits[pointi] < 0
308 && slavePointEdgeHits[pointi] < 0
309 && slavePointFaceHits[pointi].hit()
310 )
311 {
312 const label newPointi =
313 ref.setAction
314 (
315 polyAddPoint
316 (
317 projectedSlavePoints[pointi], // point
318 slaveMeshPoints[pointi], // master point
319 cutPointZoneID_.index(), // zone for point
320 true // supports a cell
321 )
322 );
323
324 // Pout<< "Inserting merge pair off face: "
325 // << slaveMeshPoints[pointi]
326 // << " " << newPointi
327 // << endl;
328
329 // Add the new edge point into the merge map
330 pointMergeMap.insert
331 (
332 slaveMeshPoints[pointi],
334 );
335
336 // Add the point into the enriched patch map
337 pointMap.insert
338 (
339 newPointi,
340 projectedSlavePoints[pointi]
341 );
342
343 if (debug)
344 {
345 Pout<< "f: " << newPointi << " = "
346 << projectedSlavePoints[pointi] << endl;
347 }
348 }
349 }
350
351 forAll(masterPointEdgeHits, pointi)
352 {
353 if (masterPointEdgeHits[pointi] > -1)
354 {
355 pointsIntoSlaveEdges[masterPointEdgeHits[pointi]].append
356 (
357 masterMeshPoints[pointi]
358 );
359 }
360 }
361
362 // Cut all slave edges.
363 // Collect all master edges the slave edge interacts with. Skip
364 // all the edges already marked as used. For every unused edge,
365 // calculate the cut and insert the new point into the master and
366 // slave edge.
367 // For the edge selection algorithm, see, comment in
368 // slidingInterfaceProjectPoints.C.
369 // Edge cutting algorithm:
370 // As the master patch defines the cutting surface, the newly
371 // inserted point needs to be on the master edge. Also, in 3-D
372 // the pair of edges generally misses each other rather than
373 // intersect. Therefore, the intersection is calculated using the
374 // plane the slave edge defines during projection. The plane is
375 // defined by the centrepoint of the edge in the original
376 // configuration and the projected end points. In case of flat
377 // geometries (when the three points are colinear), the plane is
378 // defined by the two projected end-points and the slave edge
379 // normal used as the in-plane vector. When the intersection
380 // point is created, it is added as a new point for both the
381 // master and the slave edge.
382 // In order to be able to re-create the points on edges in mesh
383 // motion without the topology change, the edge pair used to
384 // create the cut point needs to be recorded in
385 // cutPointEdgePairMap
386
387 // Note. "Processing slave edges" code is repeated twice in the
388 // sliding interface coupling in order to allow the point
389 // projection to be done separately from the actual cutting.
390 // Please change consistently with slidingInterfaceProjectPoints.C
391 //
392 if (debug)
393 {
394 Pout<< "Processing slave edges" << endl;
395 }
396
397 if (!cutPointEdgePairMapPtr_)
398 {
400 << "Cut point edge pair map pointer not set."
401 << abort(FatalError);
402 }
403
404 Map<Pair<edge>>& addToCpepm = *cutPointEdgePairMapPtr_;
405
406 // Clear the old map
407 addToCpepm.clear();
408
409 // Create a map of faces the edge can interact with
410 labelHashSet curFaceMap
411 (
412 nFacesPerSlaveEdge_*primitiveMesh::edgesPerFace_
413 );
414
416
417 forAll(slaveEdges, edgeI)
418 {
419 const edge& curEdge = slaveEdges[edgeI];
420
421 if
422 (
423 slavePointFaceHits[curEdge.start()].hit()
424 || slavePointFaceHits[curEdge.end()].hit()
425 )
426 {
427 labelHashSet& curUme = usedMasterEdges[edgeI];
428
429 // Pout<< "Doing edge " << edgeI
430 // << " curEdge: " << curEdge
431 // << " curUme: " << curUme
432 // << endl;
433
434 // Grab the faces for start and end points.
435 const label startFace =
436 slavePointFaceHits[curEdge.start()].hitObject();
437
438 const label endFace =
439 slavePointFaceHits[curEdge.end()].hitObject();
440
441 // Pout<< "startFace: " << slavePointFaceHits[curEdge.start()]
442 // << " endFace: " << slavePointFaceHits[curEdge.end()]
443 // << endl;
444
445 bool completed = false;
446
447 if (!completed)
448 {
449 // Forward sweep
450
451 // Clear the maps
452 curFaceMap.clear();
453 addedFaces.clear();
454
455 // Insert the start face into the list
456 curFaceMap.insert(startFace);
457 addedFaces.insert(startFace);
458
459 // Pout<< "curFaceMap: " << curFaceMap.toc() << endl;
460
461 for
462 (
463 label nSweeps = 0;
464 nSweeps < edgeFaceEscapeLimit_;
465 ++nSweeps
466 )
467 {
468 completed = addedFaces.found(endFace);
469
470 // Add all face neighbours of face in the map
471 const labelList cf(addedFaces.toc());
472 addedFaces.clear();
473
474 for (const label cfi : cf)
475 {
476 const labelList& curNbrs = masterFaceFaces[cfi];
477
478 for (const label nbri : curNbrs)
479 {
480 if (curFaceMap.insert(nbri))
481 {
482 addedFaces.insert(nbri);
483 }
484 }
485 }
486
487 if (completed) break;
488
489 if (debug)
490 {
491 Pout<< ".";
492 }
493 }
494 }
495
496 if (!completed)
497 {
498 // Reverse sweep
499
500 if (debug)
501 {
502 Pout<< "x";
503 }
504
505 // It is impossible to reach the end from the start, probably
506 // due to disconnected domain. Do search in opposite direction
507
508 addedFaces.clear();
509 addedFaces.insert(endFace);
510
511 for
512 (
513 label nSweeps = 0;
514 nSweeps < edgeFaceEscapeLimit_;
515 ++nSweeps
516 )
517 {
518 completed = addedFaces.found(startFace);
519
520 // Add all face neighbours of face in the map
521 const labelList cf(addedFaces.toc());
522 addedFaces.clear();
523
524 for (const label cfi : cf)
525 {
526 const labelList& curNbrs = masterFaceFaces[cfi];
527
528 for (const label nbri : curNbrs)
529 {
530 if (curFaceMap.insert(nbri))
531 {
532 addedFaces.insert(nbri);
533 }
534 }
535 }
536
537 if (completed) break;
538
539 if (debug)
540 {
541 Pout<< ".";
542 }
543 }
544 }
545
546 if (completed)
547 {
548 if (debug)
549 {
550 Pout<< "+ ";
551 }
552 }
553 else
554 {
555 if (debug)
556 {
557 Pout<< "z ";
558 }
559 }
560
561 // Collect the edges
562
563 // Create a map of edges the edge can interact with
564 labelHashSet curMasterEdgesMap
565 (
566 nFacesPerSlaveEdge_*primitiveMesh::edgesPerFace_
567 );
568
569 for (const label facei : curFaceMap)
570 {
571 // Pout<< "face: " << facei << " "
572 // << masterPatch[facei]
573 // << " local: "
574 // << masterPatch.localFaces()[facei]
575 // << endl;
576
577 curMasterEdgesMap.insert(masterFaceEdges[facei]);
578 }
579
580 const labelList curMasterEdges(curMasterEdgesMap.toc());
581 curMasterEdgesMap.clear();
582
583 // For all master edges to intersect, skip the ones
584 // already used and cut the rest with a cutting plane. If
585 // the intersection point, falls inside of both edges, it
586 // is valid.
587
588 // Note.
589 // The edge cutting code is repeated in
590 // slidingInterface::modifyMotionPoints. This is done for
591 // efficiency reasons and avoids multiple creation of cutting
592 // planes. Please update both simultaneously.
593
594 const point& a = projectedSlavePoints[curEdge.start()];
595 const point& b = projectedSlavePoints[curEdge.end()];
596
597 const point c =
598 0.5*
599 (
600 slaveLocalPoints[curEdge.start()]
601 + slavePointNormals[curEdge.start()] // Add start normal
602 + slaveLocalPoints[curEdge.end()]
603 + slavePointNormals[curEdge.end()] // Add end normal
604 );
605
606 // Create the plane
607 const plane cutPlane(a, b, c);
608
609 // Pout<< "a: " << a
610 // << " b: " << b
611 // << " c: " << c
612 // << " plane: " << cutPlane
613 // << endl;
614
615 const linePointRef curSlaveLine =
616 curEdge.line(projectedSlavePoints);
617
618 const scalar curSlaveLineMag = curSlaveLine.mag();
619
620 // Pout<< "curSlaveLine: " << curSlaveLine << endl;
621
622 for (const label cmeIndex : curMasterEdges)
623 {
624 if (!curUme.found(cmeIndex))
625 {
626 // New edge
627 if (debug)
628 {
629 Pout<< "n";
630 }
631
632 const edge& cme = masterEdges[cmeIndex];
633
634 // Pout<< "Edge " << cmeIndex
635 // << " cme: " << cme
636 // << " line: " << cme.line(masterLocalPoints)
637 // << endl;
638
639 const scalar cutOnMaster =
640 cutPlane.lineIntersect
641 (
642 cme.line(masterLocalPoints)
643 );
644
645 if
646 (
647 cutOnMaster > edgeEndCutoffTol_
648 && cutOnMaster < 1.0 - edgeEndCutoffTol_
649 )
650 {
651 // Master is cut, check the slave
652 const point masterCutPoint =
653 masterLocalPoints[cme.start()]
654 + cutOnMaster*cme.vec(masterLocalPoints);
655
656 const pointHit slaveCut =
657 curSlaveLine.nearestDist(masterCutPoint);
658
659 if (slaveCut.hit())
660 {
661 // Strict checking of slave cut to avoid capturing
662 // end points.
663 const scalar cutOnSlave =
664 (
665 (
666 slaveCut.hitPoint()
667 - curSlaveLine.start()
668 ) & curSlaveLine.vec()
669 )/sqr(curSlaveLineMag);
670
671 // Calculate merge tolerance from the
672 // target edge length
673 const scalar mergeTol = edgeCoPlanarTol_*mag(b - a);
674
675 // Pout<< "cutOnMaster: " << cutOnMaster
676 // << " masterCutPoint: " << masterCutPoint
677 // << " slaveCutPoint: " << slaveCut.hitPoint()
678 // << " slaveCut.distance(): "
679 // << slaveCut.distance()
680 // << " slave length: " << mag(b - a)
681 // << " mergeTol: " << mergeTol
682 // << " 1: " << mag(b - a)
683 // << " 2: "
684 // << cme.line(masterLocalPoints).mag()
685 // << endl;
686
687 if
688 (
689 cutOnSlave > edgeEndCutoffTol_
690 && cutOnSlave < 1.0 - edgeEndCutoffTol_
691 && slaveCut.distance() < mergeTol
692 )
693 {
694 // Cut both master and slave. Add point
695 // to edge points The point is nominally
696 // added from the start of the master edge
697 // and added to the cut point zone
698 const label newPointi =
699 ref.setAction
700 (
701 polyAddPoint
702 (
703 masterCutPoint, // point
704 masterMeshPoints[cme.start()],// m p
705 cutPointZoneID_.index(), // zone
706 true // active
707 )
708 );
709
710 // Pout<< "Inserting point: " << newPointi
711 // << " as edge to edge intersection. "
712 // << "Slave edge: "
713 // << edgeI << " " << curEdge
714 // << " master edge: "
715 // << cmeIndex << " " << cme
716 // << endl;
717
718 pointsIntoSlaveEdges[edgeI].append
719 (
721 );
722 pointsIntoMasterEdges[cmeIndex].append
723 (
725 );
726
727 // Add the point into the enriched patch map
728 pointMap.insert
729 (
730 newPointi,
731 masterCutPoint
732 );
733
734 // Record which two edges intersect to
735 // create cut point
736 addToCpepm.insert
737 (
738 newPointi, // Cut point index
739 Pair<edge>
740 (
741 edge
742 (
743 masterMeshPoints[cme.start()],
744 masterMeshPoints[cme.end()]
745 ), // Master edge
746 edge
747 (
748 slaveMeshPoints[curEdge.start()],
749 slaveMeshPoints[curEdge.end()]
750 ) // Slave edge
751 )
752 );
753
754 if (debug)
755 {
756 Pout<< " " << newPointi << " = "
757 << masterCutPoint << " ";
758 }
759 }
760 else
761 {
762 if (debug)
763 {
764 // Intersection exists but it is too far
765 Pout<< "t";
766 }
767 }
768 }
769 else
770 {
771 if (debug)
772 {
773 // Missed slave edge
774 Pout<< "x";
775 }
776 }
777 }
778 else
779 {
780 if (debug)
781 {
782 // Missed master edge
783 Pout<< "-";
784 }
785 }
786 }
787 else
788 {
789 if (debug)
790 {
791 Pout<< "u";
792 }
793 }
794 }
795
796 if (debug)
797 {
798 Pout<< endl;
799 }
800 } // End if both ends missing
801 } // End for all slave edges
802
803// Pout<< "pointsIntoMasterEdges: " << pointsIntoMasterEdges << endl;
804// Pout<< "pointsIntoSlaveEdges: " << pointsIntoSlaveEdges << endl;
805
806 // Re-pack the points into edges lists
807 labelListList pime(pointsIntoMasterEdges.size());
808
809 forAll(pointsIntoMasterEdges, i)
810 {
811 pime[i].transfer(pointsIntoMasterEdges[i]);
812 }
813
814 labelListList pise(pointsIntoSlaveEdges.size());
815
816 forAll(pointsIntoSlaveEdges, i)
817 {
818 pise[i].transfer(pointsIntoSlaveEdges[i]);
819 }
820
821 // Prepare the enriched faces
822 cutPatch.calcEnrichedFaces
823 (
824 pime,
825 pise,
826 projectedSlavePoints
827 );
828
829 // Demand driven calculate the cut faces. Apart from the
830 // cutFaces/cutFaceMaster/cutFaceSlave no information from the cutPatch
831 // is used anymore!
832 const faceList& cutFaces = cutPatch.cutFaces();
833 const labelList& cutFaceMaster = cutPatch.cutFaceMaster();
834 const labelList& cutFaceSlave = cutPatch.cutFaceSlave();
835
836 const labelList& masterFc = masterFaceCells();
837 const labelList& slaveFc = slaveFaceCells();
838
839 // Couple the interface
840
841 // Algorithm:
842 // 1) Go through the cut faces and check if the cut face is the same as the
843 // defining master or slave. If so, modify the appropriate
844 // face and mark the other for relegation into the face zone.
845 // 2) If different, mark both sides for relegation and insert the new face
846
847
848 boolList orphanedMaster(masterPatch.size(), false);
849 boolList orphanedSlave(slavePatch.size(), false);
850
851 forAll(cutFaces, facei)
852 {
853 const face& curCutFace = cutFaces[facei];
854 const label curMaster = cutFaceMaster[facei];
855 const label curSlave = cutFaceSlave[facei];
856
857// Pout<< "Doing insertion of face " << facei << ": ";
858
859 // Check if the face has changed topologically
860 bool insertedFace = false;
861
862 if (curMaster >= 0)
863 {
864 // Face has got a master
865 if (curCutFace == masterPatch[curMaster])
866 {
867 // Face is equal to master. Modify master face.
868// Pout<< "Face is equal to master and is ";
869
870 // If the face has got both master and slave, it is an
871 // internal face; otherwise it is a patch face in the
872 // master patch. Keep it in the master face zone.
873
874 if (curSlave >= 0)
875 {
876// Pout<< "internal" << endl;
877 if (masterFc[curMaster] < slaveFc[curSlave])
878 {
879 // Cut face should point into slave.
880 // Be careful about flips in zone!
881 ref.setAction
882 (
883 polyModifyFace
884 (
885 curCutFace, // new face
886 masterPatchAddr[curMaster], // master face id
887 masterFc[curMaster], // owner
888 slaveFc[curSlave], // neighbour
889 false, // flux flip
890 -1, // patch ID
891 false, // remove from zone
892 masterFaceZoneID_.index(), // zone ID
893 masterPatchFlip[curMaster] // zone flip
894 )
895 );
896
897 // Pout<< "modifying master face. Old master: "
898 // << masterPatch[curMaster]
899 // << " new face: " << curCutFace.reverseFace()
900 // << " own: " << masterFc[curMaster]
901 // << " nei: " << slaveFc[curSlave] << endl;
902 }
903 else
904 {
905 // Cut face should point into master. Flip required.
906 // Be careful about flips in zone!
907 ref.setAction
908 (
909 polyModifyFace
910 (
911 curCutFace.reverseFace(), // new face
912 masterPatchAddr[curMaster], // master face id
913 slaveFc[curSlave], // owner
914 masterFc[curMaster], // neighbour
915 true, // flux flip
916 -1, // patch ID
917 false, // remove from zone
918 masterFaceZoneID_.index(), // zone ID
919 !masterPatchFlip[curMaster] // zone flip
920 )
921 );
922 }
923
924 // Orphan the slave
925 orphanedSlave[curSlave] = true;
926 }
927 else
928 {
929// Pout<< "master boundary" << endl;
930 ref.setAction
931 (
932 polyModifyFace
933 (
934 curCutFace, // new face
935 masterPatchAddr[curMaster], // master face index
936 masterFc[curMaster], // owner
937 -1, // neighbour
938 false, // flux flip
939 masterPatchID_.index(), // patch ID
940 false, // remove from zone
941 masterFaceZoneID_.index(), // zone ID
942 masterPatchFlip[curMaster] // zone flip
943 )
944 );
945 }
946
947 insertedFace = true;
948 }
949 }
950 else if (curSlave >= 0)
951 {
952 // Face has got a slave
953
954 // Renumber the slave face into merged labels
955 face rsf(slavePatch[curSlave]);
956
957 forAll(rsf, i)
958 {
959 rsf[i] = pointMergeMap.lookup(rsf[i], rsf[i]);
960 }
961
962 if (curCutFace == rsf)
963 {
964 // Face is equal to slave. Modify slave face.
965 // Pout<< "Face is equal to slave and is ";
966
967 if (curMaster >= 0)
968 {
969 // Pout<< "regular internal" << endl;
970 if (masterFc[curMaster] < slaveFc[curSlave])
971 {
972 ref.setAction
973 (
974 polyModifyFace
975 (
976 curCutFace, // new face
977 slavePatchAddr[curSlave], // master face id
978 masterFc[curMaster], // owner
979 slaveFc[curSlave], // neighbour
980 true, // flux flip
981 -1, // patch ID
982 false, // remove from zone
983 slaveFaceZoneID_.index(), // zone ID
984 !slavePatchFlip[curMaster] // zone flip
985 )
986 );
987 }
988 else
989 {
990 // Cut face should point into master.
991 // Be careful about flips in zone!
992 // Pout<< "flipped internal" << endl;
993 ref.setAction
994 (
995 polyModifyFace
996 (
997 curCutFace.reverseFace(), // new face
998 slavePatchAddr[curSlave], // master face id
999 slaveFc[curSlave], // owner
1000 masterFc[curMaster], // neighbour
1001 false, // flux flip
1002 -1, // patch ID
1003 false, // remove from zone
1004 slaveFaceZoneID_.index(), // zone ID
1005 slavePatchFlip[curSlave] // zone flip
1006 )
1007 );
1008 }
1009
1010 // Orphan the master
1011 orphanedMaster[curMaster] = true;
1012 }
1013 else
1014 {
1015 // Pout<< "slave boundary" << endl;
1016 ref.setAction
1017 (
1018 polyModifyFace
1019 (
1020 curCutFace, // new face
1021 slavePatchAddr[curSlave], // master face index
1022 slaveFc[curSlave], // owner
1023 -1, // neighbour
1024 false, // flux flip
1025 slavePatchID_.index(), // patch ID
1026 false, // remove from zone
1027 slaveFaceZoneID_.index(), // zone ID
1028 slavePatchFlip[curSlave] // zone flip
1029 )
1030 );
1031 }
1032
1033 insertedFace = true;
1034 }
1035 }
1036 else
1037 {
1039 << "Face " << facei << " in cut faces has neither a master "
1040 << "nor a slave. Error in the cutting algorithm on modify."
1041 << abort(FatalError);
1042 }
1043
1044 if (!insertedFace)
1045 {
1046 // Face is different from both master and slave
1047 // Pout<< "Face different from both master and slave" << endl;
1048
1049 if (curMaster >= 0)
1050 {
1051 if (curSlave >= 0)
1052 {
1053 // Add internal face
1054 if (masterFc[curMaster] < slaveFc[curSlave])
1055 {
1056 // Pout<< "Adding internal face " << curCutFace
1057 // << " owner: " << masterFc[curMaster]
1058 // << " slave: " << slaveFc[curSlave]
1059 // << " master face: " << masterPatchAddr[curMaster]
1060 // << endl;
1061
1062 // Cut face should point into slave.
1063 ref.setAction
1064 (
1065 polyAddFace
1066 (
1067 curCutFace, // new face
1068 masterFc[curMaster], // owner
1069 slaveFc[curSlave], // neighbour
1070 -1, // master point
1071 -1, // master edge
1072 masterPatchAddr[curMaster], // master face id
1073 false, // flux flip
1074 -1, // patch ID
1075 cutFaceZoneID_.index(), // zone ID
1076 false // zone flip
1077 )
1078 );
1079 }
1080 else
1081 {
1082 // Cut face should point into master. Flip required.
1083 ref.setAction
1084 (
1085 polyAddFace
1086 (
1087 curCutFace.reverseFace(), // new face
1088 slaveFc[curSlave], // owner
1089 masterFc[curMaster], // neighbour
1090 -1, // master point
1091 -1, // master edge
1092 masterPatchAddr[curMaster], // master face id
1093 true, // flux flip
1094 -1, // patch ID
1095 cutFaceZoneID_.index(), // zone ID
1096 true // zone flip
1097 )
1098 );
1099 }
1100
1101 // Orphan slave
1102 orphanedSlave[curSlave] = true;
1103 }
1104 else
1105 {
1106 // Pout<< "Adding solo master face " << curCutFace
1107 // << " owner: " << masterFc[curMaster]
1108 // << " master face: " << masterPatchAddr[curMaster]
1109 // << endl;
1110
1111 // Add master patch face
1112 ref.setAction
1113 (
1114 polyAddFace
1115 (
1116 curCutFace, // new face
1117 masterFc[curMaster], // owner
1118 -1, // neighbour
1119 -1, // master point
1120 -1, // master edge
1121 masterPatchAddr[curMaster], // master face index
1122 false, // flux flip
1123 masterPatchID_.index(), // patch ID
1124 cutFaceZoneID_.index(), // zone ID
1125 false // zone flip
1126 )
1127 );
1128 }
1129
1130 // Orphan master
1131 orphanedMaster[curMaster] = true;
1132 }
1133 else if (curSlave >= 0)
1134 {
1135 // Pout<< "Adding solo slave face " << curCutFace
1136 // << " owner: " << slaveFc[curSlave]
1137 // << " master face: " << slavePatchAddr[curSlave]
1138 // << endl;
1139
1140 // Add slave patch face
1141 ref.setAction
1142 (
1143 polyAddFace
1144 (
1145 curCutFace, // new face
1146 slaveFc[curSlave], // owner
1147 -1, // neighbour
1148 -1, // master point
1149 -1, // master edge
1150 slavePatchAddr[curSlave], // master face index
1151 false, // flux flip
1152 slavePatchID_.index(), // patch ID
1153 cutFaceZoneID_.index(), // zone ID
1154 false // zone flip
1155 )
1156 );
1157
1158 // Orphan slave
1159 orphanedSlave[curSlave] = true;
1160 }
1161 else
1162 {
1164 << "Face " << facei << " in cut faces has neither a master "
1165 << "nor a slave. Error in the cutting algorithm on add."
1166 << abort(FatalError);
1167 }
1168 }
1169 }
1170
1171 // Move the orphaned faces into the face zone
1172 // Pout<< "Orphaned master faces: " << orphanedMaster << endl;
1173 // Pout<< "Orphaned slave faces: " << orphanedSlave << endl;
1174
1175 label nOrphanedMasters = 0;
1176
1177 forAll(orphanedMaster, facei)
1178 {
1179 if (orphanedMaster[facei])
1180 {
1181 nOrphanedMasters++;
1182
1184 //ref.setAction
1185 //(
1186 // polyModifyFace
1187 // (
1188 // masterPatch[facei], // new face
1189 // masterPatchAddr[facei], // master face index
1190 // -1, // owner
1191 // -1, // neighbour
1192 // false, // flux flip
1193 // -1, // patch ID
1194 // false, // remove from zone
1195 // masterFaceZoneID_.index(), // zone ID
1196 // false // zone flip
1197 // )
1198 //);
1199
1200 //Pout<< "**MJ:deleting master face " << masterPatchAddr[facei]
1201 // << " old verts:" << masterPatch[facei] << endl;
1202 ref.setAction(polyRemoveFace(masterPatchAddr[facei]));
1203 }
1204 }
1205
1206 label nOrphanedSlaves = 0;
1207
1208 forAll(orphanedSlave, facei)
1209 {
1210 if (orphanedSlave[facei])
1211 {
1212 nOrphanedSlaves++;
1213
1215 //ref.setAction
1216 //(
1217 // polyModifyFace
1218 // (
1219 // slavePatch[facei], // new face
1220 // slavePatchAddr[facei], // slave face index
1221 // -1, // owner
1222 // -1, // neighbour
1223 // false, // flux flip
1224 // -1, // patch ID
1225 // false, // remove from zone
1226 // slaveFaceZoneID_.index(), // zone ID
1227 // false // zone flip
1228 // )
1229 //);
1230
1231 //Pout<< "**MJ:deleting slave face " << slavePatchAddr[facei]
1232 // << " old verts:" << slavePatch[facei] << endl;
1233 ref.setAction(polyRemoveFace(slavePatchAddr[facei]));
1234 }
1235 }
1236
1237 if (debug)
1238 {
1239 Pout<< "Orphaned faces: "
1240 << "master = " << nOrphanedMasters << "/"
1241 << orphanedMaster.size()
1242 << " slave = " << nOrphanedSlaves << "/"
1243 << orphanedSlave.size() << endl;
1244 }
1245
1246 // Finished coupling the plane of sliding interface.
1247
1248 // Modify faces influenced by the sliding interface
1249 // These are the faces belonging to the master and slave cell
1250 // layer which have not already been modified.
1251 // Modification comes in three types:
1252 // 1) eliminate the points that have been removed when the old sliding
1253 // interface has been removed
1254 // 2) Merge the slave points that have hit points on the master patch
1255 // 3) Introduce new points resulting from the new sliding interface cut
1256
1257 // Collect all affected faces
1258
1259 // Master side
1260
1261 // Grab the list of faces in the layer
1262 const labelList& masterStickOuts = masterStickOutFaces();
1263
1264 // Pout<< "masterStickOuts: " << masterStickOuts << endl;
1265
1266 // Re-create the master stick-out faces
1267 for (const label curFaceID : masterStickOuts)
1268 {
1269 // Renumber the face and remove additional points
1270 const face& oldRichFace = faces[curFaceID];
1271
1272 bool changed = false;
1273
1274 // Remove removed points from the face
1275 face oldFace(oldRichFace.size());
1276 label nOldFace = 0;
1277
1278 for (const label pointi : oldRichFace)
1279 {
1280 if (ref.pointRemoved(pointi))
1281 {
1282 changed = true;
1283 }
1284 else
1285 {
1286 // Point off patch
1287 oldFace[nOldFace] = pointi;
1288 nOldFace++;
1289 }
1290 }
1291
1292 oldFace.setSize(nOldFace);
1293
1294 // Pout<< "old rich face[" << curFaceID << "]: " << oldRichFace
1295 // << " old face: " << oldFace << endl;
1296
1297 DynamicList<label> newFaceLabels(2*oldFace.size());
1298
1299 forAll(oldFace, pointi)
1300 {
1301 const label localFirstLabel =
1302 masterMeshPointMap.lookup(oldFace[pointi], -1);
1303
1304 if (localFirstLabel != -1)
1305 {
1306 // Point is in master patch. Add it
1307
1308 // If the point is a direct hit, grab its label;
1309 // otherwise keep the original
1310 newFaceLabels.append
1311 (
1312 pointMergeMap.lookup(oldFace[pointi], oldFace[pointi])
1313 );
1314
1315 if (newFaceLabels.last() != oldFace[pointi])
1316 {
1317 changed = true;
1318 }
1319
1320 // Find if there are additional points inserted onto the edge
1321 // between current point and the next point
1322 // Algorithm:
1323 // 1) Find all the edges in the master patch coming
1324 // out of the current point.
1325 // 2) If the next point in the face to pick the right edge
1326
1327 const labelList& curEdges = masterPointEdges[localFirstLabel];
1328
1329 const label nextLabel = oldFace.nextLabel(pointi);
1330
1331 const label localNextLabel =
1332 masterMeshPointMap.lookup(nextLabel, -1);
1333
1334 if (localNextLabel != -1)
1335 {
1336 // Pout<< "found label pair " << oldFace[pointi]
1337 // << " and " << nextLabel;
1338 // Find the points on the edge between them
1339
1340 for (const label curEdgei : curEdges)
1341 {
1342 if
1343 (
1344 masterEdges[curEdgei].otherVertex
1345 (
1346 localFirstLabel
1347 )
1348 == localNextLabel
1349 )
1350 {
1351 // Pout<< " found edge: " << curEdgei << endl;
1352
1353 // Get points on current edge
1354 const labelList& curPime = pime[curEdgei];
1355
1356 if (curPime.size())
1357 {
1358 changed = true;
1359 // Pout<< "curPime: " << curPime << endl;
1360 // Insert the edge points into the face
1361 // in the correct order
1362 const point& startPoint =
1363 masterLocalPoints[localFirstLabel];
1364
1365 const point& endPoint =
1366 masterLocalPoints[localNextLabel];
1367
1368 vector e = (endPoint - startPoint);
1369
1370 e /= magSqr(e);
1371
1372 scalarField edgePointWeights(curPime.size());
1373
1374 forAll(curPime, curPimeI)
1375 {
1376 edgePointWeights[curPimeI] =
1377 (
1378 e
1379 & (
1380 pointMap[curPime[curPimeI]]
1381 - startPoint
1382 )
1383 );
1384 }
1385
1386 if (debug)
1387 {
1388 if
1389 (
1390 min(edgePointWeights) < 0
1391 || max(edgePointWeights) > 1
1392 )
1393 {
1395 << "Error in master stick-out edge "
1396 << "point collection."
1397 << abort(FatalError);
1398 }
1399 }
1400
1401 // Go through the points and collect
1402 // them based on weights from lower to
1403 // higher. This gives the correct
1404 // order of points along the edge.
1405 for
1406 (
1407 label passI = 0;
1408 passI < edgePointWeights.size();
1409 passI++
1410 )
1411 {
1412 // Max weight can only be one, so
1413 // the sorting is done by
1414 // elimination.
1415 label nextPoint = -1;
1416 scalar dist = 2;
1417
1418 forAll(edgePointWeights, wI)
1419 {
1420 if (edgePointWeights[wI] < dist)
1421 {
1422 dist = edgePointWeights[wI];
1423 nextPoint = wI;
1424 }
1425 }
1426
1427 // Insert the next point and reset
1428 // its weight to exclude it from
1429 // future picks
1430 newFaceLabels.append(curPime[nextPoint]);
1431 edgePointWeights[nextPoint] = GREAT;
1432 }
1433 }
1434
1435 break;
1436 } // End of found edge
1437 } // End of looking through current edges
1438 }
1439 }
1440 else
1441 {
1442 newFaceLabels.append(oldFace[pointi]);
1443 }
1444 }
1445
1446 if (changed)
1447 {
1448 if (newFaceLabels.size() < 3)
1449 {
1451 << "Face " << curFaceID << " reduced to less than "
1452 << "3 points. Topological/cutting error A." << nl
1453 << "Old face: " << oldFace << " new face: " << newFaceLabels
1454 << abort(FatalError);
1455 }
1456
1457 // Get face zone and its flip
1458 const label modifiedFaceZone = faceZones.whichZone(curFaceID);
1459
1460 const bool modifiedFaceZoneFlip =
1461 (
1462 modifiedFaceZone >= 0
1463 ?
1464 faceZones[modifiedFaceZone].flipMap()
1465 [
1466 faceZones[modifiedFaceZone].whichFace(curFaceID)
1467 ]
1468 : false
1469 );
1470
1471 face newFace;
1472 newFace.transfer(newFaceLabels);
1473
1474 // Pout<< "Modifying master stick-out face[" << curFaceID
1475 // << "]: old: " << oldFace << " new: " << newFace << endl;
1476
1477 // Modify the face
1478 if (mesh.isInternalFace(curFaceID))
1479 {
1480 ref.setAction
1481 (
1482 polyModifyFace
1483 (
1484 newFace, // modified face
1485 curFaceID, // label of face being modified
1486 own[curFaceID], // owner
1487 nei[curFaceID], // neighbour
1488 false, // face flip
1489 -1, // patch for face
1490 false, // remove from zone
1491 modifiedFaceZone, // zone for face
1492 modifiedFaceZoneFlip // face flip in zone
1493 )
1494 );
1495 }
1496 else
1497 {
1498 ref.setAction
1499 (
1500 polyModifyFace
1501 (
1502 newFace, // modified face
1503 curFaceID, // label of face being modified
1504 own[curFaceID], // owner
1505 -1, // neighbour
1506 false, // face flip
1507 mesh.boundaryMesh().whichPatch(curFaceID),
1508 // patch for face
1509 false, // remove from zone
1510 modifiedFaceZone, // zone for face
1511 modifiedFaceZoneFlip // face flip in zone
1512 )
1513 );
1514 }
1515 }
1516 }
1517
1518 // Pout<< "Finished master side" << endl;
1519
1520 // Slave side
1521
1522 // Grab the list of faces in the layer
1523 const labelList& slaveStickOuts = slaveStickOutFaces();
1524
1525 // Pout<< "slaveStickOuts: " << slaveStickOuts << endl;
1526
1527 const Map<label>& rpm = retiredPointMap();
1528
1529 // Re-create the slave stick-out faces
1530
1531 for (const label curFaceID : slaveStickOuts)
1532 {
1533 // Renumber the face and remove additional points
1534 const face& oldRichFace = faces[curFaceID];
1535
1536 bool changed = false;
1537
1538 // Remove removed points from the face
1539 face oldFace(oldRichFace.size());
1540 label nOldFace = 0;
1541
1542 for (const label pointi : oldRichFace)
1543 {
1544 if
1545 (
1546 rpm.found(pointi)
1547 || slaveMeshPointMap.found(pointi)
1548 )
1549 {
1550 // Point definitely live. Add it
1551 oldFace[nOldFace] = pointi;
1552 nOldFace++;
1553 }
1554 else if (ref.pointRemoved(pointi))
1555 {
1556 // Point removed, not on slave patch and not retired
1557 // (first if takes care of that!)
1558 changed = true;
1559 }
1560 else
1561 {
1562 // Point on master or slave patch
1563 oldFace[nOldFace] = pointi;
1564 nOldFace++;
1565 }
1566 }
1567
1568 oldFace.setSize(nOldFace);
1569
1570 DynamicList<label> newFaceLabels(2*oldFace.size());
1571
1572 // Pout<< "old rich slave face: " << oldRichFace
1573 // << " old face: " << oldFace
1574 // << endl;
1575
1576 forAll(oldFace, pointi)
1577 {
1578 // Try to find the point in retired points
1579 const label curP = rpm.lookup(oldFace[pointi], oldFace[pointi]);
1580
1581 if (curP != oldFace[pointi])
1582 {
1583 changed = true;
1584 }
1585
1586 const label localFirstLabel = slaveMeshPointMap.lookup(curP, -1);
1587
1588 if (localFirstLabel != -1)
1589 {
1590 // Point is in slave patch. Add it
1591
1592 // If the point is a direct hit, grab its label;
1593 // otherwise keep the original
1594 newFaceLabels.append
1595 (
1596 pointMergeMap.lookup(curP, curP)
1597 );
1598
1599 if (newFaceLabels.last() != curP)
1600 {
1601 changed = true;
1602 }
1603
1604 // Find if there are additional points inserted onto the edge
1605 // between current point and the next point
1606 // Algorithm:
1607 // 1) Find all the edges in the slave patch coming
1608 // out of the current point.
1609 // 2) Use the next point in the face to pick the right edge
1610
1611 const labelList& curEdges = slavePointEdges[localFirstLabel];
1612
1613 label nextLabel = oldFace.nextLabel(pointi);
1614
1615 nextLabel = rpm.lookup(nextLabel, nextLabel);
1616
1617 const label localNextLabel =
1618 slaveMeshPointMap.lookup(nextLabel, -1);
1619
1620 if (localNextLabel != -1)
1621 {
1622 // Both points on the slave patch.
1623 // Find the points on the edge between them
1624
1625 for (const label curEdgei : curEdges)
1626 {
1627 if
1628 (
1629 slaveEdges[curEdgei].otherVertex
1630 (
1631 localFirstLabel
1632 )
1633 == localNextLabel
1634 )
1635 {
1636 // Pout<< " found edge: " << curEdgei
1637 // << endl;
1638
1639 // Get points on current edge
1640 const labelList& curPise = pise[curEdgei];
1641
1642 if (curPise.size())
1643 {
1644 changed = true;
1645
1646 // Pout<< "curPise: " << curPise << endl;
1647 // Insert the edge points into the face
1648 // in the correct order
1649 const point& startPoint =
1650 projectedSlavePoints[localFirstLabel];
1651
1652 const point& endPoint =
1653 projectedSlavePoints[localNextLabel];
1654
1655 vector e = endPoint - startPoint;
1656
1657 e /= magSqr(e);
1658
1659 scalarField edgePointWeights(curPise.size());
1660
1661 forAll(curPise, curPiseI)
1662 {
1663 edgePointWeights[curPiseI] =
1664 (
1665 e
1666 & (
1667 pointMap[curPise[curPiseI]]
1668 - startPoint
1669 )
1670 );
1671 }
1672
1673 if (debug)
1674 {
1675 if
1676 (
1677 min(edgePointWeights) < 0
1678 || max(edgePointWeights) > 1
1679 )
1680 {
1682 << "Error in slave stick-out edge "
1683 << "point collection."
1684 << abort(FatalError);
1685 }
1686 }
1687
1688 // Go through the points and collect
1689 // them based on weights from lower to
1690 // higher. This gives the correct
1691 // order of points along the edge.
1692 for
1693 (
1694 label passI = 0;
1695 passI < edgePointWeights.size();
1696 passI++
1697 )
1698 {
1699 // Max weight can only be one, so
1700 // the sorting is done by
1701 // elimination.
1702 label nextPoint = -1;
1703 scalar dist = 2;
1704
1705 forAll(edgePointWeights, wI)
1706 {
1707 if (edgePointWeights[wI] < dist)
1708 {
1709 dist = edgePointWeights[wI];
1710 nextPoint = wI;
1711 }
1712 }
1713
1714 // Insert the next point and reset
1715 // its weight to exclude it from
1716 // future picks
1717 newFaceLabels.append(curPise[nextPoint]);
1718 edgePointWeights[nextPoint] = GREAT;
1719 }
1720 }
1721
1722 break;
1723 }
1724 } // End of found edge
1725 } // End of looking through current edges
1726 }
1727 else
1728 {
1729 newFaceLabels.append(oldFace[pointi]);
1730 }
1731 }
1732
1733 if (changed)
1734 {
1735 if (newFaceLabels.size() < 3)
1736 {
1738 << "Face " << curFaceID << " reduced to less than "
1739 << "3 points. Topological/cutting error B." << nl
1740 << "Old face: " << oldFace << " new face: " << newFaceLabels
1741 << abort(FatalError);
1742 }
1743
1744 // Get face zone and its flip
1745 const label modifiedFaceZone =
1746 faceZones.whichZone(curFaceID);
1747
1748 const bool modifiedFaceZoneFlip
1749 (
1750 modifiedFaceZone >= 0
1751 ?
1752 faceZones[modifiedFaceZone].flipMap()
1753 [
1754 faceZones[modifiedFaceZone].whichFace(curFaceID)
1755 ]
1756 : false
1757 );
1758
1759 face newFace;
1760 newFace.transfer(newFaceLabels);
1761
1762 // Pout<< "Modifying slave stick-out face[" << curFaceID
1763 // << "]: old: " << oldFace << " new: " << newFace
1764 // << endl;
1765
1766 // Modify the face
1767 if (mesh.isInternalFace(curFaceID))
1768 {
1769 ref.setAction
1770 (
1771 polyModifyFace
1772 (
1773 newFace, // modified face
1774 curFaceID, // label of face being modified
1775 own[curFaceID], // owner
1776 nei[curFaceID], // neighbour
1777 false, // face flip
1778 -1, // patch for face
1779 false, // remove from zone
1780 modifiedFaceZone, // zone for face
1781 modifiedFaceZoneFlip // face flip in zone
1782 )
1783 );
1784 }
1785 else
1786 {
1787 ref.setAction
1788 (
1789 polyModifyFace
1790 (
1791 newFace, // modified face
1792 curFaceID, // label of face being modified
1793 own[curFaceID], // owner
1794 -1, // neighbour
1795 false, // face flip
1796 mesh.boundaryMesh().whichPatch(curFaceID),
1797 // patch for face
1798 false, // remove from zone
1799 modifiedFaceZone, // zone for face
1800 modifiedFaceZoneFlip // face flip in zone
1801 )
1802 );
1803 }
1804 }
1805 }
1806
1807 // Activate and retire slave patch points
1808 // This needs to be done last, so that the map of removed points
1809 // does not get damaged by point modifications
1810
1811 if (!retiredPointMapPtr_)
1812 {
1814 << "Retired point map pointer not set."
1815 << abort(FatalError);
1816 }
1817
1818 Map<label>& addToRpm = *retiredPointMapPtr_;
1819
1820 // Clear the old map
1821 addToRpm.clear();
1822
1823 label nRetiredPoints = 0;
1824
1825 for (const label slavePointi : slaveMeshPoints)
1826 {
1827 const label masterPointi = pointMergeMap.lookup(slavePointi, -1);
1828
1829 if (slavePointi == masterPointi)
1830 {
1831 // Identity mapping (ie, slave point already exists on master patch)
1832 continue;
1833 }
1834 else if (masterPointi != -1)
1835 {
1836 // Retire the point - only used for supporting the detached
1837 // slave patch
1838 nRetiredPoints++;
1839
1840 // ref.setAction
1841 // (
1842 // polyModifyPoint
1843 // (
1844 // slavePointi, // point ID
1845 // points[slavePointi], // point
1846 // false, // remove from zone
1847 // mesh.pointZones().whichZone(slavePointi), // zone
1848 // false // in a cell
1849 // )
1850 // );
1851 //
1852 //Pout<< "MJ retire slave point " << slavePointi
1853 // << " coord " << points[slavePointi]
1854 // << endl;
1855 ref.setAction
1856 (
1857 polyRemovePoint
1858 (
1859 slavePointi
1860 )
1861 );
1862
1863 addToRpm.insert(masterPointi, slavePointi);
1864 }
1865 else
1866 {
1867 ref.setAction
1868 (
1869 polyModifyPoint
1870 (
1871 slavePointi, // point ID
1872 points[slavePointi], // point
1873 false, // remove from zone
1874 mesh.pointZones().whichZone(slavePointi),// zone
1875 true // in a cell
1876 )
1877 );
1878 }
1879 }
1880
1881 if (debug)
1882 {
1883 Pout<< "Retired " << nRetiredPoints << "/"
1884 << slaveMeshPoints.size() << " points." << endl;
1885 }
1886
1887 // Grab cut face master and slave addressing
1888 cutFaceMasterPtr_.reset(new labelList(cutPatch.cutFaceMaster()));
1889 cutFaceSlavePtr_.reset(new labelList(cutPatch.cutFaceSlave()));
1890
1891 // Finished coupling
1892 attached_ = true;
1893
1894 if (debug)
1895 {
1896 Pout<< FUNCTION_NAME << nl
1897 << ": Finished coupling sliding interface " << name() << endl;
1898 }
1899}
1900
1901
1902// ************************************************************************* //
label index() const
The index of the first matching items, -1 if no matches.
Definition: DynamicID.H:123
void clear()
Clear all entries from table.
Definition: HashTable.C:678
label whichZone(const label objectIndex) const
Given a global object index, return the zone it is in.
Definition: ZoneMesh.C:288
label whichPatch(const label faceIndex) const
Return patch index for a given face label.
const word & name() const
Return name of this modifier.
const polyTopoChanger & topoChanger() const
Return reference to morph engine.
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:498
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1108
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1121
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:456
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1127
const pointZoneMesh & pointZones() const noexcept
Return point zone mesh.
Definition: polyMesh.H:492
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1083
const polyMesh & mesh() const
Return the mesh reference.
bool isInternalFace(const label faceIndex) const noexcept
Return true if given face label is internal to the mesh.
static const unsigned edgesPerFace_
Estimated number of edges per cell.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
rDeltaT ref()
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
const pointField & points
#define FUNCTION_NAME
const dimensionedScalar c
Speed of light in a vacuum.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
List< label > labelList
A List of labels.
Definition: List.H:66
dimensionedSymmTensor sqr(const dimensionedVector &dv)
line< point, const point & > linePointRef
A line using referred points.
Definition: linePointRef.H:47
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
vector point
Point is a vector.
Definition: point.H:43
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
ZoneMesh< faceZone, polyMesh > faceZoneMesh
A ZoneMesh with the type faceZone.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
errorManip< error > abort(error &err)
Definition: errorManip.H:144
PointHit< point > pointHit
A PointIndexHit for 3D points.
Definition: pointHit.H:44
Field< vector > vectorField
Specialisation of Field<T> for vector.
List< bool > boolList
A List of bools.
Definition: List.H:64
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
PrimitivePatch< List< face >, const pointField & > primitiveFacePatch
A PrimitivePatch with List storage for the faces, const reference for the point field.
error FatalError
List< edge > edgeList
A List of edges.
Definition: edgeList.H:63
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
label newPointi
Definition: readKivaGrid.H:496
volScalarField & b
Definition: createFields.H:27
volScalarField & e
Definition: createFields.H:11
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333