foamyHexMeshSurfaceSimplify_non_octree.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2012-2016 OpenFOAM Foundation
9  Copyright (C) 2020-2021 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 Application
28  foamyHexMeshSurfaceSimplify
29 
30 Description
31  Simplifies surfaces by resampling.
32 
33  Uses Thomas Lewiner's topology preserving MarchingCubes.
34 
35 \*---------------------------------------------------------------------------*/
36 
37 #include "argList.H"
38 #include "Time.H"
39 #include "searchableSurfaces.H"
40 #include "conformationSurfaces.H"
41 #include "triSurfaceMesh.H"
42 #include "labelVector.H"
43 
44 #include "MarchingCubes.h"
45 
46 
47 using namespace Foam;
48 
49 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
50 
51 // Main program:
52 
53 int main(int argc, char *argv[])
54 {
56  (
57  "Re-sample surfaces used in foamyHexMesh operation"
58  );
59  argList::addArgument("(nx ny nz)", "The resampling interval");
60  argList::addArgument("output", "The output triSurface/ file");
61 
62  argList::noFunctionObjects(); // Never use function objects
63 
64  #include "setRootCase.H"
65  #include "createTime.H"
66 
67  const auto n = args.get<labelVector>(1);
68  const auto exportName = args.get<fileName>(2);
69 
70  Info<< "Reading surfaces as specified in the foamyHexMeshDict and"
71  << " writing re-sampled " << n << " to " << exportName
72  << nl << endl;
73 
74  cpuTime timer;
75 
76  IOdictionary foamyHexMeshDict
77  (
78  IOobject
79  (
80  "foamyHexMeshDict",
81  runTime.system(),
82  runTime,
85  )
86  );
87 
88  // Define/load all geometry
89  searchableSurfaces allGeometry
90  (
91  IOobject
92  (
93  "cvSearchableSurfaces",
94  runTime.constant(),
95  "triSurface",
96  runTime,
99  ),
100  foamyHexMeshDict.subDict("geometry"),
101  foamyHexMeshDict.getOrDefault("singleRegionName", true)
102  );
103 
104  Info<< "Geometry read in = "
105  << timer.cpuTimeIncrement() << " s." << nl << endl;
106 
107 
109 
110  conformationSurfaces geometryToConformTo
111  (
112  runTime,
113  rndGen,
114  allGeometry,
115  foamyHexMeshDict.subDict("surfaceConformation")
116  );
117 
118  Info<< "Set up geometry in = "
119  << timer.cpuTimeIncrement() << " s." << nl << endl;
120 
121 
122 
123  // Extend
124  treeBoundBox bb = geometryToConformTo.globalBounds();
125  bb.grow(0.1*bb.span());
126 
127  Info<< "Meshing to bounding box " << bb << nl << endl;
128 
129  const vector span(bb.span());
130  const vector d
131  (
132  span.x()/(n.x()-1),
133  span.y()/(n.y()-1),
134  span.z()/(n.z()-1)
135  );
136 
137  MarchingCubes mc(span.x(), span.y(), span.z() ) ;
138  mc.set_resolution(n.x(), n.y(), n.z());
139  mc.init_all() ;
140 
141 
142  // Generate points
143  pointField points(mc.size_x()*mc.size_y()*mc.size_z());
144  label pointi = 0;
145 
146  point pt;
147  for( int k = 0 ; k < mc.size_z() ; k++ )
148  {
149  pt.z() = bb.min().z() + k*d.z();
150  for( int j = 0 ; j < mc.size_y() ; j++ )
151  {
152  pt.y() = bb.min().y() + j*d.y();
153  for( int i = 0 ; i < mc.size_x() ; i++ )
154  {
155  pt.x() = bb.min().x() + i*d.x();
156  points[pointi++] = pt;
157  }
158  }
159  }
160 
161  Info<< "Generated " << points.size() << " sampling points in = "
162  << timer.cpuTimeIncrement() << " s." << nl << endl;
163 
164 
165  // Compute data
166  const searchableSurfaces& geometry = geometryToConformTo.geometry();
167  const labelList& surfaces = geometryToConformTo.surfaces();
168 
169  scalarField signedDist;
170  labelList nearestSurfaces;
172  (
173  geometry,
174  surfaces,
175  points,
176  scalarField(points.size(), sqr(GREAT)),
177  searchableSurface::OUTSIDE, // for non-closed surfaces treat as
178  // outside
179  nearestSurfaces,
180  signedDist
181  );
182 
183  // Fill elements
184  pointi = 0;
185  for( int k = 0 ; k < mc.size_z() ; k++ )
186  {
187  for( int j = 0 ; j < mc.size_y() ; j++ )
188  {
189  for( int i = 0 ; i < mc.size_x() ; i++ )
190  {
191  mc.set_data(float(signedDist[pointi++]), i, j, k);
192  }
193  }
194  }
195 
196  Info<< "Determined signed distance in = "
197  << timer.cpuTimeIncrement() << " s." << nl << endl;
198 
199 
200  mc.run() ;
201 
202  Info<< "Constructed iso surface in = "
203  << timer.cpuTimeIncrement() << " s." << nl << endl;
204 
205 
206  mc.clean_temps() ;
207 
208 
209 
210  // Write output file
211  if (mc.ntrigs() > 0)
212  {
213  Triangle* triangles = mc.triangles();
214  List<labelledTri> tris(mc.ntrigs());
215  forAll(tris, triI)
216  {
217  tris[triI] = labelledTri
218  (
219  triangles[triI].v1,
220  triangles[triI].v2,
221  triangles[triI].v3,
222  0 // region
223  );
224  }
225 
226 
227  Vertex* vertices = mc.vertices();
228  pointField points(mc.nverts());
229  forAll(points, pointi)
230  {
231  Vertex& v = vertices[pointi];
232  points[pointi] = point
233  (
234  bb.min().x() + v.x*span.x()/mc.size_x(),
235  bb.min().y() + v.y*span.y()/mc.size_y(),
236  bb.min().z() + v.z*span.z()/mc.size_z()
237  );
238  }
239 
240 
241  // Find correspondence to original surfaces
242  labelList regionOffsets(surfaces.size());
243  label nRegions = 0;
244  forAll(surfaces, i)
245  {
246  const wordList& regions = geometry[surfaces[i]].regions();
247  regionOffsets[i] = nRegions;
248  nRegions += regions.size();
249  }
250 
251 
253  nRegions = 0;
254  forAll(surfaces, i)
255  {
256  const wordList& regions = geometry[surfaces[i]].regions();
257 
258  forAll(regions, regionI)
259  {
260  patches[nRegions] = geometricSurfacePatch
261  (
262  geometry[surfaces[i]].name() + "_" + regions[regionI],
263  nRegions,
264  "patch"
265  );
266  nRegions++;
267  }
268  }
269 
270  triSurface s(tris, patches, points, true);
271 
272  Info<< "Extracted triSurface in = "
273  << timer.cpuTimeIncrement() << " s." << nl << endl;
274 
275 
276  // Find out region on local surface of nearest point
277  {
278  List<pointIndexHit> hitInfo;
279  labelList hitSurfaces;
280  geometryToConformTo.findSurfaceNearest
281  (
282  s.faceCentres(),
283  scalarField(s.size(), sqr(GREAT)),
284  hitInfo,
285  hitSurfaces
286  );
287 
288  // Get region
289  DynamicList<pointIndexHit> surfInfo(hitSurfaces.size());
290  DynamicList<label> surfIndices(hitSurfaces.size());
291 
292  forAll(surfaces, surfI)
293  {
294  // Extract info on this surface
295  surfInfo.clear();
296  surfIndices.clear();
297  forAll(hitSurfaces, triI)
298  {
299  if (hitSurfaces[triI] == surfI)
300  {
301  surfInfo.append(hitInfo[triI]);
302  surfIndices.append(triI);
303  }
304  }
305 
306  // Calculate sideness of these surface points
307  labelList region;
308  geometry[surfaces[surfI]].getRegion(surfInfo, region);
309 
310  forAll(region, i)
311  {
312  label triI = surfIndices[i];
313  s[triI].region() = regionOffsets[surfI]+region[i];
314  }
315  }
316  }
317 
318  Info<< "Re-patched surface in = "
319  << timer.cpuTimeIncrement() << " s." << nl << endl;
320 
321  triSurfaceMesh smesh
322  (
323  IOobject
324  (
325  exportName,
326  runTime.constant(), // instance
327  "triSurface",
328  runTime, // registry
331  false
332  ),
333  s
334  );
335 
336  Info<< "writing surfMesh:\n "
337  << smesh.searchableSurface::objectPath() << nl << endl;
338  smesh.searchableSurface::write();
339 
340  Info<< "Written surface in = "
341  << timer.cpuTimeIncrement() << " s." << nl << endl;
342  }
343 
344  mc.clean_all() ;
345 
346 
347  Info<< "End\n" << endl;
348 
349  return 0;
350 }
351 
352 
353 // ************************************************************************* //
graph_traits< Graph >::vertex_descriptor Vertex
Definition: SloanRenumber.C:67
static void noFunctionObjects(bool addWithOption=false)
Remove &#39;-noFunctionObjects&#39; option and ignore any occurrences.
Definition: argList.C:514
static void addNote(const string &note)
Add extra notes for the usage information.
Definition: argList.C:453
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:118
A class for handling file names.
Definition: fileName.H:71
dimensionedSymmTensor sqr(const dimensionedVector &dv)
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
Implements a timeout mechanism via sigalarm.
Definition: timer.H:82
Random rndGen
Definition: createFields.H:23
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
std::vector< Triangle > triangles
CGAL::Triangle_3< K > Triangle
label k
Boltzmann constant.
Ignore writing from objectRegistry::writeObject()
const point & min() const noexcept
Minimum describing the bounding box.
Definition: boundBoxI.H:155
static int myProcNo(const label communicator=worldComm)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:688
static void signedDistance(const PtrList< searchableSurface > &allSurfaces, const labelList &surfacesToTest, const pointField &samples, const scalarField &nearestDistSqr, const volumeType illegalHandling, labelList &nearestSurfaces, scalarField &distance)
Find signed distance to nearest surface. Outside is positive.
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:50
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
IOoject and searching on triSurface.
pointField vertices(const blockVertexList &bvl)
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:52
const pointField & points
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:51
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Reading required, file watched for runTime modification.
const word & system() const noexcept
Return system name.
Definition: TimePathsI.H:95
Container for searchableSurfaces. The collection is specified as a dictionary. For example...
A triFace with additional (region) index.
Definition: labelledTri.H:53
Random number generator.
Definition: Random.H:55
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
const word & constant() const noexcept
Return constant name.
Definition: TimePathsI.H:89
vector point
Point is a vector.
Definition: point.H:37
T get(const label index) const
Get a value from the argument at index.
Definition: argListI.H:271
const polyBoundaryMesh & patches
Nothing to be read.
Automatically write from objectRegistry::writeObject()
static void addArgument(const string &argName, const string &usage="")
Append a (mandatory) argument to validArgs.
Definition: argList.C:342
vector span() const
The bounding box span (from minimum to maximum)
Definition: boundBoxI.H:185
Identifies a surface patch/zone by name and index, with geometric type.
Standard boundBox with extra functionality for use in octree.
Definition: treeBoundBox.H:90
messageStream Info
Information stream (stdout output on master, null elsewhere)
label n
Triangulated surface description with patch information.
Definition: triSurface.H:72
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Foam::argList args(argc, argv)
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:166
void grow(const scalar delta)
Expand box by adjusting min/max by specified amount in each dimension.
Definition: boundBoxI.H:353
Namespace for OpenFOAM.
Starts timing CPU usage and return elapsed time from start.
Definition: cpuTimePosix.H:52