1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-2010 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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
28 Renumbers the cell list in order to reduce the bandwidth, reading and
29 renumbering all fields from all the time directories.
31 \*---------------------------------------------------------------------------*/
34 #include "IOobjectList.H"
36 #include "polyTopoChange.H"
37 #include "ReadFields.H"
38 #include "volFields.H"
39 #include "surfaceFields.H"
40 #include "bandCompression.H"
42 #include "SortableList.H"
43 #include "decompositionMethod.H"
44 #include "fvMeshSubset.H"
45 #include "zeroGradientFvPatchFields.H"
50 // Calculate band of matrix
51 label getBand(const labelList& owner, const labelList& neighbour)
55 forAll(neighbour, faceI)
57 label diff = neighbour[faceI] - owner[faceI];
68 // Return new to old cell numbering
69 labelList regionBandCompression
72 const labelList& cellToRegion
75 Pout<< "Determining cell order:" << endl;
77 labelList cellOrder(cellToRegion.size());
79 label nRegions = max(cellToRegion)+1;
81 labelListList regionToCells(invertOneToMany(nRegions, cellToRegion));
85 forAll(regionToCells, regionI)
87 Pout<< " region " << regionI << " starts at " << cellI << endl;
89 // Per region do a reordering.
90 fvMeshSubset subsetter(mesh);
91 subsetter.setLargeCellSubset(cellToRegion, regionI);
92 const fvMesh& subMesh = subsetter.subMesh();
93 labelList subCellOrder(bandCompression(subMesh.cellCells()));
95 const labelList& cellMap = subsetter.cellMap();
97 forAll(subCellOrder, i)
99 cellOrder[cellI++] = cellMap[subCellOrder[i]];
108 // Determine face order such that inside region faces are sorted
109 // upper-triangular but inbetween region faces are handled like boundary faces.
110 labelList regionFaceOrder
112 const primitiveMesh& mesh,
113 const labelList& cellOrder, // new to old cell
114 const labelList& cellToRegion // old cell to region
117 Pout<< "Determining face order:" << endl;
119 labelList reverseCellOrder(invert(cellOrder.size(), cellOrder));
121 labelList oldToNewFace(mesh.nFaces(), -1);
125 label prevRegion = -1;
127 forAll(cellOrder, newCellI)
129 label oldCellI = cellOrder[newCellI];
131 if (cellToRegion[oldCellI] != prevRegion)
133 prevRegion = cellToRegion[oldCellI];
134 Pout<< " region " << prevRegion << " internal faces start at "
138 const cell& cFaces = mesh.cells()[oldCellI];
140 SortableList<label> nbr(cFaces.size());
144 label faceI = cFaces[i];
146 if (mesh.isInternalFace(faceI))
148 // Internal face. Get cell on other side.
149 label nbrCellI = reverseCellOrder[mesh.faceNeighbour()[faceI]];
150 if (nbrCellI == newCellI)
152 nbrCellI = reverseCellOrder[mesh.faceOwner()[faceI]];
155 if (cellToRegion[oldCellI] != cellToRegion[cellOrder[nbrCellI]])
157 // Treat like external face. Do later.
160 else if (newCellI < nbrCellI)
167 // nbrCell is master. Let it handle this face.
173 // External face. Do later.
184 oldToNewFace[cFaces[nbr.indices()[i]]] = newFaceI++;
189 // Do region interfaces
190 label nRegions = max(cellToRegion)+1;
192 // Sort in increasing region
193 SortableList<label> sortKey(mesh.nFaces(), labelMax);
195 for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
197 label ownRegion = cellToRegion[mesh.faceOwner()[faceI]];
198 label neiRegion = cellToRegion[mesh.faceNeighbour()[faceI]];
200 if (ownRegion != neiRegion)
203 min(ownRegion, neiRegion)*nRegions
204 +max(ownRegion, neiRegion);
213 label key = sortKey[i];
222 Pout<< " faces inbetween region " << key/nRegions
223 << " and " << key%nRegions
224 << " start at " << newFaceI << endl;
228 oldToNewFace[sortKey.indices()[i]] = newFaceI++;
232 // Leave patch faces intact.
233 for (label faceI = newFaceI; faceI < mesh.nFaces(); faceI++)
235 oldToNewFace[faceI] = faceI;
239 // Check done all faces.
240 forAll(oldToNewFace, faceI)
242 if (oldToNewFace[faceI] == -1)
246 "polyDualMesh::getFaceOrder"
247 "(const labelList&, const labelList&, const label) const"
248 ) << "Did not determine new position"
249 << " for face " << faceI
250 << abort(FatalError);
255 return invert(mesh.nFaces(), oldToNewFace);
259 // cellOrder: old cell for every new cell
260 // faceOrder: old face for every new face. Ordering of boundary faces not
262 autoPtr<mapPolyMesh> reorderMesh
265 const labelList& cellOrder,
266 const labelList& faceOrder
269 labelList reverseCellOrder(invert(cellOrder.size(), cellOrder));
270 labelList reverseFaceOrder(invert(faceOrder.size(), faceOrder));
272 faceList newFaces(reorder(reverseFaceOrder, mesh.faces()));
278 reorder(reverseFaceOrder, mesh.faceOwner())
281 labelList newNeighbour
286 reorder(reverseFaceOrder, mesh.faceNeighbour())
290 // Check if any faces need swapping.
291 forAll(newNeighbour, faceI)
293 label own = newOwner[faceI];
294 label nei = newNeighbour[faceI];
298 newFaces[faceI].flip();
299 Swap(newOwner[faceI], newNeighbour[faceI]);
303 const polyBoundaryMesh& patches = mesh.boundaryMesh();
304 labelList patchSizes(patches.size());
305 labelList patchStarts(patches.size());
306 labelList oldPatchNMeshPoints(patches.size());
307 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());
319 Xfer<pointField>::null(),
322 xferMove(newNeighbour),
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::addBoolOption
371 "order cells into regions (using decomposition)"
373 argList::addBoolOption
376 "order points into internal and boundary points"
378 argList::addBoolOption
381 "write cellMap, faceMap, pointMap in polyMesh/"
384 # include "addRegionOption.H"
385 # include "addOverwriteOption.H"
386 # include "addTimeOptions.H"
388 # include "setRootCase.H"
389 # include "createTime.H"
390 runTime.functionObjects().off();
393 instantList Times = runTime.times();
395 // set startTime and endTime depending on -time and -latestTime options
396 # include "checkTimeOptions.H"
398 runTime.setTime(Times[startTime], startTime);
400 # include "createNamedMesh.H"
401 const word oldInstance = mesh.pointsInstance();
403 const bool blockOrder = args.optionFound("blockOrder");
406 Info<< "Ordering cells into regions (using decomposition);"
407 << " ordering faces into region-internal and region-external." << nl
411 const bool orderPoints = args.optionFound("orderPoints");
414 Info<< "Ordering points into internal and boundary points." << nl
418 const bool writeMaps = args.optionFound("writeMaps");
422 Info<< "Writing renumber maps (new to old) to polyMesh." << nl
426 const bool overwrite = args.optionFound("overwrite");
428 label band = getBand(mesh.faceOwner(), mesh.faceNeighbour());
430 Info<< "Mesh size: " << returnReduce(mesh.nCells(), sumOp<label>()) << nl
431 << "Band before renumbering: "
432 << returnReduce(band, maxOp<label>()) << nl << endl;
435 // Read parallel reconstruct maps
436 labelIOList cellProcAddressing
440 "cellProcAddressing",
441 mesh.facesInstance(),
442 polyMesh::meshSubDir,
444 IOobject::READ_IF_PRESENT
449 labelIOList faceProcAddressing
453 "faceProcAddressing",
454 mesh.facesInstance(),
455 polyMesh::meshSubDir,
457 IOobject::READ_IF_PRESENT
461 labelIOList pointProcAddressing
465 "pointProcAddressing",
466 mesh.pointsInstance(),
467 polyMesh::meshSubDir,
469 IOobject::READ_IF_PRESENT
473 labelIOList boundaryProcAddressing
477 "boundaryProcAddressing",
478 mesh.pointsInstance(),
479 polyMesh::meshSubDir,
481 IOobject::READ_IF_PRESENT
487 // Read objects in time directory
488 IOobjectList objects(mesh, runTime.timeName());
492 PtrList<volScalarField> vsFlds;
493 ReadFields(mesh, objects, vsFlds);
495 PtrList<volVectorField> vvFlds;
496 ReadFields(mesh, objects, vvFlds);
498 PtrList<volSphericalTensorField> vstFlds;
499 ReadFields(mesh, objects, vstFlds);
501 PtrList<volSymmTensorField> vsymtFlds;
502 ReadFields(mesh, objects, vsymtFlds);
504 PtrList<volTensorField> vtFlds;
505 ReadFields(mesh, objects, vtFlds);
507 // Read surface fields.
509 PtrList<surfaceScalarField> ssFlds;
510 ReadFields(mesh, objects, ssFlds);
512 PtrList<surfaceVectorField> svFlds;
513 ReadFields(mesh, objects, svFlds);
515 PtrList<surfaceSphericalTensorField> sstFlds;
516 ReadFields(mesh, objects, sstFlds);
518 PtrList<surfaceSymmTensorField> ssymtFlds;
519 ReadFields(mesh, objects, ssymtFlds);
521 PtrList<surfaceTensorField> stFlds;
522 ReadFields(mesh, objects, stFlds);
525 autoPtr<mapPolyMesh> map;
529 // Renumbering in two phases. Should be done in one so mapping of
530 // fields is done correctly!
532 // Read decomposePar dictionary
533 IOdictionary decomposeDict
540 IOobject::MUST_READ_IF_MODIFIED,
544 autoPtr<decompositionMethod> decomposePtr = decompositionMethod::New
549 labelList cellToRegion
551 decomposePtr().decompose
558 // For debugging: write out region
560 volScalarField cellDist
572 dimensionedScalar("cellDist", dimless, 0),
573 zeroGradientFvPatchScalarField::typeName
576 forAll(cellToRegion, cellI)
578 cellDist[cellI] = cellToRegion[cellI];
583 Info<< nl << "Written decomposition as volScalarField to "
584 << cellDist.name() << " for use in postprocessing."
588 // Use block based renumbering.
589 //labelList cellOrder(bandCompression(mesh.cellCells()));
590 labelList cellOrder(regionBandCompression(mesh, cellToRegion));
592 // Determine new to old face order with new cell numbering
609 map = reorderMesh(mesh, cellOrder, faceOrder);
613 // Use built-in renumbering.
615 polyTopoChange meshMod(mesh);
623 map = meshMod.changeMesh
627 true, // parallel sync
628 true, // cell ordering
629 orderPoints // point ordering
634 mesh.updateMesh(map);
637 if (cellProcAddressing.headerOk())
639 Info<< "Renumbering processor cell decomposition map "
640 << cellProcAddressing.name() << endl;
642 cellProcAddressing = labelList
644 UIndirectList<label>(cellProcAddressing, map().cellMap())
647 if (faceProcAddressing.headerOk())
649 Info<< "Renumbering processor face decomposition map "
650 << faceProcAddressing.name() << endl;
652 faceProcAddressing = labelList
654 UIndirectList<label>(faceProcAddressing, map().faceMap())
657 if (pointProcAddressing.headerOk())
659 Info<< "Renumbering processor point decomposition map "
660 << pointProcAddressing.name() << endl;
662 pointProcAddressing = labelList
664 UIndirectList<label>(pointProcAddressing, map().pointMap())
669 // Move mesh (since morphing might not do this)
670 if (map().hasMotionPoints())
672 mesh.movePoints(map().preMotionPoints());
676 band = getBand(mesh.faceOwner(), mesh.faceNeighbour());
678 Info<< "Band after renumbering: "
679 << returnReduce(band, maxOp<label>()) << nl << endl;
684 // Force edge calculation (since only reason that points would need to
688 label nTotPoints = returnReduce
693 label nTotIntPoints = returnReduce
695 mesh.nInternalPoints(),
699 label nTotEdges = returnReduce
704 label nTotIntEdges = returnReduce
706 mesh.nInternalEdges(),
709 label nTotInt0Edges = returnReduce
711 mesh.nInternal0Edges(),
714 label nTotInt1Edges = returnReduce
716 mesh.nInternal1Edges(),
720 Info<< "Points:" << nl
721 << " total : " << nTotPoints << nl
722 << " internal: " << nTotIntPoints << nl
723 << " boundary: " << nTotPoints-nTotIntPoints << nl
725 << " total : " << nTotEdges << nl
726 << " internal: " << nTotIntEdges << nl
727 << " internal using 0 boundary points: "
728 << nTotInt0Edges << nl
729 << " internal using 1 boundary points: "
730 << nTotInt1Edges-nTotInt0Edges << nl
731 << " internal using 2 boundary points: "
732 << nTotIntEdges-nTotInt1Edges << nl
733 << " boundary: " << nTotEdges-nTotIntEdges << nl
740 mesh.setInstance(oldInstance);
743 Info<< "Writing mesh to " << mesh.facesInstance() << endl;
746 if (cellProcAddressing.headerOk())
748 cellProcAddressing.instance() = mesh.facesInstance();
749 cellProcAddressing.write();
751 if (faceProcAddressing.headerOk())
753 faceProcAddressing.instance() = mesh.facesInstance();
754 faceProcAddressing.write();
756 if (pointProcAddressing.headerOk())
758 pointProcAddressing.instance() = mesh.facesInstance();
759 pointProcAddressing.write();
761 if (boundaryProcAddressing.headerOk())
763 boundaryProcAddressing.instance() = mesh.facesInstance();
764 boundaryProcAddressing.write();
775 mesh.facesInstance(),
776 polyMesh::meshSubDir,
789 mesh.facesInstance(),
790 polyMesh::meshSubDir,
803 mesh.facesInstance(),
804 polyMesh::meshSubDir,
814 Info<< "\nEnd.\n" << endl;
820 // ************************************************************************* //