1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM 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 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 Renumbers the cell list in order to reduce the bandwidth, reading and
30 renumbering all fields from all the time directories.
32 \*---------------------------------------------------------------------------*/
35 #include "IOobjectList.H"
37 #include "polyTopoChange.H"
38 #include "ReadFields.H"
39 #include "volFields.H"
40 #include "surfaceFields.H"
41 #include "bandCompression.H"
43 #include "SortableList.H"
44 #include "decompositionMethod.H"
45 #include "fvMeshSubset.H"
46 #include "zeroGradientFvPatchFields.H"
51 // Calculate band of matrix
52 label getBand(const labelList& owner, const labelList& neighbour)
56 forAll(neighbour, faceI)
58 label diff = neighbour[faceI] - owner[faceI];
69 // Return new to old cell numbering
70 labelList regionBandCompression
73 const labelList& cellToRegion
76 Pout<< "Determining cell order:" << endl;
78 labelList cellOrder(cellToRegion.size());
80 label nRegions = max(cellToRegion)+1;
82 labelListList regionToCells(invertOneToMany(nRegions, cellToRegion));
86 forAll(regionToCells, regionI)
88 Pout<< " region " << regionI << " starts at " << cellI << endl;
90 // Per region do a reordering.
91 fvMeshSubset subsetter(mesh);
92 subsetter.setLargeCellSubset(cellToRegion, regionI);
93 const fvMesh& subMesh = subsetter.subMesh();
94 labelList subCellOrder(bandCompression(subMesh.cellCells()));
96 const labelList& cellMap = subsetter.cellMap();
98 forAll(subCellOrder, i)
100 cellOrder[cellI++] = cellMap[subCellOrder[i]];
109 // Determine face order such that inside region faces are sorted
110 // upper-triangular but inbetween region faces are handled like boundary faces.
111 labelList regionFaceOrder
113 const primitiveMesh& mesh,
114 const labelList& cellOrder, // new to old cell
115 const labelList& cellToRegion // old cell to region
118 Pout<< "Determining face order:" << endl;
120 labelList reverseCellOrder(invert(cellOrder.size(), cellOrder));
122 labelList oldToNewFace(mesh.nFaces(), -1);
126 label prevRegion = -1;
128 forAll (cellOrder, newCellI)
130 label oldCellI = cellOrder[newCellI];
132 if (cellToRegion[oldCellI] != prevRegion)
134 prevRegion = cellToRegion[oldCellI];
135 Pout<< " region " << prevRegion << " internal faces start at "
139 const cell& cFaces = mesh.cells()[oldCellI];
141 SortableList<label> nbr(cFaces.size());
145 label faceI = cFaces[i];
147 if (mesh.isInternalFace(faceI))
149 // Internal face. Get cell on other side.
150 label nbrCellI = reverseCellOrder[mesh.faceNeighbour()[faceI]];
151 if (nbrCellI == newCellI)
153 nbrCellI = reverseCellOrder[mesh.faceOwner()[faceI]];
156 if (cellToRegion[oldCellI] != cellToRegion[cellOrder[nbrCellI]])
158 // Treat like external face. Do later.
161 else if (newCellI < nbrCellI)
168 // nbrCell is master. Let it handle this face.
174 // External face. Do later.
185 oldToNewFace[cFaces[nbr.indices()[i]]] = newFaceI++;
190 // Do region interfaces
191 label nRegions = max(cellToRegion)+1;
193 // Sort in increasing region
194 SortableList<label> sortKey(mesh.nFaces(), labelMax);
196 for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
198 label ownRegion = cellToRegion[mesh.faceOwner()[faceI]];
199 label neiRegion = cellToRegion[mesh.faceNeighbour()[faceI]];
201 if (ownRegion != neiRegion)
204 min(ownRegion, neiRegion)*nRegions
205 +max(ownRegion, neiRegion);
214 label key = sortKey[i];
223 Pout<< " faces inbetween region " << key/nRegions
224 << " and " << key%nRegions
225 << " start at " << newFaceI << endl;
229 oldToNewFace[sortKey.indices()[i]] = newFaceI++;
233 // Leave patch faces intact.
234 for (label faceI = newFaceI; faceI < mesh.nFaces(); faceI++)
236 oldToNewFace[faceI] = faceI;
240 // Check done all faces.
241 forAll(oldToNewFace, faceI)
243 if (oldToNewFace[faceI] == -1)
247 "polyDualMesh::getFaceOrder"
248 "(const labelList&, const labelList&, const label) const"
249 ) << "Did not determine new position"
250 << " for face " << faceI
251 << abort(FatalError);
256 return invert(mesh.nFaces(), oldToNewFace);
260 // cellOrder: old cell for every new cell
261 // faceOrder: old face for every new face. Ordering of boundary faces not
263 autoPtr<mapPolyMesh> reorderMesh
266 const labelList& cellOrder,
267 const labelList& faceOrder
270 labelList reverseCellOrder(invert(cellOrder.size(), cellOrder));
271 labelList reverseFaceOrder(invert(faceOrder.size(), faceOrder));
273 faceList newFaces(reorder(reverseFaceOrder, mesh.faces()));
279 reorder(reverseFaceOrder, mesh.faceOwner())
282 labelList newNeighbour
287 reorder(reverseFaceOrder, mesh.faceNeighbour())
291 // Check if any faces need swapping.
292 forAll(newNeighbour, faceI)
294 label own = newOwner[faceI];
295 label nei = newNeighbour[faceI];
299 newFaces[faceI] = newFaces[faceI].reverseFace();
300 Swap(newOwner[faceI], newNeighbour[faceI]);
304 const polyBoundaryMesh& patches = mesh.boundaryMesh();
305 labelList patchSizes(patches.size());
306 labelList patchStarts(patches.size());
307 labelList oldPatchNMeshPoints(patches.size());
308 labelListList patchPointMap(patches.size());
309 forAll(patches, patchI)
311 patchSizes[patchI] = patches[patchI].size();
312 patchStarts[patchI] = patches[patchI].start();
313 oldPatchNMeshPoints[patchI] = patches[patchI].nPoints();
314 patchPointMap[patchI] = identity(patches[patchI].nPoints());
328 return autoPtr<mapPolyMesh>
332 mesh, //const polyMesh& mesh,
333 mesh.nPoints(), // nOldPoints,
334 mesh.nFaces(), // nOldFaces,
335 mesh.nCells(), // nOldCells,
336 identity(mesh.nPoints()), // pointMap,
337 List<objectMap>(0), // pointsFromPoints,
338 faceOrder, // faceMap,
339 List<objectMap>(0), // facesFromPoints,
340 List<objectMap>(0), // facesFromEdges,
341 List<objectMap>(0), // facesFromFaces,
342 cellOrder, // cellMap,
343 List<objectMap>(0), // cellsFromPoints,
344 List<objectMap>(0), // cellsFromEdges,
345 List<objectMap>(0), // cellsFromFaces,
346 List<objectMap>(0), // cellsFromCells,
347 identity(mesh.nPoints()), // reversePointMap,
348 reverseFaceOrder, // reverseFaceMap,
349 reverseCellOrder, // reverseCellMap,
350 labelHashSet(0), // flipFaceFlux,
351 patchPointMap, // patchPointMap,
352 labelListList(0), // pointZoneMap,
353 labelListList(0), // faceZonePointMap,
354 labelListList(0), // faceZoneFaceMap,
355 labelListList(0), // cellZoneMap,
356 pointField(0), // preMotionPoints,
357 patchStarts, // oldPatchStarts,
358 oldPatchNMeshPoints // oldPatchNMeshPoints
364 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
366 int main(int argc, char *argv[])
368 argList::validOptions.insert("blockOrder", "");
369 argList::validOptions.insert("orderPoints", "");
370 argList::validOptions.insert("writeMaps", "");
371 argList::validOptions.insert("overwrite", "");
373 # include "addTimeOptions.H"
375 # include "setRootCase.H"
376 # include "createTime.H"
379 instantList Times = runTime.times();
381 // set startTime and endTime depending on -time and -latestTime options
382 # include "checkTimeOptions.H"
384 runTime.setTime(Times[startTime], startTime);
387 # include "createMesh.H"
390 const bool blockOrder = args.options().found("blockOrder");
394 Info<< "Ordering cells into regions (using decomposition);"
395 << " ordering faces into region-internal and region-external." << nl
399 const bool orderPoints = args.options().found("orderPoints");
403 Info<< "Ordering points into internal and boundary points." << nl
407 const bool writeMaps = args.options().found("writeMaps");
411 Info<< "Writing renumber maps (new to old) to polyMesh." << nl
415 bool overwrite = args.options().found("overwrite");
417 label band = getBand(mesh.faceOwner(), mesh.faceNeighbour());
419 Info<< "Mesh size: " << returnReduce(mesh.nCells(), sumOp<label>()) << nl
420 << "Band before renumbering: "
421 << returnReduce(band, maxOp<label>()) << nl << endl;
423 // Read objects in time directory
424 IOobjectList objects(mesh, runTime.timeName());
428 PtrList<volScalarField> vsFlds;
429 ReadFields(mesh, objects, vsFlds);
431 PtrList<volVectorField> vvFlds;
432 ReadFields(mesh, objects, vvFlds);
434 PtrList<volSphericalTensorField> vstFlds;
435 ReadFields(mesh, objects, vstFlds);
437 PtrList<volSymmTensorField> vsymtFlds;
438 ReadFields(mesh, objects, vsymtFlds);
440 PtrList<volTensorField> vtFlds;
441 ReadFields(mesh, objects, vtFlds);
443 // Read surface fields.
445 PtrList<surfaceScalarField> ssFlds;
446 ReadFields(mesh, objects, ssFlds);
448 PtrList<surfaceVectorField> svFlds;
449 ReadFields(mesh, objects, svFlds);
451 PtrList<surfaceSphericalTensorField> sstFlds;
452 ReadFields(mesh, objects, sstFlds);
454 PtrList<surfaceSymmTensorField> ssymtFlds;
455 ReadFields(mesh, objects, ssymtFlds);
457 PtrList<surfaceTensorField> stFlds;
458 ReadFields(mesh, objects, stFlds);
461 autoPtr<mapPolyMesh> map;
465 // Renumbering in two phases. Should be done in one so mapping of
466 // fields is done correctly!
468 // Read decomposePar dictionary
469 IOdictionary decomposeDict
480 autoPtr<decompositionMethod> decomposePtr = decompositionMethod::New
486 labelList cellToRegion(decomposePtr().decompose(mesh.cellCentres()));
488 // For debugging: write out region
490 volScalarField cellDist
502 dimensionedScalar("cellDist", dimless, 0),
503 zeroGradientFvPatchScalarField::typeName
506 forAll(cellToRegion, cellI)
508 cellDist[cellI] = cellToRegion[cellI];
513 Info<< nl << "Written decomposition as volScalarField to "
514 << cellDist.name() << " for use in postprocessing."
518 // Use block based renumbering.
519 //labelList cellOrder(bandCompression(mesh.cellCells()));
520 labelList cellOrder(regionBandCompression(mesh, cellToRegion));
522 // Determine new to old face order with new cell numbering
539 map = reorderMesh(mesh, cellOrder, faceOrder);
543 // Use built-in renumbering.
545 polyTopoChange meshMod(mesh);
553 map = meshMod.changeMesh
557 true, // parallel sync
558 true, // cell ordering
559 orderPoints // point ordering
564 mesh.updateMesh(map);
566 // Move mesh (since morphing might not do this)
567 if (map().hasMotionPoints())
569 mesh.movePoints(map().preMotionPoints());
573 band = getBand(mesh.faceOwner(), mesh.faceNeighbour());
575 Info<< "Band after renumbering: "
576 << returnReduce(band, maxOp<label>()) << nl << endl;
581 // Force edge calculation (since only reason that points would need to
585 label nTotPoints = returnReduce
590 label nTotIntPoints = returnReduce
592 mesh.nInternalPoints(),
596 label nTotEdges = returnReduce
601 label nTotIntEdges = returnReduce
603 mesh.nInternalEdges(),
606 label nTotInt0Edges = returnReduce
608 mesh.nInternal0Edges(),
611 label nTotInt1Edges = returnReduce
613 mesh.nInternal1Edges(),
617 Info<< "Points:" << nl
618 << " total : " << nTotPoints << nl
619 << " internal: " << nTotIntPoints << nl
620 << " boundary: " << nTotPoints-nTotIntPoints << nl
622 << " total : " << nTotEdges << nl
623 << " internal: " << nTotIntEdges << nl
624 << " internal using 0 boundary points: "
625 << nTotInt0Edges << nl
626 << " internal using 1 boundary points: "
627 << nTotInt1Edges-nTotInt0Edges << nl
628 << " internal using 2 boundary points: "
629 << nTotIntEdges-nTotInt1Edges << nl
630 << " boundary: " << nTotEdges-nTotIntEdges << nl
634 Info<< "Writing mesh to " << runTime.timeName() << endl;
645 mesh.facesInstance(),
646 polyMesh::meshSubDir,
659 mesh.facesInstance(),
660 polyMesh::meshSubDir,
673 mesh.facesInstance(),
674 polyMesh::meshSubDir,
684 Info<< "\nEnd.\n" << endl;
690 // ************************************************************************* //