Commit 5682e383 authored by Thomas Witkowski's avatar Thomas Witkowski
Browse files

Refactoring of StdMpi and documentation of this class.

parent b1bd6c98
...@@ -419,7 +419,7 @@ namespace AMDiS { ...@@ -419,7 +419,7 @@ namespace AMDiS {
recvIt != recvDofs.end(); ++recvIt) recvIt != recvDofs.end(); ++recvIt)
stdMpi.recv(recvIt->first, recvIt->second.size()); stdMpi.recv(recvIt->first, recvIt->second.size());
stdMpi.startCommunication<double>(MPI_DOUBLE); stdMpi.startCommunication();
for (RankToDofContainer::iterator recvIt = recvDofs.begin(); for (RankToDofContainer::iterator recvIt = recvDofs.begin();
recvIt != recvDofs.end(); ++recvIt) recvIt != recvDofs.end(); ++recvIt)
...@@ -452,7 +452,7 @@ namespace AMDiS { ...@@ -452,7 +452,7 @@ namespace AMDiS {
recvIt != recvDofs.end(); ++recvIt) recvIt != recvDofs.end(); ++recvIt)
stdMpi.recv(recvIt->first, recvIt->second.size() * nComponents); stdMpi.recv(recvIt->first, recvIt->second.size() * nComponents);
stdMpi.startCommunication<double>(MPI_DOUBLE); stdMpi.startCommunication();
for (RankToDofContainer::iterator recvIt = recvDofs.begin(); for (RankToDofContainer::iterator recvIt = recvDofs.begin();
recvIt != recvDofs.end(); ++recvIt) { recvIt != recvDofs.end(); ++recvIt) {
...@@ -579,14 +579,8 @@ namespace AMDiS { ...@@ -579,14 +579,8 @@ namespace AMDiS {
MeshStructure elCode; MeshStructure elCode;
elCode.init(it->rankObj); elCode.init(it->rankObj);
MeshManipulation meshManipulation(feSpace); MeshManipulation mm(feSpace);
meshChanged |= meshChanged |= !(mm.fitElementToMeshCode(elCode, it->neighObj));
!(meshManipulation.startFitElementToMeshCode(elCode,
it->neighObj.el,
it->neighObj.subObj,
it->neighObj.ithObj,
it->neighObj.elType,
it->neighObj.reverseMode));
} }
} else { } else {
if ((mesh->getDim() == 2 && it->rankObj.subObj == EDGE) || if ((mesh->getDim() == 2 && it->rankObj.subObj == EDGE) ||
...@@ -663,8 +657,9 @@ namespace AMDiS { ...@@ -663,8 +657,9 @@ namespace AMDiS {
StdMpi<MeshCodeVec> stdMpi(mpiComm, true); StdMpi<MeshCodeVec> stdMpi(mpiComm, true);
stdMpi.send(sendCodes); stdMpi.send(sendCodes);
stdMpi.recv(allBound); for (RankToBoundMap::iterator it = allBound.begin(); it != allBound.end(); ++it)
stdMpi.startCommunication<uint64_t>(MPI_UNSIGNED_LONG); stdMpi.recv(it->first);
stdMpi.startCommunication();
// === Compare received mesh structure codes. === // === Compare received mesh structure codes. ===
...@@ -684,14 +679,8 @@ namespace AMDiS { ...@@ -684,14 +679,8 @@ namespace AMDiS {
if (elCode.getCode() != recvCodes[i].getCode()) { if (elCode.getCode() != recvCodes[i].getCode()) {
TEST_EXIT_DBG(refineManager)("Refinement manager is not set correctly!\n"); TEST_EXIT_DBG(refineManager)("Refinement manager is not set correctly!\n");
MeshManipulation meshManipulation(feSpace); MeshManipulation mm(feSpace);
meshChanged |= meshChanged |= mm.fitElementToMeshCode(recvCodes[i], boundIt->rankObj);
meshManipulation.startFitElementToMeshCode(recvCodes[i],
boundIt->rankObj.el,
boundIt->rankObj.subObj,
boundIt->rankObj.ithObj,
boundIt->rankObj.elType,
boundIt->rankObj.reverseMode);
} }
} }
} }
...@@ -940,9 +929,9 @@ namespace AMDiS { ...@@ -940,9 +929,9 @@ namespace AMDiS {
elCode.init(mesh, *elIt); elCode.init(mesh, *elIt);
sendCodes[it->first].push_back(elCode); sendCodes[it->first].push_back(elCode);
for (unsigned int i = 0; i < testVec.size(); i++) { for (unsigned int i = 0; i < interchangeVectors.size(); i++) {
vector<double> valVec; vector<double> valVec;
elCode.getMeshStructureValues(mesh, *elIt, testVec[i], valVec); elCode.getMeshStructureValues(mesh, *elIt, interchangeVectors[i], valVec);
sendValues[it->first].push_back(valVec); sendValues[it->first].push_back(valVec);
} }
} }
...@@ -950,13 +939,17 @@ namespace AMDiS { ...@@ -950,13 +939,17 @@ namespace AMDiS {
StdMpi<MeshCodeVec> stdMpi(mpiComm, true); StdMpi<MeshCodeVec> stdMpi(mpiComm, true);
stdMpi.send(sendCodes); stdMpi.send(sendCodes);
stdMpi.recv(partitioner->getRecvElements()); for (std::map<int, std::vector<int> >::iterator it = partitioner->getRecvElements().begin();
stdMpi.startCommunication<uint64_t>(MPI_UNSIGNED_LONG); it != partitioner->getRecvElements().end(); ++it)
stdMpi.recv(it->first);
stdMpi.startCommunication();
StdMpi<vector<vector<double> > > stdMpi2(mpiComm, true); StdMpi<vector<vector<double> > > stdMpi2(mpiComm, true);
stdMpi2.send(sendValues); stdMpi2.send(sendValues);
stdMpi2.recv(partitioner->getRecvElements()); for (std::map<int, std::vector<int> >::iterator it = partitioner->getRecvElements().begin();
stdMpi2.startCommunication<double>(MPI_DOUBLE); it != partitioner->getRecvElements().end(); ++it)
stdMpi2.recv(it->first);
stdMpi2.startCommunication();
// === Adapte the new macro elements due to the received mesh structure codes. === // === Adapte the new macro elements due to the received mesh structure codes. ===
...@@ -974,8 +967,11 @@ namespace AMDiS { ...@@ -974,8 +967,11 @@ namespace AMDiS {
elIt != it->second.end(); ++elIt) { elIt != it->second.end(); ++elIt) {
recvCodes[i].fitMeshToStructure(mesh, refineManager, false, *elIt); recvCodes[i].fitMeshToStructure(mesh, refineManager, false, *elIt);
for (unsigned int k = 0; k < testVec.size(); k++) for (unsigned int k = 0; k < interchangeVectors.size(); k++)
recvCodes[i].setMeshStructureValues(mesh, *elIt, testVec[k], recvValues[j++]); recvCodes[i].setMeshStructureValues(mesh,
*elIt,
interchangeVectors[k],
recvValues[j++]);
i++; i++;
} }
...@@ -1327,7 +1323,7 @@ namespace AMDiS { ...@@ -1327,7 +1323,7 @@ namespace AMDiS {
StdMpi<vector<AtomicBoundary> > stdMpi(mpiComm); StdMpi<vector<AtomicBoundary> > stdMpi(mpiComm);
stdMpi.send(myIntBoundary.boundary); stdMpi.send(myIntBoundary.boundary);
stdMpi.recv(otherIntBoundary.boundary); stdMpi.recv(otherIntBoundary.boundary);
stdMpi.startCommunication<int>(MPI_INT); stdMpi.startCommunication();
// === The information about all neighbouring boundaries has been received. So === // === The information about all neighbouring boundaries has been received. So ===
...@@ -1386,7 +1382,7 @@ namespace AMDiS { ...@@ -1386,7 +1382,7 @@ namespace AMDiS {
stdMpi.send(sendBounds.boundary); stdMpi.send(sendBounds.boundary);
stdMpi.recv(recvBounds.boundary); stdMpi.recv(recvBounds.boundary);
stdMpi.startCommunication<int>(MPI_INT); stdMpi.startCommunication();
for (RankToBoundMap::iterator rankIt = periodicBoundary.boundary.begin(); for (RankToBoundMap::iterator rankIt = periodicBoundary.boundary.begin();
rankIt != periodicBoundary.boundary.end(); ++rankIt) { rankIt != periodicBoundary.boundary.end(); ++rankIt) {
...@@ -1548,7 +1544,7 @@ namespace AMDiS { ...@@ -1548,7 +1544,7 @@ namespace AMDiS {
} }
stdMpi.updateSendDataSize(); stdMpi.updateSendDataSize();
stdMpi.recv(recvDofs); stdMpi.recv(recvDofs);
stdMpi.startCommunication<int>(MPI_INT); stdMpi.startCommunication();
for (RankToDofContainer::iterator recvIt = recvDofs.begin(); for (RankToDofContainer::iterator recvIt = recvDofs.begin();
...@@ -1677,7 +1673,7 @@ namespace AMDiS { ...@@ -1677,7 +1673,7 @@ namespace AMDiS {
} }
stdMpi.updateSendDataSize(); stdMpi.updateSendDataSize();
stdMpi.startCommunication<int>(MPI_INT); stdMpi.startCommunication();
// === The rank has received the dofs from the rank on the other side of === // === The rank has received the dofs from the rank on the other side of ===
...@@ -1749,7 +1745,7 @@ namespace AMDiS { ...@@ -1749,7 +1745,7 @@ namespace AMDiS {
stdMpi2.recv(it->first); stdMpi2.recv(it->first);
} }
stdMpi2.startCommunication<int>(MPI_INT); stdMpi2.startCommunication();
for (std::map<int, PeriodicDofMap>::iterator it = stdMpi2.getRecvData().begin(); for (std::map<int, PeriodicDofMap>::iterator it = stdMpi2.getRecvData().begin();
it != stdMpi2.getRecvData().end(); ++it) it != stdMpi2.getRecvData().end(); ++it)
......
...@@ -88,6 +88,13 @@ namespace AMDiS { ...@@ -88,6 +88,13 @@ namespace AMDiS {
void addProblemStat(ProblemVec *probVec); void addProblemStat(ProblemVec *probVec);
/// Adds a DOFVector to the set of \ref interchangeVecs. Thus, this vector will
/// be automatically interchanged between ranks when mesh is repartitioned.
void addInterchangeVector(DOFVector<double> *vec)
{
interchangeVectors.push_back(vec);
}
/** \brief /** \brief
* This function checks if the mesh has changed on at least on rank. In this case, * This function checks if the mesh has changed on at least on rank. In this case,
* the interior boundaries are adapted on all ranks such that they fit together on * the interior boundaries are adapted on all ranks such that they fit together on
...@@ -392,9 +399,6 @@ namespace AMDiS { ...@@ -392,9 +399,6 @@ namespace AMDiS {
} }
} }
public:
vector<DOFVector<double>* > testVec;
protected: protected:
/// ///
vector<ProblemVec*> probStat; vector<ProblemVec*> probStat;
...@@ -528,6 +532,11 @@ namespace AMDiS { ...@@ -528,6 +532,11 @@ namespace AMDiS {
*/ */
map<int, std::set<BoundaryType> > periodicDofAssociations; map<int, std::set<BoundaryType> > periodicDofAssociations;
/// This set of values must be interchanged between ranks when the mesh is
/// repartitioned.
vector<DOFVector<double>*> interchangeVectors;
/// Is the index of the first row of the linear system, which is owned by the rank. /// Is the index of the first row of the linear system, which is owned by the rank.
int rstart; int rstart;
......
...@@ -201,16 +201,12 @@ namespace AMDiS { ...@@ -201,16 +201,12 @@ namespace AMDiS {
} }
bool MeshManipulation::startFitElementToMeshCode(MeshStructure &code, bool MeshManipulation::fitElementToMeshCode(MeshStructure &code,
Element *el, BoundaryObject &boundEl)
GeoIndex subObj,
int ithObj,
int elType,
bool reverseMode)
{ {
FUNCNAME("MeshManipulation::startFitElementToMeshCode()"); FUNCNAME("MeshManipulation::fitElementToMeshCode()");
TEST_EXIT_DBG(el)("No element given!\n"); TEST_EXIT_DBG(boundEl.el)("No element given!\n");
// If the code is empty, the element does not matter and the function can // If the code is empty, the element does not matter and the function can
// return without chaning the mesh. // return without chaning the mesh.
...@@ -220,8 +216,10 @@ namespace AMDiS { ...@@ -220,8 +216,10 @@ namespace AMDiS {
// s0 and s1 are the number of the edge/face in both child of the element, // s0 and s1 are the number of the edge/face in both child of the element,
// which contain the edge/face the function has to traverse through. If the // which contain the edge/face the function has to traverse through. If the
// edge/face is not contained in one of the children, s0 or s1 is -1. // edge/face is not contained in one of the children, s0 or s1 is -1.
int s0 = el->getSubObjOfChild(0, subObj, ithObj, elType); int s0 =
int s1 = el->getSubObjOfChild(1, subObj, ithObj, elType); boundEl.el->getSubObjOfChild(0, boundEl.subObj, boundEl.ithObj, boundEl.elType);
int s1 =
boundEl.el->getSubObjOfChild(1, boundEl.subObj, boundEl.ithObj, boundEl.elType);
TEST_EXIT_DBG(s0 != -1 || s1 != -1)("This should not happen!\n"); TEST_EXIT_DBG(s0 != -1 || s1 != -1)("This should not happen!\n");
...@@ -231,29 +229,32 @@ namespace AMDiS { ...@@ -231,29 +229,32 @@ namespace AMDiS {
// Test for reverse mode, in which the left and right children of elements // Test for reverse mode, in which the left and right children of elements
// are flipped. // are flipped.
if (reverseMode) if (boundEl.reverseMode)
traverseFlag |= Mesh::CALL_REVERSE_MODE; traverseFlag |= Mesh::CALL_REVERSE_MODE;
// === If the edge/face is contained in both children. === // === If the edge/face is contained in both children. ===
Mesh *mesh = boundEl.el->getMesh();
if (s0 != -1 && s1 != -1) { if (s0 != -1 && s1 != -1) {
// Create traverse stack and traverse within the mesh until the element, // Create traverse stack and traverse within the mesh until the element,
// which should be fitted to the mesh structure code, is reached. // which should be fitted to the mesh structure code, is reached.
TraverseStack stack; TraverseStack stack;
ElInfo *elInfo = stack.traverseFirst(el->getMesh(), -1, traverseFlag); ElInfo *elInfo = stack.traverseFirst(mesh, -1, traverseFlag);
while (elInfo && elInfo->getElement() != el) while (elInfo && elInfo->getElement() != boundEl.el)
elInfo = stack.traverseNext(elInfo); elInfo = stack.traverseNext(elInfo);
TEST_EXIT_DBG(elInfo->getElement() == el)("This should not happen!\n"); TEST_EXIT_DBG(elInfo->getElement() == boundEl.el)("This should not happen!\n");
return fitElementToMeshCode(code, stack, subObj, ithObj, reverseMode); return fitElementToMeshCode(code, stack, boundEl.subObj,
boundEl.ithObj, boundEl.reverseMode);
} }
// === The edge/face is contained in only on of the both children. === // === The edge/face is contained in only on of the both children. ===
if (el->isLeaf()) { if (boundEl.el->isLeaf()) {
// If element is leaf and code contains only one leaf element, we are finished. // If element is leaf and code contains only one leaf element, we are finished.
if (code.getNumElements() == 1 && code.isLeafElement()) if (code.getNumElements() == 1 && code.isLeafElement())
...@@ -261,23 +262,23 @@ namespace AMDiS { ...@@ -261,23 +262,23 @@ namespace AMDiS {
// Create traverse stack and traverse the mesh to the element. // Create traverse stack and traverse the mesh to the element.
TraverseStack stack; TraverseStack stack;
ElInfo *elInfo = stack.traverseFirst(el->getMesh(), -1, traverseFlag); ElInfo *elInfo = stack.traverseFirst(mesh, -1, traverseFlag);
while (elInfo && elInfo->getElement() != el) while (elInfo && elInfo->getElement() != boundEl.el)
elInfo = stack.traverseNext(elInfo); elInfo = stack.traverseNext(elInfo);
TEST_EXIT_DBG(elInfo)("This should not happen!\n"); TEST_EXIT_DBG(elInfo)("This should not happen!\n");
// Code is not leaf, therefore refine the element. // Code is not leaf, therefore refine the element.
el->setMark(1); boundEl.el->setMark(1);
refineManager->setMesh(el->getMesh()); refineManager->setMesh(boundEl.el->getMesh());
refineManager->setStack(&stack); refineManager->setStack(&stack);
refineManager->refineFunction(elInfo); refineManager->refineFunction(elInfo);
meshChanged = true; meshChanged = true;
} }
Element *child0 = el->getFirstChild(); Element *child0 = boundEl.el->getFirstChild();
Element *child1 = el->getSecondChild(); Element *child1 = boundEl.el->getSecondChild();
if (reverseMode) { if (boundEl.reverseMode) {
swap(s0, s1); swap(s0, s1);
swap(child0, child1); swap(child0, child1);
} }
...@@ -287,18 +288,20 @@ namespace AMDiS { ...@@ -287,18 +288,20 @@ namespace AMDiS {
// === To the mesh structure code. === // === To the mesh structure code. ===
TraverseStack stack; TraverseStack stack;
ElInfo *elInfo = stack.traverseFirst(el->getMesh(), -1, traverseFlag); ElInfo *elInfo = stack.traverseFirst(mesh, -1, traverseFlag);
if (s0 != -1) { if (s0 != -1) {
while (elInfo && elInfo->getElement() != child0) while (elInfo && elInfo->getElement() != child0)
elInfo = stack.traverseNext(elInfo); elInfo = stack.traverseNext(elInfo);
meshChanged |= fitElementToMeshCode(code, stack, subObj, s0, reverseMode); meshChanged |=
fitElementToMeshCode(code, stack, boundEl.subObj, s0, boundEl.reverseMode);
} else { } else {
while (elInfo && elInfo->getElement() != child1) while (elInfo && elInfo->getElement() != child1)
elInfo = stack.traverseNext(elInfo); elInfo = stack.traverseNext(elInfo);
meshChanged |= fitElementToMeshCode(code, stack, subObj, s1, reverseMode); meshChanged |=
fitElementToMeshCode(code, stack, boundEl.subObj, s1, boundEl.reverseMode);
} }
......
...@@ -45,25 +45,15 @@ namespace AMDiS { ...@@ -45,25 +45,15 @@ namespace AMDiS {
* then \ref fitElementToMeshCode, that mainly refines the element such that * then \ref fitElementToMeshCode, that mainly refines the element such that
* it fits to the mesh structure code. * it fits to the mesh structure code.
* *
* \param[in] code The mesh structure code to which the edge/face of * \param[in] code The mesh structure code to which the edge/face of
* an element must be fitted. * an element must be fitted.
* \param[in] el Pointer to the element. * \param[in] boundEl Defines the element and its sub-object, i.e., edge or
* \param[in] subObj Defines whether an edge or a face must be fitted. * face that must be fitted.
* \param[in] ithObj Defines which edge/face must be fitted.
* \param[in] elType Element type of the element (only important in 3D).
* \param[in] reverseMode Defines, whether the mesh structure code is given
* in reverse mode, i.e., left and right children where
* changed when the code was created.
* *
* \return Returns true, if the mesh was changed, i.e. refined, to fit the * \return Returns true, if the mesh was changed, i.e. refined, to fit the
* element to the structure code. * element to the structure code.
*/ */
bool startFitElementToMeshCode(MeshStructure &code, bool fitElementToMeshCode(MeshStructure &code, BoundaryObject &boundEl);
Element *el,
GeoIndex subObj,
int ithObj,
int elType,
bool reverseMode);
private: private:
/** \brief /** \brief
......
...@@ -172,7 +172,7 @@ namespace AMDiS { ...@@ -172,7 +172,7 @@ namespace AMDiS {
stdMpi.send(0, pdb.periodicDof); stdMpi.send(0, pdb.periodicDof);
} }
stdMpi.startCommunication<int>(MPI_INT); stdMpi.startCommunication();
int foundError = 0; int foundError = 0;
...@@ -280,7 +280,7 @@ namespace AMDiS { ...@@ -280,7 +280,7 @@ namespace AMDiS {
StdMpi<CoordsVec> stdMpiCoords(pdb.mpiComm, true); StdMpi<CoordsVec> stdMpiCoords(pdb.mpiComm, true);
stdMpiCoords.send(sendCoords); stdMpiCoords.send(sendCoords);
stdMpiCoords.recv(recvCoords); stdMpiCoords.recv(recvCoords);
stdMpiCoords.startCommunication<double>(MPI_DOUBLE); stdMpiCoords.startCommunication();
for (RankToCoords::iterator it = sendCoords.begin(); for (RankToCoords::iterator it = sendCoords.begin();
...@@ -408,7 +408,7 @@ namespace AMDiS { ...@@ -408,7 +408,7 @@ namespace AMDiS {
StdMpi<CoordsVec> stdMpi(pdb.mpiComm, true); StdMpi<CoordsVec> stdMpi(pdb.mpiComm, true);
stdMpi.send(sendCoords); stdMpi.send(sendCoords);
stdMpi.recv(recvCoords); stdMpi.recv(recvCoords);
stdMpi.startCommunication<double>(MPI_DOUBLE); stdMpi.startCommunication();
int dimOfWorld = Global::getGeo(WORLD); int dimOfWorld = Global::getGeo(WORLD);
...@@ -478,7 +478,7 @@ namespace AMDiS { ...@@ -478,7 +478,7 @@ namespace AMDiS {
it != pdb.recvDofs.end(); ++it) it != pdb.recvDofs.end(); ++it)
stdMpi.recv(it->first); stdMpi.recv(it->first);
stdMpi.startCommunication<double>(MPI_DOUBLE); stdMpi.startCommunication();
int foundError = 0; int foundError = 0;
for (RankToDofContainer::iterator it = pdb.recvDofs.begin(); for (RankToDofContainer::iterator it = pdb.recvDofs.begin();
...@@ -565,7 +565,7 @@ namespace AMDiS { ...@@ -565,7 +565,7 @@ namespace AMDiS {
stdMpi.send(sendNumber); stdMpi.send(sendNumber);
for (RankToDofContainer::iterator it = recvDofs.begin(); it != recvDofs.end(); ++it) for (RankToDofContainer::iterator it = recvDofs.begin(); it != recvDofs.end(); ++it)
stdMpi.recv(it->first); stdMpi.recv(it->first);
stdMpi.startCommunication<int>(MPI_INT); stdMpi.startCommunication();
int foundError = 0; int foundError = 0;
for (std::map<int, int>::iterator it = stdMpi.getRecvData().begin(); for (std::map<int, int>::iterator it = stdMpi.getRecvData().begin();
......
...@@ -403,7 +403,7 @@ namespace AMDiS { ...@@ -403,7 +403,7 @@ namespace AMDiS {
for (std::set<int>::iterator it = recvFromRank.begin(); for (std::set<int>::iterator it = recvFromRank.begin();
it != recvFromRank.end(); ++it) it != recvFromRank.end(); ++it)
stdMpi.recv(*it); stdMpi.recv(*it);
stdMpi.startCommunication<int>(MPI_INT); stdMpi.startCommunication();
// === Evaluate the nnz structure this rank got from other ranks and add it to === // === Evaluate the nnz structure this rank got from other ranks and add it to ===
......
...@@ -14,66 +14,91 @@ ...@@ -14,66 +14,91 @@
namespace AMDiS { namespace AMDiS {
int intSizeOf(int &data) MPI_Datatype StdMpiHelper<int>::mpiDataType = MPI_INT;
MPI_Datatype StdMpiHelper<std::vector<int> >::mpiDataType = MPI_INT;
MPI_Datatype StdMpiHelper<std::vector<double> >::mpiDataType = MPI_DOUBLE;
MPI_Datatype StdMpiHelper<std::vector<std::vector<double> > >::mpiDataType = MPI_DOUBLE;
MPI_Datatype StdMpiHelper<std::vector<MeshStructure> >::mpiDataType = MPI_UNSIGNED_LONG;
MPI_Datatype StdMpiHelper<std::vector<AtomicBoundary> >::mpiDataType = MPI_INT;
MPI_Datatype StdMpiHelper<std::map<BoundaryType, std::map<DegreeOfFreedom, DegreeOfFreedom> > >::mpiDataType = MPI_INT;
MPI_Datatype StdMpiHelper<std::vector<std::pair<int, int> > >::mpiDataType = MPI_INT;
MPI_Datatype StdMpiHelper<std::vector<WorldVector<double> > >::mpiDataType = MPI_DOUBLE;
MPI_Datatype StdMpiHelper<std::map<WorldVector<double>, int> >::mpiDataType = MPI_DOUBLE;
// T = int
int StdMpiHelper<int>::getBufferSize(int &data)
{ {
return 1; return 1;
} }
int intSizeOf(std::map<const DegreeOfFreedom*, DegreeOfFreedom> &data) void StdMpiHelper<int>::createBuffer(int &data, int *buf)
{ {
return data.size() * 2; buf[0] = data;