Add the OpenFOAM source tree

This commit is contained in:
Henry
2014-12-10 22:40:10 +00:00
parent ee487c860d
commit 446e5777f0
13379 changed files with 3983377 additions and 0 deletions

View 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
// ************************************************************************* //

View 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
// ************************************************************************* //

View 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
// ************************************************************************* //

View 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
// ************************************************************************* //

View File

@ -0,0 +1,4 @@
router.C
Test-processorRouter.C
EXE = $(FOAM_USER_APPBIN)/Test-processorRouter

View File

@ -0,0 +1,6 @@
EXE_INC = \
-IGather \
-I$(LIB_SRC)/finiteVolume/lnInclude
EXE_LIBS = \
-lfiniteVolume

View 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;
}
// ************************************************************************* //

View 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;
}
// ************************************************************************* //

View 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
// ************************************************************************* //

View 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)
);
// ************************************************************************* //