Commit 5f9656c6 authored by Thomas Witkowski's avatar Thomas Witkowski
Browse files

Added some documentation to parallel code.

parent 4354cab8
This diff is collapsed.
......@@ -31,138 +31,137 @@
#include "Global.h"
#include "Boundary.h"
#include "Serializer.h"
#include "FiniteElemSpace.h"
namespace AMDiS {
using namespace std;
/// Just to templatize the typedef.
template<typename T>
struct PerBoundMap
{
struct PerBoundMap {
typedef map<pair<T, T>, BoundaryType> type;
typedef typename type::iterator iterator;
};
/// Defines one element object. This may be either a vertex, edge or face.
struct ElementObjectData {
ElementObjectData(int a = -1, int b = 0, BoundaryType c = INTERIOR)
ElementObjectData(int a = -1, int b = 0)
: elIndex(a),
ithObject(b),
boundaryType(c)
ithObject(b)
{}
/// Index of the element this object is part of.
int elIndex;
/// Index of the object within the element.
int ithObject;
BoundaryType boundaryType;
/// Write this element object to disk.
void serialize(ostream &out) const
{
SerUtil::serialize(out, elIndex);
SerUtil::serialize(out, ithObject);
SerUtil::serialize(out, boundaryType);
}
/// Read this element object from disk.
void deserialize(istream &in)
{
SerUtil::deserialize(in, elIndex);
SerUtil::deserialize(in, ithObject);
SerUtil::deserialize(in, boundaryType);
}
/// Compare this element object with another one.
bool operator==(ElementObjectData& cmp) const
{
return (elIndex == cmp.elIndex &&
ithObject == cmp.ithObject &&
boundaryType == cmp.boundaryType);
return (elIndex == cmp.elIndex && ithObject == cmp.ithObject);
}
/// Define a strict order on element objects.
bool operator<(const ElementObjectData& rhs) const
{
return (elIndex < rhs.elIndex ||
(elIndex == rhs.elIndex &&
ithObject < rhs.ithObject));
return (elIndex < rhs.elIndex ||
(elIndex == rhs.elIndex && ithObject < rhs.ithObject));
}
};
/** \brief
* This class is a database of element objects. An element object is either a
* vertex, edge or the face of a specific element. This database is used to store
* all objects of all elements of a mesh. The information is stored in a way that
* makes it possible to identify all elements, which have a given vertex, edge or
* face in common. If is is known which element is owned by which rank in parallel
* computations, it is thus possible to get all interior boundaries on object
* level. This is required, because two elements may share a common vertex without
* beging neighbours in the definition of AMDiS.
*/
class ElementObjects {
public:
ElementObjects()
: iterGeoPos(CENTER)
: feSpace(NULL),
mesh(NULL),
iterGeoPos(CENTER)
{}
void addVertex(Element *el, int ith, BoundaryType bound = INTERIOR)
{
DegreeOfFreedom vertex = el->getDof(ith, 0);
int elIndex = el->getIndex();
ElementObjectData elObj(elIndex, ith, bound);
vertexElements[vertex].push_back(elObj);
vertexLocalMap[elObj] = vertex;
}
void addEdge(Element *el, int ith, BoundaryType bound = INTERIOR)
/// Set the finite element space that should be used for the database (especially
/// the mesh is of interest).
void setFeSpace(FiniteElemSpace *fe)
{
DofEdge edge = el->getEdge(ith);
int elIndex = el->getIndex();
ElementObjectData elObj(elIndex, ith, bound);
edgeElements[edge].push_back(elObj);
edgeLocalMap[elObj] = edge;
feSpace = fe;
mesh = feSpace->getMesh();
}
void addFace(Element *el, int ith, BoundaryType bound = INTERIOR)
{
DofFace face = el->getFace(ith);
int elIndex = el->getIndex();
ElementObjectData elObj(elIndex, ith, bound);
faceElements[face].push_back(elObj);
faceLocalMap[elObj] = face;
}
void addElement(Element *el, BoundaryType bound = INTERIOR)
{
for (int i = 0; i < el->getGeo(VERTEX); i++)
addVertex(el, i);
for (int i = 0; i < el->getGeo(EDGE); i++)
addEdge(el, i);
for (int i = 0; i < el->getGeo(FACE); i++)
addFace(el, i);
}
void addPeriodicVertex(pair<DegreeOfFreedom, DegreeOfFreedom> perVertex,
BoundaryType bType)
{
periodicVertices[perVertex] = bType;
}
void addPeriodicEdge(pair<DofEdge, DofEdge> perEdge, BoundaryType bType)
{
periodicEdges[perEdge] = bType;
}
void addPeriodicFace(pair<DofFace, DofFace> perFace, BoundaryType bType)
{
periodicFaces[perFace] = bType;
}
/** \brief
* Adds an element to the object database. If the element is part of a periodic
* boundary, all information about subobjects of the element on this boundary
* are collected.
*
* \param[in] elInfo ElInfo object of the element.
*/
void addElement(ElInfo *elInfo);
/** \brief
* Creates final data of the periodic boundaries. Must be called after all
* elements of the mesh are added to the object database. Then this functions
* search for interectly connected vertices in periodic boundaries. This is only
* the case, if there are more than one boundary conditions. Then, e.g., in 2D,
* all edges of a square are iterectly connected. In 3D, if the macro mesh is a
* box, all eight vertex nodes and always four of the 12 edges are iterectly
* connected.
*/
void createPeriodicData();
/** \brief
* Create for a filled object database the membership information for all element
* objects. An object is owned by a rank, if the rank has the heighest rank
* number of all ranks where the object is part of.
*
* \param[in] macroElementRankMap Maps to each macro element of the mesh the
* rank that owns this macro element.
*/
void createRankData(map<int, int>& macroElementRankMap);
/** \brief
* Iterates over all elements for one geometrical index, i.e., over all vertices,
* edges or faces in the mesh. The function returns true, if the result is valid.
* Otherwise the iterator is at the end position.
*
* \param[in] pos Must be either VERTEX, EDGE or FACE and defines the elements
* that should be traversed.
*/
bool iterate(GeoIndex pos)
{
// CENTER marks the variable "iterGeoPos" to be in an undefined state. I.e.,
// there is no iteration that is actually running.
if (iterGeoPos == CENTER) {
iterGeoPos = pos;
switch (iterGeoPos) {
......@@ -221,6 +220,7 @@ namespace AMDiS {
}
/// Returns the data of the current iterator position.
map<int, ElementObjectData>& getIterateData()
{
switch (iterGeoPos) {
......@@ -242,6 +242,7 @@ namespace AMDiS {
}
/// Returns the rank owner of the current iterator position.
int getIterateOwner()
{
switch (iterGeoPos) {
......@@ -263,121 +264,220 @@ namespace AMDiS {
}
/// Returns the rank owner of a vertex DOF.
int getOwner(DegreeOfFreedom vertex)
{
return vertexOwner[vertex];
}
/// Returns the rank owner of an edge.
int getOwner(DofEdge edge)
{
return edgeOwner[edge];
}
/// Returns the rank owner of an face.
int getOwner(DofFace face)
{
return faceOwner[face];
}
/// Checks if a given vertex DOF is in a given rank.
int isInRank(DegreeOfFreedom vertex, int rank)
{
return (vertexInRank[vertex].count(rank));
}
/// Checks if a given edge is in a given rank.
int isInRank(DofEdge edge, int rank)
{
return (edgeInRank[edge].count(rank));
}
/// Checks if a given face is in a given rank.
int isInRank(DofFace face, int rank)
{
return (faceInRank[face].count(rank));
}
/// Returns a vector with all macro elements that have a given vertex DOF in common.
vector<ElementObjectData>& getElements(DegreeOfFreedom vertex)
{
return vertexElements[vertex];
}
/// Returns a vector with all macro elements that have a given edge in common.
vector<ElementObjectData>& getElements(DofEdge edge)
{
return edgeElements[edge];
}
/// Returns a vector with all macro elements that have a given face in common.
vector<ElementObjectData>& getElements(DofFace face)
{
return faceElements[face];
}
/// Returns a map that maps to each rank all macro elements in this rank that
/// have a given vertex DOF in common.
map<int, ElementObjectData>& getElementsInRank(DegreeOfFreedom vertex)
{
return vertexInRank[vertex];
}
/// Returns a map that maps to each rank all macro elements in this rank that
/// have a given edge in common.
map<int, ElementObjectData>& getElementsInRank(DofEdge edge)
{
return edgeInRank[edge];
}
/// Returns a map that maps to each rank all macro elements in this rank that
/// have a given face in common.
map<int, ElementObjectData>& getElementsInRank(DofFace face)
{
return faceInRank[face];
}
/// Returns to an element object data the appropriate vertex DOF.
DegreeOfFreedom getVertexLocalMap(ElementObjectData &data)
{
return vertexLocalMap[data];
}
/// Returns to an element object data the appropriate edge.
DofEdge getEdgeLocalMap(ElementObjectData &data)
{
return edgeLocalMap[data];
}
/// Returns to an element object data the appropriate face.
DofFace getFaceLocalMap(ElementObjectData &data)
{
return faceLocalMap[data];
}
/// Write the element database to disk.
void serialize(ostream &out);
/// Read the element database from disk.
void deserialize(istream &in);
private:
protected:
/// Adds the i-th DOF vertex of an element to the object database.
void addVertex(Element *el, int ith)
{
DegreeOfFreedom vertex = el->getDof(ith, 0);
int elIndex = el->getIndex();
ElementObjectData elObj(elIndex, ith);
vertexElements[vertex].push_back(elObj);
vertexLocalMap[elObj] = vertex;
}
/// Adds the i-th edge of an element to the object database.
void addEdge(Element *el, int ith)
{
DofEdge edge = el->getEdge(ith);
int elIndex = el->getIndex();
ElementObjectData elObj(elIndex, ith);
edgeElements[edge].push_back(elObj);
edgeLocalMap[elObj] = edge;
}
/// Adds the i-th face of an element to the object database.
void addFace(Element *el, int ith)
{
DofFace face = el->getFace(ith);
int elIndex = el->getIndex();
ElementObjectData elObj(elIndex, ith);
faceElements[face].push_back(elObj);
faceLocalMap[elObj] = face;
}
/// Some auxiliary function to write the element object database to disk.
void serialize(ostream &out, vector<ElementObjectData>& elVec);
/// Some auxiliary function to read the element object database from disk.
void deserialize(istream &in, vector<ElementObjectData>& elVec);
/// Some auxiliary function to write the element object database to disk.
void serialize(ostream &out, map<int, ElementObjectData>& data);
/// Some auxiliary function to read the element object database from disk.
void deserialize(istream &in, map<int, ElementObjectData>& data);
private:
/// The used FE space.
FiniteElemSpace *feSpace;
/// The mesh that is used to store all its element information in the database.
Mesh *mesh;
/// Maps to each vertex DOF all element objects that represent this vertex.
map<DegreeOfFreedom, vector<ElementObjectData> > vertexElements;
/// Maps to each edge all element objects that represent this edge.
map<DofEdge, vector<ElementObjectData> > edgeElements;
map<DofFace, vector<ElementObjectData> > faceElements;
/// Maps to each face all element objects that represent this edge.
map<DofFace, vector<ElementObjectData> > faceElements;
/// Maps to an element object the corresponding vertex DOF.
map<ElementObjectData, DegreeOfFreedom> vertexLocalMap;
/// Maps to an element object the corresponding edge.
map<ElementObjectData, DofEdge> edgeLocalMap;
/// Maps to an element object the corresponding face.
map<ElementObjectData, DofFace> faceLocalMap;
/// Defines for all vertex DOFs the rank that ownes this vertex DOF.
map<DegreeOfFreedom, int> vertexOwner;
/// Defines for all edges the rank that ownes this edge.
map<DofEdge, int> edgeOwner;
/// Defines for all faces the rank that ownes this face.
map<DofFace, int> faceOwner;
/// Defines to each vertex DOF a map that maps to each rank number the element
/// objects that have this vertex DOF in common.
map<DegreeOfFreedom, map<int, ElementObjectData> > vertexInRank;
/// Defines to each edge a map that maps to each rank number the element objects
/// that have this edge in common.
map<DofEdge, map<int, ElementObjectData> > edgeInRank;
/// Defines to each face a map that maps to each rank number the element objects
/// that have this face in common.
map<DofFace, map<int, ElementObjectData> > faceInRank;
/// Vertex iterator to iterate over \ref vertexInRank
map<DegreeOfFreedom, map<int, ElementObjectData> >::iterator vertexIter;
/// Edge iterator to iterate over \ref edgeInRank
map<DofEdge, map<int, ElementObjectData> >::iterator edgeIter;
/// Face iterator to iterate over \ref faceInRank
map<DofFace, map<int, ElementObjectData> >::iterator faceIter;
/// Defines the geometrical iteration index of the iterators. I.e., the value
/// is either VERTEX, EDGE or FACE and the corresponding element objects are
/// traversed. The value CENTER is used to define a not defined states of the
/// iterators, i.e., if no iteration is running.
GeoIndex iterGeoPos;
public:
......@@ -385,6 +485,12 @@ namespace AMDiS {
PerBoundMap<DegreeOfFreedom>::type periodicVertices;
PerBoundMap<DofEdge>::type periodicEdges;
PerBoundMap<DofFace>::type periodicFaces;
// Stores to each vertex all its periodic associations.
std::map<DegreeOfFreedom, std::set<BoundaryType> > periodicDofAssoc;
// Stores to each edge all its periodic associations.
std::map<DofEdge, std::set<DofEdge> > periodicEdgeAssoc;
};
}
......
......@@ -103,6 +103,8 @@ namespace AMDiS {
TEST_EXIT(feSpace)("No FE space has been defined for the mesh distributor!\n");
TEST_EXIT(mesh)("No mesh has been defined for the mesh distributor!\n");
elObjects.setFeSpace(feSpace);
// If the problem has been already read from a file, we need only to set
// isRankDofs to all matrices and rhs vector and to remove periodic
// boundary conditions (if there are some).
......@@ -1265,9 +1267,7 @@ namespace AMDiS {
FUNCNAME("MeshDistributor::createInteriorBoundaryInfo()");
createMeshElementData();
createBoundaryData();
}
......@@ -1276,7 +1276,6 @@ namespace AMDiS {
FUNCNAME("MeshDistributor::updateInteriorBoundaryInfo()");
elObjects.createRankData(partitionVec);
createBoundaryData();
}
......@@ -1285,12 +1284,6 @@ namespace AMDiS {
{
FUNCNAME("MeshDistributor::createMeshElementData()");
// Stores to each vertex all its periodic associations.
std::map<DegreeOfFreedom, std::set<BoundaryType> > periodicDofAssoc;
// Stores to each edge all its periodic associations.
std::map<DofEdge, std::set<DofEdge> > periodicEdgeAssoc;
// === Fills macro element data structures. ===
......@@ -1304,274 +1297,19 @@ namespace AMDiS {
Element *el = elInfo->getElement();
macroElIndexMap[el->getIndex()] = el;
macroElIndexTypeMap[el->getIndex()] = elInfo->getType();
// === Add all sub object of the element to the variable elObjects. ===
elObjects.addElement(elInfo);
elObjects.addElement(el);
// === Get periodic boundary information. ===
switch (mesh->getDim()) {
case 2:
for (int i = 0; i < el->getGeo(EDGE); i++) {
if (mesh->isPeriodicAssociation(elInfo->getBoundary(EDGE, i))) {
Element *neigh = elInfo->getNeighbour(i);
DofEdge edge1 = el->getEdge(i);
DofEdge edge2 = neigh->getEdge(elInfo->getOppVertex(i));
BoundaryType boundaryType = elInfo->getBoundary(EDGE, i);
elObjects.addPeriodicEdge(std::make_pair(edge1, edge2), boundaryType);
periodicEdgeAssoc[edge1].insert(edge2);
elObjects.addPeriodicVertex(std::make_pair(edge1.first, edge2.first), boundaryType);
elObjects.addPeriodicVertex(std::make_pair(edge1.second, edge2.second), boundaryType);
periodicDofAssoc[edge1.first].insert(boundaryType);
periodicDofAssoc[edge1.second].insert(boundaryType);
TEST_EXIT_DBG(edge1.first == mesh->getPeriodicAssociations(boundaryType)[edge2.first] &&
edge1.second == mesh->getPeriodicAssociations(boundaryType)[edge2.second])
("Should not happen!\n");
}
}
break;
case 3:
for (int i = 0; i < el->getGeo(FACE); i++) {
if (mesh->isPeriodicAssociation(elInfo->getBoundary(FACE, i))) {
Element *neigh = elInfo->getNeighbour(i);
DofFace face1 = el->getFace(i);
DofFace face2 = neigh->getFace(elInfo->getOppVertex(i));
BoundaryType boundaryType = elInfo->getBoundary(FACE, i);
elObjects.addPeriodicFace(std::make_pair(face1, face2), elInfo->getBoundary(i));
elObjects.addPeriodicVertex(std::make_pair(face1.get<0>(), face2.get<0>()), boundaryType);
elObjects.addPeriodicVertex(std::make_pair(face1.get<1>(), face2.get<1>()), boundaryType);
elObjects.addPeriodicVertex(std::make_pair(face1.get<2>(), face2.get<2>()), boundaryType);
periodicDofAssoc[face1.get<0>()].insert(boundaryType);
periodicDofAssoc[face1.get<1>()].insert(boundaryType);
periodicDofAssoc[face1.get<2>()].insert(boundaryType);
TEST_EXIT_DBG(face1.get<0>() == mesh->getPeriodicAssociations(boundaryType)[face2.get<0>()] &&
face1.get<1>() == mesh->getPeriodicAssociations(boundaryType)[face2.get<1>()] &&
face1.get<2>() == mesh->getPeriodicAssociations(boundaryType)[face2.get<2>()])
("Should not happen!\n");
DofEdge elEdge1 = std::make_pair(face1.get<0>(), face1.get<1>());
DofEdge elEdge2 = std::make_pair(face1.get<0>(), face1.get<2>());
DofEdge elEdge3 = std::make_pair(face1.get<1>(), face1.get<2>());
DofEdge neighEdge1 = std::make_pair(face2.get<0>(), face2.get<1>());
DofEdge neighEdge2 = std::make_pair(face2.get<0>(), face2.get<2>());
DofEdge neighEdge3 = std::make_pair(face2.get<1>(), face2.get<2>());
elObjects.addPeriodicEdge(std::make_pair(elEdge1, neighEdge1), boundaryType);
elObjects.addPeriodicEdge(std::make_pair(elEdge2, neighEdge2), boundaryType);
elObjects.addPeriodicEdge(std::make_pair(elEdge3, neighEdge3), boundaryType);
periodicEdgeAssoc[elEdge1].insert(neighEdge1);
periodicEdgeAssoc[elEdge2].insert(neighEdge2);
periodicEdgeAssoc[elEdge3].insert(neighEdge3);
}
}
break;
}
elInfo = stack.traverseNext(elInfo);
}
// === Create periodic data, if there are periodic boundary conditions. ===
elObjects.createPeriodicData();
// === Create mesh element data for this rank. ===
// === Create mesh element data for this rank. ===
elObjects.createRankData(partitionVec);
// === Search for interectly connected vertices in periodic boundaries. ===
if (elObjects.periodicVertices.size() > 0) {
// === Search for an unsed boundary index. ===
BoundaryType newPeriodicBoundaryType = 0;
for (std::map<BoundaryType, VertexVector*>::iterator it = mesh->getPeriodicAssociations().begin();