openfoam/applications/test/router/Test-processorRouter.C
2023-04-21 15:49:27 +02:00

250 lines
6.2 KiB
C

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Description
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "label.H"
#include "labelList.H"
#include "Fstream.H"
#include "point.H"
#include "Time.H"
#include "fvMesh.H"
#include "router.H"
#include "processorPolyPatch.H"
#include "typeInfo.H"
#include "Gather.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Get list of my processor neighbours
labelList procNeighbours(const polyMesh& mesh)
{
word procLabel = '[' + word(name(Pstream::myProcNo())) + "]-";
label nNeighbours = 0;
forAll(mesh.boundaryMesh(), patchi)
{
if (isA<processorPolyPatch>(mesh.boundaryMesh()[patchi]))
{
++nNeighbours;
}
}
labelList neighbours(nNeighbours);
nNeighbours = 0;
forAll(mesh.boundaryMesh(), patchi)
{
const auto* procPatch =
isA<processorPolyPatch>(mesh.boundaryMesh()[patchi]);
if (procPatch)
{
neighbours[nNeighbours++] = procPatch->neighbProcNo();
}
}
return neighbours;
}
// Calculate some average position for mesh.
point meshCentre(const polyMesh& mesh)
{
return average(mesh.points());
}
// Main program:
int main(int argc, char *argv[])
{
#include "setRootCase.H"
#include "createTime.H"
#include "createPolyMesh.H"
word procLabel = '[' + word(name(Pstream::myProcNo())) + "]-";
if (!Pstream::parRun())
{
FatalErrorInFunction
<< "Please run in parallel" << exit(FatalError);
}
// 'Gather' processor-processor topology
Gather<labelList> connections
(
static_cast<const labelList&>(procNeighbours(mesh))
);
// Collect centres of individual meshes (for visualization only)
Gather<point> meshCentres(meshCentre(mesh));
if (!Pstream::master())
{
return 0;
}
//
// At this point we have the connections between processors and the
// processor-mesh centres.
//
Info<< "connections:" << connections << endl;
Info<< "meshCentres:" << meshCentres << endl;
//
// Dump connections and meshCentres to OBJ file
//
fileName fName("decomposition.obj");
Info<< "Writing decomposition to " << fName << endl;
OFstream objFile(fName);
// Write processors as single vertex in centre of mesh
forAll(meshCentres, proci)
{
const point& pt = meshCentres[proci];
objFile << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
}
// Write connections as lines between processors (duplicated)
forAll(connections, proci)
{
const labelList& nbs = connections[proci];
forAll(nbs, nbI)
{
objFile << "l " << proci + 1 << ' ' << nbs[nbI] + 1 << endl;
}
}
//
// Read paths to route from dictionary
//
IFstream dictFile("routerDict");
dictionary routeDict(dictFile);
labelListList paths(routeDict.lookup("paths"));
//
// Iterate over routing. Route as much as possible during each iteration
// and stop if all paths have been routed. No special ordering to maximize
// routing during one iteration.
//
boolList routeOk(paths.size(), false);
label nOk = 0;
label iter = 0;
while (nOk < paths.size())
{
Info<< "Iteration:" << iter << endl;
Info<< "---------------" << endl;
// Dump to OBJ file
fileName fName("route_" + name(iter) + ".obj");
Info<< "Writing route to " << fName << endl;
OFstream objFile(fName);
forAll(meshCentres, proci)
{
const point& pt = meshCentres[proci];
objFile << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z()
<< endl;
}
// Router
router cellRouter(connections, meshCentres);
// Try to route as many paths possible during this iteration.
forAll(paths, pathI)
{
if (!routeOk[pathI])
{
const labelList& path = paths[pathI];
Info<< "Trying to route path " << pathI
<< " nodes " << path << endl;
routeOk[pathI] = cellRouter.route(path, -(pathI + 1));
Info<< "Result of routing:" << routeOk[pathI] << endl;
if (routeOk[pathI])
{
nOk++;
// Dump route as lines.
labelList route(cellRouter.getRoute(-(pathI + 1)));
for (label elemI = 1; elemI < route.size(); elemI++)
{
objFile
<< "l " << route[elemI-1]+1 << ' '
<< route[elemI]+1 << endl;
}
Info<< "route:" << route << endl;
}
}
}
Info<< endl;
iter++;
}
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //