1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
25 Converts neutral file format as written by Netgen v4.4.
30 1.000000 1.000000 1.000000
31 0.000000 1.000000 1.000000
32 0.000000 0.000000 1.000000
33 1.000000 0.000000 1.000000
34 0.000000 1.000000 0.000000
35 1.000000 1.000000 0.000000
36 1.000000 0.000000 0.000000
37 0.000000 0.000000 0.000000
38 0.500000 0.500000 0.500000
67 - reverse order of boundary faces using geometric test.
68 (not very space efficient)
69 - order of tet vertices only tested on one file.
70 - all patch/cell/vertex numbers offset by one.
72 \*---------------------------------------------------------------------------*/
75 #include "objectRegistry.H"
79 #include "polyPatch.H"
80 #include "cellModeller.H"
85 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
89 int main(int argc, char *argv[])
91 argList::validArgs.append("Neutral file");
93 # include "setRootCase.H"
94 # include "createTime.H"
96 fileName neuFile(args.additionalArgs()[0]);
99 IFstream str(neuFile);
105 label nNodes(readLabel(str));
107 Info<< "nNodes:" << nNodes << endl;
110 pointField points(nNodes);
112 forAll(points, pointI)
118 points[pointI] = point(x, y, z);
124 label nTets(readLabel(str));
126 Info<< "nTets:" << nTets << endl;
128 const cellModel& tet = *(cellModeller::lookup("tet"));
130 cellShapeList cells(nTets);
132 labelList tetPoints(4);
136 label domain(readLabel(str));
140 WarningIn(args.executable())
141 << "Cannot handle multiple domains"
142 << nl << "Ignoring domain " << domain << " setting on line "
143 << str.lineNumber() << endl;
146 tetPoints[1] = readLabel(str) - 1;
147 tetPoints[0] = readLabel(str) - 1;
148 tetPoints[2] = readLabel(str) - 1;
149 tetPoints[3] = readLabel(str) - 1;
151 cells[cellI] = cellShape(tet, tetPoints);
156 label nFaces(readLabel(str));
158 Info<< "nFaces:" << nFaces << endl;
160 // Unsorted boundary faces
161 faceList boundaryFaces(nFaces);
163 // For each boundary faces the Foam patchID
164 labelList boundaryPatch(nFaces, -1);
169 // Boundary faces as three vertices
170 HashTable<label, triFace, Hash<triFace> > vertsToBoundary(nFaces);
172 forAll(boundaryFaces, faceI)
174 label patchI(readLabel(str));
178 FatalErrorIn(args.executable())
179 << "Invalid boundary region number " << patchI
180 << " on line " << str.lineNumber()
185 maxPatch = max(maxPatch, patchI);
187 triFace tri(readLabel(str)-1, readLabel(str)-1, readLabel(str)-1);
189 // Store boundary face as is for now. Later on reverse it.
190 boundaryFaces[faceI].setSize(3);
191 boundaryFaces[faceI][0] = tri[0];
192 boundaryFaces[faceI][1] = tri[1];
193 boundaryFaces[faceI][2] = tri[2];
194 boundaryPatch[faceI] = patchI;
196 vertsToBoundary.insert(tri, faceI);
199 label nPatches = maxPatch + 1;
202 // Use hash of points to get owner cell and orient the boundary face.
203 // For storage reasons I store the triangles and loop over the cells instead
204 // of the other way around (store cells and loop over triangles) though
205 // that would be faster.
208 const cellShape& cll = cells[cellI];
210 // Get the four (outwards pointing) faces of the cell
211 faceList tris(cll.faces());
215 const face& f = tris[i];
217 // Is there any boundary face with same vertices?
218 // (uses commutative hash)
219 HashTable<label, triFace, Hash<triFace> >::iterator iter =
220 vertsToBoundary.find(triFace(f[0], f[1], f[2]));
222 if (iter != vertsToBoundary.end())
224 label faceI = iter();
225 const triFace& tri = iter.key();
227 // Determine orientation of tri v.s. cell centre.
228 point cc(cll.centre(points));
229 point fc(tri.centre(points));
230 vector fn(tri.normal(points));
232 if (((fc - cc) & fn) < 0)
234 // Boundary face points inwards. Flip.
235 boundaryFaces[faceI] = boundaryFaces[faceI].reverseFace();
238 // Done this face so erase from hash
239 vertsToBoundary.erase(iter);
245 if (vertsToBoundary.size())
247 // Didn't find cells connected to boundary faces.
248 WarningIn(args.executable())
249 << "There are boundary faces without attached cells."
250 << "Boundary faces (as triFaces):" << vertsToBoundary.toc()
255 // Storage for boundary faces sorted into patches
257 faceListList patchFaces(nPatches);
259 wordList patchNames(nPatches);
261 forAll(patchNames, patchI)
263 patchNames[patchI] = word("patch") + name(patchI);
266 wordList patchTypes(nPatches, polyPatch::typeName);
267 word defaultFacesName = "defaultFaces";
268 word defaultFacesType = polyPatch::typeName;
269 wordList patchPhysicalTypes(nPatches, polyPatch::typeName);
272 // Sort boundaryFaces by patch.
273 List<DynamicList<face> > allPatchFaces(nPatches);
275 forAll(boundaryPatch, faceI)
277 label patchI = boundaryPatch[faceI];
279 allPatchFaces[patchI].append(boundaryFaces[faceI]);
282 Info<< "Patches:" << nl
283 << "\tNeutral Boundary\tPatch name\tSize" << nl
284 << "\t----------------\t----------\t----" << endl;
286 forAll(allPatchFaces, patchI)
288 Info<< '\t' << patchI << "\t\t\t"
289 << patchNames[patchI] << "\t\t"
290 << allPatchFaces[patchI].size() << endl;
292 patchFaces[patchI].transfer(allPatchFaces[patchI]);
303 polyMesh::defaultRegion,
317 Info<< "Writing mesh to " << runTime.constant() << endl << endl;
322 Info<< "End\n" << endl;
328 // ************************************************************************* //