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 -------------------------------------------------------------------------------
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  netgenNeutralToFoam
29 
30 Group
31  grpMeshConversionUtilities
32 
33 Description
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 
75 NOTE:
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 
91 using namespace Foam;
92 
93 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
94 
95 
96 int main(int argc, char *argv[])
97 {
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 
135 
136  cellShapeList cells(nTets);
137 
138  labelList tetPoints(4);
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
170  labelList boundaryPatch(nFaces, -1);
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 
303  polyMesh mesh
304  (
305  IOobject
306  (
308  runTime.constant(),
309  runTime
310  ),
311  std::move(points),
312  cells,
313  patchFaces,
314  patchNames,
315  patchTypes,
318  patchPhysicalTypes
319  );
320 
321  // Set the precision of the points data to 10
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 // ************************************************************************* //
runTime
engineTime & runTime
Definition: createEngineTime.H:13
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:169
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::fileName
A class for handling file names.
Definition: fileName.H:73
Foam::fvMesh::write
virtual bool write(const bool valid=true) const
Write mesh using IO settings from time.
Definition: fvMesh.C:1041
Foam::polyMesh::defaultRegion
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:318
polyPatch.H
Foam::cellShape::centre
point centre(const UList< point > &points) const
Centroid of the cell.
Definition: cellShapeI.H:287
Foam::IFstream
Input from file stream, using an ISstream.
Definition: IFstream.H:53
Foam::triFace::areaNormal
vector areaNormal(const UList< point > &points) const
The area normal - with magnitude equal to area of face.
Definition: triFaceI.H:187
Foam::argList::addNote
static void addNote(const string &note)
Add extra notes for the usage information.
Definition: argList.C:412
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::cellShape::faces
faceList faces() const
Faces of this cell.
Definition: cellShapeI.H:227
triFace.H
polyMesh.H
defaultFacesType
word defaultFacesType
Definition: readKivaGrid.H:456
Foam::argList::get
T get(const label index) const
Get a value from the argument at index.
Definition: argListI.H:278
Foam::cellModel::TET
tet
Definition: cellModel.H:85
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
patchTypes
wordList patchTypes(nPatches)
Foam::boundaryPatch
Like polyPatch but without reference to mesh. Used in boundaryMesh to hold data on patches....
Definition: boundaryPatch.H:54
Foam::argList::addArgument
static void addArgument(const string &argName, const string &usage="")
Append a (mandatory) argument to validArgs.
Definition: argList.C:301
nPatches
const label nPatches
Definition: printMeshSummary.H:30
Foam::Field< vector >
cellModel.H
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::polyMesh::removeFiles
void removeFiles(const fileName &instanceDir) const
Remove all files from mesh instance.
Definition: polyMesh.C:1325
argList.H
patchNames
wordList patchNames(nPatches)
Foam::cellModel::ref
static const cellModel & ref(const modelType model)
Look up reference to cellModel by enumeration. Fatal on failure.
Definition: cellModels.C:157
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
IFstream.H
Foam::triFace::centre
point centre(const UList< point > &points) const
Return centre (centroid)
Definition: triFaceI.H:176
Foam::FatalError
error FatalError
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::cellShape
An analytical geometric cellShape.
Definition: cellShape.H:69
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::HashTable::transfer
void transfer(HashTable< T, Key, Hash > &rhs)
Transfer contents into this table.
Definition: HashTable.C:671
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::tetPoints
Tet storage. Null constructable (unfortunately tetrahedron<point, point> is not)
Definition: tetPoints.H:53
Foam::HashTable
A HashTable similar to std::unordered_map.
Definition: HashTable.H:105
Foam::IOstream::defaultPrecision
static unsigned int defaultPrecision() noexcept
Return the default precision.
Definition: IOstream.H:342
Time.H
setRootCase.H
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::nl
constexpr char nl
Definition: Ostream.H:404
defaultFacesName
word defaultFacesName
Definition: readKivaGrid.H:455
Foam::triFace
A triangular face using a FixedList of labels corresponding to mesh vertices.
Definition: triFace.H:69
f
labelList f(nPoints)
Foam::Vector< scalar >
Foam::readLabel
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition: label.H:66
Foam::List< cellShape >
points
const pointField & points
Definition: gmvOutputHeader.H:1
createTime.H
x
x
Definition: LISASMDCalcMethod2.H:52
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
Foam::cellModel
Maps a geometry to a set of cell primitives.
Definition: cellModel.H:72
Foam::point
vector point
Point is a vector.
Definition: point.H:43
Foam::patchIdentifier::defaultName
static word defaultName(const label n=-1)
Default patch name: "patch" or "patchN".
Definition: patchIdentifier.H:76
Foam::TimePaths::constant
const word & constant() const
Return constant name.
Definition: TimePathsI.H:96
args
Foam::argList args(argc, argv)
triFace
face triFace(3)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
y
scalar y
Definition: LISASMDCalcMethod1.H:14