mirror of
https://github.com/OpenFOAM/OpenFOAM-6.git
synced 2025-12-08 06:57:46 +00:00
Add the OpenFOAM source tree
This commit is contained in:
125
applications/test/router/Gather/Gather.C
Normal file
125
applications/test/router/Gather/Gather.C
Normal file
@ -0,0 +1,125 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
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 "Gather.H"
|
||||
#include "IPstream.H"
|
||||
#include "OPstream.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
// Construct from component
|
||||
template<class T0>
|
||||
Gather<T0>::Gather(const T0& localData, const bool redistribute)
|
||||
:
|
||||
List<T0>(0),
|
||||
nProcs_(max(1, Pstream::nProcs()))
|
||||
{
|
||||
this->setSize(nProcs_);
|
||||
|
||||
//
|
||||
// Collect sizes on all processor
|
||||
//
|
||||
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
if (Pstream::master())
|
||||
{
|
||||
this->operator[](0) = localData;
|
||||
|
||||
// Receive data
|
||||
for
|
||||
(
|
||||
int slave = Pstream::firstSlave(), procIndex = 1;
|
||||
slave <= Pstream::lastSlave();
|
||||
slave++, procIndex++
|
||||
)
|
||||
{
|
||||
IPstream fromSlave(Pstream::scheduled, slave);
|
||||
fromSlave >> this->operator[](procIndex);
|
||||
}
|
||||
|
||||
// Send data
|
||||
for
|
||||
(
|
||||
int slave = Pstream::firstSlave(), procIndex = 1;
|
||||
slave <= Pstream::lastSlave();
|
||||
slave++, procIndex++
|
||||
)
|
||||
{
|
||||
OPstream toSlave(Pstream::scheduled, slave);
|
||||
|
||||
if (redistribute)
|
||||
{
|
||||
toSlave << *this;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Dummy send just to balance sends/receives
|
||||
toSlave << 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Slave: send my local data to master
|
||||
{
|
||||
OPstream toMaster(Pstream::scheduled, Pstream::masterNo());
|
||||
toMaster << localData;
|
||||
}
|
||||
|
||||
// Receive data from master
|
||||
{
|
||||
IPstream fromMaster(Pstream::scheduled, Pstream::masterNo());
|
||||
if (redistribute)
|
||||
{
|
||||
fromMaster >> *this;
|
||||
}
|
||||
else
|
||||
{
|
||||
label dummy;
|
||||
fromMaster >> dummy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->operator[](0) = localData;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
96
applications/test/router/Gather/Gather.H
Normal file
96
applications/test/router/Gather/Gather.H
Normal file
@ -0,0 +1,96 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
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/>.
|
||||
|
||||
Class
|
||||
Foam::Gather
|
||||
|
||||
Description
|
||||
Gather data from all processors onto all processors.
|
||||
|
||||
SourceFiles
|
||||
Gather.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Gather_H
|
||||
#define Gather_H
|
||||
|
||||
#include "List.H"
|
||||
#include "labelList.H"
|
||||
#include "GatherBase.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class Gather Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class T0>
|
||||
class Gather
|
||||
:
|
||||
public GatherBase,
|
||||
public List<T0>
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- Number of processors (1 for sequential)
|
||||
label nProcs_;
|
||||
|
||||
//- Storage of type 0
|
||||
//List<T0> data0_;
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from containers across processors
|
||||
Gather(const T0&, const bool redistribute=true);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// const List<T0>& data0() const
|
||||
// {
|
||||
// return data0_;
|
||||
// }
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
# include "Gather.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
116
applications/test/router/Gather/GatherBase.C
Normal file
116
applications/test/router/Gather/GatherBase.C
Normal file
@ -0,0 +1,116 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
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/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "GatherBase.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Type GatherBase::flatten(const List<Type> lst)
|
||||
{
|
||||
label sum = 0;
|
||||
|
||||
forAll(lst, lstI)
|
||||
{
|
||||
sum += lst[lstI].size();
|
||||
}
|
||||
|
||||
Type result(sum);
|
||||
|
||||
label index = 0;
|
||||
|
||||
forAll(lst, lstI)
|
||||
{
|
||||
const Type& sub = lst[lstI];
|
||||
|
||||
forAll(sub, subI)
|
||||
{
|
||||
result[index++] = sub[subI];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template<class DataType, class IndexType, class AddOp>
|
||||
IndexType GatherBase::offset
|
||||
(
|
||||
const List<DataType>& values,
|
||||
const List<IndexType>& indices,
|
||||
AddOp aop
|
||||
)
|
||||
{
|
||||
if (values.size() != indices.size())
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"GatherBase::offset(const List<DataType>&, "
|
||||
"const List<IndexType>&, AddOp)"
|
||||
) << "Input data and indices lists not equal size." << endl
|
||||
<< "data size:" << values.size()
|
||||
<< " indices:" << indices.size()
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
|
||||
label sum = 0;
|
||||
|
||||
forAll(indices, lstI)
|
||||
{
|
||||
sum += indices[lstI].size();
|
||||
}
|
||||
|
||||
IndexType result(sum);
|
||||
|
||||
label index = 0;
|
||||
|
||||
label offset = 0;
|
||||
|
||||
forAll(indices, lstI)
|
||||
{
|
||||
const IndexType& sub = indices[lstI];
|
||||
|
||||
forAll(sub, subI)
|
||||
{
|
||||
result[index++] = aop(sub[subI], offset);
|
||||
}
|
||||
offset += values[lstI].size();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
102
applications/test/router/Gather/GatherBase.H
Normal file
102
applications/test/router/Gather/GatherBase.H
Normal file
@ -0,0 +1,102 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
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/>.
|
||||
|
||||
Class
|
||||
Foam::GatherBase
|
||||
|
||||
Description
|
||||
|
||||
SourceFiles
|
||||
GatherBase.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef GatherBase_H
|
||||
#define GatherBase_H
|
||||
|
||||
#include "List.H"
|
||||
#include "labelList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class GatherBase Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class GatherBase
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//- Flatten: appends all elements of list into one single list.
|
||||
// Used to collapse 'Gathered' data.
|
||||
template<class T>
|
||||
static T flatten(const List<T>);
|
||||
|
||||
//- Flatten and offset 'Gathered' indices (into value) so they
|
||||
// remain valid with respect to values (after they have been flattened)
|
||||
template<class DataType, class IndexType, class AddOp>
|
||||
static IndexType offset
|
||||
(
|
||||
const List<DataType>& values,
|
||||
const List<IndexType>& indices,
|
||||
AddOp aop
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
template<class T>
|
||||
class AddOp
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
T operator()
|
||||
(
|
||||
const T& x,
|
||||
const label offset
|
||||
) const
|
||||
{
|
||||
return x + offset;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
# include "GatherBase.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
4
applications/test/router/Make/files
Normal file
4
applications/test/router/Make/files
Normal file
@ -0,0 +1,4 @@
|
||||
router.C
|
||||
Test-processorRouter.C
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-processorRouter
|
||||
6
applications/test/router/Make/options
Normal file
6
applications/test/router/Make/options
Normal file
@ -0,0 +1,6 @@
|
||||
EXE_INC = \
|
||||
-IGather \
|
||||
-I$(LIB_SRC)/finiteVolume/lnInclude
|
||||
|
||||
EXE_LIBS = \
|
||||
-lfiniteVolume
|
||||
253
applications/test/router/Test-processorRouter.C
Normal file
253
applications/test/router/Test-processorRouter.C
Normal file
@ -0,0 +1,253 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
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 "OStringStream.H"
|
||||
#include "IStringStream.H"
|
||||
#include "OFstream.H"
|
||||
#include "IFstream.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)
|
||||
{
|
||||
if (isA<processorPolyPatch>(mesh.boundaryMesh()[patchI]))
|
||||
{
|
||||
const polyPatch& patch = mesh.boundaryMesh()[patchI];
|
||||
|
||||
const processorPolyPatch& procPatch =
|
||||
refCast<const processorPolyPatch>(patch);
|
||||
|
||||
label procId = procPatch.neighbProcNo() - Pstream::firstSlave() + 1;
|
||||
|
||||
neighbours[nNeighbours++] = procId;
|
||||
}
|
||||
}
|
||||
|
||||
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 "createMesh.H"
|
||||
|
||||
word procLabel = '[' + word(name(Pstream::myProcNo())) + "]-";
|
||||
|
||||
if (!Pstream::parRun())
|
||||
{
|
||||
FatalErrorIn(args.executable())
|
||||
<< "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;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
405
applications/test/router/router.C
Normal file
405
applications/test/router/router.C
Normal file
@ -0,0 +1,405 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
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 "router.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::label Foam::router::count(const label weight) const
|
||||
{
|
||||
label cnt = 0;
|
||||
|
||||
forAll(weights_, nodeI)
|
||||
{
|
||||
cnt += weights_[nodeI];
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
// Given connections between nodes set minimum distance from nodeI
|
||||
void Foam::router::setWeights
|
||||
(
|
||||
const label weight,
|
||||
const label nodeI
|
||||
)
|
||||
{
|
||||
// Set weight at current node
|
||||
weights_[nodeI] = weight;
|
||||
|
||||
const labelList& myNeighbours = connections_[nodeI];
|
||||
|
||||
forAll(myNeighbours, neighbourI)
|
||||
{
|
||||
if (weights_[myNeighbours[neighbourI]] > weight + 1)
|
||||
{
|
||||
// Distribute weight+1 to neighbours
|
||||
setWeights
|
||||
(
|
||||
weight+1,
|
||||
myNeighbours[neighbourI]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Mark shortest path from endNode to startNode by setting the weights
|
||||
// to 0.
|
||||
void Foam::router::fixWeights
|
||||
(
|
||||
const label startNodeI,
|
||||
const label endNodeI,
|
||||
|
||||
const label nodeI,
|
||||
const label prevNodeI
|
||||
)
|
||||
{
|
||||
// Mark this node
|
||||
weights_[nodeI] = 0;
|
||||
|
||||
label minNodeI = -1;
|
||||
label minDist = labelMax;
|
||||
label nMinNodes = 0;
|
||||
|
||||
const labelList& myNeighbours = connections_[nodeI];
|
||||
|
||||
forAll(myNeighbours, neighbourI)
|
||||
{
|
||||
label nbrNodeI = myNeighbours[neighbourI];
|
||||
|
||||
if (nbrNodeI != prevNodeI)
|
||||
{
|
||||
if (weights_[nbrNodeI] == 0)
|
||||
{
|
||||
// Reached end
|
||||
minDist = 0;
|
||||
break;
|
||||
}
|
||||
else if (weights_[nbrNodeI] > 0)
|
||||
{
|
||||
if (weights_[nbrNodeI] < minDist)
|
||||
{
|
||||
minDist = weights_[nbrNodeI];
|
||||
minNodeI = nbrNodeI;
|
||||
nMinNodes = 1;
|
||||
}
|
||||
else if (weights_[nbrNodeI] == minDist)
|
||||
{
|
||||
nMinNodes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (minDist == 0)
|
||||
{
|
||||
// Reached starting point.
|
||||
return;
|
||||
}
|
||||
|
||||
if (minNodeI == -1)
|
||||
{
|
||||
WarningIn
|
||||
(
|
||||
"Foam::router::fixWeights"
|
||||
"(const label startNodeI, const label endNodeI,"
|
||||
"const label nodeI, const label prevNodeI)"
|
||||
) << "Cannot route from node " << nodeI
|
||||
<< " since all neigbours of node "
|
||||
<< "already allocated:" << endl;
|
||||
|
||||
forAll(myNeighbours, neighbourI)
|
||||
{
|
||||
label nbrNodeI = myNeighbours[neighbourI];
|
||||
|
||||
WarningIn
|
||||
(
|
||||
"Foam::router::fixWeights"
|
||||
"(const label startNodeI, const label endNodeI,"
|
||||
"const label nodeI, const label prevNodeI)"
|
||||
) << " neighbour:" << nbrNodeI
|
||||
<< " weight:" << weights_[nbrNodeI] << endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (nMinNodes > 1)
|
||||
{
|
||||
// Multiple paths, all with same weight. Use some heuristic
|
||||
// to choose one. Here: smallest angle to vector end-start
|
||||
vector n(coords_[endNodeI] - coords_[startNodeI]);
|
||||
|
||||
scalar maxCosAngle = -GREAT;
|
||||
|
||||
forAll(myNeighbours, neighbourI)
|
||||
{
|
||||
label nbrNodeI = myNeighbours[neighbourI];
|
||||
|
||||
if (weights_[nbrNodeI] == minDist)
|
||||
{
|
||||
vector n2(coords_[nbrNodeI] - coords_[startNodeI]);
|
||||
|
||||
scalar magN2 = mag(n2);
|
||||
|
||||
if (magN2 > SMALL)
|
||||
{
|
||||
n2 /= mag(n2);
|
||||
|
||||
scalar cosAngle = n & n2;
|
||||
|
||||
if (cosAngle > maxCosAngle)
|
||||
{
|
||||
maxCosAngle = cosAngle;
|
||||
minNodeI = nbrNodeI;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Recursively go mark the path at minNode
|
||||
fixWeights
|
||||
(
|
||||
startNodeI,
|
||||
endNodeI,
|
||||
minNodeI,
|
||||
nodeI
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::router::getValue(const label pathValue) const
|
||||
{
|
||||
forAll(weights_, nodeI)
|
||||
{
|
||||
if (weights_[nodeI] == pathValue)
|
||||
{
|
||||
return nodeI;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// Find node which has no neighbours with pathValue
|
||||
Foam::label Foam::router::findEndNode
|
||||
(
|
||||
const label startNodeI,
|
||||
const label prevNodeI,
|
||||
const label pathValue
|
||||
) const
|
||||
{
|
||||
const labelList& myNeighbours = connections_[startNodeI];
|
||||
|
||||
forAll(myNeighbours, neighbourI)
|
||||
{
|
||||
label nodeI = myNeighbours[neighbourI];
|
||||
|
||||
if (nodeI != prevNodeI)
|
||||
{
|
||||
if (weights_[nodeI] == pathValue)
|
||||
{
|
||||
return findEndNode(nodeI, startNodeI, pathValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No neighbours with pathValue found. Return this node
|
||||
return startNodeI;
|
||||
}
|
||||
|
||||
|
||||
// Append all pathValue weights to route.
|
||||
void Foam::router::storeRoute
|
||||
(
|
||||
const label startNodeI,
|
||||
const label prevNodeI,
|
||||
const label pathValue,
|
||||
DynamicList<label>& route
|
||||
) const
|
||||
{
|
||||
const labelList& myNeighbours = connections_[startNodeI];
|
||||
|
||||
forAll(myNeighbours, neighbourI)
|
||||
{
|
||||
label nodeI = myNeighbours[neighbourI];
|
||||
|
||||
if (nodeI != prevNodeI)
|
||||
{
|
||||
if (weights_[nodeI] == pathValue)
|
||||
{
|
||||
route.append(nodeI);
|
||||
|
||||
storeRoute
|
||||
(
|
||||
nodeI,
|
||||
startNodeI,
|
||||
pathValue,
|
||||
route
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
// Construct from connections, route later
|
||||
Foam::router::router
|
||||
(
|
||||
const labelListList& connections,
|
||||
const List<point>& coords
|
||||
)
|
||||
:
|
||||
connections_(connections),
|
||||
coords_(coords),
|
||||
weights_(coords.size(), 0)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::router::route(const labelList& path, const label pathValue)
|
||||
{
|
||||
if (pathValue >= 0)
|
||||
{
|
||||
FatalErrorIn("router::route(const labelList&, const label)")
|
||||
<< "Illegal pathValue " << pathValue << exit(FatalError);
|
||||
}
|
||||
|
||||
// Reset all non-allocated weights to maximum distance
|
||||
forAll(weights_, nodeI)
|
||||
{
|
||||
if (weights_[nodeI] >= 0)
|
||||
{
|
||||
weights_[nodeI] = labelMax;
|
||||
}
|
||||
}
|
||||
|
||||
if (weights_[path[0]] < 0)
|
||||
{
|
||||
// Already used
|
||||
return false;
|
||||
}
|
||||
// Get weights according to distance to starting node
|
||||
setWeights(0, path[0]);
|
||||
|
||||
// Check if all endPoints can be reached
|
||||
for (label leafI = 1; leafI < path.size(); leafI++)
|
||||
{
|
||||
if (weights_[path[leafI]] == labelMax)
|
||||
{
|
||||
//Info<< "Cannot route leaf from " << path[0]
|
||||
// << " to " << path[leafI] << " of path " << path
|
||||
// << " since there is no valid route between them" << endl;
|
||||
|
||||
// Do not fix any paths but return
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Search back from all endpoints to start and fix weights
|
||||
for (label leafI = 1; leafI < path.size(); leafI++)
|
||||
{
|
||||
fixWeights
|
||||
(
|
||||
path[0],
|
||||
path[leafI],
|
||||
path[leafI],
|
||||
-1
|
||||
);
|
||||
|
||||
if (leafI < path.size() - 1)
|
||||
{
|
||||
// Update distance to take new connections into account
|
||||
forAll(weights_, nodeI)
|
||||
{
|
||||
if (weights_[nodeI]== 0)
|
||||
{
|
||||
// Include these nodes in distance calculation
|
||||
setWeights(0, nodeI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// All nodes on the path will now have value 0.
|
||||
// Mark these nodes with the (negative) pathvalue
|
||||
forAll(weights_, nodeI)
|
||||
{
|
||||
if (weights_[nodeI] == 0)
|
||||
{
|
||||
weights_[nodeI] = pathValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset unallocated weights to 0
|
||||
forAll(weights_, nodeI)
|
||||
{
|
||||
if (weights_[nodeI] > 0)
|
||||
{
|
||||
weights_[nodeI] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Foam::labelList Foam::router::getRoute(const label pathValue) const
|
||||
{
|
||||
// Find a starting point
|
||||
label pathNodeI = getValue(pathValue);
|
||||
|
||||
if (pathNodeI == -1)
|
||||
{
|
||||
FatalErrorIn("router::getRoute(const label)")
|
||||
<< "No route with value " << pathValue << endl;
|
||||
}
|
||||
|
||||
// Find end or start by walking
|
||||
label startNodeI = findEndNode(pathNodeI, -1, pathValue);
|
||||
|
||||
// Walk to other end and store
|
||||
|
||||
DynamicList<label> route(weights_.size());
|
||||
|
||||
route.append(startNodeI);
|
||||
|
||||
storeRoute(startNodeI, -1, pathValue, route);
|
||||
|
||||
route.shrink();
|
||||
|
||||
return route;
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
211
applications/test/router/router.H
Normal file
211
applications/test/router/router.H
Normal file
@ -0,0 +1,211 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
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/>.
|
||||
|
||||
Class
|
||||
Foam::router
|
||||
|
||||
Description
|
||||
Lee's PCB routing algorithm. Construct with list of connections between
|
||||
nodes (i.e. topology) and list of coordinates of nodes (can be vector::zero)
|
||||
|
||||
Use e.g.
|
||||
|
||||
// Enter topology/geometry
|
||||
router cellRouter
|
||||
(
|
||||
mesh().cellCells(),
|
||||
mesh().cellCentres()
|
||||
);
|
||||
|
||||
// Try to route connections one by one. Specify unique value (<0) to
|
||||
// mark path with.
|
||||
forAll(wantedConnections, i)
|
||||
{
|
||||
bool success = cellRouter.route(wantedConnections[i], -(i+1));
|
||||
}
|
||||
|
||||
|
||||
The coordinates are only used at the moment for diagonal preference of
|
||||
routing:
|
||||
|
||||
So not:
|
||||
|
||||
+A
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
------+B
|
||||
|
||||
But:
|
||||
|
||||
+ A
|
||||
|_
|
||||
|_
|
||||
|_
|
||||
|_
|
||||
|
|
||||
+ B
|
||||
|
||||
|
||||
Lee algo: take array with same dimensions as grid of nodes. Initialize to
|
||||
large number. Put 0 at starting point. Now recursively assign neighbours
|
||||
as current value plus one. Stop if you hit node which has smaller number.
|
||||
Phase two is where you search path with lowest value. These are assigned
|
||||
negative number so they for next route are not overwritten.
|
||||
|
||||
SourceFiles
|
||||
router.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef router_H
|
||||
#define router_H
|
||||
|
||||
#include "labelList.H"
|
||||
#include "pointField.H"
|
||||
#include "DynamicList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class router Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class router
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- Connections
|
||||
const labelListList connections_;
|
||||
|
||||
//- Coordinates of nodes
|
||||
const pointField coords_;
|
||||
|
||||
//- Routing table
|
||||
labelList weights_;
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Return number of weights. Utility function
|
||||
label count(const label weight) const;
|
||||
|
||||
//- Set distance from nodeI
|
||||
void setWeights
|
||||
(
|
||||
const label weight,
|
||||
const label nodeI
|
||||
);
|
||||
|
||||
//- Finds path from nodeI to startNodeI by travelling in direction
|
||||
// of lowest weight
|
||||
void fixWeights
|
||||
(
|
||||
const label startNodeI,
|
||||
const label endNodeI,
|
||||
const label nodeI,
|
||||
const label prevNodeI
|
||||
);
|
||||
|
||||
//- Routes single path
|
||||
bool shortestPath
|
||||
(
|
||||
const labelList& path,
|
||||
const label pathValue
|
||||
);
|
||||
|
||||
//- Linear search for element with weight
|
||||
label getValue(const label) const;
|
||||
|
||||
//- Find node which has no neighbours with pathValue
|
||||
label findEndNode
|
||||
(
|
||||
const label startNodeI,
|
||||
const label prevNodeI,
|
||||
const label pathValue
|
||||
) const;
|
||||
|
||||
//- Append all pathValue weights to route.
|
||||
void storeRoute
|
||||
(
|
||||
const label startNodeI,
|
||||
const label prevNodeI,
|
||||
const label pathValue,
|
||||
DynamicList<label>& route
|
||||
) const;
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
router(const router&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const router&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from connections, route later.
|
||||
router
|
||||
(
|
||||
const labelListList& connections,
|
||||
const List<point>& coords
|
||||
);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
const labelList& weights() const
|
||||
{
|
||||
return weights_;
|
||||
}
|
||||
|
||||
// Edit
|
||||
|
||||
//- Find path from first element in path to all other elements
|
||||
// Mark resulting path in weights with (negative) pathValue.
|
||||
// Returns false and does not mark any elements if cannot route.
|
||||
bool route(const labelList& path, const label pathValue);
|
||||
|
||||
//- Extract labels of route with given value.
|
||||
labelList getRoute(const label pathValue) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
27
applications/test/router/routerDict
Normal file
27
applications/test/router/routerDict
Normal file
@ -0,0 +1,27 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: dev |
|
||||
| \\ / A nd | Web: www.OpenFOAM.org |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
object routeDict;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Connected cells
|
||||
paths
|
||||
(
|
||||
(0 11)
|
||||
(0 4)
|
||||
(1 2)
|
||||
(3 7)
|
||||
(5 6)
|
||||
);
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user