netgenNeutralToFoam.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2016 OpenFOAM Foundation
9 Copyright (C) 2020-2021 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27Application
28 netgenNeutralToFoam
29
30Group
31 grpMeshConversionUtilities
32
33Description
34 Convert a neutral file format (Netgen v4.4) to OpenFOAM.
35
36 Example:
37
38 9
39 1.000000 1.000000 1.000000
40 0.000000 1.000000 1.000000
41 0.000000 0.000000 1.000000
42 1.000000 0.000000 1.000000
43 0.000000 1.000000 0.000000
44 1.000000 1.000000 0.000000
45 1.000000 0.000000 0.000000
46 0.000000 0.000000 0.000000
47 0.500000 0.500000 0.500000
48 12
49 1 7 8 9 3
50 1 5 9 6 8
51 1 5 9 2 1
52 1 4 9 7 6
53 1 7 8 6 9
54 1 4 6 1 9
55 1 5 9 8 2
56 1 4 1 2 9
57 1 1 6 5 9
58 1 2 3 4 9
59 1 8 9 3 2
60 1 4 9 3 7
61 12
62 1 1 2 4
63 1 3 4 2
64 2 5 6 8
65 2 7 8 6
66 3 1 4 6
67 3 7 6 4
68 5 2 1 5
69 5 6 5 1
70 5 3 2 8
71 5 5 8 2
72 6 4 3 7
73 6 8 7 3
74
75NOTE:
76 - reverse order of boundary faces using geometric test.
77 (not very space efficient)
78 - order of tet vertices only tested on one file.
79 - all patch/cell/vertex numbers offset by one.
80
81\*---------------------------------------------------------------------------*/
82
83#include "argList.H"
84#include "Time.H"
85#include "polyMesh.H"
86#include "IFstream.H"
87#include "polyPatch.H"
88#include "cellModel.H"
89#include "triFace.H"
90
91using namespace Foam;
92
93// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
94
95
96int main(int argc, char *argv[])
97{
98 argList::addNote
99 (
100 "Convert a neutral file format (Netgen v4.4) to OpenFOAM"
101 );
102 argList::addArgument("Neutral file");
103
104 #include "setRootCase.H"
105 #include "createTime.H"
106
107 IFstream str(args.get<fileName>(1));
108
109 //
110 // Read nodes.
111 //
112 label nNodes(readLabel(str));
113
114 Info<< "nNodes:" << nNodes << endl;
115
116 pointField points(nNodes);
117
118 forAll(points, pointi)
119 {
120 scalar x,y,z;
121
122 str >> x >> y >> z;
123
124 points[pointi] = point(x, y, z);
125 }
126
127
128
129
130 label nTets(readLabel(str));
131
132 Info<< "nTets:" << nTets << endl;
133
134 const cellModel& tet = cellModel::ref(cellModel::TET);
135
136 cellShapeList cells(nTets);
137
139
140 forAll(cells, celli)
141 {
142 label domain(readLabel(str));
143
144 if (domain != 1)
145 {
147 << "Cannot handle multiple domains"
148 << nl << "Ignoring domain " << domain << " setting on line "
149 << str.lineNumber() << endl;
150 }
151
152 tetPoints[1] = readLabel(str) - 1;
153 tetPoints[0] = readLabel(str) - 1;
154 tetPoints[2] = readLabel(str) - 1;
155 tetPoints[3] = readLabel(str) - 1;
156
157 cells[celli].reset(tet, tetPoints);
158 }
159
160
161
162 label nFaces(readLabel(str));
163
164 Info<< "nFaces:" << nFaces << endl;
165
166 // Unsorted boundary faces
167 faceList boundaryFaces(nFaces);
168
169 // For each boundary faces the Foam patchID
171
172 // Max patch.
173 label maxPatch = 0;
174
175 // Boundary faces as three vertices
176 HashTable<label, triFace> vertsToBoundary(nFaces);
177
178 forAll(boundaryFaces, facei)
179 {
180 label patchi(readLabel(str));
181
182 if (patchi < 0)
183 {
185 << "Invalid boundary region number " << patchi
186 << " on line " << str.lineNumber()
187 << exit(FatalError);
188 }
189
190
191 maxPatch = max(maxPatch, patchi);
192
193 triFace tri(readLabel(str)-1, readLabel(str)-1, readLabel(str)-1);
194
195 // Store boundary face as is for now. Later on reverse it.
196 boundaryFaces[facei].setSize(3);
197 boundaryFaces[facei][0] = tri[0];
198 boundaryFaces[facei][1] = tri[1];
199 boundaryFaces[facei][2] = tri[2];
200 boundaryPatch[facei] = patchi;
201
202 vertsToBoundary.insert(tri, facei);
203 }
204
205 label nPatches = maxPatch + 1;
206
207
208 // Use hash of points to get owner cell and orient the boundary face.
209 // For storage reasons I store the triangles and loop over the cells instead
210 // of the other way around (store cells and loop over triangles) though
211 // that would be faster.
212 forAll(cells, celli)
213 {
214 const cellShape& cll = cells[celli];
215
216 // Get the four (outwards pointing) faces of the cell
217 faceList tris(cll.faces());
218
219 for (const face& f : tris)
220 {
221 // Is there any boundary face with same vertices?
222 // (uses commutative hash)
223 auto iter = vertsToBoundary.find(triFace(f[0], f[1], f[2]));
224
225 if (iter.found())
226 {
227 const triFace& tri = iter.key();
228 const label facei = iter.val();
229
230 // Determine orientation of tri v.s. cell centre.
231 point cc(cll.centre(points));
232 point fc(tri.centre(points));
233
234 const vector areaNorm(tri.areaNormal(points));
235
236 if (((fc - cc) & areaNorm) < 0)
237 {
238 // Boundary face points inwards. Flip.
239 boundaryFaces[facei].flip();
240 }
241
242 // Done this face so erase from hash
243 vertsToBoundary.erase(iter);
244 }
245 }
246 }
247
248
249 if (vertsToBoundary.size())
250 {
251 // Didn't find cells connected to boundary faces.
253 << "There are boundary faces without attached cells."
254 << "Boundary faces (as triFaces):" << vertsToBoundary.toc()
255 << endl;
256 }
257
258
259 // Storage for boundary faces sorted into patches
260
261 faceListList patchFaces(nPatches);
262
264
265 forAll(patchNames, patchi)
266 {
267 patchNames[patchi] = polyPatch::defaultName(patchi);
268 }
269
270 wordList patchTypes(nPatches, polyPatch::typeName);
271 word defaultFacesName = "defaultFaces";
272 word defaultFacesType = polyPatch::typeName;
273 wordList patchPhysicalTypes(nPatches, polyPatch::typeName);
274
275 {
276 // Sort boundaryFaces by patch.
277 List<DynamicList<face>> allPatchFaces(nPatches);
278
279 forAll(boundaryPatch, facei)
280 {
281 label patchi = boundaryPatch[facei];
282
283 allPatchFaces[patchi].append(boundaryFaces[facei]);
284 }
285
286 Info<< "Patches:" << nl
287 << "\tNeutral Boundary\tPatch name\tSize" << nl
288 << "\t----------------\t----------\t----" << endl;
289
290 forAll(allPatchFaces, patchi)
291 {
292 Info<< '\t' << patchi << "\t\t\t"
293 << patchNames[patchi] << "\t\t"
294 << allPatchFaces[patchi].size() << endl;
295
296 patchFaces[patchi].transfer(allPatchFaces[patchi]);
297 }
298
299 Info<< endl;
300 }
301
302
304 (
306 (
307 polyMesh::defaultRegion,
308 runTime.constant(),
309 runTime
310 ),
311 std::move(points),
312 cells,
313 patchFaces,
318 patchPhysicalTypes
319 );
320
321 // Set the precision of the points data to 10
322 IOstream::defaultPrecision(max(10u, IOstream::defaultPrecision()));
323
324 Info<< "Writing mesh ..." << endl;
325 mesh.removeFiles();
326 mesh.write();
327
328 Info<< "End\n" << endl;
329
330 return 0;
331}
332
333
334// ************************************************************************* //
scalar y
Y[inertIndex] max(0.0)
A HashTable similar to std::unordered_map.
Definition: HashTable.H:123
Input from file stream, using an ISstream.
Definition: IFstream.H:57
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
T get(const label index) const
Get a value from the argument at index.
Definition: argListI.H:278
Like polyPatch but without reference to mesh. Used in boundaryMesh to hold data on patches....
Definition: boundaryPatch.H:57
Maps a geometry to a set of cell primitives.
Definition: cellModel.H:73
An analytical geometric cellShape.
Definition: cellShape.H:72
point centre(const UList< point > &points) const
Centroid of the cell.
Definition: cellShapeI.H:287
faceList faces() const
Faces of this cell.
Definition: cellShapeI.H:227
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
A class for handling file names.
Definition: fileName.H:76
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:81
Tet storage. Null constructable (unfortunately tetrahedron<point, point> is not)
Definition: tetPoints.H:56
A triangular face using a FixedList of labels corresponding to mesh vertices.
Definition: triFace.H:72
point centre(const UList< point > &points) const
Return centre (centroid)
Definition: triFaceI.H:187
vector areaNormal(const UList< point > &points) const
The area normal - with magnitude equal to area of face.
Definition: triFaceI.H:198
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
A class for handling words, derived from Foam::string.
Definition: word.H:68
dynamicFvMesh & mesh
engineTime & runTime
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
const labelList nFaces(UPstream::listGatherValues< label >(aMesh.nFaces()))
const label nPatches
const pointField & points
const cellShapeList & cells
#define WarningInFunction
Report a warning using Foam::Warning.
Namespace for OpenFOAM.
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition: label.H:66
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
wordList patchTypes(nPatches)
wordList patchNames(nPatches)
face triFace(3)
labelList f(nPoints)
word defaultFacesName
Definition: readKivaGrid.H:455
word defaultFacesType
Definition: readKivaGrid.H:456
Foam::argList args(argc, argv)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333