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

Added some documentation to parallel code.

parent 4354cab8
......@@ -11,69 +11,369 @@
#include "ElementObjectData.h"
#include "VertexVector.h"
namespace AMDiS {
void ElementObjects::createRankData(std::map<int, int>& macroElementRankMap)
void ElementObjects::addElement(ElInfo *elInfo)
{
FUNCNAME("ElementObjects::addElement()");
TEST_EXIT_DBG(mesh)("Mesh not set!\n");
Element *el = elInfo->getElement();
// === First, add all element objects to the database. ===
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);
// === 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))) {
// The current element's i-th edge is periodic.
Element *neigh = elInfo->getNeighbour(i);
DofEdge edge0 = el->getEdge(i);
DofEdge edge1 = neigh->getEdge(elInfo->getOppVertex(i));
BoundaryType boundaryType = elInfo->getBoundary(EDGE, i);
// Add the periodic edge.
periodicEdges[make_pair(edge0, edge1)] = boundaryType;
periodicEdgeAssoc[edge0].insert(edge1);
// Add both vertices of the edge to be periodic.
periodicVertices[make_pair(edge0.first, edge1.first)] = boundaryType;
periodicVertices[make_pair(edge0.second, edge1.second)] = boundaryType;
periodicDofAssoc[edge0.first].insert(boundaryType);
periodicDofAssoc[edge0.second].insert(boundaryType);
TEST_EXIT_DBG(edge0.first ==
mesh->getPeriodicAssociations(boundaryType)[edge1.first] &&
edge0.second ==
mesh->getPeriodicAssociations(boundaryType)[edge1.second])
("Should not happen!\n");
}
}
break;
case 3:
for (int i = 0; i < el->getGeo(FACE); i++) {
if (mesh->isPeriodicAssociation(elInfo->getBoundary(FACE, i))) {
// The current element's i-th face is periodic.
Element *neigh = elInfo->getNeighbour(i);
DofFace face0 = el->getFace(i);
DofFace face1 = neigh->getFace(elInfo->getOppVertex(i));
BoundaryType boundaryType = elInfo->getBoundary(FACE, i);
// Add the periodic face.
periodicFaces[make_pair(face0, face1)] = elInfo->getBoundary(i);
/// Add all three vertices of the face to be periodic.
periodicVertices[make_pair(face0.get<0>(), face1.get<0>())] = boundaryType;
periodicVertices[make_pair(face0.get<1>(), face1.get<1>())] = boundaryType;
periodicVertices[make_pair(face0.get<2>(), face1.get<2>())] = boundaryType;
periodicDofAssoc[face0.get<0>()].insert(boundaryType);
periodicDofAssoc[face0.get<1>()].insert(boundaryType);
periodicDofAssoc[face0.get<2>()].insert(boundaryType);
TEST_EXIT_DBG(face0.get<0>() ==
mesh->getPeriodicAssociations(boundaryType)[face1.get<0>()] &&
face0.get<1>() ==
mesh->getPeriodicAssociations(boundaryType)[face1.get<1>()] &&
face0.get<2>() ==
mesh->getPeriodicAssociations(boundaryType)[face1.get<2>()])
("Should not happen!\n");
// Create all three edges of the element and add them to be periodic.
DofEdge elEdge0 = make_pair(face0.get<0>(), face0.get<1>());
DofEdge elEdge1 = make_pair(face0.get<0>(), face0.get<2>());
DofEdge elEdge2 = make_pair(face0.get<1>(), face0.get<2>());
DofEdge neighEdge0 = make_pair(face1.get<0>(), face1.get<1>());
DofEdge neighEdge1 = make_pair(face1.get<0>(), face1.get<2>());
DofEdge neighEdge2 = make_pair(face1.get<1>(), face1.get<2>());
periodicEdges[make_pair(elEdge0, neighEdge0)] = boundaryType;
periodicEdges[make_pair(elEdge1, neighEdge1)] = boundaryType;
periodicEdges[make_pair(elEdge2, neighEdge2)] = boundaryType;
periodicEdgeAssoc[elEdge0].insert(neighEdge0);
periodicEdgeAssoc[elEdge1].insert(neighEdge1);
periodicEdgeAssoc[elEdge2].insert(neighEdge2);
}
}
break;
default:
ERROR_EXIT("Should not happen!\n");
}
}
void ElementObjects::createPeriodicData()
{
FUNCNAME("ElementObjects::createPeriodicData()");
TEST_EXIT_DBG(mesh)("Mesh not set!\n");
// === Return, if there are no periodic vertices, i.e., there are no no ===
// === periodic boundaries in the mesh. ===
if (periodicVertices.size() == 0)
return;
// === Search for an unsed boundary index. ===
BoundaryType newPeriodicBoundaryType = 0;
for (map<BoundaryType, VertexVector*>::iterator it = mesh->getPeriodicAssociations().begin();
it != mesh->getPeriodicAssociations().end(); ++it)
newPeriodicBoundaryType = min(newPeriodicBoundaryType, it->first);
TEST_EXIT_DBG(newPeriodicBoundaryType < 0)("Should not happen!\n");
newPeriodicBoundaryType--;
mesh->getPeriodicAssociations()[newPeriodicBoundaryType] =
new VertexVector(feSpace->getAdmin(), "");
// === Get all vertex DOFs that have multiple periodic associations. ===
// We group all vertices together, that have either two or three periodic
// associations. For rectangular domains in 2D, the four corner vertices have all
// two periodic associations. For box domains in 3D, the eight corner vertices
// have all three periodic associations.
vector<DegreeOfFreedom> multPeriodicDof2, multPeriodicDof3;
for (map<DegreeOfFreedom, std::set<BoundaryType> >::iterator it = periodicDofAssoc.begin();
it != periodicDofAssoc.end(); ++it) {
TEST_EXIT_DBG((mesh->getDim() == 2 && it->second.size() <= 2) ||
(mesh->getDim() == 3 && it->second.size() <= 3))
("Should not happen!\n");
if (it->second.size() == 2)
multPeriodicDof2.push_back(it->first);
if (it->second.size() == 3)
multPeriodicDof3.push_back(it->first);
}
if (mesh->getDim() == 2) {
TEST_EXIT_DBG(multPeriodicDof2.size() == 0 ||
multPeriodicDof2.size() == 4)
("Should not happen (%d)!\n", multPeriodicDof2.size());
TEST_EXIT_DBG(multPeriodicDof3.size() == 0)("Should not happen!\n");
}
if (mesh->getDim() == 3) {
TEST_EXIT_DBG(multPeriodicDof3.size() == 0 ||
multPeriodicDof3.size() == 8)
("Should not happen (%d)!\n", multPeriodicDof3.size());
}
if (multPeriodicDof2.size() > 0) {
for (unsigned int i = 0; i < multPeriodicDof2.size(); i++) {
DegreeOfFreedom dof0 = multPeriodicDof2[i];
if (dof0 == -1)
continue;
DegreeOfFreedom dof1 = -1;
DegreeOfFreedom dof2 = -1;
BoundaryType type0 = *(periodicDofAssoc[dof0].begin());
BoundaryType type1 = *(++(periodicDofAssoc[dof0].begin()));
for (PerBoundMap<DegreeOfFreedom>::iterator it = periodicVertices.begin();
it != periodicVertices.end(); ++it) {
if (it->first.first == dof0 && it->second == type0)
dof1 = it->first.second;
if (it->first.first == dof0 && it->second == type1)
dof2 = it->first.second;
if (dof1 != -1 && dof2 != -1)
break;
}
TEST_EXIT_DBG(dof1 != -1 && dof2 != -1)("Should not happen!\n");
DegreeOfFreedom dof3 = -1;
for (PerBoundMap<DegreeOfFreedom>::iterator it = periodicVertices.begin();
it != periodicVertices.end(); ++it) {
if (it->first.first == dof1 && it->second == type1) {
dof3 = it->first.second;
TEST_EXIT_DBG(periodicVertices[make_pair(dof2, dof3)] == type0)
("Should not happen!\n");
break;
}
}
TEST_EXIT_DBG(dof3 != -1)("Should not happen!\n");
TEST_EXIT_DBG(periodicVertices.count(make_pair(dof0, dof3)) == 0)
("Should not happen!\n");
TEST_EXIT_DBG(periodicVertices.count(make_pair(dof3, dof0)) == 0)
("Should not happen!\n");
periodicVertices[make_pair(dof0, dof3)] = newPeriodicBoundaryType;
periodicVertices[make_pair(dof3, dof0)] = newPeriodicBoundaryType;
for (unsigned int j = i + 1; j < multPeriodicDof2.size(); j++)
if (multPeriodicDof2[j] == dof3)
multPeriodicDof2[j] = -1;
}
}
if (multPeriodicDof3.size() > 0) {
int nMultPeriodicDofs = multPeriodicDof3.size();
for (int i = 0; i < nMultPeriodicDofs; i++) {
for (int j = i + 1; j < nMultPeriodicDofs; j++) {
pair<DegreeOfFreedom, DegreeOfFreedom> perDofs0 =
make_pair(multPeriodicDof3[i], multPeriodicDof3[j]);
pair<DegreeOfFreedom, DegreeOfFreedom> perDofs1 =
make_pair(multPeriodicDof3[j], multPeriodicDof3[i]);
if (periodicVertices.count(perDofs0) == 0) {
TEST_EXIT_DBG(periodicVertices.count(perDofs1) == 0)
("Should not happen!\n");
periodicVertices[perDofs0] = newPeriodicBoundaryType;
periodicVertices[perDofs1] = newPeriodicBoundaryType;
newPeriodicBoundaryType--;
mesh->getPeriodicAssociations()[newPeriodicBoundaryType] =
new VertexVector(feSpace->getAdmin(), "");
}
}
}
}
// === Get all edges that have multiple periodic associations (3D only!). ===
for (map<DofEdge, std::set<DofEdge> >::iterator it = periodicEdgeAssoc.begin();
it != periodicEdgeAssoc.end(); ++it) {
if (it->second.size() > 1) {
TEST_EXIT_DBG(mesh->getDim() == 3)("Should not happen!\n");
TEST_EXIT_DBG(it->second.size() == 2)("Should not happen!\n");
pair<DofEdge, DofEdge> perEdge0 =
make_pair(*(it->second.begin()), *(++(it->second.begin())));
pair<DofEdge, DofEdge> perEdge1 =
make_pair(perEdge0.second, perEdge0.first);
periodicEdges[perEdge0] = newPeriodicBoundaryType;
periodicEdges[perEdge1] = newPeriodicBoundaryType;
newPeriodicBoundaryType--;
mesh->getPeriodicAssociations()[newPeriodicBoundaryType] =
new VertexVector(feSpace->getAdmin(), "");
}
}
// === In debug mode we make some tests, if the periodic structures are set ===
// === in a symmetric way, i.e., if A -> B for a specific boundary type, ===
// === there must be a mapping B -> A with the same boundary type. ===
#if (DEBUG != 0)
for (PerBoundMap<DegreeOfFreedom>::iterator it = periodicVertices.begin();
it != periodicVertices.end(); ++it) {
pair<DegreeOfFreedom, DegreeOfFreedom> testVertex =
make_pair(it->first.second, it->first.first);
TEST_EXIT_DBG(periodicVertices.count(testVertex) == 1)("Should not happen!\n");
TEST_EXIT_DBG(periodicVertices[testVertex] == it->second)("Should not happen!\n");
}
for (PerBoundMap<DofEdge>::iterator it = periodicEdges.begin();
it != periodicEdges.end(); ++it) {
pair<DofEdge, DofEdge> testEdge =
make_pair(it->first.second, it->first.first);
TEST_EXIT_DBG(periodicEdges.count(testEdge) == 1)("Should not happen!\n");
TEST_EXIT_DBG(periodicEdges[testEdge] == it->second)("Should not happen!\n");
}
for (PerBoundMap<DofFace>::iterator it = periodicFaces.begin();
it != periodicFaces.end(); ++it) {
pair<DofFace, DofFace> testFace =
make_pair(it->first.second, it->first.first);
TEST_EXIT_DBG(periodicFaces.count(testFace) == 1)("Should not happen!\n");
TEST_EXIT_DBG(periodicFaces[testFace] == it->second)("Should not happen!\n");
}
#endif
}
void ElementObjects::createRankData(map<int, int>& macroElementRankMap)
{
FUNCNAME("ElementObjects::createRankData()");
vertexOwner.clear();
vertexInRank.clear();
for (std::map<DegreeOfFreedom, std::vector<ElementObjectData> >::iterator it = vertexElements.begin();
for (map<DegreeOfFreedom, vector<ElementObjectData> >::iterator it = vertexElements.begin();
it != vertexElements.end(); ++it) {
for (std::vector<ElementObjectData>::iterator it2 = it->second.begin();
for (vector<ElementObjectData>::iterator it2 = it->second.begin();
it2 != it->second.end(); ++it2) {
int elementInRank = macroElementRankMap[it2->elIndex];
if (it2->elIndex > vertexInRank[it->first][elementInRank].elIndex)
vertexInRank[it->first][elementInRank] = *it2;
vertexOwner[it->first] = std::max(vertexOwner[it->first], elementInRank);
vertexOwner[it->first] = max(vertexOwner[it->first], elementInRank);
}
}
edgeOwner.clear();
edgeInRank.clear();
for (std::map<DofEdge, std::vector<ElementObjectData> >::iterator it = edgeElements.begin();
for (map<DofEdge, vector<ElementObjectData> >::iterator it = edgeElements.begin();
it != edgeElements.end(); ++it) {
for (std::vector<ElementObjectData>::iterator it2 = it->second.begin();
for (vector<ElementObjectData>::iterator it2 = it->second.begin();
it2 != it->second.end(); ++it2) {
int elementInRank = macroElementRankMap[it2->elIndex];
if (it2->elIndex > edgeInRank[it->first][elementInRank].elIndex)
edgeInRank[it->first][elementInRank] = *it2;
edgeOwner[it->first] = std::max(edgeOwner[it->first], elementInRank);
edgeOwner[it->first] = max(edgeOwner[it->first], elementInRank);
}
}
faceOwner.clear();
faceInRank.clear();
for (std::map<DofFace, std::vector<ElementObjectData> >::iterator it = faceElements.begin();
for (map<DofFace, vector<ElementObjectData> >::iterator it = faceElements.begin();
it != faceElements.end(); ++it) {
for (std::vector<ElementObjectData>::iterator it2 = it->second.begin();
for (vector<ElementObjectData>::iterator it2 = it->second.begin();
it2 != it->second.end(); ++it2) {
int elementInRank = macroElementRankMap[it2->elIndex];
if (it2->elIndex > faceInRank[it->first][elementInRank].elIndex)
faceInRank[it->first][elementInRank] = *it2;
faceOwner[it->first] = std::max(faceOwner[it->first], elementInRank);
faceOwner[it->first] = max(faceOwner[it->first], elementInRank);
}
}
}
void ElementObjects::serialize(std::ostream &out)
void ElementObjects::serialize(ostream &out)
{
FUNCNAME("ElementObjects::serialize()");
int nSize = vertexElements.size();
SerUtil::serialize(out, nSize);
for (std::map<DegreeOfFreedom, std::vector<ElementObjectData> >::iterator it = vertexElements.begin();
for (map<DegreeOfFreedom, vector<ElementObjectData> >::iterator it = vertexElements.begin();
it != vertexElements.end(); ++it) {
SerUtil::serialize(out, it->first);
serialize(out, it->second);
......@@ -81,7 +381,7 @@ namespace AMDiS {
nSize = edgeElements.size();
SerUtil::serialize(out, nSize);
for (std::map<DofEdge, std::vector<ElementObjectData> >::iterator it = edgeElements.begin();
for (map<DofEdge, vector<ElementObjectData> >::iterator it = edgeElements.begin();
it != edgeElements.end(); ++it) {
SerUtil::serialize(out, it->first);
serialize(out, it->second);
......@@ -89,7 +389,7 @@ namespace AMDiS {
nSize = faceElements.size();
SerUtil::serialize(out, nSize);
for (std::map<DofFace, std::vector<ElementObjectData> >::iterator it = faceElements.begin();
for (map<DofFace, vector<ElementObjectData> >::iterator it = faceElements.begin();
it != faceElements.end(); ++it) {
SerUtil::serialize(out, it->first);
serialize(out, it->second);
......@@ -99,7 +399,7 @@ namespace AMDiS {
nSize = vertexLocalMap.size();
SerUtil::serialize(out, nSize);
for (std::map<ElementObjectData, DegreeOfFreedom>::iterator it = vertexLocalMap.begin();
for (map<ElementObjectData, DegreeOfFreedom>::iterator it = vertexLocalMap.begin();
it != vertexLocalMap.end(); ++it) {
it->first.serialize(out);
SerUtil::serialize(out, it->second);
......@@ -107,7 +407,7 @@ namespace AMDiS {
nSize = edgeLocalMap.size();
SerUtil::serialize(out, nSize);
for (std::map<ElementObjectData, DofEdge>::iterator it = edgeLocalMap.begin();
for (map<ElementObjectData, DofEdge>::iterator it = edgeLocalMap.begin();
it != edgeLocalMap.end(); ++it) {
it->first.serialize(out);
SerUtil::serialize(out, it->second);
......@@ -115,7 +415,7 @@ namespace AMDiS {
nSize = faceLocalMap.size();
SerUtil::serialize(out, nSize);
for (std::map<ElementObjectData, DofFace>::iterator it = faceLocalMap.begin();
for (map<ElementObjectData, DofFace>::iterator it = faceLocalMap.begin();
it != faceLocalMap.end(); ++it) {
it->first.serialize(out);
SerUtil::serialize(out, it->second);
......@@ -130,7 +430,7 @@ namespace AMDiS {
nSize = vertexInRank.size();
SerUtil::serialize(out, nSize);
for (std::map<DegreeOfFreedom, std::map<int, ElementObjectData> >::iterator it = vertexInRank.begin();
for (map<DegreeOfFreedom, map<int, ElementObjectData> >::iterator it = vertexInRank.begin();
it != vertexInRank.end(); ++it) {
SerUtil::serialize(out, it->first);
serialize(out, it->second);
......@@ -138,7 +438,7 @@ namespace AMDiS {
nSize = edgeInRank.size();
SerUtil::serialize(out, nSize);
for (std::map<DofEdge, std::map<int, ElementObjectData> >::iterator it = edgeInRank.begin();
for (map<DofEdge, map<int, ElementObjectData> >::iterator it = edgeInRank.begin();
it != edgeInRank.end(); ++it) {
SerUtil::serialize(out, it->first);
serialize(out, it->second);
......@@ -146,7 +446,7 @@ namespace AMDiS {
nSize = faceInRank.size();
SerUtil::serialize(out, nSize);
for (std::map<DofFace, std::map<int, ElementObjectData> >::iterator it = faceInRank.begin();
for (map<DofFace, map<int, ElementObjectData> >::iterator it = faceInRank.begin();
it != faceInRank.end(); ++it) {
SerUtil::serialize(out, it->first);
serialize(out, it->second);
......@@ -158,7 +458,7 @@ namespace AMDiS {
}
void ElementObjects::deserialize(std::istream &in)
void ElementObjects::deserialize(istream &in)
{
FUNCNAME("ElementObjects::deserialize()");
......@@ -167,7 +467,7 @@ namespace AMDiS {
vertexElements.clear();
for (int i = 0; i < nSize; i++) {
DegreeOfFreedom dof;
std::vector<ElementObjectData> data;
vector<ElementObjectData> data;
SerUtil::deserialize(in, dof);
deserialize(in, data);
vertexElements[dof] = data;
......@@ -177,7 +477,7 @@ namespace AMDiS {
edgeElements.clear();
for (int i = 0; i < nSize; i++) {
DofEdge edge;
std::vector<ElementObjectData> data;
vector<ElementObjectData> data;
SerUtil::deserialize(in, edge);
deserialize(in, data);
edgeElements[edge] = data;
......@@ -187,7 +487,7 @@ namespace AMDiS {
faceElements.clear();
for (int i = 0; i < nSize; i++) {
DofFace face;
std::vector<ElementObjectData> data;
vector<ElementObjectData> data;
SerUtil::deserialize(in, face);
deserialize(in, data);
faceElements[face] = data;
......@@ -235,7 +535,7 @@ namespace AMDiS {
vertexInRank.clear();
for (int i = 0; i < nSize; i++) {
DegreeOfFreedom dof;
std::map<int, ElementObjectData> data;
map<int, ElementObjectData> data;
SerUtil::deserialize(in, dof);
deserialize(in, data);
vertexInRank[dof] = data;
......@@ -245,7 +545,7 @@ namespace AMDiS {
edgeInRank.clear();
for (int i = 0; i < nSize; i++) {
DofEdge edge;
std::map<int, ElementObjectData> data;
map<int, ElementObjectData> data;
SerUtil::deserialize(in, edge);
deserialize(in, data);
edgeInRank[edge] = data;
......@@ -255,7 +555,7 @@ namespace AMDiS {
faceInRank.clear();
for (int i = 0; i < nSize; i++) {
DofFace face;
std::map<int, ElementObjectData> data;
map<int, ElementObjectData> data;
SerUtil::deserialize(in, face);
deserialize(in, data);
faceInRank[face] = data;
......@@ -267,7 +567,7 @@ namespace AMDiS {
}
void ElementObjects::serialize(std::ostream &out, std::vector<ElementObjectData>& elVec)
void ElementObjects::serialize(ostream &out, vector<ElementObjectData>& elVec)
{
int nSize = elVec.size();
SerUtil::serialize(out, nSize);
......@@ -276,7 +576,7 @@ namespace AMDiS {
}
void ElementObjects::deserialize(std::istream &in, std::vector<ElementObjectData>& elVec)
void ElementObjects::deserialize(istream &in, vector<ElementObjectData>& elVec)
{
int nSize;
SerUtil::deserialize(in, nSize);
......@@ -286,11 +586,11 @@ namespace AMDiS {
}
void ElementObjects::serialize(std::ostream &out, std::map<int, ElementObjectData>& data)
void ElementObjects::serialize(ostream &out, map<int, ElementObjectData>& data)
{
int nSize = data.size();
SerUtil::serialize(out, nSize);
for (std::map<int, ElementObjectData>::iterator it = data.begin();
for (map<int, ElementObjectData>::iterator it = data.begin();
it != data.end(); ++it) {
SerUtil::serialize(out, it->first);
it->second.serialize(out);
......@@ -298,7 +598,7 @@ namespace AMDiS {
}
void ElementObjects::deserialize(std::istream &in, std::map<int, ElementObjectData>& data)
void ElementObjects::deserialize(istream &in, map<int, ElementObjectData>& data)
{
int nSize;
SerUtil::deserialize(in, nSize);
......
......@@ -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;