autoSnapDriver.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 | Copyright (C) 2011-2015 OpenFOAM Foundation
6  \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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
19  for more details.
20 
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/>.
23 
24 Description
25  All to do with snapping to the surface
26 
27 \*----------------------------------------------------------------------------*/
28 
29 #include "autoSnapDriver.H"
30 #include "motionSmoother.H"
31 #include "polyTopoChange.H"
32 #include "syncTools.H"
33 #include "fvMesh.H"
34 #include "Time.H"
35 #include "OFstream.H"
36 #include "OBJstream.H"
37 #include "mapPolyMesh.H"
38 #include "pointEdgePoint.H"
39 #include "PointEdgeWave.H"
40 #include "mergePoints.H"
41 #include "snapParameters.H"
42 #include "refinementSurfaces.H"
43 #include "searchableSurfaces.H"
44 #include "unitConversion.H"
45 #include "localPointRegion.H"
46 #include "PatchTools.H"
47 #include "refinementFeatures.H"
48 
49 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
50 
51 namespace Foam
52 {
53 
54 defineTypeNameAndDebug(autoSnapDriver, 0);
55 
56 } // End namespace Foam
57 
58 
59 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
60 
61 // Calculate geometrically collocated points, Requires PackedList to be
62 // sized and initalised!
64 (
65  const scalar tol,
66  const pointField& points,
67  PackedBoolList& isCollocatedPoint
68 )
69 {
70  labelList pointMap;
71  label nUnique = mergePoints
72  (
73  points, // points
74  tol, // mergeTol
75  false, // verbose
76  pointMap
77  );
78  bool hasMerged = (nUnique < points.size());
79 
80  if (!returnReduce(hasMerged, orOp<bool>()))
81  {
82  return 0;
83  }
84 
85  // Determine which merged points are referenced more than once
86  label nCollocated = 0;
87 
88  // Per old point the newPoint. Or -1 (not set yet) or -2 (already seen
89  // twice)
90  labelList firstOldPoint(nUnique, -1);
91  forAll(pointMap, oldPointI)
92  {
93  label newPointI = pointMap[oldPointI];
94 
95  if (firstOldPoint[newPointI] == -1)
96  {
97  // First use of oldPointI. Store.
98  firstOldPoint[newPointI] = oldPointI;
99  }
100  else if (firstOldPoint[newPointI] == -2)
101  {
102  // Third or more reference of oldPointI -> non-manifold
103  isCollocatedPoint.set(oldPointI, 1u);
104  nCollocated++;
105  }
106  else
107  {
108  // Second reference of oldPointI -> non-manifold
109  isCollocatedPoint.set(firstOldPoint[newPointI], 1u);
110  nCollocated++;
111 
112  isCollocatedPoint.set(oldPointI, 1u);
113  nCollocated++;
114 
115  // Mark with special value to save checking next time round
116  firstOldPoint[newPointI] = -2;
117  }
118  }
119  return returnReduce(nCollocated, sumOp<label>());
120 }
121 
122 
124 (
125  const meshRefinement& meshRefiner,
126  const motionSmoother& meshMover
127 )
128 {
129  const indirectPrimitivePatch& pp = meshMover.patch();
130  const polyMesh& mesh = meshMover.mesh();
131 
132  // Get neighbour refinement
133  const hexRef8& cutter = meshRefiner.meshCutter();
134  const labelList& cellLevel = cutter.cellLevel();
135 
136 
137  // Get the faces on the boundary
138  PackedBoolList isFront(mesh.nFaces());
139  forAll(pp.addressing(), i)
140  {
141  isFront[pp.addressing()[i]] = true;
142  }
143 
144  // Walk out from the surface a bit. Poor man's FaceCellWave.
145  // Commented out for now - not sure if needed and if so how much
146  //for (label iter = 0; iter < 2; iter++)
147  //{
148  // PackedBoolList newIsFront(mesh.nFaces());
149  //
150  // forAll(isFront, faceI)
151  // {
152  // if (isFront[faceI])
153  // {
154  // label own = mesh.faceOwner()[faceI];
155  // const cell& ownFaces = mesh.cells()[own];
156  // forAll(ownFaces, i)
157  // {
158  // newIsFront[ownFaces[i]] = true;
159  // }
160  //
161  // if (mesh.isInternalFace(faceI))
162  // {
163  // label nei = mesh.faceNeighbour()[faceI];
164  // const cell& neiFaces = mesh.cells()[nei];
165  // forAll(neiFaces, i)
166  // {
167  // newIsFront[neiFaces[i]] = true;
168  // }
169  // }
170  // }
171  // }
172  //
173  // syncTools::syncFaceList
174  // (
175  // mesh,
176  // newIsFront,
177  // orEqOp<unsigned int>()
178  // );
179  //
180  // isFront = newIsFront;
181  //}
182 
183  // Mark all points on faces
184  // - not on the boundary
185  // - inbetween differing refinement levels
186  PackedBoolList isMovingPoint(mesh.nPoints());
187 
188  label nInterface = 0;
189 
190  for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
191  {
192  label ownLevel = cellLevel[mesh.faceOwner()[faceI]];
193  label neiLevel = cellLevel[mesh.faceNeighbour()[faceI]];
194 
195  if (!isFront[faceI] && ownLevel != neiLevel)
196  {
197  const face& f = mesh.faces()[faceI];
198  forAll(f, fp)
199  {
200  isMovingPoint[f[fp]] = true;
201  }
202 
203  nInterface++;
204  }
205  }
206 
207  labelList neiCellLevel;
208  syncTools::swapBoundaryCellList(mesh, cellLevel, neiCellLevel);
209 
210  for (label faceI = mesh.nInternalFaces(); faceI < mesh.nFaces(); faceI++)
211  {
212  label ownLevel = cellLevel[mesh.faceOwner()[faceI]];
213  label neiLevel = neiCellLevel[faceI-mesh.nInternalFaces()];
214 
215  if (!isFront[faceI] && ownLevel != neiLevel)
216  {
217  const face& f = mesh.faces()[faceI];
218  forAll(f, fp)
219  {
220  isMovingPoint[f[fp]] = true;
221  }
222 
223  nInterface++;
224  }
225  }
226 
227  if (debug)
228  {
229  reduce(nInterface, sumOp<label>());
230  Info<< "Found " << nInterface << " faces out of "
231  << mesh.globalData().nTotalFaces()
232  << " inbetween refinement regions." << endl;
233  }
234 
235  // Make sure that points that are coupled to a moving point are marked
236  // as well
237  syncTools::syncPointList(mesh, isMovingPoint, maxEqOp<unsigned int>(), 0);
238 
239  // Unmark any point on the boundary. If we're doing zero iterations of
240  // face-cell wave we might have coupled points not being unmarked.
241  forAll(pp.meshPoints(), pointI)
242  {
243  isMovingPoint[pp.meshPoints()[pointI]] = false;
244  }
245 
246  // Make sure that points that are coupled to meshPoints but not on a patch
247  // are unmarked as well
248  syncTools::syncPointList(mesh, isMovingPoint, minEqOp<unsigned int>(), 1);
249 
250 
251  // Calculate average of connected cells
252  labelList nCells(mesh.nPoints(), 0);
253  pointField sumLocation(mesh.nPoints(), vector::zero);
254 
255  forAll(isMovingPoint, pointI)
256  {
257  if (isMovingPoint[pointI])
258  {
259  const labelList& pCells = mesh.pointCells(pointI);
260 
261  forAll(pCells, i)
262  {
263  sumLocation[pointI] += mesh.cellCentres()[pCells[i]];
264  nCells[pointI]++;
265  }
266  }
267  }
268 
269  // Sum
270  syncTools::syncPointList(mesh, nCells, plusEqOp<label>(), label(0));
271  syncTools::syncPointList
272  (
273  mesh,
274  sumLocation,
275  plusEqOp<point>(),
276  vector::zero
277  );
278 
279  tmp<pointField> tdisplacement(new pointField(mesh.nPoints(), vector::zero));
280  pointField& displacement = tdisplacement();
281 
282  label nAdapted = 0;
283 
284  forAll(displacement, pointI)
285  {
286  if (nCells[pointI] > 0)
287  {
288  displacement[pointI] =
289  sumLocation[pointI]/nCells[pointI]-mesh.points()[pointI];
290  nAdapted++;
291  }
292  }
293 
294  reduce(nAdapted, sumOp<label>());
295  Info<< "Smoothing " << nAdapted << " points inbetween refinement regions."
296  << endl;
297 
298  return tdisplacement;
299 }
300 
301 
302 // Calculate displacement as average of patch points.
304 (
305  const motionSmoother& meshMover,
306  const List<labelPair>& baffles
307 )
308 {
309  const indirectPrimitivePatch& pp = meshMover.patch();
310 
311  // Calculate geometrically non-manifold points on the patch to be moved.
312  PackedBoolList nonManifoldPoint(pp.nPoints());
313  label nNonManifoldPoints = getCollocatedPoints
314  (
315  SMALL,
316  pp.localPoints(),
317  nonManifoldPoint
318  );
319  Info<< "Found " << nNonManifoldPoints << " non-manifold point(s)."
320  << endl;
321 
322 
323  // Average points
324  // ~~~~~~~~~~~~~~
325 
326  // We determine three points:
327  // - average of (centres of) connected patch faces
328  // - average of (centres of) connected internal mesh faces
329  // - as fallback: centre of any connected cell
330  // so we can do something moderately sensible for non/manifold points.
331 
332  // Note: the averages are calculated properly parallel. This is
333  // necessary to get the points shared by processors correct.
334 
335 
336  const labelListList& pointFaces = pp.pointFaces();
337  const labelList& meshPoints = pp.meshPoints();
338  const pointField& points = pp.points();
339  const polyMesh& mesh = meshMover.mesh();
340 
341  // Get labels of faces to count (master of coupled faces and baffle pairs)
342  PackedBoolList isMasterFace(syncTools::getMasterFaces(mesh));
343 
344  {
345  forAll(baffles, i)
346  {
347  label f0 = baffles[i].first();
348  label f1 = baffles[i].second();
349 
350  if (isMasterFace.get(f0))
351  {
352  // Make f1 a slave
353  isMasterFace.unset(f1);
354  }
355  else if (isMasterFace.get(f1))
356  {
357  isMasterFace.unset(f0);
358  }
359  else
360  {
362  << "Both sides of baffle consisting of faces " << f0
363  << " and " << f1 << " are already slave faces."
364  << abort(FatalError);
365  }
366  }
367  }
368 
369 
370  // Get average position of boundary face centres
371  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
372 
373  vectorField avgBoundary(pointFaces.size(), vector::zero);
374  labelList nBoundary(pointFaces.size(), 0);
375 
376  forAll(pointFaces, patchPointI)
377  {
378  const labelList& pFaces = pointFaces[patchPointI];
379 
380  forAll(pFaces, pfI)
381  {
382  label faceI = pFaces[pfI];
383 
384  if (isMasterFace.get(pp.addressing()[faceI]))
385  {
386  avgBoundary[patchPointI] += pp[faceI].centre(points);
387  nBoundary[patchPointI]++;
388  }
389  }
390  }
391 
392  syncTools::syncPointList
393  (
394  mesh,
395  pp.meshPoints(),
396  avgBoundary,
397  plusEqOp<point>(), // combine op
398  vector::zero // null value
399  );
400  syncTools::syncPointList
401  (
402  mesh,
403  pp.meshPoints(),
404  nBoundary,
405  plusEqOp<label>(), // combine op
406  label(0) // null value
407  );
408 
409  forAll(avgBoundary, i)
410  {
411  avgBoundary[i] /= nBoundary[i];
412  }
413 
414 
415  // Get average position of internal face centres
416  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
417 
418  vectorField avgInternal;
419  labelList nInternal;
420  {
421  vectorField globalSum(mesh.nPoints(), vector::zero);
422  labelList globalNum(mesh.nPoints(), 0);
423 
424  // Note: no use of pointFaces
425  const faceList& faces = mesh.faces();
426 
427  for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
428  {
429  const face& f = faces[faceI];
430  const point& fc = mesh.faceCentres()[faceI];
431 
432  forAll(f, fp)
433  {
434  globalSum[f[fp]] += fc;
435  globalNum[f[fp]]++;
436  }
437  }
438 
439  // Count coupled faces as internal ones (but only once)
440  const polyBoundaryMesh& patches = mesh.boundaryMesh();
441 
442  forAll(patches, patchI)
443  {
444  if
445  (
446  patches[patchI].coupled()
447  && refCast<const coupledPolyPatch>(patches[patchI]).owner()
448  )
449  {
450  const coupledPolyPatch& pp =
451  refCast<const coupledPolyPatch>(patches[patchI]);
452 
453  const vectorField::subField faceCentres = pp.faceCentres();
454 
455  forAll(pp, i)
456  {
457  const face& f = pp[i];
458  const point& fc = faceCentres[i];
459 
460  forAll(f, fp)
461  {
462  globalSum[f[fp]] += fc;
463  globalNum[f[fp]]++;
464  }
465  }
466  }
467  }
468 
469  syncTools::syncPointList
470  (
471  mesh,
472  globalSum,
473  plusEqOp<vector>(), // combine op
474  vector::zero // null value
475  );
476  syncTools::syncPointList
477  (
478  mesh,
479  globalNum,
480  plusEqOp<label>(), // combine op
481  label(0) // null value
482  );
483 
484  avgInternal.setSize(meshPoints.size());
485  nInternal.setSize(meshPoints.size());
486 
487  forAll(avgInternal, patchPointI)
488  {
489  label meshPointI = meshPoints[patchPointI];
490 
491  nInternal[patchPointI] = globalNum[meshPointI];
492 
493  if (nInternal[patchPointI] == 0)
494  {
495  avgInternal[patchPointI] = globalSum[meshPointI];
496  }
497  else
498  {
499  avgInternal[patchPointI] =
500  globalSum[meshPointI]
501  / nInternal[patchPointI];
502  }
503  }
504  }
505 
506 
507  // Precalculate any cell using mesh point (replacement of pointCells()[])
508  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
509 
510  labelList anyCell(mesh.nPoints(), -1);
511  forAll(mesh.faceOwner(), faceI)
512  {
513  label own = mesh.faceOwner()[faceI];
514  const face& f = mesh.faces()[faceI];
515 
516  forAll(f, fp)
517  {
518  anyCell[f[fp]] = own;
519  }
520  }
521 
522 
523  // Displacement to calculate.
524  tmp<pointField> tpatchDisp(new pointField(meshPoints.size(), vector::zero));
525  pointField& patchDisp = tpatchDisp();
526 
527  forAll(pointFaces, i)
528  {
529  label meshPointI = meshPoints[i];
530  const point& currentPos = pp.points()[meshPointI];
531 
532  // Now we have the two average points: avgBoundary and avgInternal
533  // and how many boundary/internal faces connect to the point
534  // (nBoundary, nInternal)
535  // Do some blending between the two.
536  // Note: the following section has some reasoning behind it but the
537  // blending factors can be experimented with.
538 
539  point newPos;
540 
541  if (!nonManifoldPoint.get(i))
542  {
543  // Points that are manifold. Weight the internal and boundary
544  // by their number of faces and blend with
545  scalar internalBlend = 0.1;
546  scalar blend = 0.1;
547 
548  point avgPos =
549  (
550  internalBlend*nInternal[i]*avgInternal[i]
551  +(1-internalBlend)*nBoundary[i]*avgBoundary[i]
552  )
553  / (internalBlend*nInternal[i]+(1-internalBlend)*nBoundary[i]);
554 
555  newPos = (1-blend)*avgPos + blend*currentPos;
556  }
557  else if (nInternal[i] == 0)
558  {
559  // Non-manifold without internal faces. Use any connected cell
560  // as internal point instead. Use precalculated any cell to avoid
561  // e.g. pointCells()[meshPointI][0]
562 
563  const point& cc = mesh.cellCentres()[anyCell[meshPointI]];
564 
565  scalar cellCBlend = 0.8;
566  scalar blend = 0.1;
567 
568  point avgPos = (1-cellCBlend)*avgBoundary[i] + cellCBlend*cc;
569 
570  newPos = (1-blend)*avgPos + blend*currentPos;
571  }
572  else
573  {
574  // Non-manifold point with internal faces connected to them
575  scalar internalBlend = 0.9;
576  scalar blend = 0.1;
577 
578  point avgPos =
579  internalBlend*avgInternal[i]
580  + (1-internalBlend)*avgBoundary[i];
581 
582  newPos = (1-blend)*avgPos + blend*currentPos;
583  }
584 
585  patchDisp[i] = newPos - currentPos;
586  }
587 
588  return tpatchDisp;
589 }
590 //XXXXXXX
591 //Foam::tmp<Foam::pointField> Foam::autoSnapDriver::avg
592 //(
593 // const indirectPrimitivePatch& pp,
594 // const pointField& localPoints
595 //)
596 //{
597 // const labelListList& pointEdges = pp.pointEdges();
598 // const edgeList& edges = pp.edges();
599 //
600 // tmp<pointField> tavg(new pointField(pointEdges.size(), vector::zero));
601 // pointField& avg = tavg();
602 //
603 // forAll(pointEdges, vertI)
604 // {
605 // vector& avgPos = avg[vertI];
606 //
607 // const labelList& pEdges = pointEdges[vertI];
608 //
609 // forAll(pEdges, myEdgeI)
610 // {
611 // const edge& e = edges[pEdges[myEdgeI]];
612 //
613 // label otherVertI = e.otherVertex(vertI);
614 //
615 // avgPos += localPoints[otherVertI];
616 // }
617 //
618 // avgPos /= pEdges.size();
619 // }
620 // return tavg;
621 //}
622 //Foam::tmp<Foam::pointField>
623 //Foam::autoSnapDriver::smoothLambdaMuPatchDisplacement
624 //(
625 // const motionSmoother& meshMover,
626 // const List<labelPair>& baffles
627 //)
628 //{
629 // const indirectPrimitivePatch& pp = meshMover.patch();
630 // pointField newLocalPoints(pp.localPoints());
631 //
632 // const label iters = 90;
633 // const scalar lambda = 0.33;
634 // const scalar mu = 0.34;
635 //
636 // for (label iter = 0; iter < iters; iter++)
637 // {
638 // // Lambda
639 // newLocalPoints =
640 // (1 - lambda)*newLocalPoints
641 // + lambda*avg(pp, newLocalPoints);
642 //
643 // // Mu
644 // newLocalPoints =
645 // (1 + mu)*newLocalPoints
646 // - mu*avg(pp, newLocalPoints);
647 // }
648 // return newLocalPoints-pp.localPoints();
649 //}
650 //XXXXXXX
651 
652 
654 (
655  const pointMesh& pMesh,
656  const indirectPrimitivePatch& pp
657 )
658 {
659  const polyMesh& mesh = pMesh();
660 
661  // Set initial changed points to all the patch points
662  List<pointEdgePoint> wallInfo(pp.nPoints());
663 
664  forAll(pp.localPoints(), ppI)
665  {
666  wallInfo[ppI] = pointEdgePoint(pp.localPoints()[ppI], 0.0);
667  }
668 
669  // Current info on points
670  List<pointEdgePoint> allPointInfo(mesh.nPoints());
671 
672  // Current info on edges
673  List<pointEdgePoint> allEdgeInfo(mesh.nEdges());
674 
676  (
677  mesh,
678  pp.meshPoints(),
679  wallInfo,
680 
681  allPointInfo,
682  allEdgeInfo,
683  mesh.globalData().nTotalPoints() // max iterations
684  );
685 
686  // Copy edge values into scalarField
687  tmp<scalarField> tedgeDist(new scalarField(mesh.nEdges()));
688  scalarField& edgeDist = tedgeDist();
689 
690  forAll(allEdgeInfo, edgeI)
691  {
692  edgeDist[edgeI] = Foam::sqrt(allEdgeInfo[edgeI].distSqr());
693  }
694 
695  return tedgeDist;
696 }
697 
698 
700 (
701  const fileName& fName,
702  const pointField& meshPts,
703  const pointField& surfPts
704 )
705 {
706  // Dump direction of growth into file
707  Info<< "Dumping move direction to " << fName << endl;
708 
709  OFstream nearestStream(fName);
710 
711  label vertI = 0;
712 
713  forAll(meshPts, ptI)
714  {
715  meshTools::writeOBJ(nearestStream, meshPts[ptI]);
716  vertI++;
717 
718  meshTools::writeOBJ(nearestStream, surfPts[ptI]);
719  vertI++;
720 
721  nearestStream<< "l " << vertI-1 << ' ' << vertI << nl;
722  }
723 }
724 
725 
726 // Check whether all displacement vectors point outwards of patch. Return true
727 // if so.
729 (
730  const indirectPrimitivePatch& pp,
731  const vectorField& patchDisp
732 )
733 {
734  const vectorField& faceNormals = pp.faceNormals();
735  const labelListList& pointFaces = pp.pointFaces();
736 
737  forAll(pointFaces, pointI)
738  {
739  const labelList& pFaces = pointFaces[pointI];
740 
741  vector disp(patchDisp[pointI]);
742 
743  scalar magDisp = mag(disp);
744 
745  if (magDisp > SMALL)
746  {
747  disp /= magDisp;
748 
749  bool outwards = meshTools::visNormal(disp, faceNormals, pFaces);
750 
751  if (!outwards)
752  {
753  Warning<< "Displacement " << patchDisp[pointI]
754  << " at mesh point " << pp.meshPoints()[pointI]
755  << " coord " << pp.points()[pp.meshPoints()[pointI]]
756  << " points through the surrounding patch faces" << endl;
757  return false;
758  }
759  }
760  else
761  {
762  //? Displacement small but in wrong direction. Would probably be ok.
763  }
764  }
765  return true;
766 }
767 
768 
769 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
770 
772 (
773  meshRefinement& meshRefiner,
774  const labelList& globalToMasterPatch,
775  const labelList& globalToSlavePatch
776 )
777 :
778  meshRefiner_(meshRefiner),
779  globalToMasterPatch_(globalToMasterPatch),
780  globalToSlavePatch_(globalToSlavePatch)
781 {}
782 
783 
784 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
785 
787 (
788  const fvMesh& mesh,
789  const snapParameters& snapParams,
790  const indirectPrimitivePatch& pp
791 )
792 {
793  const edgeList& edges = pp.edges();
794  const labelListList& pointEdges = pp.pointEdges();
795  const pointField& localPoints = pp.localPoints();
796 
797  scalarField maxEdgeLen(localPoints.size(), -GREAT);
798 
799  forAll(pointEdges, pointI)
800  {
801  const labelList& pEdges = pointEdges[pointI];
802 
803  forAll(pEdges, pEdgeI)
804  {
805  const edge& e = edges[pEdges[pEdgeI]];
806 
807  scalar len = e.mag(localPoints);
808 
809  maxEdgeLen[pointI] = max(maxEdgeLen[pointI], len);
810  }
811  }
812 
813  syncTools::syncPointList
814  (
815  mesh,
816  pp.meshPoints(),
817  maxEdgeLen,
818  maxEqOp<scalar>(), // combine op
819  -GREAT // null value
820  );
821 
822  return scalarField(snapParams.snapTol()*maxEdgeLen);
823 }
824 
825 
827 (
828  const meshRefinement& meshRefiner,
829  const snapParameters& snapParams,
830  const label nInitErrors,
831  const List<labelPair>& baffles,
832  motionSmoother& meshMover
833 )
834 {
835  const fvMesh& mesh = meshRefiner.mesh();
836 
837  labelList checkFaces;
838 
839  if (snapParams.nSmoothInternal() > 0)
840  {
841  Info<< "Smoothing patch and internal points ..." << endl;
842  }
843  else
844  {
845  Info<< "Smoothing patch points ..." << endl;
846  }
847 
848  for
849  (
850  label smoothIter = 0;
851  smoothIter < snapParams.nSmoothPatch();
852  smoothIter++
853  )
854  {
855  Info<< "Smoothing iteration " << smoothIter << endl;
856  checkFaces.setSize(mesh.nFaces());
857  forAll(checkFaces, faceI)
858  {
859  checkFaces[faceI] = faceI;
860  }
861 
862  // If enabled smooth the internal points
863  if (snapParams.nSmoothInternal() > smoothIter)
864  {
865  // Override values on internal points on refinement interfaces
866  meshMover.pointDisplacement().internalField() =
867  smoothInternalDisplacement(meshRefiner, meshMover);
868  }
869 
870  // Smooth the patch points
871  pointField patchDisp(smoothPatchDisplacement(meshMover, baffles));
872  //pointField patchDisp
873  //(
874  // smoothLambdaMuPatchDisplacement(meshMover, baffles)
875  //);
876 
877  // Take over patch displacement as boundary condition on
878  // pointDisplacement
879  meshMover.setDisplacement(patchDisp);
880 
881  // Start off from current mesh.points()
882  meshMover.correct();
883 
884  scalar oldErrorReduction = -1;
885 
886  for (label snapIter = 0; snapIter < 2*snapParams.nSnap(); snapIter++)
887  {
888  Info<< nl << "Scaling iteration " << snapIter << endl;
889 
890  if (snapIter == snapParams.nSnap())
891  {
892  Info<< "Displacement scaling for error reduction set to 0."
893  << endl;
894  oldErrorReduction = meshMover.setErrorReduction(0.0);
895  }
896 
897  // Try to adapt mesh to obtain displacement by smoothly
898  // decreasing displacement at error locations.
899  if (meshMover.scaleMesh(checkFaces, baffles, true, nInitErrors))
900  {
901  Info<< "Successfully moved mesh" << endl;
902  break;
903  }
904  }
905 
906  if (oldErrorReduction >= 0)
907  {
908  meshMover.setErrorReduction(oldErrorReduction);
909  }
910  Info<< endl;
911  }
912 
913 
914  // The current mesh is the starting mesh to smooth from.
915  meshMover.correct();
916 
917  if (debug&meshRefinement::MESH)
918  {
919  const_cast<Time&>(mesh.time())++;
920  Info<< "Writing patch smoothed mesh to time "
921  << meshRefiner.timeName() << '.' << endl;
922  meshRefiner.write
923  (
926  (
927  meshRefinement::writeLevel()
928  | meshRefinement::WRITEMESH
929  ),
930  mesh.time().path()/meshRefiner.timeName()
931  );
932  Info<< "Dumped mesh in = "
933  << mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
934  }
935 
936  Info<< "Patch points smoothed in = "
937  << mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
938 }
939 
940 
941 // Get (pp-local) indices of points that are both on zone and on patched surface
943 (
944  const fvMesh& mesh,
945  const indirectPrimitivePatch& pp,
946  const word& zoneName
947 )
948 {
949  label zoneI = mesh.faceZones().findZoneID(zoneName);
950 
951  if (zoneI == -1)
952  {
954  << "Cannot find zone " << zoneName
955  << exit(FatalError);
956  }
957 
958  const faceZone& fZone = mesh.faceZones()[zoneI];
959 
960 
961  // Could use PrimitivePatch & localFaces to extract points but might just
962  // as well do it ourselves.
963 
964  boolList pointOnZone(pp.nPoints(), false);
965 
966  forAll(fZone, i)
967  {
968  const face& f = mesh.faces()[fZone[i]];
969 
970  forAll(f, fp)
971  {
972  label meshPointI = f[fp];
973 
975  pp.meshPointMap().find(meshPointI);
976 
977  if (iter != pp.meshPointMap().end())
978  {
979  label pointI = iter();
980  pointOnZone[pointI] = true;
981  }
982  }
983  }
984 
985  return findIndices(pointOnZone, true);
986 }
987 
988 
990 (
991  const fvMesh& mesh,
992  const indirectPrimitivePatch& pp
993 )
994 {
995  const labelListList& pointFaces = pp.pointFaces();
996 
997 
998  tmp<pointField> tavgBoundary
999  (
1000  new pointField(pointFaces.size(), vector::zero)
1001  );
1002  pointField& avgBoundary = tavgBoundary();
1003  labelList nBoundary(pointFaces.size(), 0);
1004 
1005  forAll(pointFaces, pointI)
1006  {
1007  const labelList& pFaces = pointFaces[pointI];
1008 
1009  forAll(pFaces, pfI)
1010  {
1011  label faceI = pFaces[pfI];
1012  label meshFaceI = pp.addressing()[faceI];
1013 
1014  label own = mesh.faceOwner()[meshFaceI];
1015  avgBoundary[pointI] += mesh.cellCentres()[own];
1016  nBoundary[pointI]++;
1017  }
1018  }
1019 
1020  syncTools::syncPointList
1021  (
1022  mesh,
1023  pp.meshPoints(),
1024  avgBoundary,
1025  plusEqOp<point>(), // combine op
1026  vector::zero // null value
1027  );
1028  syncTools::syncPointList
1029  (
1030  mesh,
1031  pp.meshPoints(),
1032  nBoundary,
1033  plusEqOp<label>(), // combine op
1034  label(0) // null value
1035  );
1036 
1037  forAll(avgBoundary, i)
1038  {
1039  avgBoundary[i] /= nBoundary[i];
1040  }
1041  return tavgBoundary;
1042 }
1043 
1044 
1045 //Foam::tmp<Foam::scalarField> Foam::autoSnapDriver::calcEdgeLen
1046 //(
1047 // const indirectPrimitivePatch& pp
1048 //) const
1049 //{
1050 // // Get local edge length based on refinement level
1051 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1052 // // (Ripped from autoLayerDriver)
1053 //
1054 // tmp<scalarField> tedgeLen(new scalarField(pp.nPoints()));
1055 // scalarField& edgeLen = tedgeLen();
1056 // {
1057 // const fvMesh& mesh = meshRefiner_.mesh();
1058 // const scalar edge0Len = meshRefiner_.meshCutter().level0EdgeLength();
1059 // const labelList& cellLevel = meshRefiner_.meshCutter().cellLevel();
1060 //
1061 // labelList maxPointLevel(pp.nPoints(), labelMin);
1062 //
1063 // forAll(pp, i)
1064 // {
1065 // label ownLevel = cellLevel[mesh.faceOwner()[pp.addressing()[i]]];
1066 // const face& f = pp.localFaces()[i];
1067 // forAll(f, fp)
1068 // {
1069 // maxPointLevel[f[fp]] = max(maxPointLevel[f[fp]], ownLevel);
1070 // }
1071 // }
1072 //
1073 // syncTools::syncPointList
1074 // (
1075 // mesh,
1076 // pp.meshPoints(),
1077 // maxPointLevel,
1078 // maxEqOp<label>(),
1079 // labelMin // null value
1080 // );
1081 //
1082 //
1083 // forAll(maxPointLevel, pointI)
1084 // {
1085 // // Find undistorted edge size for this level.
1086 // edgeLen[pointI] = edge0Len/(1<<maxPointLevel[pointI]);
1087 // }
1088 // }
1089 // return tedgeLen;
1090 //}
1091 
1092 
1095  const scalar planarCos,
1096  const indirectPrimitivePatch& pp,
1097  const pointField& nearestPoint,
1098  const vectorField& nearestNormal,
1099 
1100  vectorField& disp
1101 ) const
1102 {
1103  Info<< "Detecting near surfaces ..." << endl;
1104 
1105  const pointField& localPoints = pp.localPoints();
1106  const labelList& meshPoints = pp.meshPoints();
1107  const refinementSurfaces& surfaces = meshRefiner_.surfaces();
1108  const fvMesh& mesh = meshRefiner_.mesh();
1109 
1111  //const scalarField edgeLen(calcEdgeLen(pp));
1112  //
1115  //
1116  //{
1117  // const scalar cos45 = Foam::cos(degToRad(45));
1118  // vector n(cos45, cos45, cos45);
1119  // n /= mag(n);
1120  //
1121  // pointField start(14*pp.nPoints());
1122  // pointField end(start.size());
1123  //
1124  // label rayI = 0;
1125  // forAll(localPoints, pointI)
1126  // {
1127  // const point& pt = localPoints[pointI];
1128  //
1129  // // Along coordinate axes
1130  //
1131  // {
1132  // start[rayI] = pt;
1133  // point& endPt = end[rayI++];
1134  // endPt = pt;
1135  // endPt.x() -= edgeLen[pointI];
1136  // }
1137  // {
1138  // start[rayI] = pt;
1139  // point& endPt = end[rayI++];
1140  // endPt = pt;
1141  // endPt.x() += edgeLen[pointI];
1142  // }
1143  // {
1144  // start[rayI] = pt;
1145  // point& endPt = end[rayI++];
1146  // endPt = pt;
1147  // endPt.y() -= edgeLen[pointI];
1148  // }
1149  // {
1150  // start[rayI] = pt;
1151  // point& endPt = end[rayI++];
1152  // endPt = pt;
1153  // endPt.y() += edgeLen[pointI];
1154  // }
1155  // {
1156  // start[rayI] = pt;
1157  // point& endPt = end[rayI++];
1158  // endPt = pt;
1159  // endPt.z() -= edgeLen[pointI];
1160  // }
1161  // {
1162  // start[rayI] = pt;
1163  // point& endPt = end[rayI++];
1164  // endPt = pt;
1165  // endPt.z() += edgeLen[pointI];
1166  // }
1167  //
1168  // // At 45 degrees
1169  //
1170  // const vector vec(edgeLen[pointI]*n);
1171  //
1172  // {
1173  // start[rayI] = pt;
1174  // point& endPt = end[rayI++];
1175  // endPt = pt;
1176  // endPt.x() += vec.x();
1177  // endPt.y() += vec.y();
1178  // endPt.z() += vec.z();
1179  // }
1180  // {
1181  // start[rayI] = pt;
1182  // point& endPt = end[rayI++];
1183  // endPt = pt;
1184  // endPt.x() -= vec.x();
1185  // endPt.y() += vec.y();
1186  // endPt.z() += vec.z();
1187  // }
1188  // {
1189  // start[rayI] = pt;
1190  // point& endPt = end[rayI++];
1191  // endPt = pt;
1192  // endPt.x() += vec.x();
1193  // endPt.y() -= vec.y();
1194  // endPt.z() += vec.z();
1195  // }
1196  // {
1197  // start[rayI] = pt;
1198  // point& endPt = end[rayI++];
1199  // endPt = pt;
1200  // endPt.x() -= vec.x();
1201  // endPt.y() -= vec.y();
1202  // endPt.z() += vec.z();
1203  // }
1204  // {
1205  // start[rayI] = pt;
1206  // point& endPt = end[rayI++];
1207  // endPt = pt;
1208  // endPt.x() += vec.x();
1209  // endPt.y() += vec.y();
1210  // endPt.z() -= vec.z();
1211  // }
1212  // {
1213  // start[rayI] = pt;
1214  // point& endPt = end[rayI++];
1215  // endPt = pt;
1216  // endPt.x() -= vec.x();
1217  // endPt.y() += vec.y();
1218  // endPt.z() -= vec.z();
1219  // }
1220  // {
1221  // start[rayI] = pt;
1222  // point& endPt = end[rayI++];
1223  // endPt = pt;
1224  // endPt.x() += vec.x();
1225  // endPt.y() -= vec.y();
1226  // endPt.z() -= vec.z();
1227  // }
1228  // {
1229  // start[rayI] = pt;
1230  // point& endPt = end[rayI++];
1231  // endPt = pt;
1232  // endPt.x() -= vec.x();
1233  // endPt.y() -= vec.y();
1234  // endPt.z() -= vec.z();
1235  // }
1236  // }
1237  //
1238  // labelList surface1;
1239  // List<pointIndexHit> hit1;
1240  // labelList region1;
1241  // vectorField normal1;
1242  //
1243  // labelList surface2;
1244  // List<pointIndexHit> hit2;
1245  // labelList region2;
1246  // vectorField normal2;
1247  // surfaces.findNearestIntersection
1248  // (
1249  // unzonedSurfaces, // surfacesToTest,
1250  // start,
1251  // end,
1252  //
1253  // surface1,
1254  // hit1,
1255  // region1,
1256  // normal1,
1257  //
1258  // surface2,
1259  // hit2,
1260  // region2,
1261  // normal2
1262  // );
1263  //
1264  // // All intersections
1265  // {
1266  // OBJstream str
1267  // (
1268  // mesh.time().path()
1269  // / "surfaceHits_" + meshRefiner_.timeName() + ".obj"
1270  // );
1271  //
1272  // Info<< "Dumping intersections with rays to " << str.name()
1273  // << endl;
1274  //
1275  // forAll(hit1, i)
1276  // {
1277  // if (hit1[i].hit())
1278  // {
1279  // str.write(linePointRef(start[i], hit1[i].hitPoint()));
1280  // }
1281  // if (hit2[i].hit())
1282  // {
1283  // str.write(linePointRef(start[i], hit2[i].hitPoint()));
1284  // }
1285  // }
1286  // }
1287  //
1288  // // Co-planar intersections
1289  // {
1290  // OBJstream str
1291  // (
1292  // mesh.time().path()
1293  // / "coplanarHits_" + meshRefiner_.timeName() + ".obj"
1294  // );
1295  //
1296  // Info<< "Dumping intersections with co-planar surfaces to "
1297  // << str.name() << endl;
1298  //
1299  // forAll(localPoints, pointI)
1300  // {
1301  // bool hasNormal = false;
1302  // point surfPointA;
1303  // vector surfNormalA;
1304  // point surfPointB;
1305  // vector surfNormalB;
1306  //
1307  // bool isCoplanar = false;
1308  //
1309  // label rayI = 14*pointI;
1310  // for (label i = 0; i < 14; i++)
1311  // {
1312  // if (hit1[rayI].hit())
1313  // {
1314  // const point& pt = hit1[rayI].hitPoint();
1315  // const vector& n = normal1[rayI];
1316  //
1317  // if (!hasNormal)
1318  // {
1319  // hasNormal = true;
1320  // surfPointA = pt;
1321  // surfNormalA = n;
1322  // }
1323  // else
1324  // {
1325  // if
1326  // (
1327  // meshRefiner_.isGap
1328  // (
1329  // planarCos,
1330  // surfPointA,
1331  // surfNormalA,
1332  // pt,
1333  // n
1334  // )
1335  // )
1336  // {
1337  // isCoplanar = true;
1338  // surfPointB = pt;
1339  // surfNormalB = n;
1340  // break;
1341  // }
1342  // }
1343  // }
1344  // if (hit2[rayI].hit())
1345  // {
1346  // const point& pt = hit2[rayI].hitPoint();
1347  // const vector& n = normal2[rayI];
1348  //
1349  // if (!hasNormal)
1350  // {
1351  // hasNormal = true;
1352  // surfPointA = pt;
1353  // surfNormalA = n;
1354  // }
1355  // else
1356  // {
1357  // if
1358  // (
1359  // meshRefiner_.isGap
1360  // (
1361  // planarCos,
1362  // surfPointA,
1363  // surfNormalA,
1364  // pt,
1365  // n
1366  // )
1367  // )
1368  // {
1369  // isCoplanar = true;
1370  // surfPointB = pt;
1371  // surfNormalB = n;
1372  // break;
1373  // }
1374  // }
1375  // }
1376  //
1377  // rayI++;
1378  // }
1379  //
1380  // if (isCoplanar)
1381  // {
1382  // str.write(linePointRef(surfPointA, surfPointB));
1383  // }
1384  // }
1385  // }
1386  //}
1387 
1388 
1389  const pointField avgCc(avgCellCentres(mesh, pp));
1390 
1391  // Construct rays through localPoints to beyond cell centre
1392  pointField start(pp.nPoints());
1393  pointField end(pp.nPoints());
1394  forAll(localPoints, pointI)
1395  {
1396  const point& pt = localPoints[pointI];
1397  const vector d = 2*(avgCc[pointI]-pt);
1398  start[pointI] = pt - d;
1399  end[pointI] = pt + d;
1400  }
1401 
1402 
1403  autoPtr<OBJstream> gapStr;
1404  if (debug&meshRefinement::ATTRACTION)
1405  {
1406  gapStr.reset
1407  (
1408  new OBJstream
1409  (
1410  mesh.time().path()
1411  / "detectNearSurfaces_" + meshRefiner_.timeName() + ".obj"
1412  )
1413  );
1414  }
1415 
1416 
1417  const PackedBoolList isPatchMasterPoint
1418  (
1419  meshRefinement::getMasterPoints
1420  (
1421  mesh,
1422  meshPoints
1423  )
1424  );
1425 
1426  label nOverride = 0;
1427 
1428  // 1. All points to non-interface surfaces
1429  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1430  {
1431  const labelList unzonedSurfaces =
1432  surfaceZonesInfo::getUnnamedSurfaces
1433  (
1434  meshRefiner_.surfaces().surfZones()
1435  );
1436 
1437  // Do intersection test
1438  labelList surface1;
1439  List<pointIndexHit> hit1;
1440  labelList region1;
1441  vectorField normal1;
1442 
1443  labelList surface2;
1444  List<pointIndexHit> hit2;
1445  labelList region2;
1446  vectorField normal2;
1447  surfaces.findNearestIntersection
1448  (
1449  unzonedSurfaces,
1450  start,
1451  end,
1452 
1453  surface1,
1454  hit1,
1455  region1,
1456  normal1,
1457 
1458  surface2,
1459  hit2,
1460  region2,
1461  normal2
1462  );
1463 
1464 
1465  forAll(localPoints, pointI)
1466  {
1467  // Current location
1468  const point& pt = localPoints[pointI];
1469 
1470  bool override = false;
1471 
1472  //if (hit1[pointI].hit())
1473  //{
1474  // if
1475  // (
1476  // meshRefiner_.isGap
1477  // (
1478  // planarCos,
1479  // nearestPoint[pointI],
1480  // nearestNormal[pointI],
1481  // hit1[pointI].hitPoint(),
1482  // normal1[pointI]
1483  // )
1484  // )
1485  // {
1486  // disp[pointI] = hit1[pointI].hitPoint()-pt;
1487  // override = true;
1488  // }
1489  //}
1490  //if (hit2[pointI].hit())
1491  //{
1492  // if
1493  // (
1494  // meshRefiner_.isGap
1495  // (
1496  // planarCos,
1497  // nearestPoint[pointI],
1498  // nearestNormal[pointI],
1499  // hit2[pointI].hitPoint(),
1500  // normal2[pointI]
1501  // )
1502  // )
1503  // {
1504  // disp[pointI] = hit2[pointI].hitPoint()-pt;
1505  // override = true;
1506  // }
1507  //}
1508 
1509  if (hit1[pointI].hit() && hit2[pointI].hit())
1510  {
1511  if
1512  (
1513  meshRefiner_.isGap
1514  (
1515  planarCos,
1516  hit1[pointI].hitPoint(),
1517  normal1[pointI],
1518  hit2[pointI].hitPoint(),
1519  normal2[pointI]
1520  )
1521  )
1522  {
1523  // TBD: check if the attraction (to nearest) would attract
1524  // good enough and not override attraction
1525 
1526  if (gapStr.valid())
1527  {
1528  const point& intPt = hit2[pointI].hitPoint();
1529  gapStr().write(linePointRef(pt, intPt));
1530  }
1531 
1532  // Choose hit2 : nearest to end point (so inside the domain)
1533  disp[pointI] = hit2[pointI].hitPoint()-pt;
1534  override = true;
1535  }
1536  }
1537 
1538  if (override && isPatchMasterPoint[pointI])
1539  {
1540  nOverride++;
1541  }
1542  }
1543  }
1544 
1545 
1546  // 2. All points on zones to their respective surface
1547  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1548 
1549  {
1550  // Surfaces with zone information
1551  const PtrList<surfaceZonesInfo>& surfZones = surfaces.surfZones();
1552 
1553  const labelList zonedSurfaces = surfaceZonesInfo::getNamedSurfaces
1554  (
1555  surfZones
1556  );
1557 
1558  forAll(zonedSurfaces, i)
1559  {
1560  label zoneSurfI = zonedSurfaces[i];
1561 
1562  const word& faceZoneName = surfZones[zoneSurfI].faceZoneName();
1563 
1564  const labelList surfacesToTest(1, zoneSurfI);
1565 
1566  // Get indices of points both on faceZone and on pp.
1567  labelList zonePointIndices
1568  (
1569  getZoneSurfacePoints
1570  (
1571  mesh,
1572  pp,
1573  faceZoneName
1574  )
1575  );
1576 
1577  // Do intersection test
1578  labelList surface1;
1579  List<pointIndexHit> hit1;
1580  labelList region1;
1581  vectorField normal1;
1582 
1583  labelList surface2;
1584  List<pointIndexHit> hit2;
1585  labelList region2;
1586  vectorField normal2;
1587  surfaces.findNearestIntersection
1588  (
1589  surfacesToTest,
1590  pointField(start, zonePointIndices),
1591  pointField(end, zonePointIndices),
1592 
1593  surface1,
1594  hit1,
1595  region1,
1596  normal1,
1597 
1598  surface2,
1599  hit2,
1600  region2,
1601  normal2
1602  );
1603 
1604 
1605  forAll(hit1, i)
1606  {
1607  label pointI = zonePointIndices[i];
1608 
1609  // Current location
1610  const point& pt = localPoints[pointI];
1611 
1612  bool override = false;
1613 
1614  //if (hit1[i].hit())
1615  //{
1616  // if
1617  // (
1618  // meshRefiner_.isGap
1619  // (
1620  // planarCos,
1621  // nearestPoint[pointI],
1622  // nearestNormal[pointI],
1623  // hit1[i].hitPoint(),
1624  // normal1[i]
1625  // )
1626  // )
1627  // {
1628  // disp[pointI] = hit1[i].hitPoint()-pt;
1629  // override = true;
1630  // }
1631  //}
1632  //if (hit2[i].hit())
1633  //{
1634  // if
1635  // (
1636  // meshRefiner_.isGap
1637  // (
1638  // planarCos,
1639  // nearestPoint[pointI],
1640  // nearestNormal[pointI],
1641  // hit2[i].hitPoint(),
1642  // normal2[i]
1643  // )
1644  // )
1645  // {
1646  // disp[pointI] = hit2[i].hitPoint()-pt;
1647  // override = true;
1648  // }
1649  //}
1650 
1651  if (hit1[i].hit() && hit2[i].hit())
1652  {
1653  if
1654  (
1655  meshRefiner_.isGap
1656  (
1657  planarCos,
1658  hit1[i].hitPoint(),
1659  normal1[i],
1660  hit2[i].hitPoint(),
1661  normal2[i]
1662  )
1663  )
1664  {
1665  if (gapStr.valid())
1666  {
1667  const point& intPt = hit2[i].hitPoint();
1668  gapStr().write(linePointRef(pt, intPt));
1669  }
1670 
1671  disp[pointI] = hit2[i].hitPoint()-pt;
1672  override = true;
1673  }
1674  }
1675 
1676  if (override && isPatchMasterPoint[pointI])
1677  {
1678  nOverride++;
1679  }
1680  }
1681  }
1682  }
1683 
1684  Info<< "Overriding nearest with intersection of close gaps at "
1685  << returnReduce(nOverride, sumOp<label>())
1686  << " out of " << returnReduce(pp.nPoints(), sumOp<label>())
1687  << " points." << endl;
1688 }
1689 
1690 
1693  const refinementSurfaces& surfaces,
1694 
1695  const labelList& surfacesToTest,
1696  const labelListList& regionsToTest,
1697 
1698  const pointField& localPoints,
1699  const labelList& zonePointIndices,
1700 
1701  scalarField& minSnapDist,
1702  labelList& snapSurf,
1703  vectorField& patchDisp,
1704 
1705  // Optional: nearest point, normal
1706  pointField& nearestPoint,
1707  vectorField& nearestNormal
1708 )
1709 {
1710  // Find nearest for points both on faceZone and pp.
1711  List<pointIndexHit> hitInfo;
1712  labelList hitSurface;
1713 
1714  if (nearestNormal.size() == localPoints.size())
1715  {
1716  labelList hitRegion;
1717  vectorField hitNormal;
1718  surfaces.findNearestRegion
1719  (
1720  surfacesToTest,
1721  regionsToTest,
1722 
1723  pointField(localPoints, zonePointIndices),
1724  sqr(scalarField(minSnapDist, zonePointIndices)),
1725 
1726  hitSurface,
1727  hitInfo,
1728  hitRegion,
1729  hitNormal
1730  );
1731 
1732  forAll(hitInfo, i)
1733  {
1734  if (hitInfo[i].hit())
1735  {
1736  label pointI = zonePointIndices[i];
1737  nearestPoint[pointI] = hitInfo[i].hitPoint();
1738  nearestNormal[pointI] = hitNormal[i];
1739  }
1740  }
1741  }
1742  else
1743  {
1744  surfaces.findNearest
1745  (
1746  surfacesToTest,
1747  regionsToTest,
1748 
1749  pointField(localPoints, zonePointIndices),
1750  sqr(scalarField(minSnapDist, zonePointIndices)),
1751 
1752  hitSurface,
1753  hitInfo
1754  );
1755  }
1756 
1757  forAll(hitInfo, i)
1758  {
1759  if (hitInfo[i].hit())
1760  {
1761  label pointI = zonePointIndices[i];
1762 
1763  patchDisp[pointI] = hitInfo[i].hitPoint() - localPoints[pointI];
1764  minSnapDist[pointI] = mag(patchDisp[pointI]);
1765  snapSurf[pointI] = hitSurface[i];
1766  }
1767  }
1768 }
1769 
1770 
1773  const bool strictRegionSnap,
1774  const meshRefinement& meshRefiner,
1775  const labelList& globalToMasterPatch,
1776  const labelList& globalToSlavePatch,
1777  const scalarField& snapDist,
1778  const indirectPrimitivePatch& pp,
1779  pointField& nearestPoint,
1780  vectorField& nearestNormal
1781 )
1782 {
1783  Info<< "Calculating patchDisplacement as distance to nearest surface"
1784  << " point ..." << endl;
1785  if (strictRegionSnap)
1786  {
1787  Info<< " non-zone points : attract to local region on surface only"
1788  << nl
1789  << " zone points : attract to local region on surface only"
1790  << nl
1791  << endl;
1792  }
1793  else
1794  {
1795  Info<< " non-zone points :"
1796  << " attract to nearest of all non-zone surfaces"
1797  << nl
1798  << " zone points : attract to zone surface only" << nl
1799  << endl;
1800  }
1801 
1802 
1803  const pointField& localPoints = pp.localPoints();
1804  const refinementSurfaces& surfaces = meshRefiner.surfaces();
1805  const fvMesh& mesh = meshRefiner.mesh();
1806 
1807  // Displacement per patch point
1808  vectorField patchDisp(localPoints.size(), vector::zero);
1809 
1810  if (returnReduce(localPoints.size(), sumOp<label>()) > 0)
1811  {
1812  // Current surface snapped to. Used to check whether points have been
1813  // snapped at all
1814  labelList snapSurf(localPoints.size(), -1);
1815 
1816  // Current best snap distance (since point might be on multiple
1817  // regions)
1818  scalarField minSnapDist(snapDist);
1819 
1820 
1821  if (strictRegionSnap)
1822  {
1823  // Attract patch points to same region only
1824 
1825  forAll(surfaces.surfaces(), surfI)
1826  {
1827  label geomI = surfaces.surfaces()[surfI];
1828  label nRegions = surfaces.geometry()[geomI].regions().size();
1829 
1830  const labelList surfacesToTest(1, surfI);
1831 
1832  for (label regionI = 0; regionI < nRegions; regionI++)
1833  {
1834  label globalI = surfaces.globalRegion(surfI, regionI);
1835  label masterPatchI = globalToMasterPatch[globalI];
1836 
1837  // Get indices of points both on patch and on pp
1838  labelList zonePointIndices
1839  (
1840  getFacePoints
1841  (
1842  pp,
1843  mesh.boundaryMesh()[masterPatchI]
1844  )
1845  );
1846 
1847  calcNearestSurface
1848  (
1849  surfaces,
1850 
1851  surfacesToTest,
1852  labelListList(1, labelList(1, regionI)), //regionsToTest
1853 
1854  localPoints,
1855  zonePointIndices,
1856 
1857  minSnapDist,
1858  snapSurf,
1859  patchDisp,
1860 
1861  // Optional: nearest point, normal
1862  nearestPoint,
1863  nearestNormal
1864  );
1865 
1866  if (globalToSlavePatch[globalI] != masterPatchI)
1867  {
1868  label slavePatchI = globalToSlavePatch[globalI];
1869 
1870  // Get indices of points both on patch and on pp
1871  labelList zonePointIndices
1872  (
1873  getFacePoints
1874  (
1875  pp,
1876  mesh.boundaryMesh()[slavePatchI]
1877  )
1878  );
1879 
1880  calcNearestSurface
1881  (
1882  surfaces,
1883 
1884  surfacesToTest,
1885  labelListList(1, labelList(1, regionI)),
1886 
1887  localPoints,
1888  zonePointIndices,
1889 
1890  minSnapDist,
1891  snapSurf,
1892  patchDisp,
1893 
1894  // Optional: nearest point, normal
1895  nearestPoint,
1896  nearestNormal
1897  );
1898  }
1899  }
1900  }
1901  }
1902  else
1903  {
1904  // Divide surfaces into zoned and unzoned
1905  const labelList unzonedSurfaces =
1906  surfaceZonesInfo::getUnnamedSurfaces
1907  (
1908  meshRefiner.surfaces().surfZones()
1909  );
1910 
1911 
1912  // 1. All points to non-interface surfaces
1913  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1914 
1915  List<pointIndexHit> hitInfo;
1916  labelList hitSurface;
1917 
1918  if (nearestNormal.size() == localPoints.size())
1919  {
1920  labelList hitRegion;
1921  vectorField hitNormal;
1922  surfaces.findNearestRegion
1923  (
1924  unzonedSurfaces,
1925  localPoints,
1926  sqr(snapDist),
1927  hitSurface,
1928  hitInfo,
1929  hitRegion,
1930  hitNormal
1931  );
1932 
1933  forAll(hitInfo, pointI)
1934  {
1935  if (hitInfo[pointI].hit())
1936  {
1937  nearestPoint[pointI] = hitInfo[pointI].hitPoint();
1938  nearestNormal[pointI] = hitNormal[pointI];
1939  }
1940  }
1941  }
1942  else
1943  {
1944  surfaces.findNearest
1945  (
1946  unzonedSurfaces,
1947  localPoints,
1948  sqr(snapDist), // sqr of attract distance
1949  hitSurface,
1950  hitInfo
1951  );
1952  }
1953 
1954  forAll(hitInfo, pointI)
1955  {
1956  if (hitInfo[pointI].hit())
1957  {
1958  patchDisp[pointI] =
1959  hitInfo[pointI].hitPoint()
1960  - localPoints[pointI];
1961 
1962  snapSurf[pointI] = hitSurface[pointI];
1963  }
1964  }
1965 
1966 
1967  const labelList zonedSurfaces =
1968  surfaceZonesInfo::getNamedSurfaces
1969  (
1970  meshRefiner.surfaces().surfZones()
1971  );
1972 
1973 
1974  // 2. All points on zones to their respective surface
1975  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1976 
1977  // Surfaces with zone information
1978  const PtrList<surfaceZonesInfo>& surfZones = surfaces.surfZones();
1979 
1980  forAll(zonedSurfaces, i)
1981  {
1982  label surfI = zonedSurfaces[i];
1983 
1984  const word& faceZoneName = surfZones[surfI].faceZoneName();
1985 
1986  const labelList surfacesToTest(1, surfI);
1987 
1988  label geomI = surfaces.surfaces()[surfI];
1989  label nRegions = surfaces.geometry()[geomI].regions().size();
1990 
1991 
1992  // Get indices of points both on faceZone and on pp.
1993  labelList zonePointIndices
1994  (
1995  getZoneSurfacePoints
1996  (
1997  mesh,
1998  pp,
1999  faceZoneName
2000  )
2001  );
2002 
2003 
2004  calcNearestSurface
2005  (
2006  surfaces,
2007 
2008  surfacesToTest,
2009  labelListList(1, identity(nRegions)),
2010 
2011  localPoints,
2012  zonePointIndices,
2013 
2014  minSnapDist,
2015  snapSurf,
2016  patchDisp,
2017 
2018  // Optional: nearest point, normal
2019  nearestPoint,
2020  nearestNormal
2021  );
2022  }
2023  }
2024 
2025 
2026  // Check if all points are being snapped
2027  forAll(snapSurf, pointI)
2028  {
2029  if (snapSurf[pointI] == -1)
2030  {
2032  << "For point:" << pointI
2033  << " coordinate:" << localPoints[pointI]
2034  << " did not find any surface within:"
2035  << minSnapDist[pointI]
2036  << " metre." << endl;
2037  }
2038  }
2039 
2040  {
2041  const PackedBoolList isPatchMasterPoint
2042  (
2043  meshRefinement::getMasterPoints
2044  (
2045  mesh,
2046  pp.meshPoints()
2047  )
2048  );
2049 
2050  scalarField magDisp(mag(patchDisp));
2051 
2052  Info<< "Wanted displacement : average:"
2053  << meshRefinement::gAverage(isPatchMasterPoint, magDisp)
2054  << " min:" << gMin(magDisp)
2055  << " max:" << gMax(magDisp) << endl;
2056  }
2057  }
2058 
2059  Info<< "Calculated surface displacement in = "
2060  << mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
2061 
2062 
2063  // Limit amount of movement. Can not happen for triSurfaceMesh but
2064  // can happen for some analytical shapes?
2065  forAll(patchDisp, patchPointI)
2066  {
2067  scalar magDisp = mag(patchDisp[patchPointI]);
2068 
2069  if (magDisp > snapDist[patchPointI])
2070  {
2071  patchDisp[patchPointI] *= snapDist[patchPointI] / magDisp;
2072 
2073  Pout<< "Limiting displacement for " << patchPointI
2074  << " from " << magDisp << " to " << snapDist[patchPointI]
2075  << endl;
2076  }
2077  }
2078 
2079  // Points on zones in one domain but only present as point on other
2080  // will not do condition 2 on all. Sync explicitly.
2081  syncTools::syncPointList
2082  (
2083  mesh,
2084  pp.meshPoints(),
2085  patchDisp,
2086  minMagSqrEqOp<point>(), // combine op
2087  vector(GREAT, GREAT, GREAT) // null value (note: cannot use VGREAT)
2088  );
2089 
2090  return patchDisp;
2091 }
2092 
2093 
2096  const snapParameters& snapParams,
2097  motionSmoother& meshMover
2098 ) const
2099 {
2100  const fvMesh& mesh = meshRefiner_.mesh();
2101  const indirectPrimitivePatch& pp = meshMover.patch();
2102 
2103  Info<< "Smoothing displacement ..." << endl;
2104 
2105  // Set edge diffusivity as inverse of distance to patch
2106  scalarField edgeGamma(1.0/(edgePatchDist(meshMover.pMesh(), pp) + SMALL));
2107  //scalarField edgeGamma(mesh.nEdges(), 1.0);
2108  //scalarField edgeGamma(wallGamma(mesh, pp, 10, 1));
2109 
2110  // Get displacement field
2111  pointVectorField& disp = meshMover.displacement();
2112 
2113  for (label iter = 0; iter < snapParams.nSmoothDispl(); iter++)
2114  {
2115  if ((iter % 10) == 0)
2116  {
2117  Info<< "Iteration " << iter << endl;
2118  }
2119  pointVectorField oldDisp(disp);
2120  meshMover.smooth(oldDisp, edgeGamma, disp);
2121  }
2122  Info<< "Displacement smoothed in = "
2123  << mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
2124 
2125  if (debug&meshRefinement::MESH)
2126  {
2127  const_cast<Time&>(mesh.time())++;
2128  Info<< "Writing smoothed mesh to time " << meshRefiner_.timeName()
2129  << endl;
2130 
2131  // Moving mesh creates meshPhi. Can be cleared out by a mesh.clearOut
2132  // but this will also delete all pointMesh but not pointFields which
2133  // gives an illegal situation.
2134 
2135  meshRefiner_.write
2136  (
2139  (
2140  meshRefinement::writeLevel()
2141  | meshRefinement::WRITEMESH
2142  ),
2143  mesh.time().path()/meshRefiner_.timeName()
2144  );
2145  Info<< "Writing displacement field ..." << endl;
2146  disp.write();
2147  tmp<pointScalarField> magDisp(mag(disp));
2148  magDisp().write();
2149 
2150  Info<< "Writing actual patch displacement ..." << endl;
2151  vectorField actualPatchDisp(disp, pp.meshPoints());
2152  dumpMove
2153  (
2154  mesh.time().path()
2155  / "actualPatchDisplacement_" + meshRefiner_.timeName() + ".obj",
2156  pp.localPoints(),
2157  pp.localPoints() + actualPatchDisp
2158  );
2159  }
2160 }
2161 
2162 
2165  const snapParameters& snapParams,
2166  const label nInitErrors,
2167  const List<labelPair>& baffles,
2168  motionSmoother& meshMover
2169 )
2170 {
2171  const fvMesh& mesh = meshRefiner_.mesh();
2172 
2173  // Relax displacement until correct mesh
2174  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2175  labelList checkFaces(identity(mesh.nFaces()));
2176 
2177  scalar oldErrorReduction = -1;
2178 
2179  bool meshOk = false;
2180 
2181  Info<< "Moving mesh ..." << endl;
2182  for (label iter = 0; iter < 2*snapParams.nSnap(); iter++)
2183  {
2184  Info<< nl << "Iteration " << iter << endl;
2185 
2186  if (iter == snapParams.nSnap())
2187  {
2188  Info<< "Displacement scaling for error reduction set to 0." << endl;
2189  oldErrorReduction = meshMover.setErrorReduction(0.0);
2190  }
2191 
2192  meshOk = meshMover.scaleMesh(checkFaces, baffles, true, nInitErrors);
2193 
2194  if (meshOk)
2195  {
2196  Info<< "Successfully moved mesh" << endl;
2197  break;
2198  }
2199  if (debug&meshRefinement::MESH)
2200  {
2201  const_cast<Time&>(mesh.time())++;
2202  Info<< "Writing scaled mesh to time " << meshRefiner_.timeName()
2203  << endl;
2204  mesh.write();
2205 
2206  Info<< "Writing displacement field ..." << endl;
2207  meshMover.displacement().write();
2208  tmp<pointScalarField> magDisp(mag(meshMover.displacement()));
2209  magDisp().write();
2210  }
2211  }
2212 
2213  if (oldErrorReduction >= 0)
2214  {
2215  meshMover.setErrorReduction(oldErrorReduction);
2216  }
2217  Info<< "Moved mesh in = "
2218  << mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
2219 
2220  return meshOk;
2221 }
2222 
2223 
2224 // After snapping: correct patching according to nearest surface.
2225 // Code is very similar to calcNearestSurface.
2226 // - calculate face-wise snap distance as max of point-wise
2227 // - calculate face-wise nearest surface point
2228 // - repatch face according to patch for surface point.
2231  const snapParameters& snapParams,
2232  const labelList& adaptPatchIDs,
2233  const labelList& preserveFaces
2234 )
2235 {
2236  const fvMesh& mesh = meshRefiner_.mesh();
2237  const refinementSurfaces& surfaces = meshRefiner_.surfaces();
2238 
2239  Info<< "Repatching faces according to nearest surface ..." << endl;
2240 
2241  // Get the labels of added patches.
2243  (
2244  meshRefinement::makePatch
2245  (
2246  mesh,
2247  adaptPatchIDs
2248  )
2249  );
2250  indirectPrimitivePatch& pp = ppPtr();
2251 
2252  // Divide surfaces into zoned and unzoned
2253  labelList zonedSurfaces =
2254  surfaceZonesInfo::getNamedSurfaces(surfaces.surfZones());
2255  labelList unzonedSurfaces =
2256  surfaceZonesInfo::getUnnamedSurfaces(surfaces.surfZones());
2257 
2258 
2259  // Faces that do not move
2260  PackedBoolList isZonedFace(mesh.nFaces());
2261  {
2262  // 1. Preserve faces in preserveFaces list
2263  forAll(preserveFaces, faceI)
2264  {
2265  if (preserveFaces[faceI] != -1)
2266  {
2267  isZonedFace.set(faceI, 1);
2268  }
2269  }
2270 
2271  // 2. All faces on zoned surfaces
2272  const PtrList<surfaceZonesInfo>& surfZones = surfaces.surfZones();
2273  const faceZoneMesh& fZones = mesh.faceZones();
2274 
2275  forAll(zonedSurfaces, i)
2276  {
2277  const label zoneSurfI = zonedSurfaces[i];
2278  const faceZone& fZone = fZones[surfZones[zoneSurfI].faceZoneName()];
2279 
2280  forAll(fZone, i)
2281  {
2282  isZonedFace.set(fZone[i], 1);
2283  }
2284  }
2285  }
2286 
2287 
2288  // Determine per pp face which patch it should be in
2289  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2290 
2291  // Patch that face should be in
2292  labelList closestPatch(pp.size(), -1);
2293  {
2294  // face snap distance as max of point snap distance
2295  scalarField faceSnapDist(pp.size(), -GREAT);
2296  {
2297  // Distance to attract to nearest feature on surface
2298  const scalarField snapDist
2299  (
2300  calcSnapDistance
2301  (
2302  mesh,
2303  snapParams,
2304  pp
2305  )
2306  );
2307 
2308  const faceList& localFaces = pp.localFaces();
2309 
2310  forAll(localFaces, faceI)
2311  {
2312  const face& f = localFaces[faceI];
2313 
2314  forAll(f, fp)
2315  {
2316  faceSnapDist[faceI] = max
2317  (
2318  faceSnapDist[faceI],
2319  snapDist[f[fp]]
2320  );
2321  }
2322  }
2323  }
2324 
2325  pointField localFaceCentres(mesh.faceCentres(), pp.addressing());
2326 
2327  // Get nearest surface and region
2328  labelList hitSurface;
2329  labelList hitRegion;
2330  surfaces.findNearestRegion
2331  (
2332  unzonedSurfaces,
2333  localFaceCentres,
2334  sqr(faceSnapDist), // sqr of attract distance
2335  hitSurface,
2336  hitRegion
2337  );
2338 
2339  // Get patch
2340  forAll(pp, i)
2341  {
2342  label faceI = pp.addressing()[i];
2343 
2344  if (hitSurface[i] != -1 && !isZonedFace.get(faceI))
2345  {
2346  closestPatch[i] = globalToMasterPatch_
2347  [
2348  surfaces.globalRegion
2349  (
2350  hitSurface[i],
2351  hitRegion[i]
2352  )
2353  ];
2354  }
2355  }
2356  }
2357 
2358 
2359  // Change those faces for which there is a different closest patch
2360  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2361 
2362  labelList ownPatch(mesh.nFaces(), -1);
2363  labelList neiPatch(mesh.nFaces(), -1);
2364 
2365  const polyBoundaryMesh& patches = mesh.boundaryMesh();
2366 
2367  forAll(patches, patchI)
2368  {
2369  const polyPatch& pp = patches[patchI];
2370 
2371  forAll(pp, i)
2372  {
2373  ownPatch[pp.start()+i] = patchI;
2374  neiPatch[pp.start()+i] = patchI;
2375  }
2376  }
2377 
2378  label nChanged = 0;
2379  forAll(closestPatch, i)
2380  {
2381  label faceI = pp.addressing()[i];
2382 
2383  if (closestPatch[i] != -1 && closestPatch[i] != ownPatch[faceI])
2384  {
2385  ownPatch[faceI] = closestPatch[i];
2386  neiPatch[faceI] = closestPatch[i];
2387  nChanged++;
2388  }
2389  }
2390 
2391  Info<< "Repatched " << returnReduce(nChanged, sumOp<label>())
2392  << " faces in = " << mesh.time().cpuTimeIncrement() << " s\n" << nl
2393  << endl;
2394 
2395  return meshRefiner_.createBaffles(ownPatch, neiPatch);
2396 }
2397 
2398 
2401  const scalar featureCos,
2402  const indirectPrimitivePatch& pp,
2403 
2404  DynamicList<label>& splitFaces,
2405  DynamicList<labelPair>& splits
2406 ) const
2407 {
2408  const fvMesh& mesh = meshRefiner_.mesh();
2409  const faceList& localFaces = pp.localFaces();
2410  const pointField& localPoints = pp.localPoints();
2411  const labelList& bFaces = pp.addressing();
2412 
2413  splitFaces.clear();
2414  splitFaces.setCapacity(bFaces.size());
2415  splits.clear();
2416  splits.setCapacity(bFaces.size());
2417 
2418  // Determine parallel consistent normals on points
2419  const vectorField pointNormals(PatchTools::pointNormals(mesh, pp));
2420 
2421  face f0(4);
2422  face f1(4);
2423 
2424  forAll(localFaces, faceI)
2425  {
2426  const face& f = localFaces[faceI];
2427 
2428  if (f.size() >= 4)
2429  {
2430  // See if splitting face across diagonal would make two faces with
2431  // biggish normal angle
2432 
2433  labelPair minDiag(-1, -1);
2434  scalar minCos(GREAT);
2435 
2436  for (label startFp = 0; startFp < f.size()-2; startFp++)
2437  {
2438  label minFp = f.rcIndex(startFp);
2439 
2440  for
2441  (
2442  label endFp = f.fcIndex(f.fcIndex(startFp));
2443  endFp < f.size() && endFp != minFp;
2444  endFp++
2445  )
2446  {
2447  // Form two faces
2448  f0.setSize(endFp-startFp+1);
2449  label i0 = 0;
2450  for (label fp = startFp; fp <= endFp; fp++)
2451  {
2452  f0[i0++] = f[fp];
2453  }
2454  f1.setSize(f.size()+2-f0.size());
2455  label i1 = 0;
2456  for (label fp = endFp; fp != startFp; fp = f.fcIndex(fp))
2457  {
2458  f1[i1++] = f[fp];
2459  }
2460  f1[i1++] = f[startFp];
2461 
2462  //Info<< "Splitting face:" << f << " into f0:" << f0
2463  // << " f1:" << f1 << endl;
2464 
2465  vector n0 = f0.normal(localPoints);
2466  scalar n0Mag = mag(n0);
2467  vector n1 = f1.normal(localPoints);
2468  scalar n1Mag = mag(n1);
2469 
2470  if (n0Mag > ROOTVSMALL && n1Mag > ROOTVSMALL)
2471  {
2472  scalar cosAngle = (n0/n0Mag) & (n1/n1Mag);
2473  if (cosAngle < minCos)
2474  {
2475  minCos = cosAngle;
2476  minDiag = labelPair(startFp, endFp);
2477  }
2478  }
2479  }
2480  }
2481 
2482 
2483  if (minCos < featureCos)
2484  {
2485  splitFaces.append(bFaces[faceI]);
2486  splits.append(minDiag);
2487  }
2488  }
2489  }
2490 }
2491 
2492 
2494 {
2495  const fvMesh& mesh = meshRefiner_.mesh();
2496 
2497  labelList internalOrBaffleFaceZones;
2498  {
2500  fzTypes[0] = surfaceZonesInfo::INTERNAL;
2501  fzTypes[1] = surfaceZonesInfo::BAFFLE;
2502  internalOrBaffleFaceZones = meshRefiner_.getZones(fzTypes);
2503  }
2504 
2505  List<labelPair> baffles
2506  (
2508  (
2509  mesh,
2510  internalOrBaffleFaceZones,
2512  )
2513  );
2514 
2515  labelList faceToDuplicate(mesh.nFaces(), -1);
2516  forAll(baffles, i)
2517  {
2518  const labelPair& p = baffles[i];
2519  faceToDuplicate[p[0]] = p[1];
2520  faceToDuplicate[p[1]] = p[0];
2521  }
2522 
2523  return faceToDuplicate;
2524 }
2525 
2526 
2529  const dictionary& snapDict,
2530  const dictionary& motionDict,
2531  const bool mergePatchFaces,
2532  const scalar featureCos,
2533  const scalar planarAngle,
2534  const snapParameters& snapParams
2535 )
2536 {
2537  fvMesh& mesh = meshRefiner_.mesh();
2538 
2539  Info<< nl
2540  << "Morphing phase" << nl
2541  << "--------------" << nl
2542  << endl;
2543 
2544  // faceZone handling
2545  // ~~~~~~~~~~~~~~~~~
2546  //
2547  // We convert all faceZones into baffles during snapping so we can use
2548  // a standard mesh motion (except for the mesh checking which for baffles
2549  // created from internal faces should check across the baffles). The state
2550  // is stored in two variables:
2551  // baffles : pairs of boundary faces
2552  // duplicateFace : from mesh face to its baffle colleague (or -1 for
2553  // normal faces)
2554  // There are three types of faceZones according to the faceType property:
2555  //
2556  // internal
2557  // --------
2558  // - baffles: need to be checked across
2559  // - duplicateFace: from face to duplicate face. Contains
2560  // all faces on faceZone to prevents merging patch faces.
2561  //
2562  // baffle
2563  // ------
2564  // - baffles: no need to be checked across
2565  // - duplicateFace: contains all faces on faceZone to prevent
2566  // merging patch faces.
2567  //
2568  // boundary
2569  // --------
2570  // - baffles: no need to be checked across. Also points get duplicated
2571  // so will no longer be baffles
2572  // - duplicateFace: contains no faces on faceZone since both sides can
2573  // merge faces independently.
2574 
2575 
2576 
2577  // faceZones of type internal
2578  const labelList internalFaceZones
2579  (
2580  meshRefiner_.getZones
2581  (
2583  (
2584  1,
2586  )
2587  )
2588  );
2589 
2590 
2591  // Create baffles (pairs of faces that share the same points)
2592  // Baffles stored as owner and neighbour face that have been created.
2593  {
2594  List<labelPair> baffles;
2595  labelList originatingFaceZone;
2596  meshRefiner_.createZoneBaffles
2597  (
2598  identity(mesh.faceZones().size()),
2599  baffles,
2600  originatingFaceZone
2601  );
2602  }
2603 
2604  // Duplicate points on faceZones of type boundary
2605  meshRefiner_.dupNonManifoldBoundaryPoints();
2606 
2607 
2608  bool doFeatures = false;
2609  label nFeatIter = 1;
2610  if (snapParams.nFeatureSnap() > 0)
2611  {
2612  doFeatures = true;
2613  nFeatIter = snapParams.nFeatureSnap();
2614 
2615  Info<< "Snapping to features in " << nFeatIter
2616  << " iterations ..." << endl;
2617  }
2618 
2619 
2620  bool meshOk = false;
2621 
2622 
2623  // Get the labels of added patches.
2624  labelList adaptPatchIDs(meshRefiner_.meshedPatches());
2625 
2626 
2627 
2628  {
2630  (
2632  (
2633  mesh,
2634  adaptPatchIDs
2635  )
2636  );
2637 
2638 
2639  // Distance to attract to nearest feature on surface
2640  scalarField snapDist(calcSnapDistance(mesh, snapParams, ppPtr()));
2641 
2642 
2643  // Construct iterative mesh mover.
2644  Info<< "Constructing mesh displacer ..." << endl;
2645  Info<< "Using mesh parameters " << motionDict << nl << endl;
2646 
2647  autoPtr<motionSmoother> meshMoverPtr
2648  (
2649  new motionSmoother
2650  (
2651  mesh,
2652  ppPtr(),
2653  adaptPatchIDs,
2655  (
2657  adaptPatchIDs
2658  ),
2659  motionDict
2660  )
2661  );
2662 
2663 
2664  // Check initial mesh
2665  Info<< "Checking initial mesh ..." << endl;
2666  labelHashSet wrongFaces(mesh.nFaces()/100);
2667  motionSmoother::checkMesh(false, mesh, motionDict, wrongFaces);
2668  const label nInitErrors = returnReduce
2669  (
2670  wrongFaces.size(),
2671  sumOp<label>()
2672  );
2673 
2674  Info<< "Detected " << nInitErrors << " illegal faces"
2675  << " (concave, zero area or negative cell pyramid volume)"
2676  << endl;
2677 
2678 
2679  Info<< "Checked initial mesh in = "
2680  << mesh.time().cpuTimeIncrement() << " s\n" << nl << endl;
2681 
2682  // Extract baffles across internal faceZones (for checking mesh quality
2683  // across
2684  labelPairList internalBaffles
2685  (
2686  meshRefiner_.subsetBaffles
2687  (
2688  mesh,
2689  internalFaceZones,
2691  )
2692  );
2693 
2694 
2695 
2696  // Pre-smooth patch vertices (so before determining nearest)
2697  preSmoothPatch
2698  (
2699  meshRefiner_,
2700  snapParams,
2701  nInitErrors,
2702  internalBaffles,
2703  meshMoverPtr()
2704  );
2705 
2706 
2707 
2708  //- Only if in feature attraction mode:
2709  // Nearest feature
2710  vectorField patchAttraction;
2711  // Constraints at feature
2712  List<pointConstraint> patchConstraints;
2713 
2714 
2715  //- Any faces to split
2716  DynamicList<label> splitFaces;
2717  //- Indices in face to split across
2718  DynamicList<labelPair> splits;
2719 
2720 
2721  for (label iter = 0; iter < nFeatIter; iter++)
2722  {
2723  Info<< nl
2724  << "Morph iteration " << iter << nl
2725  << "-----------------" << endl;
2726 
2727  // Splitting iteration?
2728  bool doSplit = false;
2729  if
2730  (
2731  doFeatures
2732  && snapParams.nFaceSplitInterval() > 0
2733  && (
2734  (iter == nFeatIter-1)
2735  || (iter > 0 && (iter%snapParams.nFaceSplitInterval()) == 0)
2736  )
2737  )
2738  {
2739  doSplit = true;
2740  }
2741 
2742 
2743 
2744  indirectPrimitivePatch& pp = ppPtr();
2745  motionSmoother& meshMover = meshMoverPtr();
2746 
2747 
2748  // Calculate displacement at every patch point. Insert into
2749  // meshMover.
2750  // Calculate displacement at every patch point
2751  pointField nearestPoint;
2752  vectorField nearestNormal;
2753 
2754  if (snapParams.detectNearSurfacesSnap())
2755  {
2756  nearestPoint.setSize(pp.nPoints(), vector::max);
2757  nearestNormal.setSize(pp.nPoints(), vector::zero);
2758  }
2759 
2760  vectorField disp = calcNearestSurface
2761  (
2762  snapParams.strictRegionSnap(), // attract points to region only
2763  meshRefiner_,
2764  globalToMasterPatch_, // for if strictRegionSnap
2765  globalToSlavePatch_, // for if strictRegionSnap
2766  snapDist,
2767  pp,
2768 
2769  nearestPoint,
2770  nearestNormal
2771  );
2772 
2773 
2774  // Override displacement at thin gaps
2775  if (snapParams.detectNearSurfacesSnap())
2776  {
2777  detectNearSurfaces
2778  (
2779  Foam::cos(degToRad(planarAngle)),// planar cos for gaps
2780  pp,
2781  nearestPoint, // surfacepoint from nearest test
2782  nearestNormal, // surfacenormal from nearest test
2783 
2784  disp
2785  );
2786  }
2787 
2788  // Override displacement with feature edge attempt
2789  if (doFeatures)
2790  {
2791  splitFaces.clear();
2792  splits.clear();
2793  disp = calcNearestSurfaceFeature
2794  (
2795  snapParams,
2796  !doSplit, // alignMeshEdges
2797  iter,
2798  featureCos,
2799  scalar(iter+1)/nFeatIter,
2800 
2801  snapDist,
2802  disp,
2803  nearestNormal,
2804  meshMover,
2805 
2806  patchAttraction,
2807  patchConstraints,
2808 
2809  splitFaces,
2810  splits
2811  );
2812  }
2813 
2814  // Check for displacement being outwards.
2815  outwardsDisplacement(pp, disp);
2816 
2817  // Set initial distribution of displacement field (on patches)
2818  // from patchDisp and make displacement consistent with b.c.
2819  // on displacement pointVectorField.
2820  meshMover.setDisplacement(disp);
2821 
2822 
2823  if (debug&meshRefinement::ATTRACTION)
2824  {
2825  dumpMove
2826  (
2827  mesh.time().path()
2828  / "patchDisplacement_" + name(iter) + ".obj",
2829  pp.localPoints(),
2830  pp.localPoints() + disp
2831  );
2832  }
2833 
2834  // Get smoothly varying internal displacement field.
2835  smoothDisplacement(snapParams, meshMover);
2836 
2837  // Apply internal displacement to mesh.
2838  meshOk = scaleMesh
2839  (
2840  snapParams,
2841  nInitErrors,
2842  internalBaffles,
2843  meshMover
2844  );
2845 
2846  if (!meshOk)
2847  {
2849  << "Did not succesfully snap mesh."
2850  << " Continuing to snap to resolve easy" << nl
2851  << " surfaces but the"
2852  << " resulting mesh will not satisfy your quality"
2853  << " constraints" << nl << endl;
2854  }
2855 
2856  if (debug&meshRefinement::MESH)
2857  {
2858  const_cast<Time&>(mesh.time())++;
2859  Info<< "Writing scaled mesh to time "
2860  << meshRefiner_.timeName() << endl;
2861  meshRefiner_.write
2862  (
2865  (
2868  ),
2869  mesh.time().path()/meshRefiner_.timeName()
2870  );
2871  Info<< "Writing displacement field ..." << endl;
2872  meshMover.displacement().write();
2873  tmp<pointScalarField> magDisp
2874  (
2875  mag(meshMover.displacement())
2876  );
2877  magDisp().write();
2878  }
2879 
2880  // Use current mesh as base mesh
2881  meshMover.correct();
2882 
2883 
2884 
2885  // See if any faces need splitting
2886  label nTotalSplit = returnReduce(splitFaces.size(), sumOp<label>());
2887  if (nTotalSplit && doSplit)
2888  {
2889  // Filter out baffle faces from faceZones of type
2890  // internal/baffle
2891 
2892  labelList duplicateFace(getInternalOrBaffleDuplicateFace());
2893 
2894  {
2895  labelList oldSplitFaces(splitFaces.xfer());
2896  List<labelPair> oldSplits(splits.xfer());
2897  forAll(oldSplitFaces, i)
2898  {
2899  if (duplicateFace[oldSplitFaces[i]] == -1)
2900  {
2901  splitFaces.append(oldSplitFaces[i]);
2902  splits.append(oldSplits[i]);
2903  }
2904  }
2905  nTotalSplit = returnReduce
2906  (
2907  splitFaces.size(),
2908  sumOp<label>()
2909  );
2910  }
2911 
2912  // Update mesh
2913  meshRefiner_.splitFacesUndo
2914  (
2915  splitFaces,
2916  splits,
2917  motionDict,
2918 
2919  duplicateFace,
2920  internalBaffles
2921  );
2922 
2923  // Redo meshMover
2924  meshMoverPtr.clear();
2925  ppPtr.clear();
2926 
2927  // Update mesh mover
2928  ppPtr = meshRefinement::makePatch(mesh, adaptPatchIDs);
2929  meshMoverPtr.reset
2930  (
2931  new motionSmoother
2932  (
2933  mesh,
2934  ppPtr(),
2935  adaptPatchIDs,
2937  (
2939  adaptPatchIDs
2940  ),
2941  motionDict
2942  )
2943  );
2944 
2945  // Update snapping distance
2946  snapDist = calcSnapDistance(mesh, snapParams, ppPtr());
2947 
2948 
2949  if (debug&meshRefinement::MESH)
2950  {
2951  const_cast<Time&>(mesh.time())++;
2952  Info<< "Writing split-faces mesh to time "
2953  << meshRefiner_.timeName() << endl;
2954  meshRefiner_.write
2955  (
2958  (
2961  ),
2962  mesh.time().path()/meshRefiner_.timeName()
2963  );
2964  }
2965  }
2966 
2967 
2968  if (debug&meshRefinement::MESH)
2969  {
2970  forAll(internalBaffles, i)
2971  {
2972  const labelPair& p = internalBaffles[i];
2973  const point& fc0 = mesh.faceCentres()[p[0]];
2974  const point& fc1 = mesh.faceCentres()[p[1]];
2975 
2976  if (mag(fc0-fc1) > meshRefiner_.mergeDistance())
2977  {
2979  << "Separated baffles : f0:" << p[0]
2980  << " centre:" << fc0
2981  << " f1:" << p[1] << " centre:" << fc1
2982  << " distance:" << mag(fc0-fc1)
2983  << exit(FatalError);
2984  }
2985  }
2986  }
2987  }
2988  }
2989 
2990 
2991  // Merge any introduced baffles (from faceZones of faceType 'internal')
2992  {
2993  autoPtr<mapPolyMesh> mapPtr = meshRefiner_.mergeZoneBaffles
2994  (
2995  true, // internal zones
2996  false // baffle zones
2997  );
2998 
2999  if (mapPtr.valid())
3000  {
3001  if (debug & meshRefinement::MESH)
3002  {
3003  const_cast<Time&>(mesh.time())++;
3004  Info<< "Writing baffle-merged mesh to time "
3005  << meshRefiner_.timeName() << endl;
3006  meshRefiner_.write
3007  (
3010  (
3013  ),
3014  meshRefiner_.timeName()
3015  );
3016  }
3017  }
3018  }
3019 
3020  // Repatch faces according to nearest. Do not repatch baffle faces.
3021  {
3022  labelList duplicateFace(getInternalOrBaffleDuplicateFace());
3023 
3024  repatchToSurface(snapParams, adaptPatchIDs, duplicateFace);
3025  }
3026 
3027  if (mergePatchFaces)
3028  {
3029  labelList duplicateFace(getInternalOrBaffleDuplicateFace());
3030 
3031  // Repatching might have caused faces to be on same patch and hence
3032  // mergeable so try again to merge coplanar faces. Do not merge baffle
3033  // faces to ensure they both stay the same.
3034  label nChanged = meshRefiner_.mergePatchFacesUndo
3035  (
3036  featureCos, // minCos
3037  featureCos, // concaveCos
3038  meshRefiner_.meshedPatches(),
3039  motionDict,
3040  duplicateFace // faces not to merge
3041  );
3042 
3043  nChanged += meshRefiner_.mergeEdgesUndo(featureCos, motionDict);
3044 
3045  if (nChanged > 0 && debug & meshRefinement::MESH)
3046  {
3047  const_cast<Time&>(mesh.time())++;
3048  Info<< "Writing patchFace merged mesh to time "
3049  << meshRefiner_.timeName() << endl;
3050  meshRefiner_.write
3051  (
3054  (
3057  ),
3058  meshRefiner_.timeName()
3059  );
3060  }
3061  }
3062 
3063  if (debug & meshRefinement::MESH)
3064  {
3065  const_cast<Time&>(mesh.time())++;
3066  }
3067 }
3068 
3069 
3070 // ************************************************************************* //
Foam::face::normal
vector normal(const pointField &) const
Vector normal; magnitude is equal to area of face.
Definition: face.C:552
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
Foam::autoSnapDriver::preSmoothPatch
static void preSmoothPatch(const meshRefinement &meshRefiner, const snapParameters &snapParams, const label nInitErrors, const List< labelPair > &baffles, motionSmoother &)
Smooth the mesh (patch and internal) to increase visibility.
Definition: autoSnapDriver.C:827
Foam::autoSnapDriver::getZoneSurfacePoints
static labelList getZoneSurfacePoints(const fvMesh &mesh, const indirectPrimitivePatch &, const word &zoneName)
Get points both on patch and facezone.
Definition: autoSnapDriver.C:943
Foam::PackedBoolList
A bit-packed bool list.
Definition: PackedBoolList.H:63
Foam::PrimitivePatch::pointFaces
const labelListList & pointFaces() const
Return point-face addressing.
Definition: PrimitivePatchTemplate.C:352
Foam::DynamicList::xfer
Xfer< List< T > > xfer()
Transfer contents to the Xfer container as a plain List.
Definition: DynamicListI.H:301
Foam::motionSmootherAlgo::setErrorReduction
scalar setErrorReduction(const scalar)
Set the errorReduction (by how much to scale the displacement.
Definition: motionSmootherAlgo.C:719
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:68
Foam::meshRefinement::WRITEMESH
@ WRITEMESH
Definition: meshRefinement.H:132
Foam::PackedBoolList::unset
void unset(const PackedList< 1 > &)
Unset specified bits.
Definition: PackedBoolList.C:203
Foam::PrimitivePatch::points
const Field< PointType > & points() const
Return reference to global points.
Definition: PrimitivePatchTemplate.H:282
Foam::Vector< scalar >::zero
static const Vector zero
Definition: Vector.H:80
p
p
Definition: pEqn.H:62
Foam::word
A class for handling words, derived from string.
Definition: word.H:59
Foam::hexRef8::cellLevel
const labelIOList & cellLevel() const
Definition: hexRef4.H:389
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::labelList
List< label > labelList
A List of labels.
Definition: labelList.H:56
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:86
Foam::OBJstream
OFstream which keeps track of vertices.
Definition: OBJstream.H:53
Foam::polyBoundaryMesh
Foam::polyBoundaryMesh.
Definition: polyBoundaryMesh.H:60
Foam::PrimitivePatch::edges
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
Definition: PrimitivePatchTemplate.C:212
Foam::cpuTime::cpuTimeIncrement
double cpuTimeIncrement() const
Return CPU time (in seconds) since last call to cpuTimeIncrement()
Definition: cpuTime.C:74
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
writeOBJ
void writeOBJ(Ostream &os, label &vertI, const tetPoints &tet)
Definition: Test-tetTetOverlap.C:38
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:118
Foam::refinementSurfaces::findNearest
void findNearest(const labelList &surfacesToTest, const pointField &samples, const scalarField &nearestDistSqr, labelList &surfaces, List< pointIndexHit > &) const
Find nearest point on surfaces.
Definition: refinementSurfaces.C:1430
Foam::DynamicList< label >
Foam::gAverage
Type gAverage(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:571
Foam::motionSmootherAlgo::correct
void correct()
Take over existing mesh position.
Definition: motionSmootherAlgo.C:413
Foam::refinementSurfaces::surfaces
const labelList & surfaces() const
Definition: refinementSurfaces.H:157
Foam::PointEdgeWave
Wave propagation of information through grid. Every iteration information goes through one layer of e...
Definition: PointEdgeWave.H:85
Foam::PrimitivePatch::localPoints
const Field< PointType > & localPoints() const
Return pointField of points in patch.
Definition: PrimitivePatchTemplate.C:432
Foam::motionSmootherAlgo::patch
const indirectPrimitivePatch & patch() const
Reference to patch.
Definition: motionSmootherAlgo.C:395
mapPolyMesh.H
Foam::PackedBoolList::set
void set(const PackedList< 1 > &)
Set specified bits.
Definition: PackedBoolList.C:169
Foam::Warning
messageStream Warning
Foam::meshRefinement::writeLevel
static writeType writeLevel()
Get/set write level.
Definition: meshRefinement.C:3065
Foam::Vector< scalar >::max
static const Vector max
Definition: Vector.H:82
Foam::autoSnapDriver::meshRefiner_
meshRefinement & meshRefiner_
Mesh+surface.
Definition: autoSnapDriver.H:61
polyTopoChange.H
motionSmoother.H
Foam::meshRefinement::getZones
labelList getZones(const List< surfaceZonesInfo::faceZoneType > &fzTypes) const
Get zones of given type.
Definition: meshRefinementBaffles.C:712
localPointRegion.H
Foam::autoSnapDriver::scaleMesh
bool scaleMesh(const snapParameters &snapParams, const label nInitErrors, const List< labelPair > &baffles, motionSmoother &)
Do the hard work: move the mesh according to displacement,.
Definition: autoSnapDriver.C:2164
Foam::meshRefinement::ATTRACTION
@ ATTRACTION
Definition: meshRefinement.H:106
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:58
Foam::maxEqOp
Definition: ops.H:77
Foam::autoSnapDriver::autoSnapDriver
autoSnapDriver(const autoSnapDriver &)
Disallow default bitwise copy construct.
Foam::motionSmootherAlgo::scaleMesh
bool scaleMesh(labelList &checkFaces, const bool smoothMesh=true, const label nAllow=0)
Move mesh with given scale. Return true if mesh ok or has.
Definition: motionSmootherAlgo.C:733
Foam::Map
A HashTable to objects of type <T> with a label key.
Definition: PrimitivePatchTemplate.H:68
unitConversion.H
Unit conversion functions.
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::coupledPolyPatch
The coupledPolyPatch is an abstract base class for patches that couple regions of the computational d...
Definition: coupledPolyPatch.H:51
refinementFeatures.H
Foam::autoSnapDriver::getInternalOrBaffleDuplicateFace
labelList getInternalOrBaffleDuplicateFace() const
Get per face -1 or label of opposite face if on internal/baffle.
Definition: autoSnapDriver.C:2493
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::HashSet< label, Hash< label > >
Foam::meshRefinement::mesh
const fvMesh & mesh() const
Reference to mesh.
Definition: meshRefinement.H:817
syncTools.H
Foam::refinementSurfaces::geometry
const searchableSurfaces & geometry() const
Definition: refinementSurfaces.H:152
Foam::help::mergePatchFaces
faceList mergePatchFaces(const List< DynList< label > > &pfcs, const pointField &polyPoints)
Definition: helperFunctionsGeometryQueriesI.H:232
Foam::autoSnapDriver::dumpMove
static void dumpMove(const fileName &, const pointField &, const pointField &)
Write displacement as .obj file.
Definition: autoSnapDriver.C:700
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
Foam::MeshObject< polyMesh, UpdateableMeshObject, pointMesh >::New
static const pointMesh & New(const polyMesh &mesh)
Definition: MeshObject.C:44
Foam::meshRefinement::subsetBaffles
static List< labelPair > subsetBaffles(const polyMesh &mesh, const labelList &zoneIDs, const List< labelPair > &baffles)
Subset baffles according to zones.
Definition: meshRefinementBaffles.C:739
OFstream.H
Foam::polyMesh::faceZones
const faceZoneMesh & faceZones() const
Return face zone mesh.
Definition: polyMesh.H:463
pFaces
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=*(cellModeller::lookup("hex"));labelList hexLabels(8);label activeCells=0;labelList pointMap(nPoints);forAll(pointMap, i){ pointMap[i]=i;}for(label i=0;i< nPoints;i++){ if(f[i] > 0.0) { hexLabels[0]=i;hexLabels[1]=i1tab[i];hexLabels[2]=i3tab[i1tab[i]];hexLabels[3]=i3tab[i];hexLabels[4]=i8tab[i];hexLabels[5]=i1tab[i8tab[i]];hexLabels[6]=i3tab[i1tab[i8tab[i]]];hexLabels[7]=i3tab[i8tab[i]];cellShapes[activeCells]=cellShape(hex, hexLabels);edgeList edges=cellShapes[activeCells].edges();forAll(edges, ei) { if(edges[ei].mag(points)< SMALL) { label start=pointMap[edges[ei].start()];while(start !=pointMap[start]) { start=pointMap[start];} label end=pointMap[edges[ei].end()];while(end !=pointMap[end]) { end=pointMap[end];} label minLabel=min(start, end);pointMap[start]=pointMap[end]=minLabel;} } cellZoning[activeCells]=idreg[i];activeCells++;}}cellShapes.setSize(activeCells);cellZoning.setSize(activeCells);forAll(cellShapes, celli){ cellShape &cs=cellShapes[celli];forAll(cs, i) { cs[i]=pointMap[cs[i]];} cs.collapse();}label bcIDs[11]={-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};const label nBCs=12;const word *kivaPatchTypes[nBCs]={ &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &symmetryPolyPatch::typeName, &wedgePolyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, &oldCyclicPolyPatch::typeName};enum patchTypeNames{ PISTON, VALVE, LINER, CYLINDERHEAD, AXIS, WEDGE, INFLOW, OUTFLOW, PRESIN, PRESOUT, SYMMETRYPLANE, CYCLIC};const char *kivaPatchNames[nBCs]={ "piston", "valve", "liner", "cylinderHead", "axis", "wedge", "inflow", "outflow", "presin", "presout", "symmetryPlane", "cyclic"};List< SLList< face > > pFaces[nBCs]
Definition: readKivaGrid.H:235
Foam::SubField
Pre-declare related SubField type.
Definition: Field.H:61
searchableSurfaces.H
Foam::snapParameters
Simple container to keep together snap specific information.
Definition: snapParameters.H:50
Foam::refinementSurfaces::surfZones
const PtrList< surfaceZonesInfo > & surfZones() const
Definition: refinementSurfaces.H:168
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:43
pointEdgePoint.H
Foam::snapParameters::nFeatureSnap
label nFeatureSnap() const
Definition: snapParameters.H:173
Foam::meshRefinement::timeName
word timeName() const
Replacement for Time::timeName() : return oldInstance (if.
Definition: meshRefinement.C:2888
Foam::autoSnapDriver::calcSnapDistance
static scalarField calcSnapDistance(const fvMesh &mesh, const snapParameters &snapParams, const indirectPrimitivePatch &)
Calculate edge length per patch point.
Definition: autoSnapDriver.C:787
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:59
Foam::Field
Pre-declare SubField and related Field type.
Definition: Field.H:57
Foam::faceZone
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:64
Foam::orOp
Definition: ops.H:178
Foam::Ostream::write
virtual Ostream & write(const token &)=0
Write next token to stream.
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::Info
messageStream Info
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
refinementSurfaces.H
Foam::minEqOp
Definition: ops.H:78
PointEdgeWave.H
MESH
@ MESH
Definition: extrudeMesh.C:60
Foam::PrimitivePatch::pointEdges
const labelListList & pointEdges() const
Return point-edge addressing.
Definition: PrimitivePatchTemplate.C:332
Foam::DynamicList::clear
void clear()
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:242
Foam::snapParameters::strictRegionSnap
Switch strictRegionSnap() const
Attract point to corresponding surface region only.
Definition: snapParameters.H:165
Foam::DynamicList::setCapacity
void setCapacity(const label)
Alter the size of the underlying storage.
Definition: DynamicListI.H:109
Foam::ZoneMesh< faceZone, polyMesh >
f1
scalar f1
Definition: createFields.H:28
Foam::GeometricField::internalField
InternalField & internalField()
Return internal field.
Definition: GeometricField.C:724
Foam::PtrList
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: List.H:61
Foam::motionSmoother
Given a displacement moves the mesh by scaling the displacement back until there are no more mesh err...
Definition: motionSmoother.H:89
Foam::identity
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
Foam::PrimitivePatch::nPoints
label nPoints() const
Return number of points supporting patch faces.
Definition: PrimitivePatchTemplate.H:293
Foam::snapParameters::nSnap
label nSnap() const
Maximum number of snapping relaxation iterations. Should stop.
Definition: snapParameters.H:149
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:137
Foam::HashTable::size
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
Foam::meshRefinement::makePatch
static autoPtr< indirectPrimitivePatch > makePatch(const polyMesh &, const labelList &)
Create patch from set of patches.
Definition: meshRefinement.C:1644
Foam::refinementSurfaces::globalRegion
label globalRegion(const label surfI, const label regionI) const
From surface and region on surface to global region.
Definition: refinementSurfaces.H:230
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:18
Foam::plusEqOp
Definition: ops.H:71
Foam::autoSnapDriver::outwardsDisplacement
static bool outwardsDisplacement(const indirectPrimitivePatch &, const vectorField &)
Check displacement is outwards pointing.
Definition: autoSnapDriver.C:729
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
fvMesh.H
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::pointMesh
Mesh representing a set of points created from polyMesh.
Definition: pointMesh.H:48
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Foam::PackedList::get
unsigned int get(const label) const
Get value at index I.
Definition: PackedListI.H:964
Foam::autoSnapDriver::smoothDisplacement
void smoothDisplacement(const snapParameters &snapParams, motionSmoother &) const
Smooth the displacement field to the internal.
Definition: autoSnapDriver.C:2095
Foam::polyPatch::start
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:312
Foam::pointEdgePoint
Holds information regarding nearest wall point. Used in PointEdgeWave. (so not standard FaceCellWave)...
Definition: pointEdgePoint.H:59
Foam::DynamicList::append
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
Foam::OFstream
Output to file stream.
Definition: OFstream.H:81
Foam::autoSnapDriver::avgCellCentres
static tmp< pointField > avgCellCentres(const fvMesh &mesh, const indirectPrimitivePatch &)
Helper: calculate average cell centre per point.
Definition: autoSnapDriver.C:990
autoSnapDriver.H
Foam::refinementSurfaces::findNearestRegion
void findNearestRegion(const labelList &surfacesToTest, const pointField &samples, const scalarField &nearestDistSqr, labelList &hitSurface, labelList &hitRegion) const
Find nearest point on surfaces. Return surface and region on.
Definition: refinementSurfaces.C:1463
Foam::max
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
Foam::surfaceZonesInfo::BAFFLE
@ BAFFLE
Definition: surfaceZonesInfo.H:76
Foam::meshRefinement::meshCutter
const hexRef8 & meshCutter() const
Reference to meshcutting engine.
Definition: meshRefinement.H:862
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::autoPtr
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:117
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
Foam::linePointRef
line< point, const point & > linePointRef
Line using referred points.
Definition: linePointRef.H:45
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:318
Foam::refinementSurfaces::findNearestIntersection
void findNearestIntersection(const labelList &surfacesToTest, const pointField &start, const pointField &end, labelList &surface1, List< pointIndexHit > &hit1, labelList &region1, labelList &surface2, List< pointIndexHit > &hit2, labelList &region2) const
Find intersection nearest to the endpoints. surface1,2 are.
Definition: refinementSurfaces.C:1063
Foam::autoSnapDriver::detectWarpedFaces
void detectWarpedFaces(const scalar featureCos, const indirectPrimitivePatch &pp, DynamicList< label > &splitFaces, DynamicList< labelPair > &splits) const
Detect warpage.
Definition: autoSnapDriver.C:2400
Foam::snapParameters::snapTol
scalar snapTol() const
Relative distance for points to be attracted by surface.
Definition: snapParameters.H:136
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:49
Foam::autoSnapDriver::smoothInternalDisplacement
static tmp< pointField > smoothInternalDisplacement(const meshRefinement &meshRefiner, const motionSmoother &)
Calculate displacement (over all mesh points) to move points.
Definition: autoSnapDriver.C:124
Foam::primitiveMesh::nFaces
label nFaces() const
Definition: primitiveMeshI.H:58
Foam::sumOp
Definition: ops.H:162
Foam::Pair
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: contiguous.H:49
Foam::Time::path
fileName path() const
Return path.
Definition: Time.H:281
Foam::snapParameters::nFaceSplitInterval
label nFaceSplitInterval() const
Definition: snapParameters.H:221
Foam::snapParameters::nSmoothInternal
label nSmoothInternal() const
Number of internal point smoothing iterations (combined with.
Definition: snapParameters.H:127
Foam::hexRef8
Refinement of (split) hexes using polyTopoChange.
Definition: hexRef4.H:64
Foam::Pout
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
Foam::polyPatch::faceCentres
const vectorField::subField faceCentres() const
Return face centres.
Definition: polyPatch.C:308
Foam::autoSnapDriver::smoothPatchDisplacement
static tmp< pointField > smoothPatchDisplacement(const motionSmoother &, const List< labelPair > &)
Calculate displacement per patch point to smooth out patch.
Definition: autoSnapDriver.C:304
Foam::PrimitivePatch::faceNormals
const Field< PointType > & faceNormals() const
Return face normals for patch.
Definition: PrimitivePatchTemplate.C:520
f
labelList f(nPoints)
Foam::motionSmootherAlgo::checkMesh
static bool checkMesh(const bool report, const polyMesh &mesh, const dictionary &dict, labelHashSet &wrongFaces)
Check mesh with mesh settings in dict. Collects incorrect faces.
Definition: motionSmootherAlgoCheck.C:415
Foam::Vector< scalar >
Foam::meshRefinement::writeType
writeType
Definition: meshRefinement.H:130
Foam::autoSnapDriver::calcNearestSurface
static void calcNearestSurface(const refinementSurfaces &surfaces, const labelList &surfacesToTest, const labelListList &regionsToTest, const pointField &localPoints, const labelList &zonePointIndices, scalarField &minSnapDist, labelList &snapSurf, vectorField &patchDisp, pointField &nearestPoint, vectorField &nearestNormal)
Per patch point calculate point on nearest surface.
Definition: autoSnapDriver.C:1692
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
Foam::sqrt
dimensionedScalar sqrt(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:142
scalarField
volScalarField scalarField(fieldObject, mesh)
Foam::snapParameters::detectNearSurfacesSnap
Switch detectNearSurfacesSnap() const
Override attraction to nearest with intersection location.
Definition: snapParameters.H:159
Foam::motionSmootherAlgo::mesh
const polyMesh & mesh() const
Reference to mesh.
Definition: motionSmootherAlgo.C:383
Foam::motionSmootherAlgo::pointDisplacement
pointVectorField & pointDisplacement()
Return reference to the point motion displacement field.
Definition: motionSmootherAlgo.H:336
Foam::primitiveMesh::faceCentres
const vectorField & faceCentres() const
Definition: primitiveMeshFaceCentresAndAreas.C:130
Foam::meshRefinement
Helper class which maintains intersections of (changing) mesh with (static) surfaces.
Definition: meshRefinement.H:82
Foam::autoPtr::valid
bool valid() const
Return true if the autoPtr valid (ie, the pointer is set).
Definition: autoPtrI.H:83
Foam::motionSmootherAlgo::setDisplacement
static void setDisplacement(const labelList &patchIDs, const indirectPrimitivePatch &pp, pointField &patchDisp, pointVectorField &displacement)
Set displacement field from displacement on patch points.
Definition: motionSmootherAlgo.C:492
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: doubleFloat.H:94
Foam::meshRefinement::write
bool write() const
Write mesh and all data.
Definition: meshRefinement.C:2707
Foam::motionSmootherAlgo::smooth
void smooth(const GeometricField< Type, pointPatchField, pointMesh > &fld, const scalarField &edgeWeight, GeometricField< Type, pointPatchField, pointMesh > &newFld) const
Fully explicit smoothing of fields (not positions)
Definition: motionSmootherAlgoTemplates.C:238
Foam::PtrList::size
label size() const
Return the number of elements in the PtrList.
Definition: PtrListI.H:32
Foam::autoSnapDriver::getCollocatedPoints
static label getCollocatedPoints(const scalar tol, const pointField &, PackedBoolList &)
Calculates (geometric) shared points.
Definition: autoSnapDriver.C:64
Foam::autoSnapDriver::repatchToSurface
autoPtr< mapPolyMesh > repatchToSurface(const snapParameters &snapParams, const labelList &adaptPatchIDs, const labelList &preserveFaces)
Repatch faces according to surface nearest the face centre.
Definition: autoSnapDriver.C:2230
snapParameters.H
Foam::autoSnapDriver::edgePatchDist
static tmp< scalarField > edgePatchDist(const pointMesh &, const indirectPrimitivePatch &)
Per edge distance to patch.
Definition: autoSnapDriver.C:654
mergePoints.H
Merge points. See below.
Foam::autoPtr::clear
void clear()
Delete object (if the pointer is valid) and set pointer to NULL.
Definition: autoPtrI.H:126
Foam::autoPtr::reset
void reset(T *=0)
If object pointer already set, delete object and set to given.
Definition: autoPtrI.H:114
Foam::motionSmootherAlgo::pMesh
const pointMesh & pMesh() const
Reference to pointMesh.
Definition: motionSmootherAlgo.C:389
Foam::fvMesh::time
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:243
Foam::PrimitivePatch::localFaces
const List< Face > & localFaces() const
Return patch faces addressing into local point list.
Definition: PrimitivePatchTemplate.C:372
Foam::motionSmootherData::displacement
pointVectorField & displacement()
Reference to displacement field.
Definition: motionSmootherData.C:100
patches
patches[0]
Definition: createSingleCellMesh.H:36
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
Foam::minMagSqrEqOp
Definition: ops.H:79
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::gMin
Type gMin(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:563
Foam::PrimitivePatch::meshPointMap
const Map< label > & meshPointMap() const
Mesh point map. Given the global point index find its.
Definition: PrimitivePatchTemplate.C:412
Foam::autoSnapDriver::doSnap
void doSnap(const dictionary &snapDict, const dictionary &motionDict, const bool mergePatchFaces, const scalar featureCos, const scalar planarAngle, const snapParameters &snapParams)
Definition: autoSnapDriver.C:2528
Foam::meshTools::visNormal
bool visNormal(const vector &n, const vectorField &faceNormals, const labelList &faceLabels)
Check if n is in same direction as normals of all faceLabels.
Definition: meshTools.C:33
Foam::PrimitivePatch::meshPoints
const labelList & meshPoints() const
Return labelList of mesh points in patch.
Definition: PrimitivePatchTemplate.C:392
Foam::GeometricField
Generic GeometricField class.
Definition: surfaceFieldsFwd.H:52
Foam::autoSnapDriver::detectNearSurfaces
void detectNearSurfaces(const scalar planarCos, const indirectPrimitivePatch &, const pointField &nearestPoint, const vectorField &nearestNormal, vectorField &disp) const
Per patch point override displacement if in gap situation.
Definition: autoSnapDriver.C:1094
Foam::refinementSurfaces
Container for data on surfaces used for surface-driven refinement. Contains all the data about the le...
Definition: refinementSurfaces.H:60
Foam::snapParameters::nSmoothDispl
label nSmoothDispl() const
Number of mesh displacement smoothing iterations.
Definition: snapParameters.H:142
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::findIndices
labelList findIndices(const ListType &, typename ListType::const_reference, const label start=0)
Find all occurences of given element. Linear search.
Foam::meshRefinement::makeDisplacementField
static tmp< pointVectorField > makeDisplacementField(const pointMesh &pMesh, const labelList &adaptPatchIDs)
Helper function to make a pointVectorField with correct.
Definition: meshRefinement.C:1690
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:259
Foam::mergePoints
label mergePoints(const UList< Type > &points, const scalar mergeTol, const bool verbose, labelList &pointMap, const Type &origin=Type::zero)
Sorts and merges points. All points closer than/equal mergeTol get merged.
Foam::labelPair
Pair< label > labelPair
Label pair.
Definition: labelPair.H:48
Foam::gMax
Type gMax(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:562
OBJstream.H
Foam::name
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
Foam::meshRefinement::MESH
@ MESH
Definition: meshRefinement.H:102
Foam::snapParameters::nSmoothPatch
label nSmoothPatch() const
Number of patch smoothing iterations before finding.
Definition: snapParameters.H:120
Foam::localPointRegion::findDuplicateFacePairs
static labelPairList findDuplicateFacePairs(const polyMesh &)
Helper routine to find all baffles (two boundary faces.
Definition: localPointRegion.C:620
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatchTemplate.H:88
Foam::degToRad
scalar degToRad(const scalar deg)
Conversion from degrees to radians.
Definition: unitConversion.H:45
Foam::cos
dimensionedScalar cos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:256
Foam::meshRefinement::surfaces
const refinementSurfaces & surfaces() const
Reference to surface search engines.
Definition: meshRefinement.H:844
Foam::meshRefinement::debugType
debugType
Definition: meshRefinement.H:100
Foam::surfaceZonesInfo::INTERNAL
@ INTERNAL
Definition: surfaceZonesInfo.H:75