CV2D.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) 2013-2015 OpenFOAM Foundation
6  \\/ M anipulation |
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 \*----------------------------------------------------------------------------*/
25 
26 #include "CV2D.H"
27 #include "Random.H"
28 #include "transform.H"
29 #include "IFstream.H"
30 #include "uint.H"
31 
32 namespace Foam
33 {
34  defineTypeNameAndDebug(CV2D, 0);
35 }
36 
37 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
38 
40 {
41  Info<< "insertBoundingBox: creating bounding mesh" << endl;
42  scalar bigSpan = 10*meshControls().span();
43  insertPoint(point2D(-bigSpan, -bigSpan), Vb::FAR_POINT);
44  insertPoint(point2D(-bigSpan, bigSpan), Vb::FAR_POINT);
45  insertPoint(point2D(bigSpan, -bigSpan), Vb::FAR_POINT);
46  insertPoint(point2D(bigSpan, bigSpan), Vb::FAR_POINT);
47 }
48 
49 
50 void Foam::CV2D::fast_restore_Delaunay(Vertex_handle vh)
51 {
52  int i;
53  Face_handle f = vh->face(), next, start(f);
54 
55  do
56  {
57  i=f->index(vh);
58  if (!is_infinite(f))
59  {
60  if (!internal_flip(f, cw(i))) external_flip(f, i);
61  if (f->neighbor(i) == start) start = f;
62  }
63  f = f->neighbor(cw(i));
64  } while (f != start);
65 }
66 
67 
68 void Foam::CV2D::external_flip(Face_handle& f, int i)
69 {
70  Face_handle n = f->neighbor(i);
71 
72  if
73  (
74  CGAL::ON_POSITIVE_SIDE
75  != side_of_oriented_circle(n, f->vertex(i)->point())
76  ) return;
77 
78  flip(f, i);
79  i = n->index(f->vertex(i));
80  external_flip(n, i);
81 }
82 
83 
84 bool Foam::CV2D::internal_flip(Face_handle& f, int i)
85 {
86  Face_handle n = f->neighbor(i);
87 
88  if
89  (
90  CGAL::ON_POSITIVE_SIDE
91  != side_of_oriented_circle(n, f->vertex(i)->point())
92  )
93  {
94  return false;
95  }
96 
97  flip(f, i);
98 
99  return true;
100 }
101 
102 
103 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
104 
106 (
107  const Time& runTime,
108  const dictionary& cvMeshDict
109 )
110 :
111  Delaunay(),
112  runTime_(runTime),
113  rndGen_(64293*Pstream::myProcNo()),
114  allGeometry_
115  (
116  IOobject
117  (
118  "cvSearchableSurfaces",
119  runTime_.constant(),
120  "triSurface",
121  runTime_,
122  IOobject::MUST_READ,
123  IOobject::NO_WRITE
124  ),
125  cvMeshDict.subDict("geometry"),
126  cvMeshDict.lookupOrDefault("singleRegionName", true)
127  ),
128  qSurf_
129  (
130  runTime_,
131  rndGen_,
132  allGeometry_,
133  cvMeshDict.subDict("surfaceConformation")
134  ),
135  controls_(cvMeshDict, qSurf_.globalBounds()),
136  cellSizeControl_
137  (
138  runTime,
139  cvMeshDict.subDict("motionControl").subDict("shapeControlFunctions"),
140  qSurf_,
141  controls_.minCellSize()
142  ),
143  relaxationModel_
144  (
145  relaxationModel::New
146  (
147  cvMeshDict.subDict("motionControl"),
148  runTime
149  )
150  ),
151  z_
152  (
153  point
154  (
155  cvMeshDict.subDict("surfaceConformation").lookup("locationInMesh")
156  ).z()
157  ),
158  startOfInternalPoints_(0),
159  startOfSurfacePointPairs_(0),
160  startOfBoundaryConformPointPairs_(0),
161  featurePoints_()
162 {
163  Info<< meshControls() << endl;
164 
165  insertBoundingBox();
166  insertFeaturePoints();
167 }
168 
169 
170 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
171 
173 {}
174 
175 
176 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
177 
179 (
180  const point2DField& points,
181  const scalar nearness
182 )
183 {
184  Info<< "insertInitialPoints(const point2DField& points): ";
185 
186  startOfInternalPoints_ = number_of_vertices();
187  label nVert = startOfInternalPoints_;
188 
189  // Add the points and index them
190  forAll(points, i)
191  {
192  const point2D& p = points[i];
193 
194  if (qSurf_.wellInside(toPoint3D(p), nearness))
195  {
196  insert(toPoint(p))->index() = nVert++;
197  }
198  else
199  {
200  Warning
201  << "Rejecting point " << p << " outside surface" << endl;
202  }
203  }
204 
205  Info<< nVert << " vertices inserted" << endl;
206 
207  if (meshControls().objOutput())
208  {
209  // Checking validity of triangulation
210  assert(is_valid());
211 
212  writeTriangles("initial_triangles.obj", true);
213  writeFaces("initial_faces.obj", true);
214  }
215 }
216 
217 
218 void Foam::CV2D::insertPoints(const fileName& pointFileName)
219 {
220  IFstream pointsFile(pointFileName);
221 
222  if (pointsFile.good())
223  {
224  insertPoints
225  (
226  point2DField(pointsFile),
227  0.5*meshControls().minCellSize2()
228  );
229  }
230  else
231  {
233  << "Could not open pointsFile " << pointFileName
234  << exit(FatalError);
235  }
236 }
237 
238 
240 {
241  Info<< "insertInitialGrid: ";
242 
243  startOfInternalPoints_ = number_of_vertices();
244  label nVert = startOfInternalPoints_;
245 
246  scalar x0 = qSurf_.globalBounds().min().x();
247  scalar xR = qSurf_.globalBounds().max().x() - x0;
248  int ni = int(xR/meshControls().minCellSize()) + 1;
249  scalar deltax = xR/ni;
250 
251  scalar y0 = qSurf_.globalBounds().min().y();
252  scalar yR = qSurf_.globalBounds().max().y() - y0;
253  int nj = int(yR/meshControls().minCellSize()) + 1;
254  scalar deltay = yR/nj;
255 
256  Random rndGen(1321);
257  scalar pert = meshControls().randomPerturbation()*min(deltax, deltay);
258 
259  for (int i=0; i<ni; i++)
260  {
261  for (int j=0; j<nj; j++)
262  {
263  point p(x0 + i*deltax, y0 + j*deltay, 0);
264 
265  if (meshControls().randomiseInitialGrid())
266  {
267  p.x() += pert*(rndGen.scalar01() - 0.5);
268  p.y() += pert*(rndGen.scalar01() - 0.5);
269  }
270 
271  if (qSurf_.wellInside(p, 0.5*meshControls().minCellSize2()))
272  {
273  insert(Point(p.x(), p.y()))->index() = nVert++;
274  }
275  }
276  }
277 
278  Info<< nVert << " vertices inserted" << endl;
279 
280  if (meshControls().objOutput())
281  {
282  // Checking validity of triangulation
283  assert(is_valid());
284 
285  writeTriangles("initial_triangles.obj", true);
286  writeFaces("initial_faces.obj", true);
287  }
288 }
289 
290 
292 {
293  startOfSurfacePointPairs_ = number_of_vertices();
294 
295  if (meshControls().insertSurfaceNearestPointPairs())
296  {
297  insertSurfaceNearestPointPairs();
298  }
299 
300  write("nearest");
301 
302  // Insertion of point-pairs for near-points may cause protrusions
303  // so insertBoundaryConformPointPairs must be executed last
304  if (meshControls().insertSurfaceNearPointPairs())
305  {
306  insertSurfaceNearPointPairs();
307  }
308 
309  startOfBoundaryConformPointPairs_ = number_of_vertices();
310 }
311 
312 
314 {
315  if (!meshControls().insertSurfaceNearestPointPairs())
316  {
317  markNearBoundaryPoints();
318  }
319 
320  // Mark all the faces as SAVE_CHANGED
321  for
322  (
323  Triangulation::Finite_faces_iterator fit = finite_faces_begin();
324  fit != finite_faces_end();
325  fit++
326  )
327  {
328  fit->faceIndex() = Fb::SAVE_CHANGED;
329  }
330 
331  for (label iter=1; iter<=meshControls().maxBoundaryConformingIter(); iter++)
332  {
333  label nIntersections = insertBoundaryConformPointPairs
334  (
335  "surfaceIntersections_" + Foam::name(iter) + ".obj"
336  );
337 
338  if (nIntersections == 0)
339  {
340  break;
341  }
342  else
343  {
344  Info<< "BC iteration " << iter << ": "
345  << nIntersections << " point-pairs inserted" << endl;
346  }
347 
348  // Any faces changed by insertBoundaryConformPointPairs will now
349  // be marked CHANGED, mark those as SAVE_CHANGED and those that
350  // remained SAVE_CHANGED as UNCHANGED
351  for
352  (
353  Triangulation::Finite_faces_iterator fit = finite_faces_begin();
354  fit != finite_faces_end();
355  fit++
356  )
357  {
358  if (fit->faceIndex() == Fb::SAVE_CHANGED)
359  {
360  fit->faceIndex() = Fb::UNCHANGED;
361  }
362  else if (fit->faceIndex() == Fb::CHANGED)
363  {
364  fit->faceIndex() = Fb::SAVE_CHANGED;
365  }
366  }
367  }
368 
369  Info<< nl;
370 
371  write("boundary");
372 }
373 
374 
376 {
377  for
378  (
379  Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
380  vit != finite_vertices_end();
381  ++vit
382  )
383  {
384  if (vit->index() >= startOfSurfacePointPairs_)
385  {
386  remove(vit);
387  }
388  }
389 }
390 
391 
393 {
394  const scalar relaxation = relaxationModel_->relaxation();
395 
396  Info<< "Relaxation = " << relaxation << endl;
397 
398  Field<point2D> dualVertices(number_of_faces());
399 
400  label dualVerti = 0;
401 
402  // Find the dual point of each tetrahedron and assign it an index.
403  for
404  (
405  Triangulation::Finite_faces_iterator fit = finite_faces_begin();
406  fit != finite_faces_end();
407  ++fit
408  )
409  {
410  fit->faceIndex() = -1;
411 
412  if
413  (
414  fit->vertex(0)->internalOrBoundaryPoint()
415  || fit->vertex(1)->internalOrBoundaryPoint()
416  || fit->vertex(2)->internalOrBoundaryPoint()
417  )
418  {
419  fit->faceIndex() = dualVerti;
420 
421  dualVertices[dualVerti] = toPoint2D(circumcenter(fit));
422 
423  dualVerti++;
424  }
425  }
426 
427  dualVertices.setSize(dualVerti);
428 
429  Field<vector2D> displacementAccumulator
430  (
431  startOfSurfacePointPairs_,
433  );
434 
435  // Calculate target size and alignment for vertices
436  scalarField sizes
437  (
438  number_of_vertices(),
439  meshControls().minCellSize()
440  );
441 
442  Field<vector2D> alignments
443  (
444  number_of_vertices(),
445  vector2D(1, 0)
446  );
447 
448  for
449  (
450  Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
451  vit != finite_vertices_end();
452  ++vit
453  )
454  {
455  if (vit->internalOrBoundaryPoint())
456  {
457  point2D vert = toPoint2D(vit->point());
458 
459  // alignment and size determination
460  pointIndexHit pHit;
461  label hitSurface = -1;
462 
463  qSurf_.findSurfaceNearest
464  (
465  toPoint3D(vert),
466  meshControls().span2(),
467  pHit,
468  hitSurface
469  );
470 
471  if (pHit.hit())
472  {
473  vectorField norm(1);
474  allGeometry_[hitSurface].getNormal
475  (
476  List<pointIndexHit>(1, pHit),
477  norm
478  );
479 
480  alignments[vit->index()] = toPoint2D(norm[0]);
481 
482  sizes[vit->index()] =
483  cellSizeControl_.cellSize
484  (
485  toPoint3D(vit->point())
486  );
487  }
488  }
489  }
490 
491  // Info<< "Calculated alignments" << endl;
492 
493  scalar cosAlignmentAcceptanceAngle = 0.68;
494 
495  // Upper and lower edge length ratios for weight
496  scalar u = 1.0;
497  scalar l = 0.7;
498 
499  PackedBoolList pointToBeRetained(startOfSurfacePointPairs_, true);
500 
501  std::list<Point> pointsToInsert;
502 
503  for
504  (
505  Triangulation::Finite_edges_iterator eit = finite_edges_begin();
506  eit != finite_edges_end();
507  eit++
508  )
509  {
510  Vertex_handle vA = eit->first->vertex(cw(eit->second));
511  Vertex_handle vB = eit->first->vertex(ccw(eit->second));
512 
513  if (!vA->internalOrBoundaryPoint() || !vB->internalOrBoundaryPoint())
514  {
515  continue;
516  }
517 
518  const point2D& dualV1 = dualVertices[eit->first->faceIndex()];
519  const point2D& dualV2 =
520  dualVertices[eit->first->neighbor(eit->second)->faceIndex()];
521 
522  scalar dualEdgeLength = mag(dualV1 - dualV2);
523 
524  point2D dVA = toPoint2D(vA->point());
525  point2D dVB = toPoint2D(vB->point());
526 
527  Field<vector2D> alignmentDirsA(2);
528 
529  alignmentDirsA[0] = alignments[vA->index()];
530  alignmentDirsA[1] = vector2D
531  (
532  -alignmentDirsA[0].y(),
533  alignmentDirsA[0].x()
534  );
535 
536  Field<vector2D> alignmentDirsB(2);
537 
538  alignmentDirsB[0] = alignments[vB->index()];
539  alignmentDirsB[1] = vector2D
540  (
541  -alignmentDirsB[0].y(),
542  alignmentDirsB[0].x()
543  );
544 
545  Field<vector2D> alignmentDirs(alignmentDirsA);
546 
547  forAll(alignmentDirsA, aA)
548  {
549  const vector2D& a(alignmentDirsA[aA]);
550 
551  scalar maxDotProduct = 0.0;
552 
553  forAll(alignmentDirsB, aB)
554  {
555  const vector2D& b(alignmentDirsB[aB]);
556 
557  scalar dotProduct = a & b;
558 
559  if (mag(dotProduct) > maxDotProduct)
560  {
561  maxDotProduct = mag(dotProduct);
562 
563  alignmentDirs[aA] = a + sign(dotProduct)*b;
564 
565  alignmentDirs[aA] /= mag(alignmentDirs[aA]);
566  }
567  }
568  }
569 
570  vector2D rAB = dVA - dVB;
571 
572  scalar rABMag = mag(rAB);
573 
574  forAll(alignmentDirs, aD)
575  {
576  vector2D& alignmentDir = alignmentDirs[aD];
577 
578  if ((rAB & alignmentDir) < 0)
579  {
580  // swap the direction of the alignment so that has the
581  // same sense as rAB
582  alignmentDir *= -1;
583  }
584 
585  scalar alignmentDotProd = ((rAB/rABMag) & alignmentDir);
586 
587  if (alignmentDotProd > cosAlignmentAcceptanceAngle)
588  {
589  scalar targetFaceSize =
590  0.5*(sizes[vA->index()] + sizes[vB->index()]);
591 
592  // Test for changing aspect ratio on second alignment (first
593  // alignment is neartest surface normal)
594  // if (aD == 1)
595  // {
596  // targetFaceSize *= 2.0;
597  // }
598 
599  alignmentDir *= 0.5*targetFaceSize;
600 
601  vector2D delta = alignmentDir - 0.5*rAB;
602 
603  if (dualEdgeLength < 0.7*targetFaceSize)
604  {
605  delta *= 0;
606  }
607  else if (dualEdgeLength < targetFaceSize)
608  {
609  delta *=
610  (
611  dualEdgeLength
612  /(targetFaceSize*(u - l))
613  - 1/((u/l) - 1)
614  );
615  }
616 
617  if
618  (
619  vA->internalPoint()
620  && vB->internalPoint()
621  && rABMag > 1.75*targetFaceSize
622  && dualEdgeLength > 0.05*targetFaceSize
623  && alignmentDotProd > 0.93
624  )
625  {
626  // Point insertion
627  pointsToInsert.push_back(toPoint(0.5*(dVA + dVB)));
628  }
629  else if
630  (
631  (vA->internalPoint() || vB->internalPoint())
632  && rABMag < 0.65*targetFaceSize
633  )
634  {
635  // Point removal
636 
637  // Only insert a point at the midpoint of the short edge
638  // if neither attached point has already been identified
639  // to be removed.
640  if
641  (
642  pointToBeRetained[vA->index()] == true
643  && pointToBeRetained[vB->index()] == true
644  )
645  {
646  pointsToInsert.push_back(toPoint(0.5*(dVA + dVB)));
647  }
648 
649  if (vA->internalPoint())
650  {
651  pointToBeRetained[vA->index()] = false;
652  }
653 
654  if (vB->internalPoint())
655  {
656  pointToBeRetained[vB->index()] = false;
657  }
658  }
659  else
660  {
661  if (vA->internalPoint())
662  {
663  displacementAccumulator[vA->index()] += delta;
664  }
665 
666  if (vB->internalPoint())
667  {
668  displacementAccumulator[vB->index()] += -delta;
669  }
670  }
671  }
672  }
673  }
674 
675  vector2D totalDisp = sum(displacementAccumulator);
676  scalar totalDist = sum(mag(displacementAccumulator));
677 
678  // Relax the calculated displacement
679  displacementAccumulator *= relaxation;
680 
681  label numberOfNewPoints = pointsToInsert.size();
682 
683  for
684  (
685  Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
686  vit != finite_vertices_end();
687  ++vit
688  )
689  {
690  if (vit->internalPoint())
691  {
692  if (pointToBeRetained[vit->index()])
693  {
694  pointsToInsert.push_front
695  (
696  toPoint
697  (
698  toPoint2D(vit->point())
699  + displacementAccumulator[vit->index()]
700  )
701  );
702  }
703  }
704  }
705 
706  // Clear the triangulation and reinsert the bounding box and feature points.
707  // This is faster than removing and moving points.
708  this->clear();
709 
710  insertBoundingBox();
711 
712  reinsertFeaturePoints();
713 
714  startOfInternalPoints_ = number_of_vertices();
715 
716  label nVert = startOfInternalPoints_;
717 
718  Info<< "Inserting " << numberOfNewPoints << " new points" << endl;
719 
720  // Use the range insert as it is faster than individually inserting points.
721  insert(pointsToInsert.begin(), pointsToInsert.end());
722 
723  for
724  (
725  Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
726  vit != finite_vertices_end();
727  ++vit
728  )
729  {
730  if
731  (
732  vit->type() == Vb::INTERNAL_POINT
733  && vit->index() == Vb::INTERNAL_POINT
734  )
735  {
736  vit->index() = nVert++;
737  }
738  }
739 
740  Info<< " Total displacement = " << totalDisp << nl
741  << " Total distance = " << totalDist << nl
742  << " Points added = " << pointsToInsert.size()
743  << endl;
744 
745  write("internal");
746 
747  insertSurfacePointPairs();
748 
749  boundaryConform();
750 
751 
752 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
753 // Old Method
754 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
755 
756 // for
757 // (
758 // Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
759 // vit != finite_vertices_end();
760 // ++vit
761 // )
762 // {
763 // if (vit->internalPoint())
764 // {
765 // // Current dual-cell defining vertex ("centre")
766 // point2DFromPoint defVert0 = toPoint2D(vit->point());
767 
768 // Triangulation::Edge_circulator ec = incident_edges(vit);
769 // Triangulation::Edge_circulator ecStart = ec;
770 
771 // // Circulate around the edges to find the first which is not
772 // // infinite
773 // do
774 // {
775 // if (!is_infinite(ec)) break;
776 // } while (++ec != ecStart);
777 
778 // // Store the start-end of the first non-infinte edge
779 // point2D de0 = toPoint2D(circumcenter(ec->first));
780 
781 // // Keep track of the maximum edge length^2
782 // scalar maxEdgeLen2 = 0.0;
783 
784 // // Keep track of the index of the longest edge
785 // label edgecd0i = -1;
786 
787 // // Edge counter
788 // label edgei = 0;
789 
790 // do
791 // {
792 // if (!is_infinite(ec))
793 // {
794 // // Get the end of the current edge
795 // point2D de1 = toPoint2D
796 // (
797 // circumcenter(ec->first->neighbor(ec->second))
798 // );
799 
800 // // Store the current edge vector
801 // edges[edgei] = de1 - de0;
802 
803 // // Store the edge mid-point in the vertices array
804 // vertices[edgei] = 0.5*(de1 + de0);
805 
806 // // Move the current edge end into the edge start for the
807 // // next iteration
808 // de0 = de1;
809 
810 // // Keep track of the longest edge
811 
812 // scalar edgeLen2 = magSqr(edges[edgei]);
813 
814 // if (edgeLen2 > maxEdgeLen2)
815 // {
816 // maxEdgeLen2 = edgeLen2;
817 // edgecd0i = edgei;
818 // }
819 
820 // edgei++;
821 // }
822 // } while (++ec != ecStart);
823 
824 // // Initialise cd0 such that the mesh will align
825 // // in in the x-y directions
826 // vector2D cd0(1, 0);
827 
828 // if (meshControls().relaxOrientation())
829 // {
830 // // Get the longest edge from the array and use as the primary
831 // // direction of the coordinate system of the "square" cell
832 // cd0 = edges[edgecd0i];
833 // }
834 
835 // if (meshControls().nearWallAlignedDist() > 0)
836 // {
837 // pointIndexHit pHit = qSurf_.tree().findNearest
838 // (
839 // toPoint3D(defVert0),
840 // meshControls().nearWallAlignedDist2()
841 // );
842 
843 // if (pHit.hit())
844 // {
845 // cd0 = toPoint2D(faceNormals[pHit.index()]);
846 // }
847 // }
848 
849 // // Rotate by 45deg needed to create an averaging procedure which
850 // // encourages the cells to be square
851 // cd0 = vector2D(cd0.x() + cd0.y(), cd0.y() - cd0.x());
852 
853 // // Normalise the primary coordinate direction
854 // cd0 /= mag(cd0);
855 
856 // // Calculate the orthogonal coordinate direction
857 // vector2D cd1(-cd0.y(), cd0.x());
858 
859 
860 // // Restart the circulator
861 // ec = ecStart;
862 
863 // // ... and the counter
864 // edgei = 0;
865 
866 // // Initialise the displacement for the centre and sum-weights
867 // vector2D disp = vector2D::zero;
868 // scalar sumw = 0;
869 
870 // do
871 // {
872 // if (!is_infinite(ec))
873 // {
874 // // Pick up the current edge
875 // const vector2D& ei = edges[edgei];
876 
877 // // Calculate the centre to edge-centre vector
878 // vector2D deltai = vertices[edgei] - defVert0;
879 
880 // // Set the weight for this edge contribution
881 // scalar w = 1;
882 
883 // if (meshControls().squares())
884 // {
885 // w = magSqr(deltai.x()*ei.y() - deltai.y()*ei.x());
886 // // alternative weights
887 // //w = mag(deltai.x()*ei.y() - deltai.y()*ei.x());
888 // //w = magSqr(ei)*mag(deltai);
889 
890 // // Use the following for an ~square mesh
891 // // Find the coordinate contributions for this edge delta
892 // scalar cd0deltai = cd0 & deltai;
893 // scalar cd1deltai = cd1 & deltai;
894 
895 // // Create a "square" displacement
896 // if (mag(cd0deltai) > mag(cd1deltai))
897 // {
898 // disp += (w*cd0deltai)*cd0;
899 // }
900 // else
901 // {
902 // disp += (w*cd1deltai)*cd1;
903 // }
904 // }
905 // else
906 // {
907 // // Use this for a hexagon/pentagon mesh
908 // disp += w*deltai;
909 // }
910 
911 // // Sum the weights
912 // sumw += w;
913 // }
914 // else
915 // {
916 // FatalErrorInFunction
917 // << "Infinite triangle found in internal mesh"
918 // << exit(FatalError);
919 // }
920 
921 // edgei++;
922 
923 // } while (++ec != ecStart);
924 
925 // // Calculate the average displacement
926 // disp /= sumw;
927 // totalDisp += disp;
928 // totalDist += mag(disp);
929 
930 // // Move the point by a fraction of the average displacement
931 // movePoint(vit, defVert0 + relaxation*disp);
932 // }
933 // }
934 
935 // Info << "\nTotal displacement = " << totalDisp
936 // << " total distance = " << totalDist << endl;
937 }
938 
939 
940 //void Foam::CV2D::moveInternalPoints(const point2DField& newPoints)
941 //{
942 // label pointI = 0;
943 
944 // for
945 // (
946 // Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
947 // vit != finite_vertices_end();
948 // ++vit
949 // )
950 // {
951 // if (vit->internalPoint())
952 // {
953 // movePoint(vit, newPoints[pointI++]);
954 // }
955 // }
956 //}
957 
958 
959 void Foam::CV2D::write() const
960 {
961  if (meshControls().objOutput())
962  {
963  writeFaces("allFaces.obj", false);
964  writeFaces("faces.obj", true);
965  writeTriangles("allTriangles.obj", false);
966  writeTriangles("triangles.obj", true);
967  writePatch("patch.pch");
968  }
969 }
970 
971 
972 void Foam::CV2D::write(const word& stage) const
973 {
974  if (meshControls().objOutput())
975  {
976  Foam::mkDir(stage + "Faces");
977  Foam::mkDir(stage + "Triangles");
978 
979  writeFaces
980  (
981  stage
982  + "Faces/allFaces_"
983  + runTime_.timeName()
984  + ".obj",
985  false
986  );
987 
988  writeTriangles
989  (
990  stage
991  + "Triangles/allTriangles_"
992  + runTime_.timeName()
993  + ".obj",
994  false
995  );
996  }
997 }
998 
999 
1000 // ************************************************************************* //
Foam::scalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Definition: primitiveFieldsFwd.H:48
Foam::CV2D::insertSurfacePointPairs
void insertSurfacePointPairs()
Insert all surface point-pairs from.
p
p
Definition: pEqn.H:62
Foam::compressible::New
autoPtr< BasicCompressibleTurbulenceModel > New(const volScalarField &rho, const volVectorField &U, const surfaceScalarField &phi, const typename BasicCompressibleTurbulenceModel::transportModel &transport, const word &propertiesName)
Definition: turbulentFluidThermoModel.C:36
Foam::CV2D::write
void write() const
clear
UEqn clear()
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::Warning
messageStream Warning
Foam::CV2D::CV2D
CV2D(const CV2D &)
Disallow default bitwise copy construct.
Foam::CV2D::insertPoints
void insertPoints(const point2DField &points, const scalar nearness)
Create the initial mesh from the given internal points.
Foam::CV2D::insertBoundingBox
void insertBoundingBox()
Create the initial mesh from the bounding-box.
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::cv2DControls::span
scalar span() const
Return the span.
Definition: cv2DControlsI.H:104
CGAL::indexedVertex::INTERNAL_POINT
@ INTERNAL_POINT
Definition: indexedVertex.H:98
Foam::CV2D::newPoints
void newPoints()
Move the internal points to the given new locations and update.
Foam::Vector2D< scalar >::zero
static const Vector2D zero
Definition: Vector2D.H:70
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::sign
dimensionedScalar sign(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:179
Foam::point2DField
vector2DField point2DField
point2DField is a vector2DField.
Definition: point2DFieldFwd.H:42
constant
Constant dispersed-phase particle diameter model.
Foam::vectorField
Field< vector > vectorField
Specialisation of Field<T> for vector.
Definition: primitiveFieldsFwd.H:49
CGAL::indexedVertex::FAR_POINT
@ FAR_POINT
Definition: indexedVertex.H:100
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::CV2D::insertGrid
void insertGrid()
Create the initial mesh as a regular grid of points.
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::constant::physicoChemical::b
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:28
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::Info
messageStream Info
delta
scalar delta
Definition: LISASMDCalcMethod2.H:8
Foam::y0
dimensionedScalar y0(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:272
IFstream.H
Foam::FatalError
error FatalError
Foam::toPoint
PointFrompoint toPoint(const Foam::point &p)
Definition: pointConversion.H:80
Foam::CV2D::~CV2D
~CV2D()
Destructor.
CGAL::indexedFace::UNCHANGED
@ UNCHANGED
Definition: indexedFace.H:64
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::cachedRandom::scalar01
scalar scalar01()
Returns the current sample.
Definition: cachedRandom.C:32
Foam::point2D
vector2D point2D
Point2D is a vector.
Definition: point2D.H:41
Foam::CV2D::removeSurfacePointPairs
void removeSurfacePointPairs()
Remove the point-pairs introduced by insertSurfacePointPairs.
uint.H
System uinteger.
Random.H
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
CGAL::indexedFace::SAVE_CHANGED
@ SAVE_CHANGED
Definition: indexedFace.H:66
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:318
Foam::pointIndexHit
PointIndexHit< point > pointIndexHit
Definition: pointIndexHit.H:42
Foam::CV2D::internal_flip
bool internal_flip(Face_handle &f, int i)
f
labelList f(nPoints)
Foam::vector2D
Vector2D< scalar > vector2D
vector2D obtained from generic Vector2D
Definition: vector2D.H:49
Foam::CV2D::meshControls
const cv2DControls & meshControls() const
Definition: CV2DI.H:118
CGAL::indexedFace::CHANGED
@ CHANGED
Definition: indexedFace.H:65
Foam::CV2D::external_flip
void external_flip(Face_handle &f, int i)
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:333
x
x
Definition: LISASMDCalcMethod2.H:52
Foam::CV2D::insertPoint
label insertPoint(const point2D &pt, const label type)
Insert point and return it's index.
Definition: CV2DI.H:29
Point
CGAL::Point_3< K > Point
Definition: CGALIndexedPolyhedron.H:51
List
Definition: Test.C:19
Foam::writePatch
void writePatch(const bool binary, const word &setName, const primitiveFacePatch &fp, const word &fieldName, labelList &fieldValues, const fileName &fileName)
transform.H
3D tensor transformation operations.
Foam::point
vector point
Point is a vector.
Definition: point.H:41
Foam::mkDir
bool mkDir(const fileName &, mode_t=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:419
Foam::CV2D::boundaryConform
void boundaryConform()
Insert point-pairs where there are protrusions into.
Delaunay
CGAL::Delaunay_triangulation_3< K, Tds, CompactLocator > Delaunay
Definition: CGALTriangulation3Ddefs.H:53
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::min
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
rndGen
cachedRandom rndGen(label(0), -1)
CV2D.H
write
Tcoeff write()
Foam::name
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
insert
timeIndices insert(timeIndex, timeDirs[timeI].value())
y
scalar y
Definition: LISASMDCalcMethod1.H:14
lookup
stressControl lookup("compactNormalStress") >> compactNormalStress
Foam::CV2D::fast_restore_Delaunay
void fast_restore_Delaunay(Vertex_handle vh)
Restore the Delaunay contraint.