Forward compatibility: flex
[foam-extend-3.2.git] / applications / utilities / mesh / generation / cfMesh / mergeSurfacePatches / mergeSurfacePatches.C
blob4d6c94efe7e5bd7c63a4e8c8c35181e9cbfdbd82
1 /*---------------------------------------------------------------------------*\
2   =========                 |
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 -------------------------------------------------------------------------------
8 License
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/>.
24 Description
25     cfMesh utility to merge the supplied list of patches onto a single
26     patch.
28 Author
29     Ivor Clifford <ivor.clifford@psi.ch>
31 \*---------------------------------------------------------------------------*/
33 #include "argList.H"
34 #include "objectRegistry.H"
35 #include "foamTime.H"
36 #include "autoPtr.H"
37 #include "triSurf.H"
38 #include "triSurfModifier.H"
39 #include "demandDrivenData.H"
40 #include "Pair.H"
42 using namespace Foam;
44 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
46 // Find the supplied list of patch names and return a list of patch Ids
47 void getPatchIds
49     const triSurf& origSurf,
50     const wordList& patchNames,
51     DynamicList<label>& patchIds
54     const geometricSurfacePatchList& origPatches = origSurf.patches();
56     // Create patch name map
57     HashSet<word> patchNameHash(patchNames);
59     // Find selected patches
60     label nFound = 0;
61     forAll(origPatches, patchI)
62     {
63         if (patchNameHash.found(origPatches[patchI].name()))
64         {
65             patchIds.append(patchI);
66             nFound++;
67         }
68     }
70     if (nFound != patchNames.size())
71     {
72         WarningIn("getPatchIds")
73             << "Not all supplied patch names were found on the surface mesh" << endl;
74     }
78 // Copy all face subsets from one triSurf to another
79 void copyFaceSubsets
81     const triSurf& origSurf,
82     triSurf& newSurf
85     DynList<label> subsetIds;
86     origSurf.facetSubsetIndices(subsetIds);
88     forAll(subsetIds, subsetI)
89     {
90         label newSubsetId = newSurf.addFacetSubset
91         (
92             origSurf.facetSubsetName(subsetI)
93         );
95         labelList origFaces;
96         origSurf.facetsInSubset(subsetI, origFaces);
98         forAll(origFaces, faceI)
99         {
100             newSurf.addFacetToSubset
101             (
102                 newSubsetId,
103                 origFaces[faceI]
104             );
105         }
106     }
110 // Copy all edge subsets from one triSurf to another
111 void copyEdgeSubsets
113     const triSurf& origSurf,
114     triSurf& newSurf
117     DynList<label> subsetIds;
118     origSurf.edgeSubsetIndices(subsetIds);
120     forAll(subsetIds, subsetI)
121     {
122         label newSubsetId = newSurf.addEdgeSubset
123         (
124             origSurf.edgeSubsetName(subsetI)
125         );
127         labelList origEdges;
128         origSurf.edgesInSubset(subsetI, origEdges);
130         forAll(origEdges, faceI)
131         {
132             newSurf.addEdgeToSubset
133             (
134                 newSubsetId,
135                 origEdges[faceI]
136             );
137         }
138     }
142 // Copy all point subsets from one triSurf to another
143 void copyPointSubsets
145     const triSurf& origSurf,
146     triSurf& newSurf
149     DynList<label> subsetIds;
150     origSurf.pointSubsetIndices(subsetIds);
152     forAll(subsetIds, subsetI)
153     {
154         label newSubsetId = newSurf.addPointSubset
155         (
156             origSurf.pointSubsetName(subsetI)
157         );
159         labelList origPoints;
160         origSurf.pointsInSubset(subsetI, origPoints);
162         forAll(origPoints, faceI)
163         {
164             newSurf.addPointToSubset
165             (
166                 newSubsetId,
167                 origPoints[faceI]
168             );
169         }
170     }
174 // Merge the supplied list of patchIds onto a new patch
175 autoPtr<triSurf> mergeSurfacePatches
177     const triSurf& origSurf,        // Surface
178     const UList<label>& patchIds,   // Ids of patches to merge
179     const word& newPatchName,       // Name of new (merged) patch
180     bool keepPatches                // Keep the original patches - they will be emptied
183     const geometricSurfacePatchList& origPatches = origSurf.patches();
184     const LongList<labelledTri>& origFacets = origSurf.facets();
186     label newPatchId = origPatches.size();
188     // Determine new patch type
189     word newPatchType = origPatches[patchIds[0]].geometricType();
191     // Create patch addressing
192     List<DynamicList<label> > patchAddr(origPatches.size()+1);
194     forAll(origFacets, faceI)
195     {
196         patchAddr[origFacets[faceI].region()].append(faceI);
197     }
199     // Move selected patches to new patch
200     forAll(patchIds, patchI)
201     {
202         patchAddr[newPatchId].append(patchAddr[patchIds[patchI]]);
203         patchAddr[patchIds[patchI]].clear();
204     }
206     // Create new facets list
207     LongList<labelledTri> newFacets(origFacets.size());
208     labelList newFaceAddr(origFacets.size(), -1);
210     label patchCount = 0;
211     label faceI = 0;
212     forAll(patchAddr, patchI)
213     {
214         const unallocLabelList& addr = patchAddr[patchI];
216         if(addr.size())
217         {
218             forAll(addr, i)
219             {
220                 newFacets[faceI] = origFacets[addr[i]];
221                 newFacets[faceI].region() = patchCount;
223                 newFaceAddr[addr[i]] = faceI;
225                 faceI++;
226             }
227         }
229         if(addr.size() || keepPatches)
230         {
231             patchCount++;
232         }
233     }
235     // Create new patch list
236     geometricSurfacePatchList newPatches(patchCount);
238     patchCount = 0;
239     forAll(origPatches, patchI)
240     {
241         // Only add patches if they contain faces
242         if(patchAddr[patchI].size())
243         {
244             newPatches[patchCount] = origPatches[patchI];
245             newPatches[patchCount].index() = patchCount;
246         }
248         if(patchAddr[patchI].size() || keepPatches)
249         {
250             patchCount++;
251         }
252     }
254     // Add new patch if it contains faces
255     if(patchAddr[patchAddr.size()-1].size())
256     {
257         newPatches[patchCount] = geometricSurfacePatch
258         (
259             newPatchType,
260             newPatchName,
261             patchCount
262         );
263     }
264     if(patchAddr[patchAddr.size()-1].size() || keepPatches)
265     {
266         patchCount++;
267     }
269     // Create new surface
270     autoPtr<triSurf> newSurf
271     (
272         new triSurf
273         (
274             newFacets,
275             newPatches,
276             origSurf.featureEdges(),
277             origSurf.points()
278         )
279     );
281     // Transfer face subsets
282     copyFaceSubsets(origSurf, newSurf());
283     newSurf->updateFacetsSubsets(newFaceAddr);
285     // Transfer feature edge subsets
286     copyEdgeSubsets(origSurf, newSurf());
288     // Transfer point subsets
289     copyPointSubsets(origSurf, newSurf());
291     // Done
292     return newSurf;
295 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
297 int main(int argc, char *argv[])
299     argList::noParallel();
300     argList::validArgs.clear();
302     argList::validArgs.append("input surface file");
303     argList::validArgs.append("new patch");
304     argList::validOptions.insert("patchNames", "list of names");
305     argList::validOptions.insert("patchIds", "list of patchIds");
306     argList::validOptions.insert("patchIdRange", "( start end )");
307     argList::validOptions.insert("output", "file name (default overwrite)");
308     argList::validOptions.insert("keep", "");
309     argList args(argc, argv);
311     // Process commandline arguments
312     fileName inFileName(args.args()[1]);
314     word newPatchName(args.args()[2]);
316     fileName outFileName(inFileName);
318     if( args.options().found("output") )
319     {
320         outFileName = args.options()["output"];
321     }
323     bool keepPatches = false;
325     if( args.options().found("keep") )
326     {
327         keepPatches = true;
328     }
330     // Read original surface
331     triSurf origSurf(inFileName);
333     // Get patch ids
334     DynamicList<label> patchIds;
336     if (args.options().found("patchNames"))
337     {
338         if (args.options().found("patchIds"))
339         {
340             FatalError() << "Cannot specify both patch names and ids"
341                 << Foam::abort(FatalError);
342         }
344         IStringStream is(args.options()["patchNames"]);
345         wordList patchNames(is);
347         getPatchIds
348         (
349             origSurf,
350             patchNames,
351             patchIds
352         );
353     }
354     if (args.options().found("patchIds"))
355     {
356         IStringStream is(args.options()["patchIds"]);
358         patchIds = labelList(is);
359     }
360     if (args.options().found("patchIds"))
361     {
362         IStringStream is(args.options()["patchIds"]);
364         patchIds.append(labelList(is));
365     }
366     if (args.options().found("patchIdRange"))
367     {
368         IStringStream is(args.options()["patchIdRange"]);
370         Pair<label> idRange(is);
372         for(label id = idRange.first(); id <= idRange.second(); id++)
373         {
374             patchIds.append(id);
375         }
376     }
377     if (!patchIds.size())
378     {
379         FatalError() << "No patches specified"
380             << Foam::abort(FatalError);
381     }
383     // Merge patches
384     autoPtr<triSurf> newSurf = mergeSurfacePatches
385     (
386         origSurf,
387         patchIds,
388         newPatchName,
389         keepPatches
390     );
392     // Write new surface mesh
393     newSurf->writeSurface(outFileName);
395     Info << "Original surface patches: " << origSurf.patches().size() << endl;
396     Info << "Final surface patches: " << newSurf->patches().size() << endl;
397     Info << "Surface written to " << outFileName <<  endl;
399     Info << "End\n" << endl;
401     return 0;
404 // ************************************************************************* //